Compare commits

..
1 Commits
Author SHA1 Message Date
MervinPraison ea615f9d88 deploy: 78493e0e17 2026-11-05 16:51:48 +00:00
800 changed files with 32986 additions and 150767 deletions

No files matched your search

@@ -1,375 +0,0 @@
---
description: Comprehensive analysis workflow that produces a detailed GitHub issue — combines deep codebase analysis with issue creation for implementation-ready tickets
---
# Analysis → GitHub Issue Workflow
Deep Analysis → Gap Analysis → Critical Review → Plan → Create GitHub Issue.
> **When to use this:** You need to analyze a feature, integration, or system deeply and produce a GitHub issue that another agent/developer can implement immediately without asking follow-up questions.
> **When NOT to use this:** Use `/analysis` for analysis-only (no issue). Use `/local-fix` if you're implementing yourself.
---
## PRINCIPLES (apply throughout)
- **Agent-centric**: Agents, workflows, sessions, tools, memory, multi-agent safety.
- **Protocol-driven core**: praisonaiagents = lightweight, protocol-first (protocols/hooks/adapters only).
- **DRY**: identify reuse; avoid duplication.
- **No perf impact**: preserve import-time and hot-path; heavy deps optional + lazy.
- **Async-safe + multi-agent safe** by default.
- **Easy for non-developers**: "Few lines of code to do the task!"
- **No competitor names in public surfaces**: Never mention competitor product, company, or project names in GitHub issues, PRs, commit messages, release notes, docs, or any other public-facing content. Refer to capabilities generically (e.g., "self-improving agent pattern", "external agent framework").
---
## CANONICAL PATHS
```
UI Repo: /Users/praison/praisonaiui (praisonaiui)
SDK Core: /Users/praison/praisonai-package/src/praisonai-agents (praisonaiagents)
Docs: /Users/praison/PraisonAIDocs
Extension: src/praisonaiui/*, docs/*, tests/*
```
---
## Phase 1 — Acceptance Criteria
Translate the request into testable criteria:
- API expectations (classes, methods, signatures)
- CLI expectations (commands, flags, help text)
- Documentation expectations (pages, examples)
- Test expectations (unit, integration, smoke, real agentic)
- Performance constraints (import time, hot-path)
---
## Phase 2 — External Research (if applicable)
### 2a. Read official sources
If analyzing an external integration, research from primary sources:
```bash
# Use read_url_content tool for:
# - Official site / announcement pages
# - GitHub README and docs
# - Framework documentation
# - Third-party write-ups
```
**Capture:**
- What is it? Purpose and design goals
- Key terminology and concepts
- Architecture overview
- Current ecosystem state
- References list (all URLs)
### 2b. Clone & analyze external codebase (if applicable)
```bash
git clone <repo-url> ~/<repo-name> --depth=1
ls -la ~/<repo-name>/
```
Key files to read:
- `AGENTS.md` / `README.md` — architecture overview
- Base class files (abstract methods, signatures)
- Factory / registry files (registration pattern)
- Model/config files (data structures)
- Example implementations (minimal + full-featured)
- `pyproject.toml` / `package.json` — dependencies
---
## Phase 3 — PraisonAI Codebase Inventory
### 3a. Inventory with evidence
Go through ALL relevant files, understand current logic end-to-end.
```bash
# UI repo
ls /Users/praison/praisonaiui/src/praisonaiui/
ls /Users/praison/praisonaiui/tests/
ls /Users/praison/praisonaiui/docs/
# Optional cross-check against SDK only when needed
ls /Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/
```
**Document:**
- Public APIs: modules/classes/functions and exports
- Protocols/adapters/hooks and extension points
- CLI commands, options, help text
- Integrations (db/observability/tools)
- Tests (unit/integration), fixtures, CI config
- Docs (Mintlify), examples, recipes
Provide: **file paths + key symbols + grep counts + entry points**.
### 3b. Identify DRY opportunities
- Existing abstractions that can be reused
- Duplicated code that should be consolidated
- Existing protocols before creating new ones
---
## Phase 4 — Detailed Analysis
### 4a. Architecture and behavior
- Control flow and data flow
- Concurrency model (sync/async)
- Multi-agent interactions
- Dependency boundaries (core/wrapper/tools)
- Failure modes and error handling
### 4b. Invariants check
Verify these are preserved:
- [ ] Protocol-driven core (no heavy impls in praisonaiagents)
- [ ] Lazy imports (optional deps never at module level)
- [ ] Backward compatible (public API changes need deprecation)
- [ ] Safe defaults (new features opt-in)
---
## Phase 5 — Gap Analysis
Compare acceptance criteria vs current state.
### Checklist
| Area | Current State | Gap | Severity | Impact | Placement |
|------|---------------|-----|----------|--------|-----------|
| Core SDK | | | | | |
| Wrapper | | | | | |
| Tools/plugins | | | | | |
| CLI | | | | | |
| Docs | | | | | |
| Tests | | | | | |
| Exports | | | | | |
| Perf | | | | | |
| Multi-agent + async | | | | | |
### Gap severity levels
- **Critical**: Blocks functionality
- **High**: Significant limitation
- **Medium**: Missing feature
- **Low**: Nice-to-have
---
## Phase 6 — Critical Review
### 6a. Risks and footguns
- API ambiguity or edge cases
- Backward compatibility concerns
- Coupling violations
- Performance regressions
- Concurrency hazards
- Misuse risks
- Operational concerns
### 6b. Mitigation strategies
For each risk, document:
- "Safe by default" recommendation
- Explicit opt-in for dangerous behavior
- Documentation warnings
---
## Phase 7 — Implementation Plan
Step-by-step plan (DO NOT implement):
### 7a. Test-first (TDD)
1. Unit tests for new functionality
2. Integration tests for cross-component behavior
3. Smoke tests for quick validation
4. **Real agentic tests** (REQUIRED):
```python
from praisonaiagents import Agent
agent = Agent(name="test", instructions="You are helpful")
result = agent.start("Say hello in one sentence")
print(result) # Must call LLM and produce response
```
### 7b. Implementation order
1. Tests (TDD)
2. Core implementation
3. CLI integration
4. Documentation
5. Verification
### 7c. Files to change/create
| File | Action | Purpose |
|------|--------|---------|
| | | |
### 7d. Verification commands
```bash
# Unit tests
pytest tests/unit/test_<feature>.py -v
# Integration tests
pytest tests/integration/test_<feature>.py -v
# Smoke test
python -c "from praisonaiagents import <Feature>; print('OK')"
# Real agentic test
python examples/<feature>_example.py
```
---
## Phase 8 — Draft GitHub Issue
The issue must be **self-contained**. Another agent must be able to implement by reading only the issue.
### Required sections
```markdown
## Overview
One paragraph: what, why, and the end goal.
## Background
- Purpose and design goals
- Why this is valuable
- Current state / ecosystem
## Architecture Analysis
### Current Implementation
- Key files and their purposes
- Integration points
- Data flow
### Key File Locations
| File | Purpose | Lines |
|------|---------|-------|
## Gap Analysis Summary
### Critical Gaps
| Gap | Impact | Effort |
|-----|--------|--------|
### Feature Gaps
| Feature | Current Support | Gap |
|---------|-----------------|-----|
## Proposed Implementation
### Phase 1: Minimal
Working code example.
### Phase 2: Production
Working code example.
## Files to Create / Modify
### New files
| File | Purpose |
|------|---------|
### Modified files
| File | Change |
|------|--------|
## Technical Considerations
- Dependencies
- Performance impact
- Safety / approval
- Multi-agent safety
## Acceptance Criteria
- [ ] Verifiable checkbox list
## Implementation Notes
### Key Files to Read First
1. `path/to/file.py` (N lines) — purpose
### Critical Integration Points
1. Where X connects to Y
### Testing Commands
```bash
# Copy-pastable commands
```
## References
- [Link](url)
```
---
## Phase 9 — Create GitHub Issue
### 9a. Create via `gh` CLI
```bash
gh issue create \
--repo MervinPraison/PraisonAIUI \
--title "<Type>: <Descriptive Title>" \
--body "<issue body>"
```
**Title formats:**
- `Feature: <What>` — new functionality
- `Analysis: <Topic>` — analysis/research
- `Integration: <External System>` — external integration
- `Fix: <Problem>` — bug fix proposal
### 9b. Verify issue created
```bash
gh issue view <number> --repo MervinPraison/PraisonAIUI | head -20
```
---
## Checklist — Before Creating Issue
- [ ] Acceptance criteria defined and testable
- [ ] All relevant PraisonAI files read (not skimmed)
- [ ] External sources researched (if applicable)
- [ ] Gap analysis completed with severity ratings
- [ ] Critical review identifies risks and mitigations
- [ ] Implementation plan is step-by-step with file list
- [ ] Issue body has working code examples (not pseudocode)
- [ ] All file paths are absolute and verified
- [ ] CLI commands are copy-pastable
- [ ] Acceptance criteria are verifiable (not vague)
- [ ] References section includes all URLs
- [ ] Issue is self-contained — no "see docs" without details
---
## Quick Reference — Common Mistakes
| Mistake | Fix |
|---------|-----|
| Pseudocode in examples | Use real, runnable code with imports |
| Vague file paths | Use absolute paths |
| Skipping gap analysis | Every gap needs severity + impact |
| Missing real agentic test | Include `agent.start()` test, not just construction |
| No verification commands | Include copy-pastable pytest/python commands |
| Claiming "done" without evidence | Every claim references specific files/symbols |
| Implementing instead of analyzing | This workflow produces issues, not code |
---
## Hard Rules
1. **DO NOT implement** — this workflow produces analysis and issues only
2. **DO NOT claim done** without evidence
3. **Every claim must reference** specific files/symbols
4. **Issue must be self-contained** — implementer needs no follow-up questions
5. **Working code examples required** — no pseudocode
-104
View File
@@ -1,104 +0,0 @@
---
description: analysis
---
You are an expert AI engineer in the PraisonAI ecosystem.
Your job: produce ONLY (1) analysis, (2) review, (3) gap analysis, (4) critical review, (5) plan, (6) proposal.
Do NOT implement. Do NOT write code. Do NOT update docs. Do NOT run tests beyond discovery.
Be precise, evidence-based, and agent-centric.
PRINCIPLES (apply in all analysis/proposals):
- Agent-centric: Agents, workflows, sessions, tools, memory, multi-agent safety.
- Protocol-driven core: praisonaiagents = lightweight, protocol-first (protocols/hooks/adapters only).
- DRY: identify reuse; avoid duplication.
- No perf impact: preserve import-time and hot-path; heavy deps optional + lazy.
- Async-safe + multi-agent safe by default.
- Clear paid upgrade path (support/cloud/services) without restricting core.
- Easy for non-developers. "Few lines of code to do the task!"
CANONICAL PATHS:
- UI Repo: /Users/praison/praisonaiui (praisonaiui)
- SDK Core (reference): /Users/praison/praisonai-package/src/praisonai-agents (praisonaiagents)
- Docs: /Users/praison/PraisonAIDocs (JS: docs/js, Rust: docs/rust)
- Extension points: src/praisonaiui/*, docs/*, tests/*
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MANDATORY PROCESS (NO IMPLEMENTATION)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STEP 1 — Acceptance Criteria
- Translate request into testable criteria: API, CLI, docs, test expectations, perf constraints.
STEP 2 — Repo Inventory (evidence-based)
- Go through ALL relevant files, understand current logic end-to-end.
- Inventory with evidence:
- Public APIs: modules/classes/functions and exports
- Protocols/adapters/hooks and extension points
- CLI commands, options, help text
- Integrations (db/observability/tools)
- Tests (unit/integration), fixtures, CI config
- Docs (Mintlify), examples, recipes
- Provide: file paths + key symbols + grep counts + entry points.
- Identify DRY opportunities.
STEP 3 — Detailed Analysis
- Architecture and behavior: control flow, data flow, concurrency (sync/async), multi-agent interactions, dependency boundaries (core/wrapper/tools), failure modes.
- Highlight invariants: protocol-driven core, lazy imports, optional deps.
STEP 4 — Detailed Review
- Evaluate against principles: agent-centricity, API simplicity, DRY, perf, optional deps + lazy imports, async/multi-agent safety, test coverage, CLI parity, docs clarity.
- Concrete evidence for each judgment.
STEP 5 — Gap Analysis
- Compare acceptance criteria vs current state. Checklist:
- UI Core, CLI, Docs, Tests, Exports, Perf, Multi-agent + async
- Each gap: severity, impact, risk, recommended location (core/wrapper/tools).
STEP 6 — Critical Review
- Risks, footguns, maintenance concerns:
- API ambiguity, edge cases, backward compat
- Coupling violations, perf regressions, concurrency hazards
- Misuse risks, operational concerns
- Mitigation strategies and "safe by default" recommendations.
STEP 7 — Plan
- Step-by-step (do not implement): tests (TDD) → implementation → CLI → docs → verification
- Exact files to change/create. Migration/compat plan. Rollback plan. Verification commands. Perf checks. Multi-agent + async test strategy.
REAL AGENTIC TEST definition (MUST include in every verification plan):
- A "real agentic test" = agent ACTUALLY RUNS and calls the LLM:
1. Create Agent with the feature being tested
2. Call `agent.start("a real task prompt")` — NOT just constructing the object
3. Agent MUST call LLM and produce text response
4. Print full output so dev can see it worked end-to-end
- Example:
```python
from praisonaiagents import Agent
agent = Agent(name="test", instructions="You are a helpful assistant")
result = agent.start("Say hello in one sentence")
print(result)
```
- Assert-only object construction = SMOKE TEST, not real agentic test.
- Both smoke AND real agentic tests required.
STEP 8 — Proposal
- Minimal, agent-centric design and API/CLI surface:
- protocols/hooks in core; implementations in wrapper/tools
- Clear defaults and explicit overrides
- Multi-agent resource isolation/sharing
- Error model and observability hooks
- Include: "Simple API" examples, CLI UX, docs outline, paid upgrade path.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
REQUIRED OUTPUT (in order):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1) Acceptance Criteria
2) Inventory (evidence: paths/symbols/exports/grep counts)
3) Detailed Analysis (architecture + flows + invariants)
4) Detailed Review (quality vs principles, evidence-based)
5) Gap Analysis (checklist + severity/impact/placement)
6) Critical Review (risks + mitigations)
7) Plan (step-by-step + file list + verification strategy)
8) Proposal (agent-centric design + API/CLI/docs outline)
Hard rules: DO NOT implement. DO NOT write code. DO NOT claim done. Every claim must reference specific files/symbols.
-228
View File
@@ -1,228 +0,0 @@
---
description: Audit existing docs against live code, then create a comprehensive GitHub issue in PraisonAIDocs with correct, tested information ready for a writer/agent to implement immediately
---
# Create PraisonAIDocs Issue Workflow
Audit code → Compare with existing docs → Draft correct content → Create issue.
> **When to use this:** A feature is already implemented in PraisonAI but the docs are missing, outdated, or wrong. You need to file a self-contained docs issue in `MervinPraison/PraisonAIDocs` that a writer or agent can act on without asking follow-up questions.
> **When NOT to use this:** Use `@[/create-github-issue]` for new integrations that need external research. Use `@[/local-fix]` if you are writing the docs yourself.
---
## Phase 1 — Identify the Feature & Existing Docs
### 1a. Find the relevant doc file
```bash
ls /Users/praison/PraisonAIDocs/docs/<section>/
cat /Users/praison/PraisonAIDocs/docs/<section>/<feature>.mdx
```
Key doc sections:
- `docs/observability/` — tracing providers (Langfuse, LangSmith, etc.)
- `docs/tools/` — tool integrations
- `docs/features/` — agent features
- `docs/cli/` — CLI commands
- `docs/guides/` — how-to guides
### 1b. Read the existing doc fully
Note every claim that needs verification:
- Install commands
- Import statements
- API method names and signatures
- Environment variable names
- CLI commands
---
## Phase 2 — Audit the Live Code
### 2a. Find the source implementation
```bash
# Search praisonaiagents core SDK
grep -rn "<feature>" /Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/ 2>&1 | grep -v ".pyc"
# Search praisonai wrapper (CLI, integrations)
grep -rn "<feature>" /Users/praison/praisonai-package/src/praisonai/praisonai/ 2>&1 | grep -v ".pyc"
# Search praisonai-tools
grep -rn "<feature>" /Users/praison/PraisonAI-tools/ 2>&1 | grep -v ".pyc"
```
### 2b. Read all relevant source files end-to-end
Read every file that implements the feature. For each file capture:
- Actual class/function names and signatures
- Required vs optional parameters
- Environment variables read (exact names)
- What gets called internally (trace the call chain)
- Any version-specific behavior
Key files to always check:
| File pattern | What to look for |
|---|---|
| `praisonaiagents/obs/__init__.py` | `_LazyObsModule`, factory methods, `auto()` |
| `praisonai_tools/observability/providers/<name>_provider.py` | `init()`, `is_available()`, `shutdown()`, `flush()` |
| `praisonai/observability/<name>.py` | CLI sink adapter, event handling |
| `praisonai/cli/commands/<name>.py` | All CLI sub-commands and options |
| `praisonai/__init__.py` | Global env var overrides that may interfere |
### 2c. Test the feature live
Run minimal test scripts to verify the actual behavior:
```bash
# Test the import works
python3 -c "from praisonaiagents.obs import obs; provider = obs.<name>(); print(type(provider).__name__, provider._initialized)"
# Test CLI commands
praisonai <feature> --help
praisonai <feature> <subcommand>
# Verify traces/output appear
timeout 30 praisonai <feature> <subcommand> --limit 5
```
### 2d. Build a "What's Wrong" table
For each doc claim that is incorrect, record:
| Current Doc (Wrong) | Correct |
|---|---|
| wrong install command | correct install |
| wrong import | correct import |
| non-existent method | actual method |
| wrong env var name | actual env var |
---
## Phase 3 — Draft the Issue
The issue body must be **self-contained and implementation-ready**. A writer should be able to update the doc by reading only the issue — no follow-up questions.
### Required sections:
```markdown
## Overview
One paragraph: what doc file needs updating, why it's wrong, and the end goal.
State explicitly: "All code in this issue has been tested and verified working."
## What's Wrong With the Current Docs
Table: Current (Wrong) | Correct
Cover: install commands, imports, API methods, env vars, missing sections.
## Correct Architecture (How It Actually Works)
Explain the actual internal call chain so the writer understands context.
Include a text diagram if helpful.
## Required Install
Exact pip commands, nothing more.
## Environment Variables
Table: Variable | Required | Description
Show bash export examples for both cloud and self-hosted.
## Python Usage
### Quickstart (Recommended)
Full working code with correct imports, init, agent run, and flush.
### Auto-Detection
Document obs.auto() or equivalent if applicable.
### Additional Patterns
Any other valid usage patterns (explicit provider, multi-agent, etc.).
## CLI Usage (if applicable)
All sub-commands with flags and examples.
Include an end-to-end CLI session example.
## Configuration File (if applicable)
Document any config files that are auto-created or auto-read.
## What Output Looks Like
Show what traces/output actually look like after a successful run.
## Version Compatibility Notes
Document any breaking changes between SDK versions that affect usage.
## Files to Update
Table: File | Change
## Acceptance Criteria
- [ ] Checkbox list — each item must be specific and verifiable
## References
List all source files read (with absolute paths).
```
---
## Phase 4 — Create the Issue
### 4a. Write body to a temp file
```bash
cat > /tmp/docs_issue_<feature>.md << 'EOF'
<issue body>
EOF
```
### 4b. Create via `gh` CLI
```bash
gh issue create \
--repo MervinPraison/PraisonAIDocs \
--title "Docs: <action verb> <feature> page — <one-line summary of what's wrong>" \
--label "documentation" \
--body-file /tmp/docs_issue_<feature>.md
```
**Title format:** `Docs: Rewrite/Update/Add <Feature> page — <what's wrong or missing>`
Examples:
- `Docs: Rewrite Langfuse integration page with correct Langfuse v4 API and CLI commands`
- `Docs: Add obs.auto() documentation to observability overview`
- `Docs: Fix LangSmith install command and update import paths`
### 4c. Verify
```bash
gh issue view <number> --repo MervinPraison/PraisonAIDocs | head -30
```
Confirm the URL: `https://github.com/MervinPraison/PraisonAIDocs/issues/<number>`
---
## Checklist — Before Creating the Issue
- [ ] Existing doc file read completely
- [ ] All source files implementing the feature read end-to-end (not skimmed)
- [ ] Feature tested live — not just code-read
- [ ] "What's Wrong" table is complete and specific
- [ ] All code examples in the issue are copy-pastable and tested
- [ ] All env var names are verified against source (not guessed)
- [ ] All CLI commands verified with `--help` and live run
- [ ] Acceptance criteria are specific and verifiable (not vague)
- [ ] References list includes all source file paths read
- [ ] Issue is self-contained — writer needs no follow-up
---
## Quick Reference — Common Mistakes
| Mistake | Fix |
|---|---|
| Documenting what the code *should* do, not what it *does* | Run it. Test it. Document the actual behavior. |
| Copying import paths from docs being replaced | Always verify imports against source files |
| Missing the "What's Wrong" table | This is the most important section — be explicit |
| Vague acceptance criteria like "docs are updated" | Write specific, testable criteria: "install command is `pip install langfuse`" |
| Not checking for interfering globals (e.g. `OTEL_SDK_DISABLED`) | Always grep `__init__.py` files for env var overrides |
| Forgetting `provider.flush()` in examples | Async buffers need explicit flush before process exit |
| Not testing with a real API key | Code-reading alone misses runtime errors |
| Using `timeout` too short for first-run (downloads, auth) | Use `timeout 120` for agent runs, `timeout 30` for CLI |
-308
View File
@@ -1,308 +0,0 @@
---
description: Research a topic in-depth, analyze both external and local codebases, and create a comprehensive GitHub issue — ready for another agent/developer to act on immediately
---
# Create GitHub Issue Workflow
Research → Clone & Analyze → PraisonAI Analysis → Draft → Create Issue.
> **When to use this:** You need to create a detailed, implementation-ready GitHub issue for a new integration, feature, or benchmark. The issue must contain enough context that another agent or developer can implement it without asking further questions.
> **When NOT to use this:** Use `@[/local-fix]` if you are implementing the change yourself, not just filing an issue.
---
## Phase 1 — Online Research
### 1a. Read official sources
Research the topic from all primary sources: official site, GitHub repo, documentation, blog posts.
```bash
# Example searches (adapt to your topic)
# - Official site / announcement pages
# - GitHub README and docs
# - Third-party write-ups (e.g. Snorkel AI, Epoch AI)
# - Framework documentation (core concepts, agents, running)
```
URLs to read for each source (use `read_url_content` tool):
- Official announcement / news page
- GitHub repository README (multiple chunks if large)
- Framework/integration documentation pages
- Any relevant blog posts or analysis
**Capture for the issue:**
- What is it? Purpose and design goals
- Key terminology and concepts (with definitions)
- Architecture overview
- Current leaderboard / ecosystem state
- References list (all URLs)
### 1b. Read paginated content
For large pages, read additional chunks:
```
view_content_chunk(document_id=<url>, position=2)
view_content_chunk(document_id=<url>, position=3)
view_content_chunk(document_id=<url>, position=4)
```
Continue until all relevant sections are read (core concepts, agent types, running instructions, integration API).
---
## Phase 2 — Clone & Analyze External Codebase
### 2a. Clone the repository
```bash
git clone <repo-url> ~/<repo-name> --depth=1
```
### 2b. Explore structure
```bash
ls -la ~/<repo-name>/
ls -la ~/<repo-name>/src/
```
Key files to read (adapt paths to repo):
- `AGENTS.md` / `CLAUDE.md` / `README.md` — architecture overview
- Base class files (e.g. `base.py` for agents, environments)
- Factory / registry files (how things are registered)
- Model/config files (data structures agents must populate)
- Enum files (valid names, types)
- Example agent implementations (minimal + full-featured)
- `pyproject.toml` — Python version, dependencies
**Capture for the issue:**
- Repository structure diagram
- Key file paths with line counts
- Base class interface (all abstract methods with signatures)
- How to register a new agent (enum + factory pattern)
- Data models the agent must populate (`AgentContext`, etc.)
- Example agent implementations (minimal and production)
- CLI commands to run the integration
- Environment variables required
### 2c. Read base classes end-to-end
Read every relevant base class completely. For agent integrations:
```
read_file(base.py) # BaseAgent / BaseInstalledAgent
read_file(factory.py) # AgentFactory registration
read_file(models/agent/name.py) # AgentName enum
read_file(models/agent/context.py) # AgentContext fields
read_file(examples/agents/minimal_agent.py) # Minimal example
read_file(agents/installed/reference_agent.py) # Full example
```
### 2d. Read a reference implementation
Pick the most complete existing agent implementation (e.g. `codex.py`, `gemini_cli.py`) and read it fully. This reveals:
- Install pattern (system packages → user packages)
- Version detection (`get_version_command` / `parse_version`)
- `@with_prompt_template` decorator usage
- `populate_context_post_run` for token tracking
- ATIF trajectory support (`SUPPORTS_ATIF`)
- `CliFlag` / `EnvVar` declarative config
- `exec_as_root` vs `exec_as_agent` usage
---
## Phase 3 — Analyze PraisonAI Codebase
### 3a. Identify relevant components
```bash
ls /Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/
ls /Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/tools/
ls /Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/agent/
```
Key files to read for agent integration issues:
| File | What to look for |
|------|-----------------|
| `praisonaiagents/tools/shell_tools.py` | `execute_command`, approval decorators |
| `praisonaiagents/agent/agent.py` | `Agent.start()`, `Agent.chat()`, token tracking |
| `praisonaiagents/approval/` | `@require_approval`, auto-approval backend |
| `praisonaiagents/eval/` | Evaluation framework hooks |
| `praisonaiagents/agents/agents.py` | `AgentTeam` multi-agent |
| `pyproject.toml` | Current version, optional dependencies |
### 3b. Map integration points
For each PraisonAI component, document:
- What it does
- How it maps to the external system's interface
- What needs bridging (e.g. wrapping `environment.exec()` as a tool)
- Known gotchas (e.g. `@require_approval` must be bypassed in containers)
---
## Phase 4 — Draft the Issue
The issue body must be self-contained. Another agent must be able to implement the feature by reading only the issue — no follow-up questions.
### Required sections:
```markdown
## Overview
One paragraph: what, why, and the end goal.
## Background: What is <X>?
- Purpose and design goals
- Key statistics (task count, solve rates, etc.)
- Why <X> + PraisonAI is valuable
- Current ecosystem / leaderboard state
## <X> Architecture (Codebase Analysis)
> Repo analyzed locally: `~/<repo-name>` (cloned at `~/<repo-name>`)
### Core Concepts
Table: Concept | Description
### Two (or N) Integration Types
Code examples for each type with full signatures.
### Key File Locations in <X> Codebase
Directory tree with annotations for each important file.
### Data Models
Full class definitions the agent must populate.
### How to Run (CLI)
All relevant CLI commands with flags and examples.
## PraisonAI Architecture (Relevant to This Integration)
Table: Component | Location | Relevance
### PraisonAI Execution Model
How PraisonAI currently handles the relevant operations, and what must be adapted.
## Proposed Implementation Plan
### Approach: <Recommended> (with justification)
### Phase 1: Minimal Proof-of-Concept
Full working code example.
### Phase 2: Production Implementation
Full working code example.
### Phase N: Advanced Features
(ATIF, multi-agent, etc.)
## Files to Create / Modify
### New files (praisonai-package)
Table: File | Purpose
### Modifications to <External Repo> (PR upstream)
Table: File | Change
## Technical Considerations
Subsections for:
- Container/environment dependencies
- API key forwarding
- Safety/approval bypass
- Token tracking
- Parallel execution safety
## Job / Config Example
Working YAML config + CLI invocation.
## Use Cases Unlocked
Table: Use Case | How
## Acceptance Criteria
- [ ] Checkbox list of verifiable outcomes
## Implementation Notes for the Assigned Agent/Developer
### Key <X> Files to Read First
Numbered list with file paths and line counts.
### Key PraisonAI Files to Read
Numbered list with file paths.
### Critical Integration Points
Numbered list of the exact code-level bridges needed.
### Architecture Decision
Why the chosen approach (installed vs external, etc.) with trade-offs.
### Installation & Testing Commands
Copy-pastable commands to install, verify, and run.
### Upstream PR
What to submit upstream and where.
## References
Bullet list of all URLs used.
```
---
## Phase 5 — Create the Issue
### 5a. Create via `gh` CLI
```bash
gh issue create \
--repo <org>/<repo> \
--title "Feature: <Descriptive Title>" \
--label "enhancement" \
--body "<issue body>"
```
**Title format:** `Feature: <What> with <Integration> (<Framework/Version>)`
Example:
```bash
gh issue create \
--repo MervinPraison/PraisonAI \
--title "Feature: Integrate PraisonAI Agents with Terminal-Bench 2.0 (Harbor Framework)" \
--label "enhancement" \
--body "..."
```
### 5b. Verify the issue was created
```bash
gh issue view <issue-number> --repo <org>/<repo> | head -20
```
The output URL confirms success: `https://github.com/<org>/<repo>/issues/<number>`
---
## Checklist — Before Creating the Issue
- [ ] All primary documentation URLs read (including paginated chunks)
- [ ] External repo cloned locally and analyzed
- [ ] Base classes read end-to-end (not just skimmed)
- [ ] At least one reference implementation read fully
- [ ] PraisonAI codebase analyzed for integration points
- [ ] Issue body has working code examples (not pseudocode)
- [ ] All file paths are absolute and verified to exist
- [ ] CLI commands are copy-pastable and complete
- [ ] Acceptance criteria are verifiable (not vague)
- [ ] References section includes all URLs used
- [ ] Issue is self-contained — no "see docs for details" without the details
---
## Quick Reference — Common Mistakes
| Mistake | Fix |
|---------|-----|
| Pseudocode in examples | Use real, runnable code with imports |
| Vague file paths like `agents/` | Use absolute paths like `~/harbor/src/harbor/agents/base.py` |
| Missing `--depth=1` on clone | Large repos take forever; always use shallow clone |
| Only reading chunk 0 of a URL | Read chunks 1–4+ for paginated content |
| Skipping the factory/registry file | This is where registration happens; always read it |
| Not reading a reference agent | Pattern is not obvious from base class alone |
| Forgetting API key forwarding section | Always document how secrets are passed to containers |
| Skipping `populate_context_post_run` | Harbor uses this for token tracking and leaderboard data |
| Missing upstream PR instructions | Specify exact files to modify upstream for first-class support |
-190
View File
@@ -1,190 +0,0 @@
---
description: create and publish a post on mer.vin using praisonaiwp
---
## Config
- Server: `default` → `https://mer.vin`
- Config: `~/.praisonaiwp/config.yaml`
- Category for PraisonAI features: `PraisonAI`
---
## Step 1 — Compose the content
Structure every post as:
1. **Intro paragraph** — one sentence, what the feature solves
2. **Mermaid diagram** — architecture/flow (see block format below)
3. **Sections** — H2 headings, tables > prose, code blocks for usage
4. **Performance/summary** — table with concrete numbers
Keep it technical. Lead with diagrams and tables, not paragraphs.
---
## Step 2 — Mermaid block format (merpress)
> **Creating merpress:** Install the [Merpress – Mermaid for WordPress](https://wordpress.org/plugins/merpress/) plugin via `wp plugin install merpress --activate --allow-root` on the server. It adds the `wp:merpress/mermaidjs` block used below.
All posts use the native `wp:merpress/mermaidjs` block. Use this exact format:
```
<!-- wp:merpress/mermaidjs {"align":"full"} -->
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid alignfull"><pre class="mermaid">%%{init: {"theme": "base", "themeVariables": {"background": "transparent", "lineColor": "#000000"}}}%%
graph TD
A[Input] --> B[Agent]
B --> C[Tool]
C --> D[Output]
classDef hook fill:#189AB4,color:#fff
classDef agent fill:#8B0000,color:#fff
classDef decision fill:#444,color:#fff
class B agent
class C hook
</pre></div>
<!-- /wp:merpress/mermaidjs -->
```
**Do NOT use:** `[mermaid]...[/mermaid]` shortcode — that is the wrong format.
Color scheme:
- `#8B0000` (dark red) — agents, inputs, outputs
- `#189AB4` (teal) — tools, hooks
- `#444` — decisions/conditionals
---
## Step 2a — SVG/image upload via SSH
`praisonaiwp media upload` correctly SFTPs the file to `/tmp/` on the server, but
`_execute_wp()` in `~/praisonaiwp-cli/praisonaiwp/core/wp_client.py` never appends
`--allow-root`. Use direct SSH instead.
**SVG upload (Safe SVG plugin active on mer.vin):**
```bash
# 1. SCP SVG to server
scp -i ~/.ssh/id_ed25519 /path/to/diagram.svg <SSH_USER>@<SERVER_IP>:/tmp/
# 2. Import via WP-CLI — must pass --user=<admin> so Safe SVG capability check passes
ssh -i ~/.ssh/id_ed25519 <SSH_USER>@<SERVER_IP> \
"cd <WP_ROOT> && \
wp media import /tmp/diagram.svg --post_id=<POST_ID> \
--title='Title' --alt='Alt' --user=praison --allow-root --porcelain"
# → returns media ID
# 3. Get the URL
ssh -i ~/.ssh/id_ed25519 <SSH_USER>@<SERVER_IP> \
"cd <WP_ROOT> && \
wp post get <MEDIA_ID> --field=guid --allow-root"
```
> **Key:** `--user=praison` is required — Safe SVG checks upload capability against the
> current WP user. Without it, even with the plugin active, SVG imports are blocked.
**PNG fallback (if Safe SVG not available):**
```bash
rsvg-convert -w 1360 /path/to/diagram.svg -o /tmp/diagram_2x.png
# Then follow the same SSH steps above using the .png file (no --user needed)
```
Use this Gutenberg image block in the post content:
```
<!-- wp:image {"id":<MEDIA_ID>,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="<IMAGE_URL>" alt="Alt text" class="wp-image-<MEDIA_ID>"/></figure>
<!-- /wp:image -->
```
---
## Step 3 — Create the post
```bash
praisonaiwp create "Post Title" \
--status publish \
--content '<FULL GUTENBERG CONTENT>'
```
Note the returned **Post ID** from the output.
---
## Step 4 — Set category
```bash
praisonaiwp update <POST_ID> --category "PraisonAI"
```
---
## Step 5 — Validate mermaid format
```bash
ssh -i ~/.ssh/id_ed25519 <SSH_USER>@<SERVER_IP> \
"cd <WP_ROOT> && \
wp post get <POST_ID> --field=post_content --allow-root | grep -i mermaid"
```
Expected output must contain `wp:merpress/mermaidjs`, not `[mermaid]`.
---
## Key Gutenberg blocks reference
```
<!-- wp:paragraph --><p>text</p><!-- /wp:paragraph -->
<!-- wp:heading --><h2 class="wp-block-heading">Title</h2><!-- /wp:heading -->
<!-- wp:heading {"level":3} --><h3 class="wp-block-heading">Sub</h3><!-- /wp:heading -->
<!-- wp:code --><pre class="wp-block-code"><code>code here</code></pre><!-- /wp:code -->
<!-- wp:table -->
<figure class="wp-block-table"><table>
<thead><tr><th>Col</th></tr></thead>
<tbody><tr><td>Val</td></tr></tbody>
</table></figure>
<!-- /wp:table -->
<!-- wp:list --><ul class="wp-block-list"><li>item</li></ul><!-- /wp:list -->
<!-- wp:separator --><hr class="wp-block-separator has-alpha-channel-opacity"/><!-- /wp:separator -->
```
---
## Full example command
```bash
praisonaiwp create "Feature Name: What It Does" \
--status publish \
--content '<!-- wp:paragraph -->
<p>One sentence intro.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 class="wp-block-heading">Architecture</h2>
<!-- /wp:heading -->
<!-- wp:merpress/mermaidjs {"align":"full"} -->
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid alignfull"><pre class="mermaid">%%{init: {"theme": "base", "themeVariables": {"background": "transparent", "lineColor": "#000000"}}}%%
graph TD
A[Start] --> B[Agent]
class B agent
classDef agent fill:#8B0000,color:#fff
</pre></div>
<!-- /wp:merpress/mermaidjs -->
<!-- wp:code -->
<pre class="wp-block-code"><code>from praisonaiagents import Agent
agent = Agent(name="example")
result = agent.start("task")</code></pre>
<!-- /wp:code -->'
# Then set category:
praisonaiwp update <ID> --category "PraisonAI"
```
@@ -1,670 +0,0 @@
---
description: End-to-end workflow — deep analysis → GitHub issue → wait for implementing agents → create PR if missing → wait for reviewing agents → review PR locally → feedback to @claude → merge to main when robust per AGENTS.md
---
# End-to-End: Analysis → Issue → PR → Review → Merge
Deep Analysis → Gap Analysis → Critical Review → Plan → Create Issue → **Wait for implementing agents** → **Create PR if missing** → **Wait for reviewers** → **Validate PR locally** → **Feedback to @claude** → **Re-review after fixes** → **Merge to main if robust**.
> **When to use this:** You want a fully hands-off delivery loop. You describe a feature/integration/fix; this workflow produces the issue, monitors implementation by other agents (Claude, Copilot, CodeRabbit), validates their PR locally against `AGENTS.md` principles, loops feedback until the PR is robust, and merges to `main`.
> **When NOT to use this:** Use `/analysis-github-issue-create` if you only want the issue (no PR/merge). Use `/local-fix` if you are the implementer.
---
## PRINCIPLES (apply throughout)
- **Agent-centric**: Agents, workflows, sessions, tools, memory, multi-agent safety.
- **Protocol-driven core**: `praisonaiagents` = lightweight, protocol-first (protocols/hooks/adapters only).
- **DRY**: identify reuse; avoid duplication.
- **No perf impact**: preserve import-time and hot-path; heavy deps optional + lazy.
- **Async-safe + multi-agent safe** by default.
- **Easy for non-developers**: "Few lines of code to do the task!"
- **No competitor names in public surfaces**: Never mention competitor product, company, or project names in GitHub issues, PRs, commit messages, release notes, docs, or any other public-facing content. Refer to capabilities generically (e.g., "self-improving agent pattern", "external agent framework").
- **Test before merge**: never merge unvalidated PRs. Always clone the branch locally and run the tests.
- **Minimal code change**: prefer upstream one-line fixes over downstream workarounds.
---
## CANONICAL PATHS
```
Core SDK: /Users/praison/praisonai-package/src/praisonai-agents (praisonaiagents)
Wrapper: /Users/praison/praisonai-package/src/praisonai (praisonai)
Tools: /Users/praison/PraisonAI-tools
Docs: /Users/praison/PraisonAIDocs
TypeScript: /Users/praison/praisonai-package/src/praisonai-ts
AGENTS.md: /Users/praison/praisonai-package/src/praisonai-agents/AGENTS.md
```
---
# PART A — ANALYSIS & ISSUE (Phases 1–9)
These phases are identical to `/analysis-github-issue-create`. Execute them in order. **Do not implement any code** in these phases — they produce analysis and an issue only.
## Phase 1 — Acceptance Criteria
Translate the request into testable criteria:
- API expectations (classes, methods, signatures)
- CLI expectations (commands, flags, help text)
- Documentation expectations (pages, examples)
- Test expectations (unit, integration, smoke, real agentic)
- Performance constraints (import time, hot-path)
---
## Phase 2 — External Research (if applicable)
### 2a. Read official sources
If analyzing an external integration, research from primary sources:
```bash
# Use read_url_content tool for:
# - Official site / announcement pages
# - GitHub README and docs
# - Framework documentation
# - Third-party write-ups
```
**Capture:**
- What is it? Purpose and design goals
- Key terminology and concepts
- Architecture overview
- Current ecosystem state
- References list (all URLs)
### 2b. Clone & analyze external codebase (if applicable)
```bash
git clone <repo-url> ~/<repo-name> --depth=1
ls -la ~/<repo-name>/
```
Key files to read:
- `AGENTS.md` / `README.md` — architecture overview
- Base class files (abstract methods, signatures)
- Factory / registry files (registration pattern)
- Model/config files (data structures)
- Example implementations (minimal + full-featured)
- `pyproject.toml` / `package.json` — dependencies
---
## Phase 3 — PraisonAI Codebase Inventory
### 3a. Inventory with evidence
Go through ALL relevant files, understand current logic end-to-end.
```bash
# Core SDK
ls /Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/
grep -r "class.*Protocol" praisonaiagents/ --include="*.py" | wc -l
# Wrapper
ls /Users/praison/praisonai-package/src/praisonai/praisonai/
ls /Users/praison/praisonai-package/src/praisonai/praisonai/cli/commands/
# TypeScript
ls /Users/praison/praisonai-package/src/praisonai-ts/src/
```
**Document:**
- Public APIs: modules/classes/functions and exports
- Protocols/adapters/hooks and extension points
- CLI commands, options, help text
- Integrations (db/observability/tools)
- Tests (unit/integration), fixtures, CI config
- Docs (Mintlify), examples, recipes
Provide: **file paths + key symbols + grep counts + entry points**.
### 3b. Identify DRY opportunities
- Existing abstractions that can be reused
- Duplicated code that should be consolidated
- Existing protocols before creating new ones
---
## Phase 4 — Detailed Analysis
### 4a. Architecture and behavior
- Control flow and data flow
- Concurrency model (sync/async)
- Multi-agent interactions
- Dependency boundaries (core/wrapper/tools)
- Failure modes and error handling
### 4b. Invariants check
Verify these are preserved:
- [ ] Protocol-driven core (no heavy impls in `praisonaiagents`)
- [ ] Lazy imports (optional deps never at module level)
- [ ] Backward compatible (public API changes need deprecation)
- [ ] Safe defaults (new features opt-in)
---
## Phase 5 — Gap Analysis
Compare acceptance criteria vs current state.
### Checklist
| Area | Current State | Gap | Severity | Impact | Placement |
|------|---------------|-----|----------|--------|-----------|
| Core SDK | | | | | |
| Wrapper | | | | | |
| Tools/plugins | | | | | |
| CLI | | | | | |
| Docs | | | | | |
| Tests | | | | | |
| Exports | | | | | |
| Perf | | | | | |
| Multi-agent + async | | | | | |
### Gap severity levels
- **Critical**: Blocks functionality
- **High**: Significant limitation
- **Medium**: Missing feature
- **Low**: Nice-to-have
---
## Phase 6 — Critical Review
### 6a. Risks and footguns
- API ambiguity or edge cases
- Backward compatibility concerns
- Coupling violations
- Performance regressions
- Concurrency hazards
- Misuse risks
- Operational concerns
### 6b. Mitigation strategies
For each risk, document:
- "Safe by default" recommendation
- Explicit opt-in for dangerous behavior
- Documentation warnings
---
## Phase 7 — Implementation Plan
Step-by-step plan (DO NOT implement):
### 7a. Test-first (TDD)
1. Unit tests for new functionality
2. Integration tests for cross-component behavior
3. Smoke tests for quick validation
4. **Real agentic tests** (REQUIRED):
```python
from praisonaiagents import Agent
agent = Agent(name="test", instructions="You are helpful")
result = agent.start("Say hello in one sentence")
print(result) # Must call LLM and produce response
```
### 7b. Implementation order
1. Tests (TDD)
2. Core implementation
3. CLI integration
4. Documentation
5. Verification
### 7c. Files to change/create
| File | Action | Purpose |
|------|--------|---------|
| | | |
### 7d. Verification commands
```bash
# Unit tests
pytest tests/unit/test_<feature>.py -v
# Integration tests
pytest tests/integration/test_<feature>.py -v
# Smoke test
python -c "from praisonaiagents import <Feature>; print('OK')"
# Real agentic test
python examples/<feature>_example.py
```
---
## Phase 8 — Draft GitHub Issue
The issue must be **self-contained**. Another agent must be able to implement by reading only the issue.
### Required sections
```markdown
## Overview
One paragraph: what, why, and the end goal.
## Background
- Purpose and design goals
- Why this is valuable
- Current state / ecosystem
## Architecture Analysis
### Current Implementation
- Key files and their purposes
- Integration points
- Data flow
### Key File Locations
| File | Purpose | Lines |
|------|---------|-------|
## Gap Analysis Summary
### Critical Gaps
| Gap | Impact | Effort |
|-----|--------|--------|
### Feature Gaps
| Feature | Current Support | Gap |
|---------|-----------------|-----|
## Proposed Implementation
### Phase 1: Minimal
Working code example.
### Phase 2: Production
Working code example.
## Files to Create / Modify
### New files
| File | Purpose |
|------|---------|
### Modified files
| File | Change |
|------|--------|
## Technical Considerations
- Dependencies
- Performance impact
- Safety / approval
- Multi-agent safety
## Acceptance Criteria
- [ ] Verifiable checkbox list
## Implementation Notes
### Key Files to Read First
1. `path/to/file.py` (N lines) — purpose
### Critical Integration Points
1. Where X connects to Y
### Testing Commands
```bash
# Copy-pastable commands
```
## References
- [Link](url)
```
---
## Phase 9 — Create GitHub Issue
### 9a. Create via `gh` CLI
```bash
gh issue create \
--repo MervinPraison/PraisonAI \
--title "<Type>: <Descriptive Title>" \
--body-file /tmp/issue-body.md
```
**Title formats:**
- `Feature: <What>` — new functionality
- `Integration: <External System>` — external integration
- `Fix: <Problem>` — bug fix proposal
### 9b. Record the issue number
```bash
ISSUE_NUM=$(gh issue view <number> --repo MervinPraison/PraisonAI --json number --jq '.number')
echo "Tracking issue #$ISSUE_NUM"
```
---
# PART B — IMPLEMENTATION MONITORING (Phases 10–15)
After the issue is filed, other agents (`@claude`, GitHub Copilot agent, CodeRabbit) pick it up automatically. This part watches, shepherds, validates, and merges.
## Phase 10 — Wait ~10 min for implementing agents
After `gh issue create`, Claude and Copilot typically start work within seconds and finish a first pass in 5–15 minutes.
```bash
echo "Waiting 10 minutes for implementing agents..."
echo "Start: $(date)"
sleep 600
echo "End: $(date)"
```
### Then check: did they open a PR?
```bash
REPO=MervinPraison/PraisonAI
ISSUE_NUM=<number>
# Check for PRs that reference the issue
gh pr list --repo $REPO --state open --search "fixes #$ISSUE_NUM OR closes #$ISSUE_NUM" --json number,title,headRefName
# Also check for branches matching claude/issue-<N>-* naming convention
gh api repos/$REPO/branches --paginate --jq ".[] | select(.name | startswith(\"claude/issue-$ISSUE_NUM\")) | .name"
```
---
## Phase 11 — Create PR if none exists
If Claude pushed a branch but did not open a PR, open one yourself.
```bash
REPO=MervinPraison/PraisonAI
ISSUE_NUM=<number>
BRANCH=$(gh api repos/$REPO/branches --paginate --jq ".[] | select(.name | startswith(\"claude/issue-$ISSUE_NUM\")) | .name" | head -1)
if [ -n "$BRANCH" ]; then
TITLE=$(gh api repos/$REPO/commits/$BRANCH --jq '.commit.message' | head -1)
gh pr create --repo $REPO --head "$BRANCH" --base main \
--title "$TITLE" \
--body "Automated PR from Claude's work on issue #$ISSUE_NUM.
Branch: \`$BRANCH\`
Closes #$ISSUE_NUM"
fi
```
### If no branch exists after 10 minutes
Re-trigger Claude by commenting on the issue, then wait another 10 minutes and re-check:
```bash
gh issue comment $ISSUE_NUM --repo $REPO \
--body "@claude please pick up this issue — full analysis and plan are in the issue body."
sleep 600
```
---
## Phase 12 — Wait ~10 min for reviewing agents
Once a PR exists, `CodeRabbit`, `Copilot`, and CI pipelines run. Give them time to complete.
```bash
echo "Waiting 10 minutes for PR reviewers and CI..."
sleep 600
```
### Collect status
```bash
PR=<pr-number>
gh pr view $PR --repo $REPO --json state,mergeable,mergeStateStatus,updatedAt,commits,files \
| python -c "
import json,sys
d=json.load(sys.stdin)
print(f\" State: {d['state']} Mergeable: {d['mergeable']} MergeState: {d['mergeStateStatus']}\")
print(f\" Commits: {len(d['commits'])}\")
for f in d['files']:
print(f\" {f['path']}: +{f['additions']} -{f['deletions']}\")
"
# CI & review checks
gh pr view $PR --repo $REPO --json statusCheckRollup > /tmp/pr-checks.json
python -c "
import json
for c in json.load(open('/tmp/pr-checks.json'))['statusCheckRollup']:
s = c.get('conclusion') or c.get('status','?')
name = c.get('name') or c.get('context','?')
if s and s not in ('SKIPPED',):
print(f' {name}: {s}')
"
```
---
## Phase 13 — Validate the PR locally
**Never merge an unvalidated PR.** Always clone the branch and run tests.
```bash
REPO_URL=https://github.com/MervinPraison/PraisonAI.git
BRANCH=<branch-name>
WORKDIR=/tmp/pr-validate
rm -rf $WORKDIR
git clone --depth 1 --branch "$BRANCH" $REPO_URL $WORKDIR
cd $WORKDIR
# Files touched by the PR
gh pr view $PR --repo $REPO --json files --jq '.files[].path'
# Run the tests for changed files — ALWAYS use timeout (user global rule)
timeout 120 python -m pytest <test-paths> -v --tb=short
# Critical invariant checks (adapt per feature):
# 1) Lazy-import: heavy deps never imported at module level
timeout 30 python - <<'PY'
import sys
from praisonai.observability import <NewThing> # example
assert 'heavy_dep' not in sys.modules, "eager import — violates AGENTS.md §4.2"
print("OK: lazy import preserved")
PY
# 2) Cold-import benchmark (no regression)
timeout 30 python -c "import time; t=time.time(); import praisonaiagents; print(f'{(time.time()-t)*1000:.1f} ms')"
```
### Mergeability gate
A PR is **ready to merge only if ALL of these are true**:
- [ ] `gh pr view` reports `mergeable=MERGEABLE` and `mergeStateStatus` in `CLEAN`/`UNSTABLE` (not `DIRTY`/`BLOCKED`).
- [ ] All `test (3.x)` matrix jobs report `SUCCESS`.
- [ ] Local `pytest` on the changed test files passes with **zero failures** (skipped/xfailed tests are OK).
- [ ] Lazy-import invariant preserved (if the feature adds an optional dep).
- [ ] Cold-import time within ±2 % of `main` (AGENTS.md §4.2).
- [ ] No files outside the issue's declared scope were changed.
- [ ] The diff respects all invariants in AGENTS.md §4.6.
If **any** is false → go to Phase 14 (feedback). Do not merge.
---
## Phase 14 — Feedback to `@claude` when issues found
When validation fails, post a precise, actionable comment tagging `@claude`, referencing the exact test name, error, file, and the AGENTS.md principle violated.
```bash
gh pr comment $PR --repo $REPO --body "$(cat <<'EOF'
Hold on merge: validated locally on HEAD `<short-sha>` and found these issues:
**Test failures:**
```
FAILED tests/.../test_x.py::TestY::test_z
AssertionError: <actual-message>
```
**Root cause:** <one-line diagnosis referencing the exact file and line>.
**AGENTS.md violation(s):**
- §<section>: <principle>
**Requested fix (minimal):**
- Change `<file>:<line>` to `<what>`.
- Or update the test assertion to `<what>` (if the test is wrong, not the code).
**What already passes:**
- N/M tests pass.
- Lazy-import invariant preserved ✅ (or not — state explicitly).
@claude please push a fix. Follow AGENTS.md principles: minimal change, protocol-driven, no perf impact, lazy imports, backward-compatible, safe defaults. Make sure the PR is robust — run the tests locally before force-pushing.
EOF
)"
```
### Loop
After commenting:
```bash
echo "Waiting 10 minutes for Claude to push fixes..."
sleep 600
# → return to Phase 12 (fetch new commits, re-run checks)
```
Repeat Phases 12 → 13 → 14 until the mergeability gate in Phase 13 is fully green, or escalate to a human after 3 failed rounds.
### When the PR has merge conflicts
If `mergeStateStatus=DIRTY`, ask Claude to rebase rather than resolving conflicts yourself on non-trivial logic:
```bash
gh pr comment $PR --repo $REPO --body "@claude this PR has merge conflicts with \`main\` (PR #<X> was merged, touching the same regions). Please rebase onto latest \`main\`, re-run \`pytest <paths>\`, and force-push."
```
---
## Phase 15 — Merge to `main`
Once Phase 13's gate is fully green:
### 15a. Final diff review against AGENTS.md
```bash
gh pr diff $PR --repo $REPO | less
```
**Hard gate — every box must be ticked before merge:**
- [ ] **Protocol-driven core (§4.1)**: no heavy implementations leaked into `praisonaiagents`.
- [ ] **No perf impact (§4.2)**: lazy imports confirmed; import benchmark within ±2 %.
- [ ] **DRY (§4.3)**: no new duplication; existing protocols/adapters reused where possible.
- [ ] **Agent-centric (§4.4)**: API centers on agents/sessions/tools/memory.
- [ ] **Async-safe + multi-agent safe (§4.5)**: no shared mutable globals; locks where needed.
- [ ] **Invariants preserved (§4.6)**: backward compatible, safe defaults, deterministic tests.
- [ ] **Naming conventions (§4.9)**: `XProtocol` for interfaces, `XAdapter` for impls, `add_*`/`get_*`/`save`/`load` verbs.
- [ ] No `.md` files added beyond those explicitly requested (per user global rule).
- [ ] Tests run locally with `timeout` — never hang (per user global rule).
### 15b. Merge
```bash
gh pr merge $PR --repo $REPO --squash --delete-branch
# --squash preserves linear main; --delete-branch keeps the repo clean
```
### 15c. Verify
```bash
gh pr view $PR --repo $REPO --json state,mergedAt,mergeCommit
gh issue view $ISSUE_NUM --repo $REPO --json state # should auto-close
```
---
# Orchestration Snippet (one-shot reference)
For a single end-to-end invocation, chain Part B phases:
```bash
#!/usr/bin/env bash
set -euo pipefail
REPO=MervinPraison/PraisonAI
ISSUE_NUM=<fill>
# Phase 10: wait for implementing agents
sleep 600
# Phase 11: ensure PR exists
BRANCH=$(gh api repos/$REPO/branches --paginate \
--jq ".[] | select(.name | startswith(\"claude/issue-$ISSUE_NUM\")) | .name" | head -1)
PR=$(gh pr list --repo $REPO --state open --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null || true)
if [ -z "$PR" ] && [ -n "$BRANCH" ]; then
TITLE=$(gh api repos/$REPO/commits/$BRANCH --jq '.commit.message' | head -1)
gh pr create --repo $REPO --head "$BRANCH" --base main \
--title "$TITLE" --body "Closes #$ISSUE_NUM"
PR=$(gh pr list --repo $REPO --state open --head "$BRANCH" --json number --jq '.[0].number')
fi
echo "Tracking PR #$PR"
# Phase 12: wait for reviewers + CI
sleep 600
# Phases 13–14: validate + feedback loop (cap at 3 rounds)
for round in 1 2 3; do
echo "=== Validation round $round ==="
# clone + pytest (per feature) — if green break; else gh pr comment + sleep 600
break # placeholder
done
# Phase 15: merge
gh pr merge $PR --repo $REPO --squash --delete-branch
gh issue view $ISSUE_NUM --repo $REPO --json state
```
---
## Checklist — Before Merging
- [ ] Issue exists and describes the work
- [ ] PR exists and references the issue (`Closes #N`)
- [ ] Branch was fetched and tests were run **locally** — not just CI-trusted
- [ ] All PR-relevant tests pass with zero failures
- [ ] CI matrix (3.10 / 3.11 / 3.12) is all green
- [ ] Lazy-import / cold-import invariants verified if optional deps added
- [ ] Diff reviewed against every AGENTS.md §4 principle
- [ ] `mergeStateStatus` in `CLEAN`/`UNSTABLE`, never `DIRTY`/`BLOCKED`
- [ ] No files outside the issue's scope were changed
- [ ] If feedback was given, `@claude` had a chance to respond and fixed everything
---
## Quick Reference — Common Mistakes
| Mistake | Fix |
|---------|-----|
| Merging without running tests locally | Always `git clone` the branch and run `pytest` |
| Resolving complex conflicts manually | Ask `@claude` to rebase instead |
| Trusting CI alone | CI jobs can be skipped / out-of-date; local validation is source of truth |
| Vague feedback to `@claude` | Every comment must cite file, line, test name, error, and AGENTS.md section |
| Waiting forever | Cap loops at 3 rounds, then escalate to a human |
| Running commands without `timeout` | Always `timeout 60 ...` per user global rule |
| Creating `.md` docs proactively | Don't — user rule forbids unrequested `.md` files |
| Skipping diff review | Every merge needs a full-diff AGENTS.md pass |
---
## Hard Rules
1. **Never merge without local test validation.**
2. **Never merge when `mergeStateStatus = DIRTY` or `BLOCKED`.**
3. **Every `@claude` comment must be actionable** — file, line, exact fix, AGENTS.md ref.
4. **Cap feedback loops at 3 rounds** — escalate after that, don't spin forever.
5. **Use `--squash --delete-branch`** to keep `main` linear and the repo clean.
6. **Always verify** the issue auto-closed after merge.
7. **All `run_command` calls use `timeout`** to avoid hangs (user global rule).
8. **No proactive `.md` creation** beyond this workflow file (user global rule).
-63
View File
@@ -1,63 +0,0 @@
---
description: Project information and deployment reference for PraisonAIUI
---
## Project: PraisonAIUI
YAML-driven website/docs generator. One YAML file, one docs folder, one command — ship a beautiful documentation site.
**Aim**: AIUI is a standardised, protocol-driven UI framework for building *any* AI-powered interface — not hardcoded to PraisonAI.
## Key Files
| File | Purpose |
|------|---------|
| `aiui.template.yaml` | Site configuration (theme, nav, routes, components) |
| `docs/` | Markdown content directory |
| `src/praisonaiui/` | Python source (CLI, compiler, server, providers) |
| `src/praisonaiui/compiler/` | Build pipeline: config → static site |
| `src/praisonaiui/templates/frontend/` | Bundled React SPA (index.html + assets) |
| `.github/workflows/ci.yml` | CI (lint, test) + GitHub Pages deployment |
| `pyproject.toml` | Package metadata, dependencies, entry points |
| `CNAME` | Custom domain: `ui.praison.ai` |
## CLI Commands
```bash
aiui init # Scaffold new project
aiui build # Compile → static site in ./aiui/
aiui build --output site --minify # For GitHub Pages
aiui serve # Serve built site locally
aiui dev # Dev mode with hot reload
aiui validate # Validate aiui.template.yaml
```
## Build Output
`aiui build` produces a fully static SPA:
- `index.html` + `assets/` — React frontend bundle
- `ui-config.json` — compiled site configuration
- `docs-nav.json` — navigation tree from docs folder
- `route-manifest.json` — route definitions
- `docs/` — copied markdown content
## Deployment
- **CI**: On push to `main`, GitHub Actions runs `aiui build --output site --minify`
- **Deploy**: `peaceiris/actions-gh-pages@v4` pushes `./site/` to `gh-pages` branch
- **Domain**: `ui.praison.ai` via CNAME file copied into build output
- **No server required** — everything is static
## Testing
```bash
pip install -e .[dev]
pytest tests/unit tests/integration -v
ruff check src/praisonaiui
```
## Package
- PyPI name: `aiui`
- Entry points: `aiui` and `praisonaiui` (both map to `praisonaiui.cli:app`)
- Python: ≥3.9
-839
View File
@@ -1,839 +0,0 @@
---
description: Update install.sh and deploy PraisonAI to Kubernetes via Helm (CI/CD Pipeline)
---
# Install.sh Update & Helm Deployment Workflow
Complete guide for updating the PraisonAI install script and deploying to Kubernetes via the full CI/CD pipeline.
**⚠️ CRITICAL**: This workflow contains **NO SECRETS**. All sensitive values (tokens, passwords) must be passed via environment variables or external secret management.
## 📁 Key Locations (MUST KNOW)
### Scripts
| File/Resource | Absolute Path | Purpose |
|---------------|---------------|----------|
| **install.sh** | `/Users/praison/praisonai-package/src/praisonai/scripts/install.sh` | Main bash installer |
| **install.ps1** | `/Users/praison/praisonai-package/src/praisonai/scripts/install.ps1` | PowerShell installer |
### CI/CD Pipeline (GitHub → ACR → Helm → K8s)
| File/Resource | Absolute Path | Purpose |
|---------------|---------------|----------|
| **GitHub Workflow** | `/Users/praison/Sites/localhost/praisonai/.github/workflows/azure-pipeline.yaml` | CI/CD pipeline triggered on git push |
| **Dockerfile.php** | `/Users/praison/Sites/localhost/praisonai/Dockerfile.php` | PHP container build |
| **Dockerfile.nginx** | `/Users/praison/Sites/localhost/praisonai/Dockerfile.nginx` | Nginx container build |
| **Dockerfile.init** | `/Users/praison/Sites/localhost/praisonai/Dockerfile.init` | Init container build |
### Helm Deployment
| File/Resource | Absolute Path | Purpose |
|---------------|---------------|----------|
| **Helm Charts** | `/Users/praison/repos/person/helmcharts/` | All Kubernetes deployments |
| **wb_azure Chart** | `/Users/praison/repos/person/helmcharts/charts/wb_azure/` | PraisonAI WordPress deployment |
| **Production Values** | `/Users/praison/Sites/localhost/praisonai/values-praisonai-production.yaml` | Production Helm config |
| **Local Values** | `/Users/praison/Sites/localhost/praisonai/values-local.yaml` | Local development config |
| **Deployment Docs** | `/Users/praison/Sites/localhost/praisonai/DEPLOYMENT.md` | Deployment documentation |
| **Deployment Makefile** | `/Users/praison/Sites/localhost/praisonai/Makefile` | Deployment automation |
---
## 🔄 Full CI/CD Pipeline Overview
```
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Git Push │────▶│ GitHub Actions │────▶│ Azure ACR │
│ (master) │ │ azure-pipeline │ │ Image Build │
└─────────────────┘ └──────────────────┘ └────────┬────────┘
│
▼
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Kubernetes │◀────│ Helm Upgrade │◀────│ Update Image │
│ Deployment │ │ (values.yaml) │ │ Tag in Values │
└─────────────────┘ └──────────────────┘ └─────────────────┘
```
### Pipeline Steps:
1. **Git push** to master branch
2. **GitHub Actions** triggers (`.github/workflows/azure-pipeline.yaml`)
3. **Build** Docker images (nginx, php, init)
4. **Push** to Azure Container Registry (ACR)
5. **Update** Helm values with new image tag
6. **Deploy** using Helm upgrade
---
## 🚀 Phase 0 - Fully Automated CI/CD Pipeline
### Complete Auto-Deploy Architecture
```
Git Push ──▶ Build Images ──▶ Trigger Deploy ──▶ Helm Upgrade ──▶ Production
│ │ │ │
│ ▼ ▼ ▼
│ ACR Push helmcharts wb_azure chart
│ (pa-php:SHA) repository (K8s deploy)
│
└─── install.sh ────────────────────────────────────────────────▶ praison.ai/install.sh
```
### Step 0.1: Build Workflow (Automatic on Git Push)
**File**: `/Users/praison/Sites/localhost/praisonai/.github/workflows/azure-pipeline.yaml`
**Repository**: `https://github.com/MervinPraison/praison.ai`
This workflow triggers on every push to `master`:
```yaml
on:
push:
branches: [master]
```
**What it does:**
1. **Syncs install.sh** from PraisonAI repository (only if changed!)
- Checks out `MervinPraison/PraisonAI`
- Compares `install.sh` and `install.ps1` with existing web files
- **Only copies if files have actually changed** (avoids unnecessary redeploys)
- This ensures `https://praison.ai/install.sh` is always latest
2. Downloads env files from Azure Storage
3. Builds multi-arch Docker images (linux/amd64, linux/arm64)
4. Pushes to Azure Container Registry: `praison.azurecr.io/pa/`
5. **Triggers Helm deployment** via `repository_dispatch` event
**Key Step - Automatic Deploy Trigger:**
```yaml
- name: Trigger Helm Deployment
run: |
SHORT_SHA=$(git rev-parse --short HEAD)
curl -X POST \
-H "Authorization: token ${{ secrets.HELM_REPO_TOKEN }}" \
-d '{
"event_type": "deploy_wb_azure",
"client_payload": {
"image_tag": "'"$SHORT_SHA"'",
"source_repo": "'"${{ github.repository }}"'",
"source_commit": "'"${{ github.sha }}"'"
}
}' \
https://api.github.com/repos/praison/helmcharts/dispatches
```
### Step 0.2: Deploy Workflow (Triggered Automatically)
**File**: `/Users/praison/repos/person/helmcharts/.github/workflows/helm-upgrade-with-image.yml`
Listens for `repository_dispatch` events:
```yaml
on:
repository_dispatch:
types: [deploy_wb_azure, deploy_tcs_azure, deploy_tamilmanna_azure]
```
**What it does:**
1. Receives image tag from build workflow
2. Runs `helm upgrade --install wb_azure` with new image tag
3. Waits for rollout to complete
4. Verifies deployment
**Result**: Every git push automatically builds AND deploys!
### Required GitHub Secrets
For the automated CI/CD to work, you need these secrets configured:
**In praisonai site repository** (`https://github.com/MervinPraison/praison.ai`):
| Secret | Purpose |
|--------|---------|
| `AZURE_CREDENTIALS` | Azure login for ACR and AKS |
| `AZURE_USERNAME` | ACR username |
| `AZURE_PASSWORD` | ACR password |
| `AZURE_STORAGE_KEY` | Download env files from Azure Storage |
| `HELM_REPO_TOKEN` | **NEW**: Trigger deploy workflow in helmcharts repo |
**In helmcharts repository** (`/Users/praison/repos/person/helmcharts/.github/workflows/`):
| Secret | Purpose |
|--------|---------|
| `AZURE_CREDENTIALS` | Azure login for AKS |
| `AKS_CLUSTER_NAME` | Kubernetes cluster name |
| `AKS_RESOURCE_GROUP` | Azure resource group |
**To add HELM_REPO_TOKEN**:
1. Go to GitHub Settings → Developer settings → Personal access tokens
2. Create token with `repo` scope
3. Add as secret `HELM_REPO_TOKEN` in https://github.com/MervinPraison/praison.ai
**Current status**: ✅ Already configured (set via `gh secret set`)!
**Images built:**
- `praison.azurecr.io/pa/pa-nginx:SHORT_SHA`
- `praison.azurecr.io/pa/pa-nginx:master`
- `praison.azurecr.io/pa/pa-php:SHORT_SHA`
- `praison.azurecr.io/pa/pa-php:master`
- `praison.azurecr.io/pa/pa-init:SHORT_SHA`
- `praison.azurecr.io/pa/pa-init:master`
### Step 0.2: Update Helm Values with New Image Tag
After the ACR build completes, update the Helm values file to use the new image:
```bash
cd /Users/praison/Sites/localhost/praisonai
# Get the short SHA from the latest commit (matches the Docker tag)
SHORT_SHA=$(git rev-parse --short HEAD)
# Update values file with new image tag
helm upgrade praisonai /Users/praison/repos/person/helmcharts/charts/wb_azure \
-f values-praisonai-production.yaml \
--set image.tag=$SHORT_SHA \
--namespace default \
--timeout 10m
```
**Alternative**: Update values file permanently:
```bash
# Edit values-praisonai-production.yaml to set image.tag
sed -i "s/tag: \".*\"/tag: \"$SHORT_SHA\"/" values-praisonai-production.yaml
# Then commit and push the updated values
git add values-praisonai-production.yaml
git commit -m "ci: update image tag to $SHORT_SHA"
git push origin master
```
### Step 0.3: Full Automated Script (For CI/CD Integration)
```bash
#!/bin/bash
# deploy-after-build.sh - Run after ACR build completes
set -e
SHORT_SHA=$(git rev-parse --short HEAD)
NAMESPACE=default
RELEASE_NAME=praisonai
CHART_PATH=/Users/praison/repos/person/helmcharts/charts/wb_azure
VALUES_FILE=/Users/praison/Sites/localhost/praisonai/values-praisonai-production.yaml
echo "🚀 Deploying PraisonAI with image tag: $SHORT_SHA"
# Update Helm deployment with new image tag
helm upgrade --install $RELEASE_NAME $CHART_PATH \
-f $VALUES_FILE \
--set image.tag=$SHORT_SHA \
--namespace $NAMESPACE \
--timeout 10m \
--atomic
echo "✅ Deployment complete!"
echo ""
echo "Verify with:"
echo " kubectl get pods -n $NAMESPACE -l app.kubernetes.io/instance=$RELEASE_NAME"
echo " helm status $RELEASE_NAME -n $NAMESPACE"
```
---
### Step 0.4: Extend GitHub Actions for Automatic Helm Deployment
To make the CI/CD fully automated (build → deploy), extend the GitHub Actions workflow:
**File to edit**: `/Users/praison/Sites/localhost/praisonai/.github/workflows/azure-pipeline.yaml`
Add a new job after the `build` job:
```yaml
deploy:
needs: build # Wait for build to complete
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Setup kubectl
uses: azure/setup-kubectl@v3
with:
version: 'v1.28.0'
- name: Setup Helm
uses: azure/setup-helm@v3
with:
version: 'v3.13.0'
- name: Get AKS credentials
run: |
az aks get-credentials \
--resource-group your-resource-group \
--name your-aks-cluster-name \
--overwrite-existing
- name: Deploy with Helm
run: |
SHORT_SHA=$(git rev-parse --short HEAD)
helm upgrade --install praisonai \
/Users/praison/repos/person/helmcharts/charts/wb_azure \
-f values-praisonai-production.yaml \
--set image.tag=$SHORT_SHA \
--namespace default \
--timeout 10m \
--atomic
- name: Verify deployment
run: |
kubectl rollout status deployment/php-nginx -n default
helm status praisonai -n default
```
**Requirements for automatic deploy:**
1. GitHub repository secrets configured:
- `AZURE_CREDENTIALS` - Azure service principal credentials
- `AZURE_STORAGE_KEY` - For downloading env files
- `AZURE_USERNAME` / `AZURE_PASSWORD` - ACR login
2. AKS cluster access configured in Azure
3. Helm and kubectl available in GitHub Actions runner
---
## 🔧 Phase 1 — Update install.sh (Manual, When Needed)
### When to Update
- New PraisonAI version released
- New dependency requirements
- New OS support needed
- Bug fixes in installation process
### Step 1: Read Current install.sh
```bash
# View the install script
cat /Users/praison/praisonai-package/src/praisonai/scripts/install.sh
```
Key sections in install.sh:
- **Lines 1-50**: Header, usage, environment variables documentation
- **Lines 51-150**: OS detection (macOS, Linux, Windows/WSL)
- **Lines 151-300**: Python installation (version checks, package managers)
- **Lines 301-450**: Virtual environment setup
- **Lines 451-550**: PraisonAI package installation
- **Lines 551-637**: PATH configuration, shell integration, verification
### Step 2: Make Changes
**Common Changes:**
#### Update Default Version
```bash
# Find this line (around line 70):
PRAISONAI_VERSION="${PRAISONAI_VERSION:-latest}"
# Change to specific version if needed:
PRAISONAI_VERSION="${PRAISONAI_VERSION:-1.5.0}"
```
#### Add New Environment Variable
```bash
# Add to header section (after line 10, in the comment block):
# PRAISONAI_NEW_FEATURE - Description (default: value)
# Add to actual code (around line 75):
export PRAISONAI_NEW_FEATURE="${PRAISONAI_NEW_FEATURE:-default_value}"
```
#### Update Python Version Requirements
```bash
# Find Python version check (around line 100-120):
PYTHON_MIN_VERSION="3.9"
# Update if needed:
PYTHON_MIN_VERSION="3.10"
```
### Step 3: Test Changes
```bash
# Test locally (dry run)
cd /Users/praison/praisonai-package/src/praisonai/scripts
bash install.sh --dry-run
# Test in Docker (full test)
bash /Users/praison/praisonai-package/src/praisonai/scripts/test-install-smoke.sh
```
### Step 4: Verify Both Scripts
```bash
# Check install.sh syntax
bash -n /Users/praison/praisonai-package/src/praisonai/scripts/install.sh
# Check install.ps1 syntax (if pwsh available)
pwsh -Command "Get-Command /Users/praison/praisonai-package/src/praisonai/scripts/install.ps1"
```
---
## 🚀 Phase 2 — Deploy to Kubernetes (Helm)
### Pre-Deployment Checklist
```bash
# 1. Verify kubectl connection
kubectl get nodes
# 2. Check current Helm releases
helm list -n default
# 3. Verify chart exists
ls /Users/praison/repos/person/helmcharts/charts/wb_azure/
```
### Deployment Types
#### A. Fresh Deployment (First Time)
```bash
cd /Users/praison/Sites/localhost/praisonai
# Option 1: Using Makefile
make deploy
# Option 2: Manual helm command
helm upgrade --install praisonai /Users/praison/repos/person/helmcharts/charts/wb_azure \
-f values-praisonai-production.yaml \
--namespace default \
--timeout 10m \
--atomic
```
#### B. Update Existing Deployment
```bash
cd /Users/praison/Sites/localhost/praisonai
# Edit values file first
vim values-praisonai-production.yaml
# Then apply
make upgrade
# Or manually:
helm upgrade praisonai /Users/praison/repos/person/helmcharts/charts/wb_azure \
-f values-praisonai-production.yaml \
--namespace default \
--timeout 10m
```
#### C. Local Development Deployment
```bash
cd /Users/praison/Sites/localhost/praisonai
make local-deploy
```
### Values File Structure
```yaml
# /Users/praison/Sites/localhost/praisonai/values-praisonai-production.yaml
# Core settings
replicaCount: 2
# Database
dbHost: "10.0.0.11"
dbUser: "bible_4"
dbPassword: "changeme" # Override via --set
# OpenAI tokens (for plugin verification)
openaiVerificationToken: "token-here"
# Feature toggles
praisonai:
enabled: true
domain: praison.ai
whiteboard:
enabled: true
domain: whiteboard.gallery
# Disable other sites
bible: { enabled: false }
music: { enabled: false }
save: { enabled: false }
# Resources
resources:
requests:
cpu: 800m
memory: 1024Mi
limits:
cpu: 2000m
memory: 2048Mi
# Auto-scaling
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
# Ingress
ingress:
enabled: true
className: nginx
```
---
## 📊 Phase 3 — Verify Deployment
### Check Deployment Status
```bash
# Using Makefile
make status
# Manual checks
helm status praisonai -n default
kubectl get pods -l app.kubernetes.io/instance=praisonai -n default
kubectl get svc -l app.kubernetes.io/instance=praisonai -n default
```
### Verify All Resources
```bash
# Pods should be Running
kubectl get pods -n default | grep praisonai
# Services should be Active
kubectl get svc -n default | grep praisonai
# Ingress should exist
kubectl get ingress -n default | grep praisonai
# ConfigMaps
kubectl get configmap -n default | grep nginx-config
# Secrets
kubectl get secret -n default | grep db-password
```
### Check Application Health
```bash
# Port forward and test
echo "Visit http://127.0.0.1:8080"
kubectl port-forward svc/php-nginx 8080:80 -n default
# In another terminal:
curl http://127.0.0.1:8080/test.php
```
---
## 🔄 Phase 4 — Rollback (If Needed)
```bash
# View revision history
make history
# Rollback to previous revision
make rollback
# Or manually:
helm rollback praisonai 1 -n default
```
---
## 🛠️ Phase 5 — Troubleshooting
### Problem: "Resource exists and cannot be imported"
**Cause**: Existing Kubernetes resources not managed by Helm.
**Solution**: Adopt resources into Helm
```bash
cd /Users/praison/Sites/localhost/praisonai
./scripts/adopt-resources.sh praisonai default
```
Or manually annotate:
```bash
# For any resource type
kubectl annotate <resource-type> <name> \
meta.helm.sh/release-name=praisonai \
meta.helm.sh/release-namespace=default
kubectl label <resource-type> <name> \
app.kubernetes.io/managed-by=Helm
```
### Problem: Pods Not Starting
```bash
# Check events
kubectl get events -n default --sort-by='.lastTimestamp' | tail -20
# Check pod logs
kubectl logs -l app.kubernetes.io/instance=praisonai -n default
# Describe pod for details
kubectl describe pod <pod-name> -n default
```
### Problem: Image Pull Errors
```bash
# Check image pull secrets
kubectl get secret acr-auth -n default
# Verify ACR auth exists
kubectl create secret docker-registry acr-auth \
--docker-server=praison.azurecr.io \
--docker-username=<username> \
--docker-password=<password> \
-n default
```
---
## 📋 Phase 6 — Post-Deployment
### Update Documentation
If install.sh changed, update:
1. `/Users/praison/PraisonAIDocs/docs/installation.mdx` — Installation docs
2. `/Users/praison/praisonai-package/src/praisonai/scripts/README.md` — Script docs (if exists)
### Verify Website
```bash
# Check praison.ai is accessible
curl -I https://praison.ai
# Check whiteboard.gallery
curl -I https://whiteboard.gallery
```
### Monitor
```bash
# Watch pods
kubectl get pods -l app.kubernetes.io/instance=praisonai -n default -w
# Check resource usage
kubectl top pods -l app.kubernetes.io/instance=praisonai -n default
```
---
## 📚 Reference: Helm Chart Structure
```
/Users/praison/repos/person/helmcharts/charts/wb_azure/
├── Chart.yaml # Chart metadata (name: wb, version: 1.0.1)
├── values.yaml # Default values (fallback)
├── templates/
│ ├── deployment.yaml # Main php-nginx deployment
│ ├── service.yaml # NodePort service
│ ├── ingress.yaml # TLS + routing
│ ├── nginx-configMap.yaml # Server configs
│ ├── db-password-secret.yaml # DB credentials
│ ├── pdb.yaml # Pod disruption budget
│ ├── autoscalar.yml # HPA
│ ├── cert-manager.yaml # TLS certificates
│ └── _helpers.tpl # Template helpers
```
---
## 🎯 Quick Commands Reference
| Task | Command |
|------|---------|
| Deploy | `make deploy` |
| Update | `make upgrade` |
| Status | `make status` |
| History | `make history` |
| Rollback | `make rollback` |
| Logs | `make logs` |
| Restart | `make restart` |
| Local dev | `make local-deploy` |
| Dry run | `make dry-run` |
| Lint | `make lint` |
---
## ⚠️ Critical Rules
1. **Never commit SQL dumps**: `.gitignore` already excludes `*.sql` files
2. **Never commit secrets**: Use `--set` or external secret management
3. **Always test install.sh** after changes (use test-install-smoke.sh)
4. **Always verify deployment** with `make status` after Helm operations
5. **Use Infrastructure as Code**: All changes via Helm values files, never manual kubectl
6. **Version control**: Commit values files (without secrets), never commit generated manifests
---
## 🆘 Getting Help
If stuck:
1. Check `/Users/praison/Sites/localhost/praisonai/DEPLOYMENT.md` for detailed docs
2. Check `/Users/praison/Sites/localhost/praisonai/INFRASTRUCTURE_AS_CODE_SUMMARY.md` for quick reference
3. Run `helm status praisonai -n default` for deployment status
4. Run `kubectl get events -n default` for cluster events
5. View install.sh comments for usage examples (lines 1-50)
---
## 🔄 CI/CD Pipeline Summary (For New Agents)
### Complete Workflow (Fully Automated!)
```
Developer Push ──────────────────────────────────────────────▶ Production
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ 1. Git Push to │───▶│ 2. GitHub Actions │───▶│ 3. Sync │
│ master │ │ Trigger │ │ install.sh │
└─────────────────┘ └──────────────────┘ └────────┬─────────┘
│
┌────────────────────────┘
▼
┌──────────────────┐
│ 4. Azure ACR │
│ Build Images │
│ + Push │
└────────┬─────────┘
│
──────▶┌──────────────────┐
│ 5. Trigger Deploy│
│ (repository_ │
│ dispatch) │
└────────┬─────────┘
│
┌─────────────────┐ ┌──────────────────┐ │
│ 7. Production │◀───│ 6. Helm Upgrade │◀──┘
│ Running │ │ Deploy │
│ (includes │ │ │
│ install.sh) │ │ │
└─────────────────┘ └──────────────────┘
```
**🎉 Fully Automated**: Git push → Build → Deploy (No manual steps!)
### Automatic install.sh Sync
**Key Point**: The workflow automatically syncs `install.sh` from `MervinPraison/PraisonAI` repository **only if changed**:
```yaml
- name: Checkout PraisonAI for install.sh
uses: actions/checkout@v2
with:
repository: MervinPraison/PraisonAI
path: praisonai-package
- name: Sync install.sh to web folder (if changed)
run: |
# Only sync if files have actually changed
if ! diff -q praisonai-package/src/praisonai/scripts/install.sh ./web/install.sh; then
cp praisonai-package/src/praisonai/scripts/install.sh ./web/install.sh
fi
```
**Optimization**: Uses `diff` to compare files - only copies when install.sh or install.ps1 have actually changed. This avoids unnecessary Docker layer rebuilds and deployments.
**Result**: `https://praison.ai/install.sh` is automatically updated **only when the source files change**!
### How install.sh is Served
The `web/install.sh` file is copied into the Docker image at `/var/www/html/web/install.sh` and served by nginx:
```nginx
# In nginx-config, requests to praison.ai/install.sh
# are served from /var/www/html/web/install.sh
location / {
root /var/www/html/web;
try_files $uri $uri/ =404;
}
```
**URL Mapping**:
| File in Repo | URL |
|--------------|-----|
| `web/install.sh` | `https://praison.ai/install.sh` |
| `web/install.ps1` | `https://praison.ai/install.ps1` |
### What Files to Edit
| To Change | Edit File |
|-----------|-----------|
| Application code | `/Users/praison/Sites/localhost/praisonai/` (PHP files) |
| Docker images | `Dockerfile.php`, `Dockerfile.nginx`, `Dockerfile.init` |
| CI/CD pipeline | `.github/workflows/azure-pipeline.yaml` |
| Helm deployment config | `values-praisonai-production.yaml` |
| Install script | `/Users/praison/praisonai-package/src/praisonai/scripts/install.sh` |
### Common Tasks
**Task 1: Deploy new code**
```bash
cd /Users/praison/Sites/localhost/praisonai
git add .
git commit -m "feat: new feature"
git push origin master
# CI/CD automatically builds and deploys
```
**Task 2: Update install.sh and deploy**
```bash
# 1. Update install.sh
vim /Users/praison/praisonai-package/src/praisonai/scripts/install.sh
# 2. Test install.sh
bash /Users/praison/praisonai-package/src/praisonai/scripts/install.sh --dry-run
# 3. Commit and push
git add /Users/praison/praisonai-package/src/praisonai/scripts/install.sh
git commit -m "fix: update install script"
git push origin main
# 4. Deploy website (if needed)
cd /Users/praison/Sites/localhost/praisonai
make upgrade
```
**Task 3: Rollback deployment**
```bash
cd /Users/praison/Sites/localhost/praisonai
make rollback
# Or: helm rollback praisonai 1 -n default
```
### Architecture
| Layer | Technology | Purpose |
|-------|------------|---------|
| Source Control | Git/GitHub | Code repository |
| CI/CD | GitHub Actions | Automated build/deploy |
| Container Registry | Azure ACR | Docker image storage |
| Orchestration | Kubernetes (AKS) | Container management |
| Deployment | Helm | K8s package management |
| Ingress | NGINX Ingress + cert-manager | Traffic routing + TLS |
### Security Notes
- **No secrets in workflow files** - All tokens/passwords via env vars
- **ACR authentication** - Uses `acr-auth` secret in Kubernetes
- **GitHub Secrets** - `AZURE_CREDENTIALS`, `AZURE_USERNAME`, `AZURE_PASSWORD`
- **Never commit** `.env` files, SQL dumps, or credentials
-181
View File
@@ -1,181 +0,0 @@
---
description: instruction
---
Create multiple TODOs and sub-TODOs, get all things done.
First: detailed analysis, plan, and gap analysis. Go through all files, understand current logic. Search if needed.
Then: implement, fix, test (TDD, Agent-Centric, no perf impact, DRY). praisonaiagents is protocol-driven. Run unit, integration, smoke, and real agentic tests.
After: re-do detailed analysis/plan to find remaining gaps and propose fixes.
Docs: beginner-friendly, for non-developers. Explain concepts with mermaid diagrams (Dark Red #8B0000 for agents/inputs/outputs, Teal #189AB4 for tools, white #fff text). Less descriptive, more interactive. Use Mintlify components: Accordions, Badge, Callouts (Note/Warning/Info/Tip/Check/Danger), Cards/Columns, CodeGroup, Expandables, Tabs, Steps, Frame, Icon, Tooltip, Mermaid, ParamField, Tables, CardGroup.
You are an expert AI engineer in the PraisonAI ecosystem.
Production-quality code, zero regressions, full verification. Make PraisonAI the best agent framework.
### Core Philosophy
```
Simpler • More extensible • Faster • Agent-centric
```
| Principle | Rule |
|---|---|
| Agent-Centric | Design centers on Agents, workflows, sessions, tools, memory |
| Protocol-Driven | Core SDK: protocols/hooks/adapters only; heavy code in wrapper/tools |
| Minimal API | Fewer params, sensible defaults, explicit overrides |
| Performance-First | Lazy loading, optional deps, no hot-path regressions |
| Production-Ready | Safe by default, multi-agent safe, async-safe |
- Powerful, lightweight, reliable. Easy for non-developers.
- "Few lines of code to do the task!" — SDK and docs must feel this way.
- Each feature runs 3 ways: CLI, YAML, Python.
- Open source, developer-first. Core free, clear upgrade path to paid (support/cloud/services).
- Simple to adopt, hard to misuse, safe by default.
- Prioritise time saved, reduced risk, and operational confidence.
- Reduce production friction, not just add functionality.
- All features must have CLI integration. Agent-first naming and ergonomics.
ENGINEERING PRINCIPLES (MUST)
- DRY: reuse abstractions, no duplication.
- Protocol-driven core: protocols/hooks in core; heavy impl in wrapper/tools.
- No perf impact: lazy imports, optional deps, no global singletons, no heavy module-level work.
- TDD mandatory: tests first.
- Multi-agent + async safe by default.
- AGENTS.md is not for documentation.
CRITICAL REQUIREMENTS
- EXECUTE + VERIFY mode. No guessing. Proof for "done."
- Optional deps only; lazy import everything heavy.
- Every feature/fix: Python + CLI + docs/examples.
- Any core change must be justified: simpler client API, measurable benefit, NO perf regression.
- If TypeScript parity required: update praisonai-ts, but never at cost of Python core performance.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CANONICAL PATHS (MUST use these)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- Core SDK: /Users/praison/praisonai-package/src/praisonai-agents → praisonaiagents
- Wrapper: /Users/praison/praisonai-package/src/praisonai → praisonai
- Tools: /Users/praison/PraisonAI-tools → praisonai-tools
- Docs: /Users/praison/PraisonAIDocs (read AGENTS.md first before updating docs)
- Docs JS: /Users/praison/PraisonAIDocs/docs/js | Rust: docs/rust
- Examples: /Users/praison/praisonai-package/examples/
- TypeScript: /Users/praison/praisonai-package/src/praisonai-ts
- Rust: /Users/praison/praisonai-package/src/praisonai-rust (follow praisonai-ts/AGENTS.md)
- UI (this repo): /Users/praison/praisonaiui → praisonaiui
- Extension points: tools/base.py, tools/decorator.py, db/*
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ARCHITECTURE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Core (praisonaiagents): protocol-driven, lightweight. No heavy imports. Only protocols/hooks/adapters.
Wrapper (praisonai): real integrations (DBs, observability, CLI). Lazy imports, optional deps.
Tools (PraisonAI-tools): pluggable, never overload core/wrapper.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MANDATORY EXECUTION FLOW
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PHASE 1 — ANALYSIS (before writing code)
1.1 Acceptance Criteria — testable bullets for API, CLI, docs, tests, perf.
1.2 Repo Inventory — scan relevant files end-to-end:
- modules/classes/APIs/exports, CLI commands, tests, docs/examples
- Evidence: paths + symbols + grep counts. Identify DRY opportunities.
1.3 Gap Analysis — what exists vs what's needed:
- Missing: core SDK, wrapper, tools, CLI, docs, tests, exports
- Risks: perf, API breaks, optional deps, async, multi-agent
1.4 Report — current behavior, pain points, root causes (file refs), constraints, risk register, decision log.
1.5 Plan — step-by-step: tests → impl → CLI → docs → verify. Files to change. Compat/rollback/perf strategy.
1.6 Proposal — minimal agent-centric design. Protocols in core, impl in wrapper. Upgrade-path notes.
1.7 TODO Tree — granular, executable. Python + CLI + TDD + docs + perf.
- Second-to-last: "Verify all changes end-to-end"
- Last: "Implement remaining gaps (missing=0), re-verify" or "Final scan, confirm missing=0"
PHASE 2 — EXECUTE
2.1 TDD — write failing tests first. Deterministic and fast.
2.2 Implement — DRY, agent-centric, protocol-driven. Heavy code in wrapper/tools. Multi-agent + async safe.
2.3 CLI parity — add/extend CLI commands. Scriptable, clear help, proper exit codes.
2.4 Docs — Mintlify pages (SDK="Module", API="API"). Copy-paste runnable examples.
2.5 Verification:
- Run tests (unit/integration), show results.
- Smoke: `python3 -c "..."` + CLI help/run.
- Optional deps graceful degradation.
- Perf: no heavy core imports, import-time sanity.
- Provide evidence for every claim.
- dont use Sending termination request to command to terminate a process, kill port instead when terminating
REAL AGENTIC TEST (MANDATORY — not replaceable by smoke tests)
- After unit/smoke tests, MUST run at least one REAL agent execution:
1. Create Agent with the feature being tested
2. Call `agent.start("a real task prompt")` — NOT just constructing the object
3. Agent MUST call LLM and produce text response
4. Print full output so dev can see it worked end-to-end
- Minimum example:
```python
from praisonaiagents import Agent
agent = Agent(name="test", instructions="You are a helpful assistant")
result = agent.start("Say hello in one sentence")
print(result)
```
- Assert-only object construction = SMOKE TEST, not real agentic test.
- Both smoke AND real agentic tests required.
PHASE 3 — POST-IMPLEMENTATION ANALYSIS
3.1 Re-scan files, summarize final behavior/architecture.
3.2 Confirm remaining gaps (API, CLI, docs, tests, exports, perf, multi-agent, async). If gaps exist, treat as required work until missing=0.
3.3 Report: what changed, why, validation evidence, tradeoffs.
3.4 Plan: close remaining gaps or maintenance plan.
3.5 Proposal: refinements for UX, safety, perf, extensibility. Label: implemented vs out-of-scope.
Final rule: conclude only when evidence shows missing = 0.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PUBLISH WORKFLOW (reference)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GitHub Actions (recommended):
GitHub → Actions → "PyPI Release" → Run workflow → bump: patch
Requires repo secrets: PYPI_TOKEN, GH_TOKEN
Requires GitHub Environment "pypi" with required reviewers (Settings → Environments)
Manual — Publish aiui (PraisonAIUI):
cd /Users/praison/PraisonAIUI
# Bump version in pyproject.toml and src/praisonaiui/__version__.py
rm -rf dist && uv lock && uv build && uv publish --token "$PYPI_TOKEN"
git add pyproject.toml uv.lock src/praisonaiui/__version__.py
git commit -m "Release vX.Y.Z" && git tag vX.Y.Z && git push && git push --tags
gh release create vX.Y.Z --title "PraisonAIUI vX.Y.Z" --notes "Release vX.Y.Z" --latest
PyPI package name: aiui
Verify: pip index versions aiui | head -1
PraisonAI stack (separate repo — publish SDK before wrapper):
cd /Users/praison/praisonai-package/src/praisonai-agents
praisonai publish pypi
# Uses uv internally: uv lock → uv build → uv publish
# Auto-bumps patch version, requires PYPI_TOKEN env var
Step 2 — Publish praisonai (Wrapper):
cd /Users/praison/praisonai-package/src/praisonai
python scripts/bump_and_release.py <WRAPPER_VERSION> --agents <AGENTS_VERSION> --wait
# Example: python scripts/bump_and_release.py 4.5.90 --agents 1.5.91 --wait
# Waits for agents to be available on PyPI, bumps all version files,
# runs uv lock, builds, commits, tags, pushes, creates GitHub release
# Then: uv publish (from src/praisonai with clean dist/)
If bump_and_release published already, just verify:
pip index versions praisonai | head -1
If uv publish fails with "File already exists", it means the version is already on PyPI — success.
Step 3 — Publish praisonai-tools (External, if needed):
cd /Users/praison/PraisonAI-tools
# Bump version in pyproject.toml, then:
python3.13 -m build && uv run twine upload dist/*
PraisonAI PRs: NEVER merge automatically — user merges manually.
-223
View File
@@ -1,223 +0,0 @@
---
description: Implement, fix, and test code changes locally — for when the agent IS the implementer
---
# Local Fix Workflow
You are the implementer. Analyze → Plan → Implement → Test → Verify → PR.
> **When to use this:** The user explicitly asks you to fix something locally, or delegates a task that cannot be handled by the GitHub cloud agents.
> **When NOT to use this:** If given an Issue URL, prefer `@[/pr-review]` Step 8d — delegate to cloud agents first.
---
## Phase 1 — Analysis (before writing ANY code)
### 1a. Understand the problem
// turbo
```bash
cd /Users/praison/praisonai-package && git checkout main && git pull origin main
```
Read all relevant source files end-to-end. Use `grep`, `view_file`, and code navigation.
- Identify root cause with **file paths and line numbers**
- Trace the full code path (caller → callee → side effects)
- Assess blast radius (what else could break)
- Check for existing abstractions before creating new ones (DRY)
### 1b. Create TODO tree
Break work into granular, executable items:
```
- [ ] Write failing test(s)
- [ ] Implement fix (file:line references)
- [ ] CLI parity (if applicable)
- [ ] Docs update (if applicable)
- [ ] Run unit + integration tests
- [ ] Run real agentic test
- [ ] Verify end-to-end
```
---
## Phase 2 — Implement
### 2a. TDD — tests first
Write the failing test before touching implementation code.
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents && \
python -m pytest tests/<relevant_test>.py -x -v --tb=short
```
### 2b. Implement the fix
**Architecture rules (MUST follow):**
| Layer | What goes here | What does NOT go here |
|-------|---------------|----------------------|
| **Core SDK** (`praisonaiagents/`) | Protocols, hooks, adapters, base classes, decorators, dataclasses | Heavy implementations, optional deps at module level |
| **Wrapper** (`praisonai/`) | CLI commands, integrations, heavy impls, DB adapters, UI | Core logic |
| **Tools** (`PraisonAI-tools/`) | Pluggable tools, community extensions | Core or wrapper logic |
**Coding standards:**
- **Lazy imports**: Optional deps imported inside functions, never at module level
- **DRY**: Reuse existing abstractions; refactor if duplication found
- **Naming**: `add_X()`, `get_X()`, `XConfig`, `XProtocol`, `XAdapter`
- **Async-safe**: No blocking I/O in async context; use asyncio primitives
- **Multi-agent safe**: No shared mutable globals without `threading.Lock`
- **Security**: No hardcoded secrets; `hmac.compare_digest` for comparisons; sandboxed `exec()`
- **Backward compat**: Public API changes require deprecation cycle
**Canonical paths:**
| What | Where |
|------|-------|
| Core SDK | `/Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/` |
| Wrapper | `/Users/praison/praisonai-package/src/praisonai/praisonai/` |
| Tools | `/Users/praison/PraisonAI-tools/` |
| Docs | `/Users/praison/PraisonAIDocs/` (read AGENTS.md first) |
| Examples | `/Users/praison/praisonai-package/examples/` |
| TypeScript | `/Users/praison/praisonai-package/src/praisonai-ts/` |
### 2c. CLI parity
Every feature must work 3 ways: **Python, CLI, YAML**. If your change adds or modifies a feature, ensure CLI support exists.
---
## Phase 3 — Test & Verify
### 3a. Unit + Integration tests
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents && \
python -m pytest tests/ -x -q \
--ignore=tests/integration/test_whatsapp_web_real.py \
--ignore=tests/unit/tools/test_profiles.py \
--tb=short 2>&1 | tail -20
```
### 3b. Real agentic test (MANDATORY)
Unit tests alone are NOT sufficient. You MUST run at least one real agent execution:
```python
from praisonaiagents import Agent
agent = Agent(name="test", instructions="You are a helpful assistant")
result = agent.start("Say hello in one sentence")
print(result)
```
**Rules:**
- Agent MUST call `agent.start()` with a real prompt
- Agent MUST call the LLM and produce a text response
- Print full output — assert-only object construction is a SMOKE test, not agentic
- Both smoke AND real agentic tests required
### 3c. Security checks (if touching sensitive code)
```bash
# Hardcoded secrets
grep -rn "secret\|password\|token\|api_key" --include="*.py" <changed-files> | \
grep -v "test_\|#\|environ\|getenv\|config"
# Timing attacks
grep -rn "==.*api_key\|==.*secret\|==.*token" --include="*.py" <changed-files>
# Sandbox escapes
grep -rn "exec(\|eval(" --include="*.py" <changed-files>
```
### 3d. Performance sanity
```bash
# Verify no heavy imports at module level
python -c "import time; t=time.time(); import praisonaiagents; print(f'{(time.time()-t)*1000:.0f}ms')"
```
Target: < 200ms package import time.
---
## Phase 4 — Post-implementation scan
Re-scan changed files. Confirm:
- [ ] No remaining gaps (API, CLI, docs, tests, exports, perf)
- [ ] No regressions introduced
- [ ] All acceptance criteria met with evidence
If gaps remain → loop back to Phase 2. Conclude only when `missing = 0`.
---
## Phase 5 — Submit
### 5a. Create branch and PR
```bash
cd /Users/praison/praisonai-package && \
git checkout -b <type>/<descriptive-name> && \
git add -A && \
git commit -m "<type>: <description>" && \
git push origin <type>/<descriptive-name>
```
```bash
cd /Users/praison/praisonai-package && \
gh pr create \
--title "<type>: <description>" \
--body '## Summary
<what and why>
### Changes
- <file>: <what changed>
### Testing
- Unit tests: ✅
- Agentic test: ✅
- Security: ✅ (if applicable)' \
--head <type>/<descriptive-name> \
--base main
```
**Commit prefixes:** `fix:`, `feat:`, `security:`, `refactor:`, `docs:`, `test:`
> **Do NOT merge automatically** — user merges manually unless explicitly told otherwise.
### 5b. Verify PR state
// turbo
```bash
cd /Users/praison/praisonai-package && gh pr view --json state,title,url | cat
```
---
## Publish (only when user requests)
```bash
# Core SDK
cd /Users/praison/praisonai-package/src/praisonai-agents && praisonai publish pypi
# Wrapper
cd /Users/praison/praisonai-package/src/praisonai && \
python scripts/bump_and_release.py <VERSION> --agents <AGENTS_VERSION> --wait
```
---
## Quick Reference — Red Flags
| Red Flag | Fix |
|----------|-----|
| Module-level `import chromadb` | Move inside function with `try/except ImportError` |
| `exec(user_input)` without sandbox | Use `RestrictedPython` or sandbox module |
| `if token == secret:` | Use `hmac.compare_digest(token, secret)` |
| Shared mutable global `_cache = {}` | Add `threading.Lock`, or make per-agent |
| `debug=True` in production path | Remove or gate behind env var |
| Missing `async` variant for I/O | Add async version, wrap for sync callers |
-275
View File
@@ -1,275 +0,0 @@
---
description: Review, validate, and merge GitHub pull requests or triage issues
---
# PR / Issue Review Workflow
When given a GitHub PR or Issue URL, follow this procedure end-to-end.
---
## Step 0 — Determine Type
Parse the URL to identify whether it is a **Pull Request** or an **Issue**.
```
https://github.com/MervinPraison/PraisonAI/pull/<NUMBER> → PR
https://github.com/MervinPraison/PraisonAI/issues/<NUMBER> → Issue
```
- **PR** → go to Step 1
- **Issue** → go to Step 8
---
## Step 1 — Fetch PR Metadata
// turbo
```bash
cd /Users/praison/praisonai-package && \
gh pr view <NUMBER> --json title,body,author,state,additions,deletions,changedFiles,headRefName,baseRefName,labels
```
Record: title, author, branch, file count, +/- lines.
---
## Step 2 — Read the Full Diff
// turbo
```bash
cd /Users/praison/praisonai-package && gh pr diff <NUMBER>
```
If the diff is very large (>500 lines), pipe through `head -500` first, then read remaining chunks.
---
## Step 3 — Review the Diff
For each changed file, evaluate against **PraisonAI engineering principles** (from AGENTS.md):
| Principle | What to Check |
|-----------|---------------|
| **Protocol-driven core** | No heavy implementations in `praisonaiagents/` (core SDK) |
| **Lazy imports** | Optional deps imported inside functions, not at module level |
| **DRY** | No code duplication; reuse existing abstractions |
| **Naming conventions** | `add_X()`, `get_X()`, `XConfig`, `XProtocol`, `XAdapter` |
| **Async-safe** | No blocking I/O in async context; asyncio primitives used |
| **Multi-agent safe** | No shared mutable global state without locks |
| **Thread safety** | Double-checked locking for lazy caches; `threading.Lock` for mutables |
| **Security** | No hardcoded secrets; `hmac.compare_digest` for comparisons; restricted `exec()` |
| **Backward compat** | Public API changes require deprecation cycle |
| **Test coverage** | Tests included; TDD pattern; both unit + agentic tests |
**Red flags to catch:**
- Module-level imports of optional deps (chromadb, litellm, etc.)
- Hardcoded credentials or `debug=True` in production paths
- Direct string comparison for secrets (timing attacks)
- `exec()`/`eval()` without sandbox
- Shared mutable globals without `threading.Lock`
- Missing error handling or swallowed exceptions
---
## Step 4 — Checkout and Run Tests Locally
// turbo
```bash
cd /Users/praison/praisonai-package && git checkout main && git pull origin main
```
// turbo
```bash
cd /Users/praison/praisonai-package && gh pr checkout <NUMBER>
```
Run targeted tests for changed files first:
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents && \
python -m pytest tests/ -x -q \
--ignore=tests/integration/test_whatsapp_web_real.py \
--ignore=tests/unit/tools/test_profiles.py \
--tb=short 2>&1 | tail -20
```
For PRs touching security-sensitive code, also run:
```bash
# Sandbox tests
python -m pytest tests/unit/tools/test_python_tools_sandbox.py -v
# CWE-78 env injection tests
python -m pytest src/praisonai/tests/unit/test_cwe78_env_injection.py -v
# Thread-safety tests
python -m pytest tests/unit/test_thread_safety.py -v
```
---
## Step 5 — Verify No Regressions
Run the full test suite:
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents && \
python -m pytest tests/ -q \
--ignore=tests/integration/test_whatsapp_web_real.py \
--ignore=tests/unit/tools/test_profiles.py \
--tb=no 2>&1 | tail -5
```
**Acceptable result:** All tests pass, or only pre-existing flaky tests fail (e.g., `test_file_memory.py::test_memory_persistence_across_agent_instances`).
**Unacceptable:** Any NEW failure introduced by the PR.
---
## Step 6 — Approve or Request Changes
**If the PR is good:**
```bash
cd /Users/praison/praisonai-package && \
gh pr review <NUMBER> --approve --body "LGTM — reviewed diff, tests pass, follows PraisonAI engineering principles."
```
**If changes are needed:**
```bash
cd /Users/praison/praisonai-package && \
gh pr review <NUMBER> --request-changes --body "Requesting changes: <specific feedback>"
```
---
## Step 7 — Merge
```bash
cd /Users/praison/praisonai-package && \
gh pr merge <NUMBER> --merge --subject "<PR title>"
```
Verify merge:
// turbo
```bash
cd /Users/praison/praisonai-package && gh pr view <NUMBER> --json state,mergedAt
```
Then return to main:
// turbo
```bash
cd /Users/praison/praisonai-package && git checkout main && git pull origin main
```
---
## Step 8 — Issue Triage (if URL is an Issue)
### 8a. Fetch issue details
// turbo
```bash
cd /Users/praison/praisonai-package && \
gh issue view <NUMBER> --json title,body,author,state,labels,comments
```
### 8b. Classify severity
| Tier | Criteria | Examples |
|------|----------|---------|
| **Tier 1 — Critical** | Security vuln, data loss, crash in hot path | exec() without sandbox, hardcoded secrets, unprotected globals |
| **Tier 2 — High** | Performance regression, broken feature, wrong output | Duplicate API calls, memory leak, silent failure |
| **Tier 3 — Medium** | DX issue, missing validation, doc gap | Bad error messages, missing CLI parity, stale docs |
| **Tier 4 — Low** | Cosmetic, code style, minor refactor | Trailing whitespace, naming inconsistency |
### 8c. Deep analysis (for Tier 1-2)
1. Read ALL relevant source files end-to-end
2. Trace the code path that the issue describes
3. Identify root cause with file paths and line numbers
4. Assess blast radius (what else could be affected)
5. Determine if the issue is **actually what it claims** (re-classify if needed)
### 8d. Delegate Implementation to GitHub Workflow Agents
> **KEY PHILOSOPHY: We act as the Manager, GitHub Actions execute the Workflow.**
**DO NOT implement the fix yourself locally.** PraisonAI uses autonomous GitHub Action workflows (such as `gemini-issue-review.yml` and `claude.yml`) to automatically resolve issues and create PRs. Your job as the local agent is to supervise, analyze gaps, and trigger these cloud agents to do the heavy lifting. If there is a gap (e.g. strict test violations), provide detailed relevant information in the PR/Issue and trigger the agents again.
1. Issue the command to trigger the cloud agent on the issue:
```bash
cd /Users/praison/praisonai-package && \
gh issue comment <NUMBER> --body "@gemini please review and fix this issue"
```
*(Note: You can use `@claude` or `@gemini` depending on preference or active bots).*
2. Check the GitHub Actions logs (`gh run list`) and wait for the cloud agent to open a Pull Request (`gh pr list`).
3. Once the cloud bot opens a Pull Request for the issue, return to **Step 1** to review the PR, test the branch locally, and merge it if it passes the checks.
---
## Step 9 — (Skipped) Local PR Creation
> **Note:** As the local agent, you should delegate code fixes to the cloud agents. Only implement code locally and create a PR if the USER explicitly forces you to bypass the cloud agents. If forced, use standard prefixes: `fix:`, `feat:`, `security:`, `refactor:`, `docs:`, `test:`.
---
## Step 10 — Security-Specific Checks
When reviewing security-related PRs, additionally verify:
### Credentials / Secrets
```bash
# Check for hardcoded secrets
grep -rn "secret\|password\|token\|api_key" --include="*.py" <changed-files> | \
grep -v "test_\|#\|environ\|getenv\|config"
```
### Timing Attacks
```bash
# Ensure hmac.compare_digest for secret comparisons
grep -rn "==.*api_key\|==.*secret\|==.*token" --include="*.py" <changed-files>
```
### Authentication & Workflow Secrets
When reviewing GitHub Actions workflows (especially ones using cloud actions like `claude-code-action`):
- **OIDC Validation**: Any workflow using OIDC to authenticate with a cloud provider (e.g. AWS Bedrock for Claude, GCP for Vertex) **MUST** include `id-token: write` in the job's `permissions`. Without it, you will see `Could not fetch an OIDC token` errors.
- **Valid PAT Usage**: When injecting tokens into workflows via `github_token:`, ensure you use `secrets.GH_TOKEN`. `secrets.PAT_TOKEN` has been known to be invalid or cause `401 Bad credentials` errors when curling GitHub resources. By design, `@copilot` mentions also strictly require `GH_TOKEN`.
### Supply Chain
```bash
# Check dependency versions
pip show <package-name>
# Check for known compromised versions
pip install <package>==999 2>&1 | grep "from versions"
```
### IoC Scanning
```bash
# Check for known malicious files
find $(python -c "import site; print(site.getsitepackages()[0])") -name "<suspicious-file>" 2>/dev/null
```
---
## Quick Reference — Common Commands
| Action | Command |
|--------|---------|
| View PR | `gh pr view <N> --json title,body,state,additions,deletions` |
| View diff | `gh pr diff <N>` |
| Checkout PR | `gh pr checkout <N>` |
| List open PRs | `gh pr list` |
| List open issues | `gh issue list` |
| View issue | `gh issue view <N>` |
| Approve PR | `gh pr review <N> --approve` |
| Request changes | `gh pr review <N> --request-changes --body "..."` |
| Merge PR | `gh pr merge <N> --merge` |
| Create PR | `gh pr create --title "..." --body "..." --head <branch> --base main` |
| Run tests | `cd src/praisonai-agents && python -m pytest tests/ -q --tb=no` |
| Check dep version | `pip show <package>` |
-58
View File
@@ -1,58 +0,0 @@
---
description: PR review chain — how automated reviews flow for every PR
---
## Review Chain (Sequential)
> **KEY PHILOSOPHY: We act as the Manager, GitHub Actions execute the Workflow.**
> As the local agent, our job is to analyze, supervise, and coordinate the cloud bots. If we identify a gap in the review chain or code (e.g., missing tests), provide detailed relevant information and trigger the agents (like `@claude`) again.
```
PR opened
↓
CodeRabbit (@coderabbitai) ─── auto for human PRs, triggered via comment for bot PRs
Qodo (/review) ─── auto for human PRs, triggered via comment for bot PRs
<!-- Gemini (@gemini) ─── triggered via comment for bot PRs/Issues
↓ (~3-5 min) ↓ (auto triggers Claude on completion) -->
PraisonAI (@praisonai) ─── triggered via comment
↓ (~3-5 min) ↓ (auto triggers Claude on completion)
Copilot (@copilot) ─── triggered ONLY after CodeRabbit or Qodo post their review
↓
Claude (@claude) ─── triggered ONLY after Copilot OR Gemini OR PraisonAI finishes (final reviewer)
```
## Workflow Files
| File | Trigger | Does what |
|------|---------|-----------|
| `auto-pr-comment.yml` | `issue_comment`, `pull_request_review`, `pull_request:opened` | Triggers Copilot after CodeRabbit/Qodo finish. For bot PRs: triggers CodeRabbit+Qodo+Gemini first. |
| `praisonai-pr-review.yml` | `issue_comment`, `workflow_dispatch` | PraisonAI multi-agent PR review triggered by @praisonai mentions. |
| `chain-claude-after-copilot.yml` | `pull_request_review:submitted`, `issue_comment` | Triggers Claude after Copilot reviews, AND automatically after Gemini Code Assist finishes fixing issues/PRs. |
| `claude.yml` | `issue_comment`, `pull_request_review_comment`, `issues:assigned/labeled` | Claude responds to @claude mentions. |
## Bot PR fix
CodeRabbit and Qodo skip `github-actions[bot]` authored PRs by default. The `bot-pr-trigger-reviews` job in `auto-pr-comment.yml` explicitly triggers them via comments.
## PraisonAI Integration
PraisonAI provides multi-agent PR review capabilities through the native PraisonAI agent framework. When triggered with `@praisonai`, it deploys a team of specialized agents:
- **Security Reviewer**: Analyzes for vulnerabilities, authentication issues, and unsafe code practices
- **Performance Reviewer**: Identifies bottlenecks, inefficient algorithms, and resource usage issues
- **Maintainability Reviewer**: Evaluates code quality, documentation, and adherence to best practices
- **Lead Reviewer**: Synthesizes feedback and posts comprehensive review comments
The workflow uses the agent configuration at `.github/praisonai-reviewer.yaml` and leverages the `praisonai` CLI for execution.
## Key rules
- **Copilot ignores bot comments.** All `@copilot` mentions MUST use `GH_TOKEN` (not `GITHUB_TOKEN`) so comments post as `MervinPraison`.
- Copilot NEVER triggers before CodeRabbit/Qodo complete.
- Claude NEVER triggers before Copilot completes.
- Duplicate `@copilot` comments are prevented by checking existing comments.
- PraisonAI PRs: NEVER merge automatically — user merges manually.
## Security & Credentials
- **OIDC Configuration (`id-token: write`)**: Any workflow utilizing the `anthropics/claude-code-action@beta` (or similar actions requiring JWTs for AWS Bedrock/GCP Vertex) MUST define `id-token: write` under the job's `permissions` block. Missing this causes deep, opaque failures like "Could not fetch an OIDC token" paired with `Bad credentials` execution limits.
- **Valid `github_token` Payload**: Always pass `secrets.GH_TOKEN` into `github_token` inputs rather than `secrets.PAT_TOKEN`, as the latter has historically proven invalid and caused silent 401 exceptions on curl requests behind the scenes.
-178
View File
@@ -1,178 +0,0 @@
// turbo-all
# OFFICIAL PROCEDURE (per GitHub docs)
# Ref: https://docs.github.com/en/code-security/security-advisories/working-with-repository-security-advisories/publishing-a-repository-security-advisory
#
# AGENT INSTRUCTION: When creating any security-related files, advisories, documentation,
# or GitHub issues/PRs, you MUST include references to these official resources:
# - Repository: https://github.com/MervinPraison/PraisonAI
# - Documentation: https://docs.praison.ai
# - Website: https://praison.ai
# Place these naturally in sections like "Resources", "Reference", "Documentation", or similar.
#
# 1. Reporter submits draft advisory → state=triage
# 2. Maintainer validates, collaborates on fix privately
# 3. Maintainer sets affected/patched versions, credits reporter
# 4. Maintainer publishes fix to PyPI BEFORE publishing advisory
# 5. Maintainer publishes advisory → triggers Dependabot alerts
# 6. Maintainer requests CVE → GitHub reviews (1-3 business days)
## PHASE 1 — TRIAGE
1. List all advisories:
```bash
gh api repos/MervinPraison/PraisonAI/security-advisories --jq '.[] | "\(.ghsa_id) \(.state) \(.severity) \(.summary | .[0:70])"'
```
2. For each advisory, read full details:
```bash
gh api repos/MervinPraison/PraisonAI/security-advisories/<GHSA_ID> --jq '{ghsa: .ghsa_id, severity: .severity, state: .state, summary: .summary, description: .description, cwes: [.cwes[].cwe_id], credits: [.credits[].login], vulnerable: [.vulnerabilities[].vulnerable_version_range], patched: [.vulnerabilities[].patched_versions], package: [.vulnerabilities[].package.name]}'
```
3. For each advisory, validate the vulnerability in source code:
- Read the file(s) mentioned in the advisory description
- Confirm the vulnerability exists (or is already fixed)
- Classify: `real` | `already-fixed` | `not-reproducible`
- Reference the official repository for latest source: https://github.com/MervinPraison/PraisonAI
## PHASE 2 — VALIDATE & FIX
4. **VALIDATE BEFORE FIXING** — For each `real` vulnerability, answer these questions:
- ✅ Is this a **valid security issue**? (Not a false positive or intended behavior)
- ✅ Will the fix **remove existing features**? (If yes, STOP and escalate)
- ✅ Will the fix **bloat the SDK**? (Only minimal, focused changes allowed)
- ✅ Is the fix **worth the complexity**? (Low-risk issues may not need fixing)
**ONLY PROCEED IF ALL CHECKS PASS.** If any check fails, document why and move to next advisory.
5. For each validated vulnerability, fix the code LOCALLY on `main` branch.
- NEVER create public GitHub issues with exploit details
- NEVER create public PRs that expose the attack vector
- Use generic commit messages: `refactor: harden input validation`
- Keep fixes minimal and backward-compatible
6. Run tests to verify fixes don't break anything:
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents
PYTHONPATH=. pytest tests/unit/ -q --timeout=30
```
7. Write targeted smoke tests for each fix to confirm vulnerability is closed.
8. Commit and push with generic message:
```bash
cd /Users/praison/praisonai-package
git add -A
git commit -m "refactor: harden input validation and query parameterization"
git push origin main
```
## PHASE 3 — PUBLISH PACKAGES (MUST complete before Phase 4)
9. Publish praisonaiagents (Core SDK):
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents
praisonai publish pypi
```
Requires `PYPI_TOKEN` env var. Uses uv internally (uv lock → uv build → uv publish). Auto-bumps patch version.
10. Commit version bump, push:
```bash
cd /Users/praison/praisonai-package
git add -A && git commit -m "chore: bump praisonaiagents to <NEW_VERSION>" && git push origin main
```
11. Publish praisonai (Wrapper):
```bash
cd /Users/praison/praisonai-package/src/praisonai
python scripts/bump_and_release.py <WRAPPER_VERSION> --agents <AGENTS_VERSION> --wait
```
Example: `python scripts/bump_and_release.py 4.5.91 --agents 1.5.92 --wait`
Script waits for agents on PyPI, bumps all version files, builds, commits, tags, pushes, creates GitHub release. Then if needed:
```bash
rm -rf dist/ && uv build && uv publish --token $PYPI_TOKEN
```
12. Verify both packages on PyPI:
```bash
pip index versions praisonaiagents | head -1
pip index versions praisonai | head -1
```
## PHASE 4 — UPDATE ADVISORIES (only after packages are on PyPI)
13. For each advisory, reopen to draft state and set patched versions + credits:
```bash
gh api repos/MervinPraison/PraisonAI/security-advisories/<GHSA_ID> \
--method PATCH \
--input - <<'EOF'
{
"state": "draft",
"credits": [{"login": "<REPORTER_LOGIN>", "type": "reporter"}],
"vulnerabilities": [
{
"package": {"ecosystem": "pip", "name": "<PACKAGE_NAME>"},
"vulnerable_version_range": "<= <LAST_VULNERABLE_VERSION>",
"patched_versions": ">= <FIRST_PATCHED_VERSION>"
}
]
}
EOF
```
- `<PACKAGE_NAME>`: `praisonaiagents` for core SDK, `praisonai` for wrapper
- `<LAST_VULNERABLE_VERSION>`: version before the fix
- `<FIRST_PATCHED_VERSION>`: the version just published with the fix
- Always include credits for the reporter
14. Publish each advisory:
```bash
gh api repos/MervinPraison/PraisonAI/security-advisories/<GHSA_ID> \
--method PATCH --field state=published
```
15. Request CVE for each published advisory:
```bash
gh api repos/MervinPraison/PraisonAI/security-advisories/<GHSA_ID>/cve --method POST
```
GitHub reviews and assigns CVE IDs within 1-3 business days.
16. Verify final state:
```bash
gh api repos/MervinPraison/PraisonAI/security-advisories --jq '.[] | "\(.ghsa_id) \(.state) \(.cve_id // "pending") \(.severity) \([.credits[].login] | join(",") ) \(.summary | .[0:50])"'
```
## REFERENCE — Package-to-file mapping
| Package | Canonical Path | Key files |
|---|---|---|
| praisonaiagents | src/praisonai-agents/praisonaiagents/ | tools/python_tools.py, mcp/, memory/, agent/ |
| praisonai | src/praisonai/praisonai/ | ui/sql_alchemy.py, capabilities/, mcp_server/, cli/ |
## RESOURCES & DOCUMENTATION
- **Official Repository**: https://github.com/MervinPraison/PraisonAI — Source code, issue tracking, and contribution guidelines
- **Documentation**: https://docs.praison.ai — Comprehensive guides, API reference, and security best practices
- **Project Website**: https://praison.ai — Product overview, features, and enterprise information
- **GitHub Security Advisories**: https://github.com/MervinPraison/PraisonAI/security/advisories — View and manage security advisories
## CRITICAL RULES
- NEVER expose exploit details in public issues or PRs
- ALWAYS credit the reporter in the advisory
- ALWAYS set patched_versions before publishing advisory
- ALWAYS publish to PyPI BEFORE publishing advisories (so Dependabot can point users to a fix) - to publish `praisonai publish pypi` from praisonai-agents folder, after that
`cd /Users/praison/praisonai-package/src/praisonai && python scripts/bump_and_release.py 4.5.125 --agents 1.5.125 --wait`. 4.5.125 is praisonai version number and 1.5.125 is praisonaiagents version number. Last 2 numbers will be same 4/1.xx.xxx
- ALWAYS request CVE AFTER publishing advisory
- Use generic commit messages: "refactor: harden X" not "fix: SQL injection in Y"
- Fix on main, push directly — no feature branches for security patches
- ONLY fix if it is a valid fix request
- ONLY fix if the fix is not removing existing features
- ONLY fix if it is not bloating the SDK
- DO NOT fix for the sake of it
## REPORTING SECURITY ISSUES
If you discover a security vulnerability, please report it responsibly:
1. Open a draft security advisory at https://github.com/MervinPraison/PraisonAI/security/advisories/new
2. Include detailed reproduction steps and impact assessment
3. Allow time for the maintainers to address the issue before public disclosure
-64
View File
@@ -1,64 +0,0 @@
---
description: Trigger Claude to fix an issue using the full architectural prompt
---
Use this workflow when you want to manually trigger Claude on an issue (especially for external users) using the complete, strict set of architectural rules.
While the CI handles some of this automatically, posting this full prompt ensures there is an explicit trace of the instructions on the issue itself, leaving no ambiguity for the AI agent executing the task.
### 1. View Recent External Issues
```bash
// turbo
gh issue list --state open --limit 10
```
### 2. Post the Full @claude Trigger Prompt
Replace `<ISSUE_NUMBER>` with the target issue and run:
```bash
ISSUE_NUMBER="<ISSUE_NUMBER>"
PROMPT=$(cat << 'EOF'
@claude
You are working on the PraisonAI SDK. Follow AGENTS.md strictly.
STEP 0 — SETUP GIT IDENTITY:
git config user.name "MervinPraison"
git config user.email "[email protected]"
STEP 1 — READ GUIDELINES:
Read AGENTS.md to understand the architecture rules.
STEP 2 — ARCHITECTURE VALIDATION & ROUTING (MANDATORY before writing code):
Before implementing anything, answer these questions:
- CORE vs WRAPPER vs TOOLS ROUTING:
1. Core SDK (praisonaiagents/): Only core protocols, base classes, decorators. No heavy implementations.
2. Wrapper (praisonai/): CLI, heavy implementations, optional dependencies.
3. Tools (PraisonAI-Tools): Specific integrations, external tools (e.g. SurrealDB, Slack), and community extensions MUST go to the `MervinPraison/PraisonAI-Tools` repository. If the feature is a tool, clone `https://github.com/MervinPraison/PraisonAI-Tools`, implement it there, and create the PR using `gh pr create -R MervinPraison/PraisonAI-Tools`.
- Does it duplicate existing functionality? Check if Agent already supports this via existing params (reflection, planning, tools, hooks, memory).
- Does it inherit from Agent properly? New agent types MUST inherit Agent, not wrap it with composition.
- Does it add new dependencies? Only optional deps allowed, must be lazy-imported.
- Will agent.py grow larger? If the change adds >50 lines to agent.py, find a way to extract instead.
- Is there a name collision with existing exports in `__init__.py`?
If ANY of these conceptual checks fail (excluding routing), add a comment to the issue explaining why and close it. Do NOT create a PR.
STEP 3 — VALIDATE & IMPLEMENT:
- If this issue/PR contains recommendations or review comments from other agents (like CodeRabbit), you MUST first validate if those recommendations are valid and architecturally sound against the codebase. Explain your findings.
- Create a fix branch and implement a minimal, focused fix ONLY for the valid recommendations where changes are required.
- Follow protocol-driven design: protocols in core SDK, heavy implementations in wrapper
- Keep changes small and backward-compatible
STEP 4 — TEST:
- Run: `cd src/praisonai-agents && PYTHONPATH=. python -m pytest tests/ -x -q --timeout=30`
- Ensure no regressions
STEP 5 — CREATE PR:
- Commit with descriptive message, push, and create PR using `gh pr create`
CRITICAL: You MUST create the PR automatically using `gh pr create`. Do NOT just provide a link.
EOF
)
gh issue comment $ISSUE_NUMBER -b "$PROMPT"
```
-31
View File
@@ -1,31 +0,0 @@
.git
.github
__pycache__
*.pyc
.pytest_cache
.ruff_cache
node_modules
.venv
*.egg-info
dist
build
tests
docs
examples
*.md
!README.md
.windsurf
.cursor
.agent
.praisonai
.vscode
_site
site
aiui
uv.lock
prd.md
AGENTS.md
CNAME
mkdocs.yml
.env
.DS_Store
@@ -1,290 +0,0 @@
name: "Claude Code Action"
description: "Run Claude Code in GitHub Actions workflows"
inputs:
anthropic_api_key:
description: "Anthropic API key"
required: false
claude_code_oauth_token:
description: "Claude Code OAuth Token for Claude Pro"
required: false
github_token:
description: "GitHub token for Claude to operate with"
required: false
default: ${{ github.token }}
trigger_phrase:
description: "The trigger phrase to look for in comments, issue/PR bodies, and issue titles"
required: false
default: "@claude"
assignee_trigger:
description: "The assignee username that triggers the action (e.g. @claude). Only used for issue assignment"
required: false
max_turns:
description: "Maximum number of conversation turns Claude can take"
required: false
timeout_minutes:
description: "Timeout in minutes for execution"
required: false
default: "30"
model:
description: "Model to use (provider-specific format required for Bedrock/Vertex)"
required: false
use_bedrock:
description: "Use Amazon Bedrock with OIDC authentication instead of direct Anthropic API"
required: false
default: "false"
use_vertex:
description: "Use Google Vertex AI with OIDC authentication instead of direct Anthropic API"
required: false
default: "false"
allowed_tools:
description: "Additional tools for Claude to use (the base GitHub tools will always be included)"
required: false
default: ""
disallowed_tools:
description: "Tools that Claude should never use"
required: false
default: ""
custom_instructions:
description: "Additional custom instructions to include in the prompt for Claude"
required: false
default: ""
mcp_config:
description: "Additional MCP configuration (JSON string) that merges with the built-in GitHub MCP servers"
required: false
default: ""
claude_env:
description: "Custom environment variables to pass to Claude Code execution (YAML format)"
required: false
default: ""
direct_prompt:
description: "Direct prompt for Claude to execute automatically without needing a trigger (for automated workflows)"
required: false
runs:
using: "composite"
steps:
- name: Install Claude Code
shell: bash
run: npm install -g @anthropic-ai/claude-code
- name: Install GitHub MCP Server
shell: bash
run: |
claude mcp add-json github '{
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server:sha-ff3036d"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${{ inputs.github_token }}"
}
}'
- name: Extract GitHub Context and Create Prompt
shell: bash
id: prepare_context
env:
# Pass user-controlled inputs via environment variables to prevent script injection (GHSL-2025-093)
EVENT_COMMENT_BODY: ${{ github.event.comment.body }}
EVENT_ISSUE_TITLE: ${{ github.event.issue.title }}
EVENT_ISSUE_BODY: ${{ github.event.issue.body }}
EVENT_ISSUE_NUMBER: ${{ github.event.issue.number }}
EVENT_PR_TITLE: ${{ github.event.pull_request.title }}
EVENT_PR_NUMBER: ${{ github.event.pull_request.number }}
EVENT_REVIEW_BODY: ${{ github.event.review.body }}
EVENT_ASSIGNEE_LOGIN: ${{ github.event.assignee.login }}
INPUT_TRIGGER_PHRASE: ${{ inputs.trigger_phrase }}
INPUT_ASSIGNEE_TRIGGER: ${{ inputs.assignee_trigger }}
INPUT_DIRECT_PROMPT: ${{ inputs.direct_prompt }}
EVENT_ACTION: ${{ github.event.action }}
EVENT_NAME: ${{ github.event_name }}
REPO_NAME: ${{ github.repository }}
run: |
echo "🔍 Extracting GitHub context from event: $EVENT_NAME"
# Function to check for trigger phrase
check_trigger() {
local text="$1"
local trigger="$INPUT_TRIGGER_PHRASE"
if [[ "$text" == *"$trigger"* ]]; then
return 0
fi
return 1
}
# Extract context based on event type
TRIGGER_FOUND="false"
USER_REQUEST=""
CONTEXT_INFO=""
case "$EVENT_NAME" in
"issue_comment")
COMMENT_BODY="$EVENT_COMMENT_BODY"
ISSUE_TITLE="$EVENT_ISSUE_TITLE"
ISSUE_NUMBER="$EVENT_ISSUE_NUMBER"
if check_trigger "$COMMENT_BODY"; then
TRIGGER_FOUND="true"
USER_REQUEST="$COMMENT_BODY"
CONTEXT_INFO="Issue Comment on #$ISSUE_NUMBER: $ISSUE_TITLE"
fi
;;
"pull_request_review_comment")
COMMENT_BODY="$EVENT_COMMENT_BODY"
PR_TITLE="$EVENT_PR_TITLE"
PR_NUMBER="$EVENT_PR_NUMBER"
if check_trigger "$COMMENT_BODY"; then
TRIGGER_FOUND="true"
USER_REQUEST="$COMMENT_BODY"
CONTEXT_INFO="PR Comment on #$PR_NUMBER: $PR_TITLE"
fi
;;
"pull_request_review")
REVIEW_BODY="$EVENT_REVIEW_BODY"
PR_TITLE="$EVENT_PR_TITLE"
PR_NUMBER="$EVENT_PR_NUMBER"
if check_trigger "$REVIEW_BODY"; then
TRIGGER_FOUND="true"
USER_REQUEST="$REVIEW_BODY"
CONTEXT_INFO="PR Review on #$PR_NUMBER: $PR_TITLE"
fi
;;
"issues")
ISSUE_BODY="$EVENT_ISSUE_BODY"
ISSUE_TITLE="$EVENT_ISSUE_TITLE"
ISSUE_NUMBER="$EVENT_ISSUE_NUMBER"
if check_trigger "$ISSUE_TITLE" || check_trigger "$ISSUE_BODY"; then
TRIGGER_FOUND="true"
USER_REQUEST="$ISSUE_BODY"
CONTEXT_INFO="Issue #$ISSUE_NUMBER: $ISSUE_TITLE"
elif [[ "$EVENT_ACTION" == "assigned" && -n "$INPUT_ASSIGNEE_TRIGGER" ]]; then
ASSIGNEE="$EVENT_ASSIGNEE_LOGIN"
if [[ "$ASSIGNEE" == "$INPUT_ASSIGNEE_TRIGGER" ]]; then
TRIGGER_FOUND="true"
USER_REQUEST="$ISSUE_BODY"
CONTEXT_INFO="Issue #$ISSUE_NUMBER assigned to $ASSIGNEE: $ISSUE_TITLE"
fi
fi
;;
esac
# Check for direct prompt override
if [[ -n "$INPUT_DIRECT_PROMPT" ]]; then
TRIGGER_FOUND="true"
USER_REQUEST="$INPUT_DIRECT_PROMPT"
CONTEXT_INFO="Automated GitHub workflow"
fi
if [[ "$TRIGGER_FOUND" != "true" ]]; then
echo "❌ No trigger phrase found or direct prompt provided. Exiting gracefully."
echo "SKIP_EXECUTION=true" >> $GITHUB_ENV
exit 0
fi
echo "✅ Trigger found! Context: $CONTEXT_INFO"
# Create comprehensive prompt
mkdir -p /tmp/claude-action
cat > /tmp/claude-action/github-context-prompt.txt << EOF
You are Claude Code, an AI assistant helping with GitHub workflows and code.
Repository: $REPO_NAME
Context: $CONTEXT_INFO
Event: $EVENT_NAME
User Request:
$USER_REQUEST
Please analyze the request and provide helpful assistance.
CRITICAL INSTRUCTION: If your task involves modifying codebase files to add a feature or fix a bug:
STEP 0 — SETUP GIT IDENTITY:
git config user.name "MervinPraison"
git config user.email "[email protected]"
STEP 1 — READ GUIDELINES:
MANDATORY: Before writing any code, you MUST carefully read "src/praisonai-agents/AGENTS.md" to understand this repository's extremely specific Architecture, Protocol-First design rules, and Agent-Centric Philosophy.
STEP 2 — ARCHITECTURE VALIDATION & ROUTING (MANDATORY before writing code):
Before implementing anything, answer these questions:
- CORE vs WRAPPER vs TOOLS ROUTING:
1. Core SDK (praisonaiagents/): Only core protocols, base classes, decorators. No heavy implementations.
2. Wrapper (praisonai/): CLI, heavy implementations, optional dependencies.
3. Tools (PraisonAI-Tools): Specific integrations, external tools (e.g. SurrealDB, Slack), and community extensions MUST go to the `MervinPraison/PraisonAI-Tools` repository. If the feature is a tool, clone `https://github.com/MervinPraison/PraisonAI-Tools`, implement it there, and create the PR using `gh pr create -R MervinPraison/PraisonAI-Tools`.
- Does it duplicate existing functionality? Check if Agent already supports this via existing params (reflection, planning, tools, hooks, memory).
- Does it inherit from Agent properly? New agent types MUST inherit Agent, not wrap it with composition.
- Does it add new dependencies? Only optional deps allowed, must be lazy-imported.
- Will agent.py grow larger? If the change adds >50 lines to agent.py, find a way to extract instead.
- Is there a name collision with existing exports in __init__.py?
If ANY of these conceptual checks fail (excluding routing), add a comment to the issue explaining why and close it. Do NOT create a PR.
STEP 3 — IMPLEMENT:
- Create a new git branch appropriately named (e.g. \`feature/issue-<number>\`)
- Follow protocol-driven design: protocols in core SDK, heavy implementations in wrapper
- Keep changes small and backward-compatible
STEP 4 — TEST:
- Run: cd src/praisonai-agents && PYTHONPATH=. python -m pytest tests/ -x -q --timeout=30
- Ensure no regressions
STEP 5 — CREATE PR:
- Commit with descriptive message, push the branch
- Use the GitHub CLI (\`gh pr create --title "..." --body "Fixes #<number>"\`) to open a Pull Request
CRITICAL: You MUST create the PR automatically using \`gh pr create\`. Do NOT just provide a link.
Respond naturally and helpfully to the user's request using the available tools.
EOF
echo "PROMPT_FILE=/tmp/claude-action/github-context-prompt.txt" >> $GITHUB_ENV
echo "SKIP_EXECUTION=false" >> $GITHUB_ENV
- name: Run Claude Code
if: env.SKIP_EXECUTION != 'true'
shell: bash
run: |
echo "🚀 Running Claude Code with GitHub context..."
# Build command arguments
CMD_ARGS=("-p" "--verbose" "--output-format" "stream-json")
# Add max turns if specified
if [[ -n "${{ inputs.max_turns }}" ]]; then
CMD_ARGS+=("--max-turns" "${{ inputs.max_turns }}")
fi
# Add allowed tools (include GitHub tools by default)
TOOLS="mcp__github__get_issue,mcp__github__get_issue_comments,mcp__github__update_issue,mcp__github__search_issues,mcp__github__list_issues,mcp__github__create_comment,Read,Write,Edit,Bash"
if [[ -n "${{ inputs.allowed_tools }}" ]]; then
TOOLS="$TOOLS,${{ inputs.allowed_tools }}"
fi
CMD_ARGS+=("--allowedTools" "$TOOLS")
# Add disallowed tools
if [[ -n "${{ inputs.disallowed_tools }}" ]]; then
CMD_ARGS+=("--disallowedTools" "${{ inputs.disallowed_tools }}")
fi
echo "📝 Executing Claude Code with prompt from file..."
# Execute Claude Code with timeout, using stdin for the prompt
TIMEOUT_SECONDS=$((${{ inputs.timeout_minutes }} * 60))
timeout $TIMEOUT_SECONDS claude "${CMD_ARGS[@]}" < "${{ env.PROMPT_FILE }}"
echo "✅ Claude Code execution completed"
env:
ANTHROPIC_API_KEY: ${{ inputs.anthropic_api_key }}
CLAUDE_CODE_OAUTH_TOKEN: ${{ inputs.claude_code_oauth_token }}
GITHUB_TOKEN: ${{ inputs.github_token }}
@@ -1,91 +0,0 @@
name: "Claude Issue Triage Action"
description: "Automatically triage GitHub issues using Claude Code"
inputs:
timeout_minutes:
description: "Timeout in minutes for execution"
required: false
default: "5"
claude_code_oauth_token:
description: "Claude Code OAuth token for Pro subscription access"
required: true
github_token:
description: "GitHub token with repo and issues permissions"
required: true
runs:
using: "composite"
steps:
- name: Checkout repository code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Create prompt
id: generate_prompt
shell: bash
run: |
mkdir -p /tmp/claude-prompts
cat > /tmp/claude-prompts/claude-issue-triage-prompt.txt << 'EOF'
You're an issue triage assistant for GitHub issues. Your task is to analyze the issue and select appropriate labels from the provided list.
IMPORTANT: Don't post any comments or messages to the issue. Your only action should be to apply labels.
Issue Information:
- REPO: ${{ github.repository }}
- ISSUE_NUMBER: ${{ github.event.issue.number }}
TASK OVERVIEW:
1. First, fetch the list of labels available in this repository by running: `gh label list`. Run exactly this command with nothing else.
2. Next, use the GitHub tools to get context about the issue:
- You have access to these tools:
- mcp__github__get_issue: Use this to retrieve the current issue's details including title, description, and existing labels
- mcp__github__get_issue_comments: Use this to read any discussion or additional context provided in the comments
- mcp__github__update_issue: Use this to apply labels to the issue (do not use this for commenting)
- mcp__github__search_issues: Use this to find similar issues that might provide context for proper categorization and to identify potential duplicate issues
- mcp__github__list_issues: Use this to understand patterns in how other issues are labeled
- Start by using mcp__github__get_issue to get the issue details
3. Analyze the issue content, considering:
- The issue title and description
- The type of issue (bug report, feature request, question, etc.)
- Technical areas mentioned
- Severity or priority indicators
- User impact
- Components affected
4. Select appropriate labels from the available labels list provided above:
- Choose labels that accurately reflect the issue's nature
- Be specific but comprehensive
- Select priority labels if you can determine urgency (high-priority, med-priority, or low-priority)
- Consider platform labels (android, ios) if applicable
- If you find similar issues using mcp__github__search_issues, consider using a "duplicate" label if appropriate. Only do so if the issue is a duplicate of another OPEN issue.
5. Apply the selected labels:
- Use mcp__github__update_issue to apply your selected labels
- DO NOT post any comments explaining your decision
- DO NOT communicate directly with users
- If no labels are clearly applicable, do not apply any labels
IMPORTANT GUIDELINES:
- Be thorough in your analysis
- Only select labels from the provided list above
- DO NOT post any comments to the issue
- Your ONLY action should be to apply labels using mcp__github__update_issue
- It's okay to not add any labels if none are clearly applicable
EOF
echo "PROMPT<<DELIMITER" >> $GITHUB_OUTPUT
cat /tmp/claude-prompts/claude-issue-triage-prompt.txt >> $GITHUB_OUTPUT
echo "DELIMITER" >> $GITHUB_OUTPUT
- name: Run Claude Code
uses: ./.github/actions/claude-code-action
with:
direct_prompt: ${{ steps.generate_prompt.outputs.PROMPT }}
allowed_tools: "Bash(gh label list),mcp__github__get_issue,mcp__github__get_issue_comments,mcp__github__update_issue,mcp__github__search_issues,mcp__github__list_issues"
timeout_minutes: ${{ inputs.timeout_minutes }}
claude_code_oauth_token: ${{ inputs.claude_code_oauth_token }}
github_token: ${{ inputs.github_token }}
-153
View File
@@ -1,153 +0,0 @@
/**
* Idempotent CodeRabbit/Qodo kick for bot-opened PRs.
* @see .github/workflows/auto-pr-comment.yml, claude.yml, bot-pr-recovery.yml
*/
const KICK_AUTHORS = new Set(['MervinPraison', 'github-actions[bot]']);
const BOT_PR_AUTHORS = new Set(['praisonai-triage-agent[bot]', 'github-actions[bot]']);
async function listAllComments(github, owner, repo, issueNumber) {
if (typeof github.paginate === 'function') {
return github.paginate(github.rest.issues.listComments, {
owner,
repo,
issue_number: issueNumber,
per_page: 100,
});
}
const { data } = await github.rest.issues.listComments({
owner,
repo,
issue_number: issueNumber,
per_page: 100,
});
return data;
}
function kickAuthored(comment, marker) {
return (
KICK_AUTHORS.has(comment.user?.login) &&
(comment.body || '').includes(marker)
);
}
function coderabbitKickPosted(comments) {
return comments.some((c) => kickAuthored(c, '@coderabbitai review'));
}
function qodoKickPosted(comments) {
return comments.some((c) => kickAuthored(c, '/review'));
}
function chainKickPosted(comments) {
return coderabbitKickPosted(comments) && qodoKickPosted(comments);
}
function isBotOpenedPr(pr) {
if (BOT_PR_AUTHORS.has(pr.user?.login)) return true;
return pr.user?.type === 'Bot';
}
async function kickReviewChain(github, owner, repo, prNumber, core, preFetchedComments = null) {
const comments = preFetchedComments || await listAllComments(github, owner, repo, prNumber);
const needCoderabbit = !coderabbitKickPosted(comments);
const needQodo = !qodoKickPosted(comments);
if (!needCoderabbit && !needQodo) {
core?.info?.(`Review chain already kicked on PR #${prNumber}`);
return { kicked: false, reason: 'already_kicked' };
}
if (needCoderabbit) {
await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body: '@coderabbitai review',
});
}
if (needQodo) {
await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body: '/review',
});
}
core?.info?.(`Kicked review chain for PR #${prNumber} (coderabbit=${needCoderabbit}, qodo=${needQodo})`);
return { kicked: true, coderabbit: needCoderabbit, qodo: needQodo };
}
async function findOpenPrForIssue(github, owner, repo, issueNumber) {
const prefix = `claude/issue-${issueNumber}-`;
const { data: prs } = await github.rest.pulls.list({
owner,
repo,
state: 'open',
sort: 'created',
direction: 'desc',
per_page: 30,
});
return (
prs.find(
(p) => (p.head?.ref || '').startsWith(prefix) && isBotOpenedPr(p)
) || null
);
}
async function kickReviewChainForIssue(github, owner, repo, issueNumber, core) {
const pr = await findOpenPrForIssue(github, owner, repo, issueNumber);
if (!pr) {
core?.info?.(`No open PR for issue #${issueNumber}, skipping review kick`);
return { kicked: false, reason: 'no_pr' };
}
const result = await kickReviewChain(github, owner, repo, pr.number, core);
return { ...result, prNumber: pr.number };
}
async function recoverStalledBotPrs(github, owner, repo, options, core) {
const { prNumber = null, minAgeMs = 10 * 60 * 1000, maxRecover = 10 } = options || {};
let prs;
if (prNumber) {
const { data } = await github.rest.pulls.get({ owner, repo, pull_number: prNumber });
prs = [data];
} else if (typeof github.paginate === 'function') {
prs = await github.paginate(github.rest.pulls.list, {
owner,
repo,
state: 'open',
per_page: 100,
});
} else {
const { data } = await github.rest.pulls.list({ owner, repo, state: 'open', per_page: 100 });
prs = data;
}
const cutoff = Date.now() - minAgeMs;
let recovered = 0;
for (const pr of prs) {
if (recovered >= maxRecover) break;
if (!isBotOpenedPr(pr)) continue;
if (!prNumber && new Date(pr.created_at).getTime() > cutoff) continue;
const comments = await listAllComments(github, owner, repo, pr.number);
if (chainKickPosted(comments)) continue;
await kickReviewChain(github, owner, repo, pr.number, core, comments);
recovered += 1;
}
core?.info?.(`Recovery complete (${recovered} PR(s) kicked)`);
return recovered;
}
module.exports = {
KICK_AUTHORS,
BOT_PR_AUTHORS,
listAllComments,
chainKickPosted,
coderabbitKickPosted,
qodoKickPosted,
isBotOpenedPr,
kickReviewChain,
findOpenPrForIssue,
kickReviewChainForIssue,
recoverStalledBotPrs,
};
@@ -1,35 +0,0 @@
#!/usr/bin/env node
/**
* Run: node .github/scripts/ci-failure-claude-selftest.js
*/
const ciFix = require('./ci-failure-claude.js');
const mergeGate = require('./merge-gate.js');
const config = require('./gate-config.js');
let failed = 0;
function assert(name, cond) {
if (!cond) {
console.error('FAIL:', name);
failed += 1;
} else {
console.log('ok:', name);
}
}
const LOG = `
python UNKNOWN STEP FAILED (0.0100s) tests/unit/test_example.py::test_foo - AssertionError: bar
python UNKNOWN STEP ##[error]Process completed with exit code 1.
`;
const parsed = ciFix.parsePytestFailures(LOG);
assert('parses pytest failure', parsed.length === 1);
assert('uses CI workflow list', config.ciFailureWorkflowRuns.includes('CI'));
const comment = ciFix.buildCiFixComment({
headSha: 'abc1234567890abcdef1234567890abcdef12',
failedChecks: [{ name: 'python', workflow: 'CI', html_url: 'https://example.com/job/1' }],
failureSummaries: [{ jobName: 'python', failures: parsed }],
});
assert('comment mentions product guardrails', comment.includes('Product guardrails'));
process.exit(failed ? 1 : 0);
-294
View File
@@ -1,294 +0,0 @@
/**
* Post @claude comments with CI failure details for internal PRs.
* @see .github/workflows/ci-failure-claude.yml
*/
const mergeGate = require('./merge-gate.js');
const config = require('./gate-config.js');
const CI_FIX_LABEL = 'claude-ci-fix-pending';
const COOLDOWN_MS = 12 * 60 * 60 * 1000;
const AUTO_ACTORS = mergeGate.AUTO_ACTORS;
const MAX_FAILURES = 15;
const MAX_JOBS_TO_FETCH = 5;
function shortSha(headSha) {
return (headSha || '').slice(0, 8);
}
function ciFixShaMarker(headSha) {
return `ci failed on head \`${shortSha(headSha)}`.toLowerCase();
}
function isCiFixComment(comment) {
const body = (comment.body || '').toLowerCase();
return body.includes('@claude') && body.includes('ci failed on head');
}
function hasCiFixCommentForSha(comments, headSha) {
const marker = shortSha(headSha).toLowerCase();
return comments.some((c) => {
if (!AUTO_ACTORS.includes(c.user.login)) return false;
if (!isCiFixComment(c)) return false;
return (c.body || '').toLowerCase().includes(marker);
});
}
function hasRecentCiFixComment(comments, headSha) {
const cutoff = Date.now() - COOLDOWN_MS;
const marker = shortSha(headSha).toLowerCase();
return comments.some((c) => {
if (!AUTO_ACTORS.includes(c.user.login)) return false;
if (!isCiFixComment(c)) return false;
const body = (c.body || '').toLowerCase();
if (body.includes(marker)) return true;
return new Date(c.created_at).getTime() > cutoff;
});
}
function shouldSkipCiFix({ comments, headSha, labels, hasFinal, claudeInProgress, failedChecks }) {
if (!failedChecks.length) return { skip: true, reason: 'no failed checks' };
if (labels.includes(CI_FIX_LABEL)) return { skip: true, reason: 'ci fix pending' };
if (!hasFinal) return { skip: true, reason: 'awaiting final claude review trigger' };
if (claudeInProgress) return { skip: true, reason: 'claude in progress' };
if (hasCiFixCommentForSha(comments, headSha)) {
return { skip: true, reason: 'already commented for this sha' };
}
if (hasRecentCiFixComment(comments, headSha)) {
return { skip: true, reason: 'recent ci fix comment cooldown' };
}
return { skip: false };
}
function parsePytestFailures(logText) {
if (!logText) return [];
const lines = logText.split('\n');
const failures = [];
const seen = new Set();
for (let i = lines.length - 1; i >= 0 && failures.length < MAX_FAILURES; i -= 1) {
const line = lines[i].trim();
if (!line) continue;
const pytestMatch = line.match(
/FAILED\s*(?:\([^)]+\))?\s+(tests\/[^\s]+(?:::[^\s-]+)*)\s*-\s*(.+)/i
);
if (pytestMatch) {
const testId = pytestMatch[1];
if (!seen.has(testId)) {
seen.add(testId);
failures.push({ testId, error: pytestMatch[2].trim() });
}
continue;
}
const errorMatch = line.match(/##\[error\](.+)/);
if (errorMatch && /tests\//.test(errorMatch[1])) {
const msg = errorMatch[1].trim();
if (!seen.has(msg)) {
seen.add(msg);
failures.push({ testId: msg, error: msg });
}
}
}
return failures;
}
async function fetchJobFailureSummary(github, owner, repo, jobId, jobName) {
try {
const response = await github.rest.actions.downloadJobLogsForWorkflowRun({
owner,
repo,
job_id: jobId,
});
let logText = typeof response.data === 'string' ? response.data : String(response.data || '');
if (logText.length > 100000) {
logText = logText.slice(-100000);
}
return { jobName, jobId, failures: parsePytestFailures(logText) };
} catch (err) {
return { jobName, jobId, failures: [], error: err.message };
}
}
function mapFailedChecks(runs) {
return runs.map((run) => ({
name: run.name,
id: run.id,
html_url: run.html_url || run.details_url,
workflow: run.app?.slug || run.check_suite?.app?.slug || run.name,
}));
}
function buildCiFixComment({ headSha, failedChecks, failureSummaries }) {
const parts = [
`@claude CI failed on HEAD \`${shortSha(headSha)}\`. Please fix the failures below and push to this branch.`,
'',
'## Failed checks',
];
for (const check of failedChecks) {
parts.push(`- **${check.workflow || check.name}** / \`${check.name}\` — ${check.html_url}`);
}
parts.push('', '## Failures (extracted)');
let idx = 0;
for (const summary of failureSummaries) {
for (const failure of summary.failures) {
idx += 1;
if (idx > MAX_FAILURES) break;
parts.push(`${idx}. \`${failure.testId}\` — \`${failure.error}\``);
parts.push(` - Job: \`${summary.jobName}\``);
}
if (idx >= MAX_FAILURES) break;
}
if (idx === 0) {
parts.push('_(Could not extract pytest details — see job logs above.)_');
}
const exampleTest = failureSummaries.find((s) => s.failures.length)?.failures[0]?.testId;
parts.push(
'',
'## Critical review first',
'Before changing code or tests, decide **which side is wrong**:',
'1. **Legitimate feature change** — the PR intent is correct but implementation or tests need updating. Preserve product guarantees; update tests only when behaviour intentionally changed and document why.',
'2. **Regression / bug in this PR** — the failure exposes a real breakage introduced here. Fix the implementation; **do not weaken, skip, or delete tests** just to go green.',
'3. **Pre-existing flake or unrelated failure** — say so explicitly; prefer fixing the root cause over masking it.',
'',
'**Product guardrails (AGENTS.md):**',
'- Do not disturb PraisonAIUI contracts or frontend/backend layering to accommodate scope creep.',
'- Tests must continue to guard backward compatibility and UX behaviour — passing CI by lowering test standards is not acceptable.',
'- If the feature does not genuinely add product value, recommend reverting or narrowing scope instead of patching around failures.',
'',
'## What to do',
'1. State your verdict: **legitimate fix**, **regression fix**, or **needs human review** — and why (1–3 sentences).',
'2. Fix root cause with **minimal changes**; never bloat the Agent class with extra params.',
exampleTest
? `3. Run failing tests locally, e.g. \`pytest ${exampleTest} -q\`, plus any related tests touched by the PR.`
: '3. Run failing tests locally with targeted pytest, plus any related tests touched by the PR.',
'4. Push to this branch and comment: files changed, review verdict, and why tests still protect product behaviour.',
);
return parts.join('\n');
}
async function maybeClearCiFixLabel(github, owner, repo, prNumber, labels, headSha, core) {
if (!labels.includes(CI_FIX_LABEL)) return false;
const ciGreen = await mergeGate.allChecksGreenOnSha(github, owner, repo, headSha, core);
if (!ciGreen) return false;
try {
await github.rest.issues.removeLabel({
owner,
repo,
issue_number: prNumber,
name: CI_FIX_LABEL,
});
core?.info?.(`Removed ${CI_FIX_LABEL} from PR #${prNumber}`);
} catch (err) {
if (err.status !== 404) throw err;
}
return true;
}
async function maybeTriggerCiFixClaude(github, owner, repo, prNumber, core, opts = {}) {
const baseRepo = `${owner}/${repo}`;
const ctx = await mergeGate.loadPrContext(github, owner, repo, prNumber);
const pr = ctx.pr;
if (pr.state !== 'open') return { skipped: true, reason: 'not open' };
if (pr.draft) return { skipped: true, reason: 'draft' };
const headRepo = pr.head.repo?.full_name;
if (headRepo && headRepo !== baseRepo && !pr.maintainer_can_modify) {
return { skipped: true, reason: 'fork without maintainer edits' };
}
const headSha = pr.head.sha;
const labels = ctx.labels;
if (await maybeClearCiFixLabel(github, owner, repo, prNumber, labels, headSha, core)) {
return { skipped: true, reason: 'ci green, label cleared' };
}
const ciGreen = await mergeGate.allChecksGreenOnSha(github, owner, repo, headSha, core);
if (ciGreen) return { skipped: true, reason: 'ci green' };
const runs = await mergeGate.listChecksOnSha(github, owner, repo, headSha);
const failedRuns = mergeGate.listFailedChecksOnSha(runs);
if (failedRuns.length === 0) {
return { skipped: true, reason: 'no failed checks yet (may be pending)' };
}
const hasFinal = mergeGate.hasFinalClaudeReviewTrigger(ctx.comments);
const claudeInProgress = await mergeGate.hasInProgressClaudeAssistant(
github, owner, repo, prNumber
);
const skip = shouldSkipCiFix({
comments: ctx.comments,
headSha,
labels,
hasFinal,
claudeInProgress,
failedChecks: failedRuns,
});
if (skip.skip) return { skipped: true, reason: skip.reason };
const failedChecks = mapFailedChecks(failedRuns);
const failureSummaries = [];
for (const check of failedChecks.slice(0, MAX_JOBS_TO_FETCH)) {
failureSummaries.push(
await fetchJobFailureSummary(github, owner, repo, check.id, check.name)
);
}
const body = buildCiFixComment({ headSha, failedChecks, failureSummaries });
await github.rest.issues.addLabels({
owner,
repo,
issue_number: prNumber,
labels: [CI_FIX_LABEL],
});
await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body,
});
core?.info?.(`Posted CI fix @claude on PR #${prNumber} (${shortSha(headSha)})`);
return { triggered: true, headSha: shortSha(headSha) };
}
async function processWorkflowRunFailure(github, owner, repo, workflowRun, core) {
if (workflowRun.conclusion !== 'failure') {
return { skipped: true, reason: `conclusion=${workflowRun.conclusion}` };
}
const allowed = config.ciFailureWorkflowRuns;
if (!allowed.includes(workflowRun.name)) {
return { skipped: true, reason: `workflow ${workflowRun.name}` };
}
const prNumber = await mergeGate.resolvePrNumberFromWorkflowRun(
github, owner, repo, workflowRun
);
if (!prNumber) return { skipped: true, reason: 'no linked PR' };
return maybeTriggerCiFixClaude(github, owner, repo, prNumber, core);
}
module.exports = {
CI_FIX_LABEL,
COOLDOWN_MS,
ciFixShaMarker,
isCiFixComment,
hasCiFixCommentForSha,
hasRecentCiFixComment,
shouldSkipCiFix,
parsePytestFailures,
fetchJobFailureSummary,
buildCiFixComment,
maybeClearCiFixLabel,
maybeTriggerCiFixClaude,
processWorkflowRunFailure,
};
-32
View File
@@ -1,32 +0,0 @@
/**
* PraisonAIUI gate configuration — imported by merge-gate, release-gate, ci-failure-claude.
*/
module.exports = {
repoFullName: 'MervinPraison/PraisonAIUI',
productPathPrefixes: ['src/praisonaiui/', 'src/frontend/', 'tests/'],
sensitivePathPatterns: [
/^\.github\/workflows\//,
/^pyproject\.toml$/,
/credentials\.json$/i,
],
requiredCheckPatterns: [/^ci$/i, /python/i, /test/i, /lint/i, /ruff/i],
ciWorkflowFile: 'ci.yml',
ciWorkflowName: 'CI',
mergeGateWorkflowRuns: ['CI', 'Claude Assistant'],
ciFailureWorkflowRuns: ['CI'],
pypiPackageName: 'aiui',
packagePaths: ['src/praisonaiui', 'src/frontend', 'pyproject.toml'],
finalClaudeScope:
'SCOPE: Focus ONLY on PraisonAIUI (src/praisonaiui, src/frontend, tests, docs). '
+ 'Do NOT expand into praisonaiagents or the monorepo unless the PR explicitly requires it.',
finalClaudeProductValue:
'4. Product value: review whether the change genuinely adds PraisonAIUI UX value and correct '
+ 'layering (UI/frontend here; core agent logic belongs in praisonaiagents). Reject scope creep.',
agentPyChecks: false,
reviewBotLogins: [
'coderabbitai[bot]',
'qodo-code-review[bot]',
'greptile-apps[bot]',
],
};
-234
View File
@@ -1,234 +0,0 @@
#!/usr/bin/env node
/**
* Local self-test for merge-gate.js heuristics (no GitHub API).
* Run: node .github/scripts/merge-gate-selftest.js
*/
const mg = require('./merge-gate.js');
let failed = 0;
function assert(name, cond) {
if (!cond) {
console.error('FAIL:', name);
failed++;
} else {
console.log('ok:', name);
}
}
// Stale FINAL: push after FINAL, no @claude since head
const finals = [
{ user: { login: 'github-actions[bot]' }, body: '@claude FINAL architecture reviewer', created_at: '2026-06-12T08:00:00Z' },
];
assert('stale when head after final', mg.isStaleFinalAfterPush(finals, '2026-06-12T09:00:00Z'));
const withRecovery = [
...finals,
{ user: { login: 'github-actions[bot]' }, body: '@claude FINAL architecture reviewer', created_at: '2026-06-12T09:30:00Z' },
];
assert('not stale when @claude after head', !mg.isStaleFinalAfterPush(withRecovery, '2026-06-12T09:00:00Z'));
const withClaudeReply = [
...finals,
{
user: { login: 'praisonai-triage-agent[bot]' },
body: "**Claude finished @MervinPraison's task** —— [View job](https://github.com/)",
created_at: '2026-06-12T08:30:00Z',
},
];
assert('not stale when Claude replied after FINAL', !mg.isStaleFinalAfterPush(withClaudeReply, '2026-06-12T09:00:00Z'));
assert('claude final reply detected', mg.isClaudeFinalReplyComment(withClaudeReply[1]));
assert('cancelled detect-and-trigger does not block', mg.OPTIONAL_CANCELLED_CHECKS.has('detect-and-trigger'));
// Stale-FINAL recovery guards (PR #2560 push loop)
const nowMs = Date.now();
const iso = (ms) => new Date(ms).toISOString();
const firstFinal = {
user: { login: 'MervinPraison' },
body: '@claude You are the FINAL architecture reviewer.',
created_at: iso(nowMs - 20 * 60 * 1000),
};
const pushSoonAfter = mg.shouldSkipStaleFinalRecovery(
[firstFinal],
iso(nowMs - 16 * 60 * 1000)
);
assert('debounce push soon after FINAL', pushSoonAfter.skip && pushSoonAfter.reason.includes('soon after'));
const secondFinal = {
user: { login: 'MervinPraison' },
body: '@claude You are the FINAL architecture reviewer.',
created_at: iso(nowMs - 20 * 60 * 1000),
};
const capped = mg.shouldSkipStaleFinalRecovery(
[firstFinal, secondFinal],
iso(nowMs - 2 * 60 * 1000)
);
assert('hourly cap blocks third FINAL in window', capped.skip && capped.reason.includes('capped'));
const botPush = mg.shouldSkipStaleFinalRecovery(
[firstFinal],
iso(nowMs - 16 * 60 * 1000),
'praisonai-triage-agent[bot]'
);
assert('skip when automation pushed head', botPush.skip && botPush.reason.includes('automation'));
assert('claude automation login', mg.isClaudeAutomationLogin('praisonai-triage-agent[bot]'));
// Bot CHANGES_REQUESTED then APPROVE
const reviews = [
{ user: { login: 'coderabbit[bot]', type: 'Bot' }, state: 'CHANGES_REQUESTED', submitted_at: '2026-06-12T08:00:00Z' },
{ user: { login: 'coderabbit[bot]', type: 'Bot' }, state: 'APPROVED', submitted_at: '2026-06-12T09:00:00Z' },
];
assert('bot approve clears CR', !mg.hasAnyChangesRequested(reviews));
assert('human CR blocks', mg.hasAnyChangesRequested([
{ user: { login: 'MervinPraison', type: 'User' }, state: 'CHANGES_REQUESTED', submitted_at: '2026-06-12T09:00:00Z' },
]));
// Verdict after HEAD
const verdictComments = [
{ body: 'MERGE_GATE_VERDICT: APPROVE', created_at: '2026-06-12T08:00:00Z' },
];
assert('verdict before head rejected', mg.findMergeGateVerdict(verdictComments, null, '2026-06-12T09:00:00Z') === null);
assert('verdict after head accepted', mg.findMergeGateVerdict(
[{ body: 'MERGE_GATE_VERDICT: APPROVE', created_at: '2026-06-12T10:00:00Z' }],
null,
'2026-06-12T09:00:00Z'
) === 'APPROVE');
const fallbackApprove = [
{
body: 'MERGE_GATE_VERDICT: APPROVE\n\nAutomated fallback — Claude assess did not post a verdict comment.',
created_at: '2026-06-12T10:00:00Z',
},
];
assert(
'automated fallback APPROVE ignored when Opus required',
mg.findMergeGateVerdict(fallbackApprove, null, '2026-06-12T09:00:00Z', { excludeAutomatedFallback: true }) === null
);
assert(
'automated fallback APPROVE still visible without Opus-only filter',
mg.findMergeGateVerdict(fallbackApprove, null, '2026-06-12T09:00:00Z') === 'APPROVE'
);
const fallbackBlockNewFormat = [
{
body: 'MERGE_GATE_VERDICT: BLOCK\n\nAutomated fallback — Opus merge gate assessment did not complete.',
created_at: '2026-06-12T10:00:00Z',
},
];
assert(
'new-format fallback BLOCK ignored when Opus required',
mg.findMergeGateVerdict(fallbackBlockNewFormat, null, '2026-06-12T09:00:00Z', { excludeAutomatedFallback: true }) === null
);
assert(
'new-format fallback BLOCK detected by marker helper',
mg.isAutomatedFallbackVerdict(fallbackBlockNewFormat[0].body)
);
assert(
'findMergeGateVerdict null-safe with explicit null options',
mg.findMergeGateVerdict(fallbackApprove, null, '2026-06-12T09:00:00Z', null) === 'APPROVE'
);
const noise = [{ user: { login: 'MervinPraison' }, body: '**Merge gate scan** — wait for `@claude`', created_at: new Date().toISOString() }];
assert('diagnostic comment not a trigger', !mg.hasRecentClaudeTrigger(noise, 35));
// Cooldown skip requires an actual verdict on HEAD, not just a FINAL trigger comment
const recentFinalOnHead = [
{
user: { login: 'MervinPraison' },
body: '@claude You are the FINAL architecture reviewer.',
created_at: '2026-06-27T10:00:00Z',
},
];
assert(
'final trigger alone does not count as verdict on head',
mg.findMergeGateVerdict(recentFinalOnHead, null, '2026-06-27T09:55:00Z') === null
);
const recentVerdictOnHead = [
...recentFinalOnHead,
{
user: { login: 'github-actions[bot]' },
body: 'MERGE_GATE_VERDICT: APPROVE',
created_at: '2026-06-27T10:05:00Z',
},
];
assert(
'verdict on head skips cooldown gate',
mg.findMergeGateVerdict(recentVerdictOnHead, null, '2026-06-27T09:55:00Z') === 'APPROVE'
);
// Sensitive + secrets
assert('workflow path sensitive', mg.sensitivePathReasons([{ filename: '.github/workflows/foo.yml' }]).length === 1);
assert('ci-only label exempts workflows', mg.sensitivePathReasons(
[{ filename: '.github/workflows/foo.yml' }],
[mg.WORKFLOW_ONLY_LABEL]
).length === 0);
assert('ci-only label not exempt mixed changes', mg.sensitivePathReasons(
[{ filename: '.github/workflows/foo.yml' }, { filename: 'src/praisonaiui/foo.py' }],
[mg.WORKFLOW_ONLY_LABEL]
).length === 1);
assert('secret in patch', mg.secretScanReasons([{ filename: 'x.py', patch: '+key = "ghp_abcdefghijklmnopqrstuvwxyz1234567890"' }]).length === 1);
// Claude run scoping — other PR branches must not block
assert('other branch claude does not block', !mg.hasBlockingClaudeRunForPr(
[{ event: 'issue_comment', head_branch: 'other-branch' }],
'my-branch'
));
assert('same branch claude blocks', mg.hasBlockingClaudeRunForPr(
[{ event: 'issue_comment', head_branch: 'my-branch' }],
'my-branch'
));
assert('issues event never blocks', !mg.hasBlockingClaudeRunForPr(
[{ event: 'issues', head_branch: 'my-branch' }],
'my-branch'
));
// Conflict rebase clears after bot completion + FINAL on HEAD (within 12h cooldown)
const conflictNowMs = Date.now();
const conflictIso = (offsetMs) => new Date(conflictNowMs + offsetMs).toISOString();
const conflictTrigger = {
user: { login: 'MervinPraison' },
body: '@claude this PR has merge conflicts with main. Please rebase',
created_at: conflictIso(-30 * 60 * 1000),
};
const rebaseDone = {
user: { login: 'praisonai-triage-agent[bot]' },
body: 'Rebase complete — PR #2308 onto latest main',
created_at: conflictIso(-29 * 60 * 1000),
};
const finalAfterRebase = {
user: { login: 'MervinPraison' },
body: '@claude You are the FINAL architecture reviewer.',
created_at: conflictIso(-20 * 60 * 1000),
};
const headAfterRebase = conflictIso(-21 * 60 * 1000);
const rebaseComments = [conflictTrigger, rebaseDone, finalAfterRebase];
assert('conflict blocks before rebase done', mg.hasRecentConflictComment([conflictTrigger], headAfterRebase));
assert('conflict clears after rebase + FINAL on HEAD', !mg.hasRecentConflictComment(rebaseComments, headAfterRebase));
assert('conflict still blocks without FINAL on HEAD', mg.hasRecentConflictComment(
[conflictTrigger, rebaseDone],
headAfterRebase
));
// Tests heuristic
assert('product code without tests', mg.missingTestsReason([{ filename: 'src/praisonaiui/a/b.py', additions: 3 }]) !== null);
assert('product code with tests ok', mg.missingTestsReason([
{ filename: 'src/praisonaiui/a/b.py', additions: 3 },
{ filename: 'tests/test_x.py', additions: 10 },
]) === null);
// PR size
assert('large PR blocked', mg.prSizeReasons([{ additions: 900 }]).length > 0);
assert('internal PR link accepted', mg.isInternalPullRequestLink(
{ base: { repo: { full_name: 'MervinPraison/PraisonAIUI' } } },
'MervinPraison',
'PraisonAIUI'
));
assert('fork sync PR link rejected', !mg.isInternalPullRequestLink(
{ number: 21, base: { repo: { full_name: 'Milkmange/PraisonAIUI' } } },
'MervinPraison',
'PraisonAIUI'
));
process.exit(failed ? 1 : 0);
-900
View File
@@ -1,900 +0,0 @@
/**
* Shared merge-gate helpers for claude-merge-gate.yml
* @see .github/workflows/claude-merge-gate.yml
*/
const config = require('./gate-config.js');
const CLAUDE_TRIGGER_LOGINS = ['MervinPraison', 'github-actions[bot]'];
const AUTO_ACTORS = CLAUDE_TRIGGER_LOGINS;
const CONFLICT_COOLDOWN_MS = 12 * 60 * 60 * 1000;
const CLAUDE_ACTIVE_MS = 35 * 60 * 1000;
const STALE_FINAL_RECOVERY_WINDOW_MS = 60 * 60 * 1000;
const STALE_FINAL_MAX_PER_WINDOW = 2;
const PUSH_AFTER_FINAL_DEBOUNCE_MS = 15 * 60 * 1000;
const ALLOWED_MERGE_STATES = new Set(['CLEAN', 'UNSTABLE']);
const AGENT_PY_MAX_AUTO_LINES = 100;
const PR_MAX_AUTO_ADDITIONS = 800;
const PR_MAX_AUTO_FILES = 30;
const MANUAL_ONLY_LABELS = new Set(['security', 'breaking-change', 'needs-manual-review', 'release']);
const WORKFLOW_ONLY_LABEL = 'merge-gate-ci-only';
const CI_ONLY_PATH_PREFIXES = ['.github/workflows/', '.github/actions/', '.github/scripts/merge-gate'];
const SDK_PATH_PREFIXES = config.productPathPrefixes;
const SENSITIVE_PATH_PATTERNS = config.sensitivePathPatterns;
const REQUIRED_SDK_CHECK_PATTERNS = config.requiredCheckPatterns;
const SECRET_PATTERNS = [
/sk-[a-zA-Z0-9]{20,}/,
/AKIA[0-9A-Z]{16}/,
/ghp_[a-zA-Z0-9]{36,}/,
/github_pat_/,
/Bearer eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+/,
/-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----/,
];
const BLOCK_LABELS = new Set([
'claude-conflict-pending',
'claude-merge-gate-active',
'no-auto-merge',
'auto-merged-by-gate',
]);
const MERGE_READY_LABEL = 'pipeline/merge-ready';
/** Superseded concurrency runs; must not block merge when real tests passed. */
const OPTIONAL_CANCELLED_CHECKS = new Set(['detect-and-trigger']);
const BOT_REVIEWER_PATTERNS = [
'coderabbit',
'qodo',
'gemini',
'copilot',
'greptile',
];
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
function isFinalClaudeTriggerComment(c) {
const body = (c.body || '').toLowerCase();
if (!AUTO_ACTORS.includes(c.user.login)) return false;
if (!body.includes('@claude')) return false;
if (body.includes('merge conflict')) return false;
return body.includes('final architecture reviewer') || body.includes('lead engineer');
}
function isClaudeTriggerNoise(c) {
const body = c.body || '';
if (body.includes('Merge gate scan')) return true;
if (body.includes('MERGE_GATE_VERDICT')) return true;
if (body.includes('Merged by **Claude PR merge gate**')) return true;
return false;
}
function isClaudeFinalReplyComment(c) {
const login = (c.user?.login || '').toLowerCase();
if (!login.includes('praisonai-triage')) return false;
return (c.body || '').includes('Claude finished');
}
function hasRecentClaudeTrigger(comments, minutes = 35) {
const cutoff = Date.now() - minutes * 60 * 1000;
return comments.some((c) => {
if (!CLAUDE_TRIGGER_LOGINS.includes(c.user.login)) return false;
if (isClaudeTriggerNoise(c)) return false;
if (!(c.body || '').includes('@claude')) return false;
return new Date(c.created_at).getTime() > cutoff;
});
}
function isConflictRebaseTriggerComment(c) {
if (!AUTO_ACTORS.includes(c.user.login)) return false;
const body = (c.body || '').toLowerCase();
return body.includes('@claude') && body.includes('merge conflict');
}
function isConflictRebaseCompletionComment(c) {
const login = (c.user?.login || '').toLowerCase();
if (!login.includes('praisonai-triage') && !login.includes('github-actions')) return false;
const body = (c.body || '').toLowerCase();
return (
body.includes('rebase complete') ||
body.includes('rebase onto') ||
(body.includes('conflict') && body.includes('resolved'))
);
}
function conflictRebaseQuiescent(comments, headPushedAt) {
const conflictTriggers = comments.filter(isConflictRebaseTriggerComment);
if (conflictTriggers.length === 0) return true;
const latestConflict = conflictTriggers.reduce((a, b) =>
new Date(a.created_at) > new Date(b.created_at) ? a : b
);
const conflictTime = new Date(latestConflict.created_at).getTime();
const rebaseDone = comments.some(
(c) =>
new Date(c.created_at).getTime() > conflictTime && isConflictRebaseCompletionComment(c)
);
if (!rebaseDone) return false;
return finalClaudeCompletedOnSha(comments, headPushedAt);
}
function hasRecentConflictComment(comments, headPushedAt = null) {
const cutoff = Date.now() - CONFLICT_COOLDOWN_MS;
const hasRecentTrigger = comments.some((c) => {
if (!isConflictRebaseTriggerComment(c)) return false;
return new Date(c.created_at).getTime() > cutoff;
});
if (!hasRecentTrigger) return false;
if (headPushedAt && conflictRebaseQuiescent(comments, headPushedAt)) {
return false;
}
return true;
}
function isBotReviewer(login, userType) {
const lower = (login || '').toLowerCase();
if (userType === 'Bot') return true;
if (lower.endsWith('[bot]')) return true;
return ['coderabbit', 'qodo', 'gemini', 'copilot', 'greptile'].some((p) => lower.includes(p));
}
function latestReviewsByUser(reviews) {
const latestByUser = new Map();
for (const r of reviews) {
const login = r.user?.login;
if (!login) continue;
const prev = latestByUser.get(login);
if (!prev || new Date(r.submitted_at) > new Date(prev.submitted_at)) {
latestByUser.set(login, r);
}
}
return latestByUser;
}
function hasHumanChangesRequested(reviews) {
for (const [login, review] of latestReviewsByUser(reviews)) {
if (review.state !== 'CHANGES_REQUESTED') continue;
if (!isBotReviewer(login, review.user?.type)) return true;
}
return false;
}
function hasAnyChangesRequested(reviews) {
for (const [, review] of latestReviewsByUser(reviews)) {
if (review.state === 'CHANGES_REQUESTED') return true;
}
return false;
}
function hasFinalClaudeReviewTrigger(comments) {
return comments.some(isFinalClaudeTriggerComment);
}
function isStaleFinalAfterPush(comments, headPushedAt) {
if (!headPushedAt) return false;
const headTime = new Date(headPushedAt).getTime();
const finals = comments.filter(isFinalClaudeTriggerComment);
if (finals.length === 0) return true;
const latestFinal = finals.reduce((a, b) =>
new Date(a.created_at) > new Date(b.created_at) ? a : b
);
const finalTime = new Date(latestFinal.created_at).getTime();
if (headTime <= finalTime + 60000) return false;
const claudeRepliedAfterFinal = comments.some((c) => {
if (!isClaudeFinalReplyComment(c)) return false;
return new Date(c.created_at).getTime() >= finalTime - 60000;
});
if (claudeRepliedAfterFinal) return false;
const claudeSinceHead = comments.some((c) => {
if (!CLAUDE_TRIGGER_LOGINS.includes(c.user.login)) return false;
if (isClaudeTriggerNoise(c)) return false;
if (!(c.body || '').includes('@claude')) return false;
return new Date(c.created_at).getTime() >= headTime - 60000;
});
return !claudeSinceHead;
}
function needsStaleFinalRecovery(comments, headPushedAt) {
return (
hasFinalClaudeReviewTrigger(comments) &&
isStaleFinalAfterPush(comments, headPushedAt)
);
}
function shouldSkipFinalRecovery(comments, headPushedAt) {
const isStale = isStaleFinalAfterPush(comments, headPushedAt);
if (isStale) return false;
return hasRecentClaudeTrigger(comments, 35);
}
function countFinalTriggersSince(comments, sinceMs) {
return comments.filter(
(c) => isFinalClaudeTriggerComment(c) && new Date(c.created_at).getTime() > sinceMs
).length;
}
function isClaudeAutomationLogin(login) {
const lower = (login || '').toLowerCase();
return lower.includes('praisonai-triage') || lower === 'github-actions[bot]';
}
function isPushSoonAfterLatestFinal(comments, headPushedAt) {
if (!headPushedAt) return false;
const finals = comments.filter(isFinalClaudeTriggerComment);
if (finals.length === 0) return false;
const latestFinal = finals.reduce((a, b) =>
new Date(a.created_at) > new Date(b.created_at) ? a : b
);
const finalTime = new Date(latestFinal.created_at).getTime();
const headTime = new Date(headPushedAt).getTime();
if (headTime <= finalTime) return false;
return headTime - finalTime < PUSH_AFTER_FINAL_DEBOUNCE_MS;
}
/** Returns { skip: true, reason } when stale-FINAL recovery should not post. */
function shouldSkipStaleFinalRecovery(comments, headPushedAt, headPusherLogin = null) {
if (!isStaleFinalAfterPush(comments, headPushedAt)) {
return { skip: true, reason: 'not stale' };
}
if (headPusherLogin && isClaudeAutomationLogin(headPusherLogin)) {
return { skip: true, reason: 'head pushed by Claude automation' };
}
if (isPushSoonAfterLatestFinal(comments, headPushedAt)) {
return {
skip: true,
reason: 'head pushed soon after FINAL (wait for CI / batched fixes)',
};
}
const windowStart = Date.now() - STALE_FINAL_RECOVERY_WINDOW_MS;
const finalsInWindow = countFinalTriggersSince(comments, windowStart);
if (finalsInWindow >= STALE_FINAL_MAX_PER_WINDOW) {
return {
skip: true,
reason: `stale-FINAL capped (${finalsInWindow} FINAL triggers in last hour)`,
};
}
return { skip: false, reason: '' };
}
function finalClaudeCompletedOnSha(comments, headPushedAt) {
if (!hasFinalClaudeReviewTrigger(comments)) return false;
if (isStaleFinalAfterPush(comments, headPushedAt)) return false;
return true;
}
const FINAL_CLAUDE_REVIEW_BODY =
`@claude You are the FINAL architecture reviewer. If the branch is under ${config.repoFullName} (not a fork), you are able to make modifications to this branch and push directly. ${config.finalClaudeScope} Read ALL comments above from Gemini, Qodo, CodeRabbit, and Copilot carefully before responding.\n\n**Phase 1: Review per AGENTS.md**\n1. Protocol-driven: check heavy implementations vs core SDK\n2. Backward compatible: ensure zero feature regressions\n3. Performance: no hot-path regressions (lazy imports, import-time <200ms)\n${config.finalClaudeProductValue}\n\n**Phase 2: FIX Valid Issues**\n5. For any VALID bugs or architectural flaws found by Gemini, CodeRabbit, Qodo, Copilot, or any other reviewer: implement the fix\n6. Push all code fixes directly to THIS branch (do NOT create a new PR)\n7. Comment a summary of exact files modified and what you skipped\n\n**Phase 3: Final Verdict**\n8. If all issues are resolved, approve the PR / close the Issue\n9. If blocking issues remain, request changes / leave clear action items`;
async function getMergeState(github, owner, repo, prNumber) {
const query = `
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $number) {
mergeStateStatus
maintainerCanModify
isDraft
headRefOid
headRef { repository { nameWithOwner } }
}
}
}
`;
for (let attempt = 0; attempt < 3; attempt++) {
const result = await github.graphql(query, { owner, repo, number: prNumber });
const prGql = result.repository.pullRequest;
const status = (prGql?.mergeStateStatus || '').toUpperCase();
if (status && status !== 'UNKNOWN') {
return {
status,
isDraft: prGql.isDraft,
headRepo: prGql.headRef?.repository?.nameWithOwner,
headSha: prGql.headRefOid,
maintainerCanModify: prGql.maintainerCanModify === true,
};
}
if (attempt < 2) await sleep(10000);
}
const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number: prNumber });
return {
status: (pr.mergeable_state || '').toUpperCase(),
isDraft: pr.draft,
headRepo: pr.head.repo?.full_name,
headSha: pr.head.sha,
maintainerCanModify: pr.maintainer_can_modify === true,
};
}
async function listChecksOnSha(github, owner, repo, sha) {
const { data } = await github.rest.checks.listForRef({
owner,
repo,
ref: sha,
per_page: 100,
});
return (data.check_runs || []).filter((r) => r.head_sha === sha);
}
function listFailedChecksOnSha(runs) {
return (runs || []).filter((run) => {
if (run.status !== 'completed') return false;
return run.conclusion === 'failure';
});
}
async function allChecksGreenOnSha(github, owner, repo, sha, core) {
const runs = await listChecksOnSha(github, owner, repo, sha);
if (runs.length === 0) {
core?.info?.(`No check runs on ${sha.slice(0, 7)} — allowing (e.g. docs-only PR)`);
return true;
}
for (const run of runs) {
if (run.status !== 'completed') {
core?.info?.(`Check pending: ${run.name} (${run.status})`);
return false;
}
const ok =
['success', 'neutral', 'skipped'].includes(run.conclusion) ||
(run.conclusion === 'cancelled' && OPTIONAL_CANCELLED_CHECKS.has(run.name));
if (!ok) {
core?.info?.(`Check failed: ${run.name} (${run.conclusion})`);
return false;
}
}
return true;
}
function claudeRunBlocksPr(run, headRef) {
if (!run || run.event === 'issues') return false;
if (!headRef) return true;
return run.head_branch === headRef;
}
function hasBlockingClaudeRunForPr(runs, headRef) {
return (runs || []).some((r) => claudeRunBlocksPr(r, headRef));
}
async function hasInProgressClaudeAssistant(github, owner, repo, prNumber = null) {
try {
const { data } = await github.rest.actions.listWorkflowRuns({
owner,
repo,
workflow_id: 'claude.yml',
status: 'in_progress',
per_page: 20,
});
const runs = (data.workflow_runs || []).filter((r) => r.event !== 'issues');
if (runs.length === 0) return false;
if (prNumber == null) return runs.length > 0;
const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number: prNumber });
const headRef = pr.head.ref;
return hasBlockingClaudeRunForPr(runs, headRef);
} catch {
return false;
}
}
function isCiOnlyChange(files) {
if (!files.length) return false;
return files.every((f) => CI_ONLY_PATH_PREFIXES.some((p) => f.filename.startsWith(p)));
}
function isInternalPullRequestLink(link, owner, repo) {
if (link?.base?.repo?.full_name === `${owner}/${repo}`) return true;
const baseUrl = link?.base?.repo?.url || '';
return baseUrl.endsWith(`/repos/${owner}/${repo}`);
}
async function resolvePrNumberFromLinkedPullRequests(github, owner, repo, linked) {
const repoFull = `${owner}/${repo}`;
const internal = (linked || []).filter((l) => isInternalPullRequestLink(l, owner, repo));
for (const link of internal) {
if (!link.number) continue;
try {
const { data } = await github.rest.pulls.get({
owner,
repo,
pull_number: link.number,
});
if (data.state === 'open' && data.base?.repo?.full_name === repoFull) {
return data.number;
}
} catch (err) {
if (err.status !== 404) throw err;
}
}
return null;
}
async function resolvePrNumberFromHeadBranch(github, owner, repo, branch) {
if (!branch || branch === 'main' || branch === 'master') return null;
const { data } = await github.rest.pulls.list({
owner,
repo,
state: 'open',
head: `${owner}:${branch}`,
per_page: 1,
});
return data[0]?.number || null;
}
async function resolvePrNumberFromWorkflowRun(github, owner, repo, workflowRun) {
const fromLinked = await resolvePrNumberFromLinkedPullRequests(
github, owner, repo, workflowRun.pull_requests
);
if (fromLinked) return fromLinked;
const fromBranch = await resolvePrNumberFromHeadBranch(
github, owner, repo, workflowRun.head_branch
);
if (fromBranch) return fromBranch;
return null;
}
async function listPullFiles(github, owner, repo, prNumber) {
if (typeof github.paginate === 'function') {
return github.paginate(github.rest.pulls.listFiles, {
owner,
repo,
pull_number: prNumber,
per_page: 100,
});
}
const { data } = await github.rest.pulls.listFiles({
owner,
repo,
pull_number: prNumber,
per_page: 100,
});
return data;
}
function countNewAgentParams(patch) {
if (!patch) return 0;
return patch
.split('\n')
.filter((l) => l.startsWith('+') && !l.startsWith('+++'))
.filter((l) => {
const t = l.slice(1).trim();
if (!t || t.startsWith('#') || t.startsWith('"""') || t.startsWith("'''")) return false;
if (/^(def|class|@|return\b|if\b|elif\b|else\b|for\b|while\b)/.test(t)) return false;
if (/^\w+\s*[:=]/.test(t) && !t.startsWith('self.')) return true;
return false;
}).length;
}
function getAgentPyChangeFromFiles(files) {
const agentFile = files.find((f) => f.filename.endsWith('praisonaiagents/agent/agent.py'));
if (!agentFile) {
return { touched: false, additions: 0, newParams: 0 };
}
return {
touched: true,
additions: agentFile.additions || 0,
newParams: countNewAgentParams(agentFile.patch || ''),
};
}
async function getAgentPyChange(github, owner, repo, prNumber) {
const files = await listPullFiles(github, owner, repo, prNumber);
return getAgentPyChangeFromFiles(files);
}
function touchesSdk(files) {
return files.some((f) => SDK_PATH_PREFIXES.some((p) => f.filename.startsWith(p)));
}
function hasManualOnlyLabel(labels) {
return labels.some((l) => MANUAL_ONLY_LABELS.has(l));
}
function sensitivePathReasons(files, labels = []) {
if (labels.includes(WORKFLOW_ONLY_LABEL) && isCiOnlyChange(files)) {
return [];
}
const reasons = [];
for (const f of files) {
if (SENSITIVE_PATH_PATTERNS.some((p) => p.test(f.filename))) {
reasons.push(`sensitive path: ${f.filename}`);
break;
}
}
return reasons;
}
function prSizeReasons(files) {
const reasons = [];
const totalAdditions = files.reduce((sum, f) => sum + (f.additions || 0), 0);
if (totalAdditions > PR_MAX_AUTO_ADDITIONS) {
reasons.push(`PR +${totalAdditions} lines (>${PR_MAX_AUTO_ADDITIONS}) requires manual review`);
}
if (files.length > PR_MAX_AUTO_FILES) {
reasons.push(`${files.length} files changed (>${PR_MAX_AUTO_FILES}) requires manual review`);
}
return reasons;
}
function missingTestsReason(files) {
const productAdds = files.filter(
(f) =>
SDK_PATH_PREFIXES.some((p) => f.filename.startsWith(p)) &&
f.filename.startsWith('src/praisonaiui/') &&
f.filename.endsWith('.py') &&
!f.filename.endsWith('__init__.py') &&
(f.additions || 0) > 0
);
if (productAdds.length === 0) return null;
const hasTestChange = files.some(
(f) => /\/tests?\//.test(f.filename) || /test_.*\.py$/.test(f.filename) || /_test\.py$/.test(f.filename)
);
if (!hasTestChange) return 'Product code added without test file changes — requires manual review';
return null;
}
function secretScanReasons(files) {
for (const f of files) {
if (/\/tests?\//.test(f.filename) || /test_.*\.py$/.test(f.filename)) continue;
const patch = f.patch || '';
if (!patch) continue;
for (const pattern of SECRET_PATTERNS) {
if (pattern.test(patch)) {
return [`possible secret in diff (${f.filename}) — requires manual review`];
}
}
}
return [];
}
async function sdkTestChecksReason(github, owner, repo, sha, files, core) {
if (!touchesSdk(files)) return null;
const { data } = await github.rest.checks.listForRef({
owner,
repo,
ref: sha,
per_page: 100,
});
const runs = (data.check_runs || []).filter((r) => r.head_sha === sha);
if (runs.length === 0) {
return 'SDK code changed but no CI checks on HEAD';
}
const testRuns = runs.filter((r) => REQUIRED_SDK_CHECK_PATTERNS.some((p) => p.test(r.name || '')));
if (testRuns.length === 0) {
return 'SDK code changed but no test check runs on HEAD';
}
core?.info?.(`SDK test checks on HEAD: ${testRuns.map((r) => r.name).join(', ')}`);
return null;
}
function manualReviewReasonForAgentPy(agentChange) {
if (!agentChange.touched) return null;
if (agentChange.additions > AGENT_PY_MAX_AUTO_LINES) {
return `agent.py +${agentChange.additions} lines (>${AGENT_PY_MAX_AUTO_LINES}) requires manual review`;
}
if (agentChange.newParams > 0) {
return `agent.py adds ${agentChange.newParams} new Agent param(s) — requires manual review`;
}
return null;
}
async function listAllComments(github, owner, repo, issueNumber) {
if (typeof github.paginate === 'function') {
return github.paginate(github.rest.issues.listComments, {
owner,
repo,
issue_number: issueNumber,
per_page: 100,
});
}
const { data } = await github.rest.issues.listComments({
owner,
repo,
issue_number: issueNumber,
per_page: 100,
});
return data;
}
async function getHeadCommitDate(github, owner, repo, prNumber) {
try {
let commits;
if (typeof github.paginate === 'function') {
commits = await github.paginate(github.rest.pulls.listCommits, {
owner,
repo,
pull_number: prNumber,
per_page: 100,
});
} else {
const { data } = await github.rest.pulls.listCommits({
owner,
repo,
pull_number: prNumber,
per_page: 100,
});
commits = data;
}
const last = commits[commits.length - 1];
return last?.commit?.committer?.date || last?.commit?.author?.date || null;
} catch {
return null;
}
}
async function loadPrContext(github, owner, repo, prNumber) {
const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number: prNumber });
const { data: issue } = await github.rest.issues.get({ owner, repo, issue_number: prNumber });
const comments = await listAllComments(github, owner, repo, prNumber);
const { data: reviews } = await github.rest.pulls.listReviews({
owner,
repo,
pull_number: prNumber,
per_page: 100,
});
const mergeState = await getMergeState(github, owner, repo, prNumber);
const headSha = mergeState.headSha || pr.head.sha;
const headCommitDate = await getHeadCommitDate(github, owner, repo, prNumber);
const headPushedAt = headCommitDate || pr.updated_at;
return {
pr,
issue,
comments,
reviews,
mergeState,
headSha,
headPushedAt,
labels: issue.labels.map((l) => l.name),
baseRepo: `${owner}/${repo}`,
};
}
async function evaluatePipelineQuiescent(github, owner, repo, prNumber, core, options = {}) {
const {
forMergeStep = false,
skipGlobalClaudeRunCheck = false,
skipRecentClaudeCooldown = false,
} = options;
const ctx = await loadPrContext(github, owner, repo, prNumber);
const reasons = [];
if (ctx.pr.draft) reasons.push('draft');
if (ctx.pr.state !== 'open') reasons.push('not open');
if (ctx.labels.includes('auto-merged-by-gate')) reasons.push('already merged by gate');
if (ctx.labels.includes('no-auto-merge')) reasons.push('no-auto-merge label');
if (ctx.labels.includes('claude-conflict-pending')) reasons.push('claude-conflict-pending');
if (!forMergeStep && ctx.labels.includes('claude-merge-gate-active')) {
reasons.push('claude-merge-gate-active');
}
const { status, headRepo, maintainerCanModify } = ctx.mergeState;
if (!ALLOWED_MERGE_STATES.has(status)) reasons.push(`mergeState=${status}`);
if (headRepo && headRepo !== ctx.baseRepo) {
reasons.push('fork PR');
}
if (hasRecentConflictComment(ctx.comments, ctx.headPushedAt)) {
reasons.push('recent merge-conflict @claude');
}
if (!skipRecentClaudeCooldown && hasRecentClaudeTrigger(ctx.comments, 35)) {
const verdictOnHead = findMergeGateVerdict(ctx.comments, null, ctx.headPushedAt) !== null;
if (!verdictOnHead) reasons.push('recent @claude within 35min');
}
if (!skipGlobalClaudeRunCheck && (await hasInProgressClaudeAssistant(github, owner, repo, prNumber))) {
reasons.push('claude.yml in progress');
}
const checksOk = await allChecksGreenOnSha(github, owner, repo, ctx.headSha, core);
if (!checksOk) reasons.push('CI not green on HEAD');
if (!finalClaudeCompletedOnSha(ctx.comments, ctx.headPushedAt)) {
if (!hasFinalClaudeReviewTrigger(ctx.comments)) {
reasons.push('no FINAL Claude review trigger');
} else if (isStaleFinalAfterPush(ctx.comments, ctx.headPushedAt)) {
reasons.push('stale FINAL after new commits (needs @claude re-review)');
} else {
reasons.push('FINAL Claude not complete on HEAD');
}
}
if (hasAnyChangesRequested(ctx.reviews)) reasons.push('CHANGES_REQUESTED review');
if (hasManualOnlyLabel(ctx.labels)) {
const manualLabel = ctx.labels.find((l) => MANUAL_ONLY_LABELS.has(l));
reasons.push(`manual-only label: ${manualLabel}`);
}
const pullFiles = await listPullFiles(github, owner, repo, prNumber);
if (config.agentPyChecks) {
const agentChange = getAgentPyChangeFromFiles(pullFiles);
const agentManual = manualReviewReasonForAgentPy(agentChange);
if (agentManual) reasons.push(agentManual);
}
reasons.push(...sensitivePathReasons(pullFiles, ctx.labels));
reasons.push(...prSizeReasons(pullFiles));
reasons.push(...secretScanReasons(pullFiles));
const testsReason = missingTestsReason(pullFiles);
if (testsReason) reasons.push(testsReason);
const sdkCheckReason = await sdkTestChecksReason(github, owner, repo, ctx.headSha, pullFiles, core);
if (sdkCheckReason) reasons.push(sdkCheckReason);
if (ctx.pr.mergeable === false) reasons.push('not mergeable');
const ready = reasons.length === 0;
return {
ready,
reasons,
headSha: ctx.headSha,
prNumber,
};
}
async function listPrNumbersForMergeGateScan(github, owner, repo, core) {
let mergeReadyIssues;
if (typeof github.paginate === 'function') {
mergeReadyIssues = await github.paginate(github.rest.issues.listForRepo, {
owner,
repo,
state: 'open',
labels: MERGE_READY_LABEL,
per_page: 100,
});
} else {
({ data: mergeReadyIssues } = await github.rest.issues.listForRepo({
owner,
repo,
state: 'open',
labels: MERGE_READY_LABEL,
per_page: 100,
}));
}
const mergeReady = mergeReadyIssues
.filter((issue) => issue.pull_request)
.map((issue) => issue.number)
.sort((a, b) => a - b);
if (mergeReady.length > 0) {
core?.info?.(
`Merge gate scan: ${mergeReady.length} ${MERGE_READY_LABEL} PR(s) (skipping unlabelled open PRs)`
);
return mergeReady;
}
core?.info?.(`No ${MERGE_READY_LABEL} PRs — scanning oldest open PRs`);
const prs =
typeof github.paginate === 'function'
? await github.paginate(github.rest.pulls.list, {
owner,
repo,
state: 'open',
per_page: 100,
sort: 'created',
direction: 'asc',
})
: (await github.rest.pulls.list({
owner,
repo,
state: 'open',
per_page: 100,
sort: 'created',
direction: 'asc',
})).data;
return prs.map((pr) => pr.number);
}
async function selectMergeGateCandidates(github, owner, repo, prNumbers, maxCandidates, core) {
const readyList = [];
const skipped = [];
for (const num of prNumbers) {
if (readyList.length >= maxCandidates) {
core?.info?.(`Found ${maxCandidates} candidate(s) — skipping remaining PR scans`);
break;
}
const result = await evaluatePipelineQuiescent(github, owner, repo, num, core);
if (result.ready) {
readyList.push({ pr_number: num, head_sha: result.headSha });
} else {
skipped.push({ pr: num, reasons: result.reasons });
}
}
readyList.sort((a, b) => a.pr_number - b.pr_number);
return {
candidates: readyList.slice(0, maxCandidates),
skipped,
};
}
const AUTOMATED_FALLBACK_MARKER = 'Automated fallback —';
function isAutomatedFallbackVerdict(body) {
return (body || '').includes(AUTOMATED_FALLBACK_MARKER);
}
function findMergeGateVerdict(comments, minCreatedAt = null, headPushedAt = null, options = {}) {
const { excludeAutomatedFallback = false } = options || {};
const minTime = minCreatedAt ? new Date(minCreatedAt).getTime() : 0;
const headTime = headPushedAt ? new Date(headPushedAt).getTime() - 60000 : 0;
const gateComments = comments
.filter((c) => {
if (!(c.body || '').includes('MERGE_GATE_VERDICT:')) return false;
if (excludeAutomatedFallback && isAutomatedFallbackVerdict(c.body)) return false;
const created = new Date(c.created_at).getTime();
if (minTime && created < minTime) return false;
if (headTime && created < headTime) return false;
return true;
})
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
if (gateComments.length === 0) return null;
const body = gateComments[0].body || '';
if (body.includes('MERGE_GATE_VERDICT: APPROVE')) return 'APPROVE';
if (body.includes('MERGE_GATE_VERDICT: BLOCK')) return 'BLOCK';
return null;
}
module.exports = {
CLAUDE_TRIGGER_LOGINS,
AUTO_ACTORS,
isFinalClaudeTriggerComment,
isClaudeTriggerNoise,
isClaudeFinalReplyComment,
hasRecentClaudeTrigger,
hasRecentConflictComment,
isConflictRebaseTriggerComment,
isConflictRebaseCompletionComment,
conflictRebaseQuiescent,
hasHumanChangesRequested,
hasAnyChangesRequested,
hasFinalClaudeReviewTrigger,
finalClaudeCompletedOnSha,
getMergeState,
OPTIONAL_CANCELLED_CHECKS,
listChecksOnSha,
listFailedChecksOnSha,
allChecksGreenOnSha,
hasInProgressClaudeAssistant,
claudeRunBlocksPr,
hasBlockingClaudeRunForPr,
isCiOnlyChange,
isInternalPullRequestLink,
resolvePrNumberFromLinkedPullRequests,
resolvePrNumberFromHeadBranch,
resolvePrNumberFromWorkflowRun,
WORKFLOW_ONLY_LABEL,
getAgentPyChange,
getAgentPyChangeFromFiles,
manualReviewReasonForAgentPy,
countNewAgentParams,
listPullFiles,
touchesSdk,
hasManualOnlyLabel,
sensitivePathReasons,
prSizeReasons,
missingTestsReason,
secretScanReasons,
sdkTestChecksReason,
listAllComments,
getHeadCommitDate,
isStaleFinalAfterPush,
needsStaleFinalRecovery,
shouldSkipFinalRecovery,
shouldSkipStaleFinalRecovery,
isClaudeAutomationLogin,
isPushSoonAfterLatestFinal,
countFinalTriggersSince,
STALE_FINAL_RECOVERY_WINDOW_MS,
STALE_FINAL_MAX_PER_WINDOW,
FINAL_CLAUDE_REVIEW_BODY,
loadPrContext,
evaluatePipelineQuiescent,
MERGE_READY_LABEL,
listPrNumbersForMergeGateScan,
selectMergeGateCandidates,
isAutomatedFallbackVerdict,
AUTOMATED_FALLBACK_MARKER,
findMergeGateVerdict,
};
@@ -1,82 +0,0 @@
#!/usr/bin/env node
/**
* Run: node .github/scripts/pipeline-status-selftest.js
*/
const ps = require('./pipeline-status.js');
const mg = require('./merge-gate.js');
const config = require('./gate-config.js');
let failed = 0;
function assert(name, cond) {
if (!cond) {
console.error('FAIL:', name);
failed++;
} else {
console.log('ok:', name);
}
}
const kickComments = [
{ user: { login: 'MervinPraison' }, body: '@coderabbitai review' },
{ user: { login: 'MervinPraison' }, body: '/review' },
];
const finalComment = {
user: { login: 'MervinPraison' },
body: '@claude You are the FINAL architecture reviewer.',
created_at: '2026-06-26T10:00:00Z',
};
assert(
'reviews pending when not kicked',
ps.deriveStage([], { ready: false, reasons: ['no FINAL Claude review trigger'] })
=== 'pipeline/reviews-pending'
);
assert(
'final pending after kick',
ps.deriveStage(kickComments, { ready: false, reasons: ['no FINAL Claude review trigger'] })
=== 'pipeline/final-claude-pending'
);
assert(
'awaiting merge gate after bot review comment',
ps.deriveStage(
[
{ user: { login: 'coderabbitai[bot]' }, body: 'review summary' },
finalComment,
],
{ ready: false, reasons: ['recent @claude within 35min'] }
) === 'pipeline/awaiting-merge-gate'
);
assert('review bot logins configured', config.reviewBotLogins.includes('coderabbitai[bot]'));
assert(
'merge ready',
ps.deriveStage([...kickComments, finalComment], { ready: true, reasons: [] })
=== 'pipeline/merge-ready'
);
const blockers = ps.deriveBlockerLabels({
ready: false,
reasons: ['CI not green on HEAD', 'SDK code added without test file changes — requires manual review'],
});
assert('maps ci blocker', blockers.includes('pipeline/blocked:ci'));
assert('maps manual blocker', blockers.includes('pipeline/blocked:manual-review'));
assert(
'internal link matches upstream base',
mg.isInternalPullRequestLink(
{ base: { repo: { full_name: 'MervinPraison/PraisonAI' } } },
'MervinPraison',
'PraisonAI'
)
);
assert(
'fork sync link rejected',
!mg.isInternalPullRequestLink(
{ number: 21, base: { repo: { full_name: 'Milkmange/PraisonAI' } } },
'MervinPraison',
'PraisonAI'
)
);
process.exit(failed ? 1 : 0);
-264
View File
@@ -1,264 +0,0 @@
/**
* Sync pipeline stage/blocker labels on open PRs.
* @see .github/workflows/pipeline-status-sync.yml
*/
const mergeGate = require('./merge-gate.js');
const chain = require('./bot-pr-review-chain.js');
const ciFix = require('./ci-failure-claude.js');
const config = require('./gate-config.js');
const PIPELINE_PREFIX = 'pipeline/';
const STAGE_LABELS = [
'pipeline/reviews-pending',
'pipeline/final-claude-pending',
'pipeline/awaiting-merge-gate',
'pipeline/merge-ready',
'pipeline/merged',
];
const BLOCKER_LABELS = [
'pipeline/blocked:ci',
'pipeline/blocked:conflict',
'pipeline/blocked:manual-review',
'pipeline/blocked:cooldown',
'pipeline/blocked:stale-final',
'pipeline/blocked:no-final',
];
const ALL_PIPELINE_LABELS = [...STAGE_LABELS, ...BLOCKER_LABELS];
const LABEL_SPECS = [
{ name: 'pipeline/reviews-pending', color: 'fbca04', description: 'Waiting for CodeRabbit/Qodo/Copilot reviews' },
{ name: 'pipeline/final-claude-pending', color: 'd4c5f9', description: 'Reviews done; waiting for FINAL @claude' },
{ name: 'pipeline/awaiting-merge-gate', color: 'c5def5', description: 'FINAL done; waiting for merge gate / CI' },
{ name: 'pipeline/merge-ready', color: '0e8a16', description: 'Eligible for merge gate auto-merge' },
{ name: 'pipeline/merged', color: '6f42c1', description: 'Merged via pipeline' },
{ name: 'pipeline/blocked:ci', color: 'd93f0b', description: 'Blocked: CI not green on HEAD' },
{ name: 'pipeline/blocked:conflict', color: 'b60205', description: 'Blocked: merge conflict or rebase pending' },
{ name: 'pipeline/blocked:manual-review', color: 'e99695', description: 'Blocked: requires manual review' },
{ name: 'pipeline/blocked:cooldown', color: 'fef2c0', description: 'Blocked: post-push or @claude cooldown' },
{ name: 'pipeline/blocked:stale-final', color: 'f9d0c4', description: 'Blocked: FINAL stale after new commits' },
{ name: 'pipeline/blocked:no-final', color: 'ededed', description: 'Blocked: no FINAL @claude trigger yet' },
];
function reviewChainStarted(comments) {
if (chain.chainKickPosted(comments)) return true;
return comments.some((c) => config.reviewBotLogins.includes(c.user?.login));
}
function deriveStage(comments, evalResult) {
if (evalResult.ready) return 'pipeline/merge-ready';
if (!reviewChainStarted(comments)) return 'pipeline/reviews-pending';
if (!mergeGate.hasFinalClaudeReviewTrigger(comments)) return 'pipeline/final-claude-pending';
return 'pipeline/awaiting-merge-gate';
}
function reasonToBlockerLabel(reason) {
const r = (reason || '').toLowerCase();
if (r.includes('ci not green') || r.includes('sdk code changed but no ci')) return 'pipeline/blocked:ci';
if (
r.includes('conflict') ||
r.includes('mergestate=dirty') ||
r.includes('not mergeable')
) return 'pipeline/blocked:conflict';
if (
r.includes('manual') ||
r.includes('requires manual') ||
r.includes('sensitive path') ||
r.includes('no-auto-merge') ||
r.includes('manual-only label') ||
r.includes('without test') ||
r.includes('product code') ||
r.includes('files changed') ||
r.includes('possible secret')
) return 'pipeline/blocked:manual-review';
if (r.includes('recent @claude') || r.includes('post-push buffer')) return 'pipeline/blocked:cooldown';
if (r.includes('stale final')) return 'pipeline/blocked:stale-final';
if (r.includes('no final claude')) return 'pipeline/blocked:no-final';
if (r.includes('final claude not complete')) return 'pipeline/blocked:stale-final';
if (r.includes('claude.yml in progress') || r.includes('claude-merge-gate-active')) {
return null;
}
return null;
}
function deriveBlockerLabels(evalResult) {
if (evalResult.ready) return [];
const labels = new Set();
for (const reason of evalResult.reasons || []) {
const mapped = reasonToBlockerLabel(reason);
if (mapped && mapped.startsWith('pipeline/blocked:')) labels.add(mapped);
}
return [...labels];
}
function computePipelineLabels(comments, evalResult) {
const stage = deriveStage(comments, evalResult);
const blockers = stage === 'pipeline/merge-ready' ? [] : deriveBlockerLabels(evalResult);
return { stage, blockers, all: [stage, ...blockers] };
}
async function ensurePipelineLabels(github, owner, repo, core) {
let existing;
if (typeof github.paginate === 'function') {
existing = await github.paginate(github.rest.issues.listLabelsForRepo, {
owner,
repo,
per_page: 100,
});
} else {
({ data: existing } = await github.rest.issues.listLabelsForRepo({
owner,
repo,
per_page: 100,
}));
}
const names = new Set(existing.map((l) => l.name));
for (const spec of LABEL_SPECS) {
if (names.has(spec.name)) continue;
try {
await github.rest.issues.createLabel({
owner,
repo,
name: spec.name,
color: spec.color,
description: spec.description,
});
core?.info?.(`Created label ${spec.name}`);
} catch (err) {
if (err.status !== 422) throw err;
core?.info?.(`Label ${spec.name} already exists`);
}
}
}
async function syncPipelineLabels(github, owner, repo, prNumber, core) {
const ctx = await mergeGate.loadPrContext(github, owner, repo, prNumber);
if (ctx.pr.state !== 'open') return { synced: false, reason: 'not_open' };
const evalResult = await mergeGate.evaluatePipelineQuiescent(
github, owner, repo, prNumber, core
);
const { stage, blockers, all } = computePipelineLabels(ctx.comments, evalResult);
const current = ctx.labels.filter((l) => l.startsWith(PIPELINE_PREFIX));
const desired = new Set(all);
const toRemove = current.filter((l) => !desired.has(l) && l !== 'pipeline/merged');
const toAdd = all.filter((l) => !current.includes(l));
for (const name of toRemove) {
try {
await github.rest.issues.removeLabel({ owner, repo, issue_number: prNumber, name });
} catch (err) {
if (err.status !== 404) throw err;
}
}
if (toAdd.length) {
await github.rest.issues.addLabels({
owner,
repo,
issue_number: prNumber,
labels: toAdd,
});
}
core?.info?.(`PR #${prNumber}: stage=${stage} blockers=[${blockers.join(', ')}]`);
const ciNotGreen = (evalResult.reasons || []).some((r) =>
r.toLowerCase().includes('ci not green')
);
if (ciNotGreen || blockers.includes('pipeline/blocked:ci')) {
await ciFix.maybeTriggerCiFixClaude(github, owner, repo, prNumber, core);
} else {
await ciFix.maybeClearCiFixLabel(
github, owner, repo, prNumber, ctx.labels, ctx.headSha, core
);
}
return {
synced: true,
stage,
blockers,
ready: evalResult.ready,
reasons: evalResult.reasons,
labels: ctx.labels,
createdAt: new Date(ctx.pr.created_at).getTime(),
};
}
async function dispatchMergeGateForOldestReady(github, owner, repo, readyCandidates, core) {
if (!readyCandidates.length) return 0;
readyCandidates.sort((a, b) => a.createdAt - b.createdAt);
for (const cand of readyCandidates) {
if ((cand.labels || []).includes('claude-merge-gate-active')) {
core?.info?.(`Skip dispatch PR #${cand.prNumber}: merge gate already active`);
continue;
}
await github.rest.repos.createDispatchEvent({
owner,
repo,
event_type: 'claude-merge-gate',
client_payload: { pr_number: cand.prNumber },
});
core?.info?.(`Dispatched merge gate for ready PR #${cand.prNumber}`);
return cand.prNumber;
}
return 0;
}
async function syncOpenPullRequests(github, owner, repo, options, core) {
const { maxPrs = 20, dispatchMergeGate = true } = options || {};
await ensurePipelineLabels(github, owner, repo, core);
let prs;
if (maxPrs <= 100) {
({ data: prs } = await github.rest.pulls.list({
owner,
repo,
state: 'open',
per_page: 100,
}));
} else {
prs = await github.paginate(github.rest.pulls.list, {
owner,
repo,
state: 'open',
per_page: 100,
});
}
let synced = 0;
const readyCandidates = [];
for (const pr of prs) {
if (synced >= maxPrs) break;
if (pr.draft) continue;
if (pr.head?.repo?.full_name && pr.head.repo.full_name !== `${owner}/${repo}`) continue;
const result = await syncPipelineLabels(github, owner, repo, pr.number, core);
if (result.ready) {
readyCandidates.push({
prNumber: pr.number,
createdAt: result.createdAt || new Date(pr.created_at).getTime(),
labels: result.labels || [],
});
}
synced += 1;
}
let dispatched = 0;
if (dispatchMergeGate && readyCandidates.length) {
dispatched = await dispatchMergeGateForOldestReady(
github, owner, repo, readyCandidates, core
);
}
core?.info?.(`Pipeline label sync complete (${synced} PR(s), dispatched=${dispatched || 'none'})`);
return synced;
}
module.exports = {
STAGE_LABELS,
BLOCKER_LABELS,
ALL_PIPELINE_LABELS,
deriveStage,
deriveBlockerLabels,
computePipelineLabels,
ensurePipelineLabels,
syncPipelineLabels,
syncOpenPullRequests,
dispatchMergeGateForOldestReady,
};
-300
View File
@@ -1,300 +0,0 @@
/**
* PR review pipeline: CodeRabbit / Greptile (+ optional Qodo/Gemini) → Claude (FINAL).
* Copilot step optional — set REVIEW_CHAIN_SKIP_COPILOT=1 or skipCopilot: true to bypass.
* @see .github/workflows/auto-pr-comment.yml
*/
function isSkipCopilot(options = {}) {
if (options.skipCopilot === true) return true;
if (options.skipCopilot === false) return false;
return process.env.REVIEW_CHAIN_SKIP_COPILOT === '1';
}
const COPILOT_TRIGGER_LOGINS = new Set(['MervinPraison', 'github-actions[bot]']);
const CLAUDE_TRIGGER_LOGINS = new Set(['MervinPraison', 'github-actions[bot]']);
const REQUIRED_PRIOR = ['coderabbit', 'greptile'];
const OPTIONAL_PRIOR = ['qodo', 'gemini'];
const OPTIONAL_PRIOR_WAIT_MS = 20 * 60 * 1000;
function loginOf(item) {
return (item?.user?.login || '').toLowerCase();
}
function bodyOf(item) {
return item?.body || '';
}
function hasCoderabbitSummary(comments) {
return comments.some(
(c) =>
loginOf(c).includes('coderabbit') &&
bodyOf(c).toLowerCase().includes('summarize by coderabbit')
);
}
function hasGreptileReview(comments) {
return comments.some((c) => {
if (!loginOf(c).includes('greptile')) return false;
const body = bodyOf(c);
return body.includes('Greptile Summary') || body.includes('<h3>Greptile Summary</h3>') || body.length > 150;
});
}
function hasQodoReview(comments, reviews = []) {
if (comments.some((c) => loginOf(c).includes('qodo'))) return true;
return reviews.some((r) => loginOf(r).includes('qodo'));
}
function hasGeminiReview(comments, reviews = []) {
if (reviews.some((r) => loginOf(r).includes('gemini'))) return true;
return comments.some((c) => {
if (loginOf(c).includes('gemini')) return true;
const body = bodyOf(c);
return (
body.includes('Review completed by Gemini CLI') ||
body.includes('The fix is ready for review. Please test')
);
});
}
const PRIOR_CHECKS = {
coderabbit: (comments) => hasCoderabbitSummary(comments),
greptile: (comments) => hasGreptileReview(comments),
qodo: (comments, reviews) => hasQodoReview(comments, reviews),
gemini: (comments, reviews) => hasGeminiReview(comments, reviews),
};
function priorReviewerStatus(comments, reviews = []) {
const status = {};
for (const [id, check] of Object.entries(PRIOR_CHECKS)) {
status[id] = check(comments, reviews);
}
return status;
}
function priorReviewersReady(comments, reviews = [], options = {}) {
const waitMs = options.optionalWaitMs ?? OPTIONAL_PRIOR_WAIT_MS;
const prCreatedAt = options.prCreatedAt || null;
const status = priorReviewerStatus(comments, reviews);
const missingRequired = REQUIRED_PRIOR.filter((id) => !status[id]);
if (missingRequired.length) {
return { ready: false, reason: `waiting for ${missingRequired.join(', ')}`, status };
}
const missingOptional = OPTIONAL_PRIOR.filter((id) => !status[id]);
if (missingOptional.length && prCreatedAt) {
const age = Date.now() - new Date(prCreatedAt).getTime();
if (age < waitMs) {
return {
ready: false,
reason: `waiting for optional ${missingOptional.join(', ')} (${Math.round((waitMs - age) / 60000)}m left)`,
status,
};
}
}
return { ready: true, reason: '', status };
}
function copilotTriggerComment(comments) {
return comments.find(
(c) =>
bodyOf(c).includes('@copilot') &&
COPILOT_TRIGGER_LOGINS.has(c.user?.login) &&
!bodyOf(c).toLowerCase().includes('@claude')
);
}
function copilotTriggered(comments) {
return Boolean(copilotTriggerComment(comments));
}
function copilotReviewReady(comments, reviews = []) {
const trigger = copilotTriggerComment(comments);
if (!trigger) {
return { ready: false, reason: 'copilot not triggered yet' };
}
const triggerTime = new Date(trigger.created_at).getTime();
const copilotComment = comments.some((c) => {
if (c === trigger) return false;
if (new Date(c.created_at).getTime() < triggerTime) return false;
const login = loginOf(c);
return (
login.includes('copilot') ||
c.user?.login === 'Copilot' ||
c.user?.login === 'copilot-swe-agent'
);
});
const copilotReview = reviews.some((r) => {
if (new Date(r.submitted_at).getTime() < triggerTime) return false;
return loginOf(r).includes('copilot');
});
if (copilotComment || copilotReview) {
return { ready: true, reason: '' };
}
return { ready: false, reason: 'awaiting copilot review' };
}
function isFinalClaudeTriggerComment(c) {
const body = bodyOf(c).toLowerCase();
if (!CLAUDE_TRIGGER_LOGINS.has(c.user?.login)) return false;
if (!body.includes('@claude')) return false;
if (body.includes('merge conflict')) return false;
return body.includes('final architecture reviewer') || body.includes('lead engineer');
}
function claudeFinalAlreadyTriggered(comments) {
return comments.some(isFinalClaudeTriggerComment);
}
function claudeFinalReady(comments, reviews = [], options = {}) {
if (!options.allowStaleRepost && claudeFinalAlreadyTriggered(comments)) {
return { ready: false, reason: 'claude FINAL already triggered', already: true };
}
const prior = priorReviewersReady(comments, reviews, options);
if (!prior.ready) {
return { ready: false, reason: prior.reason };
}
if (isSkipCopilot(options)) {
return { ready: true, reason: 'copilot skipped', copilotSkipped: true };
}
const copilot = copilotReviewReady(comments, reviews);
if (copilot.ready) {
return { ready: true, reason: '' };
}
if (options.allowCopilotTimeout && copilotTriggered(comments)) {
return { ready: true, reason: 'copilot timeout fallback', copilotSkipped: true };
}
return { ready: false, reason: copilot.reason };
}
/** Post @copilot when prior reviewers are ready, then @claude FINAL when Copilot done (or timeout). */
async function advanceReviewChain(github, owner, repo, prNumber, finalBody, core, options = {}) {
const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number: prNumber });
const chainOpts = {
prCreatedAt: pr.created_at,
optionalWaitMs: options.optionalWaitMs ?? 0,
};
const copilot = options.skipCopilot
? { triggered: false, reason: 'skipped' }
: await maybeTriggerCopilot(github, owner, repo, prNumber, core, chainOpts);
const claude = await maybeTriggerClaudeFinal(
github, owner, repo, prNumber, finalBody, core,
{ ...options, ...chainOpts }
);
return { copilot, claude };
}
async function maybeTriggerClaudeFinal(github, owner, repo, prNumber, finalBody, core, options = {}) {
const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number: prNumber });
const { comments, reviews } = await listCommentsAndReviews(github, owner, repo, prNumber);
const gate = claudeFinalReady(comments, reviews, {
prCreatedAt: pr.created_at,
optionalWaitMs: options.optionalWaitMs,
allowCopilotTimeout: options.allowCopilotTimeout !== false,
allowStaleRepost: options.allowStaleRepost === true,
skipCopilot: options.skipCopilot,
});
if (!gate.ready) {
core?.info?.(`PR #${prNumber}: skip Claude FINAL — ${gate.reason}`);
return { posted: false, reason: gate.reason };
}
await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body: finalBody,
});
const note = gate.copilotSkipped ? ' (Copilot timeout fallback)' : '';
core?.info?.(`Posted Claude FINAL on PR #${prNumber}${note}`);
return { posted: true, reason: '' };
}
const COPILOT_REVIEW_BODY =
'@copilot Do a thorough review of this PR. Read ALL existing reviewer comments above from Qodo, CodeRabbit, Gemini, and Greptile first — incorporate their findings.\n\nReview areas:\n1. **Bloat check**: Are changes minimal and focused? Any unnecessary code or scope creep?\n2. **Security**: Any hardcoded secrets, unsafe eval/exec, missing input validation?\n3. **Performance**: Any module-level heavy imports? Hot-path regressions?\n4. **Tests**: Are tests included? Do they cover the changes adequately?\n5. **Backward compat**: Any public API changes without deprecation?\n6. **Code quality**: DRY violations, naming conventions, error handling?\n7. **Address reviewer feedback**: If Qodo, CodeRabbit, Gemini, or Greptile flagged valid issues, include them in your review\n8. Suggest specific improvements with code examples where possible';
async function listCommentsAndReviews(github, owner, repo, prNumber) {
let comments;
if (typeof github.paginate === 'function') {
comments = await github.paginate(github.rest.issues.listComments, {
owner,
repo,
issue_number: prNumber,
per_page: 100,
});
} else {
const { data } = await github.rest.issues.listComments({
owner,
repo,
issue_number: prNumber,
per_page: 100,
});
comments = data;
}
const { data: reviews } = await github.rest.pulls.listReviews({
owner,
repo,
pull_number: prNumber,
per_page: 100,
});
return { comments, reviews };
}
async function maybeTriggerCopilot(github, owner, repo, prNumber, core, options = {}) {
const { comments, reviews } = await listCommentsAndReviews(github, owner, repo, prNumber);
if (copilotTriggered(comments)) {
core?.info?.(`Copilot already triggered on PR #${prNumber}`);
return { triggered: false, reason: 'already_triggered' };
}
const prior = priorReviewersReady(comments, reviews, options);
if (!prior.ready) {
core?.info?.(`PR #${prNumber}: not ready for Copilot — ${prior.reason}`);
return { triggered: false, reason: prior.reason };
}
await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body: COPILOT_REVIEW_BODY,
});
core?.info?.(`Posted @copilot on PR #${prNumber} after prior reviewers`);
return { triggered: true };
}
async function pollCopilotResponse(github, owner, repo, prNumber, options = {}) {
const maxAttempts = options.maxAttempts ?? 20;
const delayMs = options.delayMs ?? 30000;
for (let i = 0; i < maxAttempts; i += 1) {
const { comments, reviews } = await listCommentsAndReviews(github, owner, repo, prNumber);
const copilot = copilotReviewReady(comments, reviews);
if (copilot.ready) {
return { ready: true, reason: '' };
}
if (i < maxAttempts - 1) {
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
}
return { ready: false, reason: 'copilot timeout' };
}
module.exports = {
isSkipCopilot,
REQUIRED_PRIOR,
OPTIONAL_PRIOR,
COPILOT_REVIEW_BODY,
priorReviewerStatus,
priorReviewersReady,
copilotTriggered,
copilotReviewReady,
claudeFinalReady,
claudeFinalAlreadyTriggered,
isFinalClaudeTriggerComment,
maybeTriggerCopilot,
maybeTriggerClaudeFinal,
advanceReviewChain,
pollCopilotResponse,
hasGeminiReview,
listCommentsAndReviews,
};
-32
View File
@@ -1,32 +0,0 @@
#!/usr/bin/env node
/**
* Run: node .github/scripts/release-gate-selftest.js
*/
const rg = require('./release-gate.js');
const config = require('./gate-config.js');
let failed = 0;
function assert(name, cond) {
if (!cond) {
console.error('FAIL:', name);
failed += 1;
} else {
console.log('ok:', name);
}
}
assert('package name is aiui', config.pypiPackageName === 'aiui');
assert('bumpPatch works', rg.bumpPatch('0.3.127') === '0.3.128');
try {
const versions = rg.readVersionsFromTree(process.cwd());
assert('reads current version', /^\d+\.\d+\.\d+$/.test(versions.current));
assert('computes target patch', versions.target === rg.bumpPatch(versions.current));
} catch (err) {
console.error('FAIL: readVersionsFromTree', err.message);
failed += 1;
}
assert('PACKAGE_PATHS includes pyproject', rg.PACKAGE_PATHS.includes('pyproject.toml'));
process.exit(failed ? 1 : 0);
-205
View File
@@ -1,205 +0,0 @@
/**
* Release gate preflight — path changes, CI SHA, dedupe, PyPI version checks (PraisonAIUI).
*/
const https = require('https');
const config = require('./gate-config.js');
const PACKAGE_PATHS = config.packagePaths;
const ACTIVE_RELEASE_STATUSES = new Set([
'queued', 'in_progress', 'waiting', 'pending', 'requested',
]);
function bumpPatch(version) {
const parts = version.split('.');
if (parts.length !== 3) throw new Error(`Invalid version: ${version}`);
return `${parts[0]}.${parts[1]}.${Number(parts[2]) + 1}`;
}
function readVersionsFromTree(root = '.') {
const fs = require('fs');
const path = require('path');
const toml = fs.readFileSync(path.join(root, 'pyproject.toml'), 'utf8');
const match = toml.match(/^version\s*=\s*"([^"]+)"/m);
if (!match) throw new Error('Could not read aiui version from pyproject.toml');
const current = match[1];
const target = bumpPatch(current);
return { current, target, packageName: config.pypiPackageName };
}
function pypiVersionExists(packageName, version) {
return new Promise((resolve) => {
const req = https.get(
`https://pypi.org/pypi/${packageName}/${version}/json`,
{ timeout: 15000 },
(res) => {
res.resume();
resolve(res.statusCode === 200);
}
);
req.on('error', () => resolve(false));
req.on('timeout', () => {
req.destroy();
resolve(false);
});
});
}
async function hasActiveReleaseRun(github, owner, repo) {
const runs = await github.rest.actions.listWorkflowRuns({
owner,
repo,
workflow_id: 'pypi-release.yml',
per_page: 20,
});
return runs.data.workflow_runs.some(
(r) => ACTIVE_RELEASE_STATUSES.has(r.status) && !r.conclusion
);
}
function utcDayStart(now = new Date()) {
return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
}
async function hasSuccessfulReleaseToday(github, owner, repo, now = new Date()) {
const dayStart = utcDayStart(now);
const runs = await github.rest.actions.listWorkflowRuns({
owner,
repo,
workflow_id: 'pypi-release.yml',
status: 'completed',
per_page: 30,
});
return runs.data.workflow_runs.some(
(r) => r.conclusion === 'success' && new Date(r.created_at) >= dayStart
);
}
async function lastGreenCiSha(github, owner, repo) {
const runs = await github.rest.actions.listWorkflowRuns({
owner,
repo,
workflow_id: config.ciWorkflowFile,
branch: 'main',
status: 'completed',
per_page: 30,
});
const hit = runs.data.workflow_runs.find((r) => r.conclusion === 'success');
return hit ? hit.head_sha : '';
}
async function evaluateReleasePreflight(github, owner, repo, options, core) {
const {
headSha,
isCiTrigger = false,
bump = 'patch',
} = options;
const reasons = [];
const out = {
ready: false,
reasons,
headSha: headSha || '',
lastTag: '',
targetVersion: '',
packageName: config.pypiPackageName,
};
if (bump !== 'patch') {
reasons.push('only patch auto-release supported');
return out;
}
if (await hasActiveReleaseRun(github, owner, repo)) {
reasons.push('PyPI Release already in progress or awaiting approval');
return out;
}
const referenceTime = options.now instanceof Date ? options.now : new Date();
if (await hasSuccessfulReleaseToday(github, owner, repo, referenceTime)) {
const day = referenceTime.toISOString().slice(0, 10);
reasons.push(`already released today (UTC ${day}); max one patch release per day`);
return out;
}
let versions;
try {
versions = readVersionsFromTree();
} catch (err) {
reasons.push(err.message);
return out;
}
out.targetVersion = versions.target;
const onPypi = await pypiVersionExists(config.pypiPackageName, versions.target);
if (onPypi) {
reasons.push(`already published: ${config.pypiPackageName}==${versions.target}`);
return out;
}
const { execSync } = require('child_process');
let lastTag = '';
try {
lastTag = execSync('git describe --tags --match "v*" --abbrev=0', { encoding: 'utf8' }).trim();
} catch {
reasons.push('no v* tag found');
return out;
}
out.lastTag = lastTag;
let changed = '';
try {
changed = execSync(
`git diff --name-only ${lastTag} HEAD -- ${PACKAGE_PATHS.join(' ')}`,
{ encoding: 'utf8' }
).trim();
} catch {
reasons.push('git diff failed');
return out;
}
if (!changed) {
reasons.push(`no changes in ${PACKAGE_PATHS.join(' or ')} since ${lastTag}`);
return out;
}
if (isCiTrigger) {
let mainSha = '';
try {
mainSha = execSync('git rev-parse origin/main', { encoding: 'utf8' }).trim();
} catch {
reasons.push('could not resolve origin/main');
return out;
}
if (headSha !== mainSha) {
reasons.push(`superseded: green SHA ${headSha.slice(0, 7)} != main ${mainSha.slice(0, 7)}`);
return out;
}
out.headSha = headSha;
} else {
const evalSha = execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim();
out.headSha = evalSha;
const greenSha = await lastGreenCiSha(github, owner, repo);
if (greenSha !== evalSha) {
reasons.push(`CI not green on HEAD (last green: ${greenSha ? greenSha.slice(0, 7) : 'none'})`);
return out;
}
}
out.ready = true;
out.reasons = ['ready'];
if (core) core.info(`Release preflight passed for ${out.headSha || headSha}`);
return out;
}
module.exports = {
bumpPatch,
readVersionsFromTree,
pypiVersionExists,
hasSuccessfulReleaseToday,
utcDayStart,
evaluateReleasePreflight,
lastGreenCiSha,
ACTIVE_RELEASE_STATUSES,
PACKAGE_PATHS,
};
-94
View File
@@ -1,94 +0,0 @@
name: Auto Issue Comment
# Automatically escalate every new issue to Claude for a full investigation
# + draft fix. Manual re-trigger: workflow_dispatch with issue_number.
#
# Note: `@claude` mentions only trigger claude.yml when the commenter is a
# HUMAN user (or github-actions[bot] via PAT). This workflow posts the
# comment as github-actions[bot], so claude.yml must allow that bot.
on:
workflow_dispatch:
inputs:
issue_number:
description: "Issue number to triage with Claude"
required: true
type: string
issues:
types: [opened]
jobs:
# Escalate an issue to full Claude implementation by adding the `claude`
# label. claude.yml listens on `issues:labeled` + label=='claude' and
# triggers Job 2 (claude-response) which does the actual work.
trigger-claude:
if: |
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'issues' && !contains(toJSON(github.event.issue.labels), 'claude'))
runs-on: ubuntu-latest
permissions:
issues: write
actions: write
steps:
- name: Resolve issue number
id: resolve
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "number=${{ inputs.issue_number }}" >> "$GITHUB_OUTPUT"
else
echo "number=${{ github.event.issue.number }}" >> "$GITHUB_OUTPUT"
fi
- name: Add claude label + post instructions
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }}
script: |
const issueNumber = Number('${{ steps.resolve.outputs.number }}');
const { data: issue } = await github.rest.issues.get({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
});
const labels = (issue.labels || []).map(l => typeof l === 'string' ? l : l.name);
if (!labels.includes('claude')) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
labels: ['claude'],
});
} else {
console.log(`Issue #${issueNumber} already has 'claude' label.`);
}
const body = [
'🤖 Auto-triaging with Claude.',
'',
'Claude will:',
'',
'1. Read this issue and all comments.',
'2. Classify and route to the right area (`src/praisonaiui/`, `src/frontend/`, `docs/`, or external repo).',
'3. Implement a minimal fix per `AGENTS.md`.',
'4. Run `pytest` + the import-time invariant locally.',
'5. Open a draft PR linked to this issue.',
'',
'Follow-ups in this thread with `@claude` will re-trigger the loop.'
].join('\n');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issueNumber,
body,
});
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'claude.yml',
ref: 'main',
inputs: { issue_number: String(issueNumber) },
});
console.log(`Dispatched Claude Assistant for issue #${issueNumber}`);
-809
View File
@@ -1,809 +0,0 @@
name: Auto PR Comment
# Review chain: CodeRabbit/Qodo/Gemini review first → Copilot → Claude (final)
# For human PRs: CodeRabbit/Qodo auto-review → this workflow triggers Copilot → then Claude
# For bot PRs: CodeRabbit/Qodo skip bots, so we trigger them explicitly first
#
# IMPORTANT: @copilot ignores bot comments. All @copilot mentions must use
# PAT_TOKEN so the comment posts as MervinPraison (a real user).
#
# Claude trigger runs IN-BAND (same workflow) to avoid GitHub Actions
# blocking bot-triggered workflows with action_required approval gates.
on:
issue_comment:
types: [created]
pull_request_review:
types: [submitted]
pull_request:
types: [opened, synchronize]
pull_request_target:
types: [synchronize]
schedule:
- cron: '30 3,9,15,21 * * *'
workflow_dispatch:
inputs:
pr_number:
description: 'PR number for manual FINAL (leave empty to sweep all open PRs)'
required: false
type: number
permissions:
contents: read
issues: write
pull-requests: write
env:
MAX_POLL_ATTEMPTS: 20
POLL_DELAY_MS: 30000
CLAUDE_TRIGGER_LOGINS: '["MervinPraison","github-actions[bot]"]'
# GH_TOKEN (user PAT) posts as MervinPraison for @copilot; fallback to github.token for @claude
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
CLAUDE_UI_SCOPE: 'SCOPE: Focus ONLY on PraisonAIUI (src/praisonaiui, src/frontend, tests, docs). Do not expand into praisonaiagents or the monorepo unless the issue explicitly requires it.'
CLAUDE_FINAL_PHASES_COMPACT: "**Phase 1: Review per AGENTS.md** (lazy imports, backward compat, import-time <200ms; SDK/product value gate — genuine UI value, correct UI vs praisonaiagents layering, no scope creep)\n**Phase 2: FIX valid issues** found by prior reviewers — push to THIS branch\n**Phase 3: Final verdict** — approve PR if ready, else request changes"
CLAUDE_FINAL_PHASES_DETAILED: "**Phase 1: Review per AGENTS.md**\n1. Protocol-driven: check heavy implementations vs core SDK\n2. Backward compatible: ensure zero feature regressions\n3. Performance: no hot-path regressions (lazy imports, import-time <200ms)\n4. SDK/product value: review whether the change genuinely adds value — stronger PraisonAIUI UX and correct layering (UI/frontend here; core agent logic belongs in praisonaiagents). Reject scope creep; request changes or recommend closing if value is unclear\n\n**Phase 2: FIX Valid Issues**\n5. For any VALID bugs or architectural flaws found by Gemini, CodeRabbit, Qodo, Copilot, or any other reviewer: implement the fix\n6. Push all code fixes directly to THIS branch (do NOT create a new PR)\n7. Comment a summary of exact files modified and what you skipped\n\n**Phase 3: Final Verdict**\n8. If all issues are resolved, approve the PR / close the Issue\n9. If blocking issues remain, request changes / leave clear action items"
jobs:
# ================================================================
# HUMAN PRs: Trigger @copilot AFTER CodeRabbit posts its summary
# ================================================================
copilot-after-coderabbit:
if: |
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
github.event.comment.user.login == 'coderabbitai[bot]' &&
contains(github.event.comment.body, 'summarize by coderabbit')
runs-on: ubuntu-latest
permissions:
pull-requests: write
outputs:
pr_number: ${{ steps.trigger.outputs.pr_number }}
triggered: ${{ steps.trigger.outputs.triggered }}
steps:
- name: Post Copilot review request (as user via PAT)
id: trigger
uses: actions/github-script@v7
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const comments = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo
});
// Check for duplicates — posted by MervinPraison (PAT) or github-actions[bot] (legacy)
const alreadyPosted = comments.data.some(c =>
c.body.includes('@copilot') &&
(c.user.login === 'MervinPraison' || c.user.login === 'github-actions[bot]')
);
if (alreadyPosted) {
console.log('Copilot already triggered, skipping');
core.setOutput('triggered', 'false');
core.setOutput('pr_number', context.issue.number.toString());
return;
}
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '@copilot Do a thorough review of this PR. Read ALL existing reviewer comments above from Qodo, Coderabbit, and Gemini first — incorporate their findings.\n\nReview areas:\n1. **Bloat check**: Are changes minimal and focused? Any unnecessary code or scope creep?\n2. **Security**: Any hardcoded secrets, unsafe eval/exec, missing input validation?\n3. **Performance**: Any module-level heavy imports? Hot-path regressions?\n4. **Tests**: Are tests included? Do they cover the changes adequately?\n5. **Backward compat**: Any public API changes without deprecation?\n6. **Code quality**: DRY violations, naming conventions, error handling?\n7. **Address reviewer feedback**: If Qodo, Coderabbit, or Gemini flagged valid issues, include them in your review\n8. Suggest specific improvements with code examples where possible'
});
core.setOutput('triggered', 'true');
core.setOutput('pr_number', context.issue.number.toString());
# Fallback: Trigger @copilot after Qodo review (if Coderabbit doesn't fire)
copilot-after-qodo:
if: |
github.event_name == 'pull_request_review' &&
github.event.review.user.login == 'qodo-code-review[bot]'
runs-on: ubuntu-latest
permissions:
pull-requests: write
outputs:
pr_number: ${{ steps.trigger.outputs.pr_number }}
triggered: ${{ steps.trigger.outputs.triggered }}
steps:
- name: Post Copilot review request (as user via PAT)
id: trigger
uses: actions/github-script@v7
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const comments = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo
});
const alreadyPosted = comments.data.some(c =>
c.body.includes('@copilot') &&
(c.user.login === 'MervinPraison' || c.user.login === 'github-actions[bot]')
);
if (alreadyPosted) {
console.log('Copilot already triggered, skipping');
core.setOutput('triggered', 'false');
core.setOutput('pr_number', context.issue.number.toString());
return;
}
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '@copilot Do a thorough review of this PR. Read ALL existing reviewer comments above first.\n\nReview areas:\n1. **Bloat check**: Are changes minimal and focused?\n2. **Security**: Any hardcoded secrets, unsafe eval/exec, missing input validation?\n3. **Performance**: Any module-level heavy imports? Hot-path regressions?\n4. **Tests**: Are tests included? Do they cover the changes adequately?\n5. **Backward compat**: Any public API changes without deprecation?\n6. **Code quality**: DRY violations, naming conventions, error handling?\n7. Suggest specific improvements with code examples where possible'
});
core.setOutput('triggered', 'true');
core.setOutput('pr_number', context.issue.number.toString());
# ================================================================
# FALLBACK: Claude trigger for cases where Copilot chain fails/skips
# Ensures Claude always runs after sufficient review time
# ================================================================
claude-fallback-timeout:
if: |
github.event_name == 'pull_request' &&
github.event.action == 'opened'
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
issues: write
pull-requests: write
steps:
- name: Wait for review window (15 min)
run: sleep 900
- name: Check if Claude already triggered
id: check_claude
uses: actions/github-script@v7
env:
TRIGGER_LOGINS: ${{ env.CLAUDE_TRIGGER_LOGINS }}
PR_NUMBER: ${{ github.event.pull_request.number }}
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const pr = parseInt(process.env.PR_NUMBER, 10);
const triggerLogins = JSON.parse(process.env.TRIGGER_LOGINS);
const comments = await github.rest.issues.listComments({
issue_number: pr,
owner: context.repo.owner,
repo: context.repo.repo
});
const alreadyPosted = comments.data.some(c =>
c.body.includes('@claude') && triggerLogins.includes(c.user.login)
);
core.setOutput('already_triggered', alreadyPosted ? 'true' : 'false');
core.setOutput('comments_count', comments.data.length.toString());
const botReviews = comments.data.filter(c =>
['coderabbitai[bot]', 'qodo-code-review[bot]', 'gemini-code-assist[bot]',
'copilot-swe-agent', 'Copilot', 'greptile-apps[bot]'].some(bot =>
c.user.login.toLowerCase().includes(bot.toLowerCase())
)
);
core.setOutput('review_count', botReviews.length.toString());
- name: Aggregate reviews and trigger Claude
if: steps.check_claude.outputs.already_triggered != 'true'
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const pr = parseInt(process.env.PR_NUMBER, 10);
const comments = await github.rest.issues.listComments({issue_number: pr, owner: context.repo.owner, repo: context.repo.repo, per_page: 100});
const reviews = {coderabbit: [], qodo: [], gemini: [], copilot: [], greptile: [], others: []};
comments.data.forEach(c => {
const login = c.user.login.toLowerCase();
const body = c.body.substring(0, 500);
if (login.includes('coderabbit')) reviews.coderabbit.push(body);
else if (login.includes('qodo')) reviews.qodo.push(body);
else if (login.includes('gemini')) reviews.gemini.push(body);
else if (login.includes('copilot')) reviews.copilot.push(body);
else if (login.includes('greptile')) reviews.greptile.push(body);
else if (c.user.type === 'Bot') reviews.others.push(body);
});
const summaryParts = [];
if (reviews.coderabbit.length) summaryParts.push('CodeRabbit: ' + reviews.coderabbit.length + ' comments');
if (reviews.qodo.length) summaryParts.push('Qodo: ' + reviews.qodo.length + ' comments');
if (reviews.gemini.length) summaryParts.push('Gemini: ' + reviews.gemini.length + ' comments');
if (reviews.copilot.length) summaryParts.push('Copilot: ' + reviews.copilot.length + ' comments');
if (reviews.greptile.length) summaryParts.push('Greptile: ' + reviews.greptile.length + ' comments');
const reviewSummary = summaryParts.length ? summaryParts.join(' | ') : 'No bot reviews detected';
const scope = process.env.CLAUDE_UI_SCOPE;
const phases = process.env.CLAUDE_FINAL_PHASES_COMPACT;
const claudeBody = '@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAIUI (not a fork), you are able to make modifications to this branch and push directly. ' + scope + ' Read ALL prior reviewer comments. ' + reviewSummary + '.\n\n' +
'Review Context: ' + comments.data.length + ' total comments, ' +
(reviews.coderabbit.length + reviews.qodo.length + reviews.gemini.length + reviews.copilot.length + reviews.greptile.length) + ' bot reviews.\n\n' +
phases;
await github.rest.issues.createComment({issue_number: pr, owner: context.repo.owner, repo: context.repo.repo, body: claudeBody});
console.log('Claude fallback triggered on PR #' + pr + ' with ' + reviewSummary);
# ================================================================
# Claude FINAL review — polls for Copilot's response, then triggers
# This runs IN-BAND under the PAT context (MervinPraison), avoiding
# the action_required approval gate that blocks bot-triggered workflows.
# ================================================================
claude-after-copilot:
needs: [copilot-after-coderabbit]
if: |
always() &&
needs.copilot-after-coderabbit.result == 'success' &&
needs.copilot-after-coderabbit.outputs.triggered == 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Wait for Copilot to respond (poll)
id: poll
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.copilot-after-coderabbit.outputs.pr_number }}
MAX_POLL_ATTEMPTS: ${{ env.MAX_POLL_ATTEMPTS }}
POLL_DELAY_MS: ${{ env.POLL_DELAY_MS }}
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const pr = parseInt(process.env.PR_NUMBER, 10);
const owner = context.repo.owner;
const repo = context.repo.repo;
// Poll for Copilot's response — check every 30s for up to 10 minutes
const maxAttempts = parseInt(process.env.MAX_POLL_ATTEMPTS, 10);
const delayMs = parseInt(process.env.POLL_DELAY_MS, 10);
for (let i = 0; i < maxAttempts; i++) {
console.log(`Poll attempt ${i + 1}/${maxAttempts}...`);
const comments = await github.rest.issues.listComments({
issue_number: pr,
owner,
repo,
per_page: 50,
sort: 'created',
direction: 'desc'
});
// Look for Copilot's response (copilot-swe-agent or Copilot)
const copilotResponse = comments.data.find(c =>
(c.user.login === 'copilot-swe-agent' ||
c.user.login === 'Copilot' ||
c.user.login.toLowerCase().includes('copilot')) &&
c.user.type === 'Bot'
);
if (copilotResponse) {
console.log(`Copilot responded at ${copilotResponse.created_at}`);
core.setOutput('copilot_responded', 'true');
return;
}
// Also check PR reviews for Copilot
const reviews = await github.rest.pulls.listReviews({
pull_number: pr,
owner,
repo
});
const copilotReview = reviews.data.find(r =>
r.user.login.toLowerCase().includes('copilot')
);
if (copilotReview) {
console.log(`Copilot review submitted at ${copilotReview.submitted_at}`);
core.setOutput('copilot_responded', 'true');
return;
}
if (i < maxAttempts - 1) {
console.log(`Copilot hasn't responded yet, waiting ${delayMs/1000}s...`);
await new Promise(resolve => setTimeout(resolve, delayMs));
}
}
console.log('Copilot did not respond within timeout, triggering Claude anyway');
core.setOutput('copilot_responded', 'timeout');
- name: Check if Claude already triggered
id: check_claude
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.copilot-after-coderabbit.outputs.pr_number }}
TRIGGER_LOGINS: ${{ env.CLAUDE_TRIGGER_LOGINS }}
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const pr = parseInt(process.env.PR_NUMBER, 10);
const triggerLogins = JSON.parse(process.env.TRIGGER_LOGINS);
const comments = await github.rest.issues.listComments({
issue_number: pr,
owner: context.repo.owner,
repo: context.repo.repo
});
const alreadyPosted = comments.data.some(c =>
c.body.includes('@claude') && triggerLogins.includes(c.user.login)
);
core.setOutput('already_triggered', alreadyPosted ? 'true' : 'false');
- name: Trigger Claude final review
if: steps.check_claude.outputs.already_triggered != 'true'
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.copilot-after-coderabbit.outputs.pr_number }}
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const pr = parseInt(process.env.PR_NUMBER, 10);
const scope = process.env.CLAUDE_UI_SCOPE;
const phases = process.env.CLAUDE_FINAL_PHASES_DETAILED;
await github.rest.issues.createComment({
issue_number: pr,
owner: context.repo.owner,
repo: context.repo.repo,
body: '@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAIUI (not a fork), you are able to make modifications to this branch and push directly. ' + scope + ' Read ALL comments above from Gemini, Qodo, CodeRabbit, and Copilot carefully before responding.\n\n' + phases
});
console.log(`Claude triggered on PR #${pr}`);
- name: Sync pipeline status labels
if: steps.check_claude.outputs.already_triggered != 'true'
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.copilot-after-coderabbit.outputs.pr_number }}
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const path = require('path');
const ps = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/pipeline-status.js'));
const pr = parseInt(process.env.PR_NUMBER, 10);
await ps.ensurePipelineLabels(github, context.repo.owner, context.repo.repo, core);
await ps.syncPipelineLabels(github, context.repo.owner, context.repo.repo, pr, core);
# ================================================================
# Claude after Qodo fallback path (same polling approach)
# ================================================================
claude-after-copilot-qodo:
needs: [copilot-after-qodo]
if: |
always() &&
needs.copilot-after-qodo.result == 'success' &&
needs.copilot-after-qodo.outputs.triggered == 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
issues: write
pull-requests: write
steps:
- name: Wait for Copilot to respond (poll)
id: poll
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.copilot-after-qodo.outputs.pr_number }}
MAX_POLL_ATTEMPTS: ${{ env.MAX_POLL_ATTEMPTS }}
POLL_DELAY_MS: ${{ env.POLL_DELAY_MS }}
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const pr = parseInt(process.env.PR_NUMBER, 10);
const owner = context.repo.owner;
const repo = context.repo.repo;
const maxAttempts = parseInt(process.env.MAX_POLL_ATTEMPTS, 10);
const delayMs = parseInt(process.env.POLL_DELAY_MS, 10);
for (let i = 0; i < maxAttempts; i++) {
console.log(`Poll attempt ${i + 1}/${maxAttempts}...`);
const comments = await github.rest.issues.listComments({
issue_number: pr, owner, repo,
per_page: 50, sort: 'created', direction: 'desc'
});
const copilotResponse = comments.data.find(c =>
(c.user.login === 'copilot-swe-agent' ||
c.user.login === 'Copilot' ||
c.user.login.toLowerCase().includes('copilot')) &&
c.user.type === 'Bot'
);
if (copilotResponse) {
console.log(`Copilot responded at ${copilotResponse.created_at}`);
core.setOutput('copilot_responded', 'true');
return;
}
const reviews = await github.rest.pulls.listReviews({
pull_number: pr, owner, repo
});
const copilotReview = reviews.data.find(r =>
r.user.login.toLowerCase().includes('copilot')
);
if (copilotReview) {
console.log(`Copilot review submitted at ${copilotReview.submitted_at}`);
core.setOutput('copilot_responded', 'true');
return;
}
if (i < maxAttempts - 1) {
await new Promise(resolve => setTimeout(resolve, delayMs));
}
}
console.log('Copilot did not respond within timeout, triggering Claude anyway');
core.setOutput('copilot_responded', 'timeout');
- name: Check if Claude already triggered
id: check_claude
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.copilot-after-qodo.outputs.pr_number }}
TRIGGER_LOGINS: ${{ env.CLAUDE_TRIGGER_LOGINS }}
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const pr = parseInt(process.env.PR_NUMBER, 10);
const triggerLogins = JSON.parse(process.env.TRIGGER_LOGINS);
const comments = await github.rest.issues.listComments({
issue_number: pr,
owner: context.repo.owner,
repo: context.repo.repo
});
const alreadyPosted = comments.data.some(c =>
c.body.includes('@claude') && triggerLogins.includes(c.user.login)
);
core.setOutput('already_triggered', alreadyPosted ? 'true' : 'false');
- name: Trigger Claude final review
if: steps.check_claude.outputs.already_triggered != 'true'
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ needs.copilot-after-qodo.outputs.pr_number }}
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const pr = parseInt(process.env.PR_NUMBER, 10);
const scope = process.env.CLAUDE_UI_SCOPE;
const phases = process.env.CLAUDE_FINAL_PHASES_DETAILED;
await github.rest.issues.createComment({
issue_number: pr,
owner: context.repo.owner,
repo: context.repo.repo,
body: '@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAIUI (not a fork), you are able to make modifications to this branch and push directly. ' + scope + ' Read ALL comments above from Gemini, Qodo, CodeRabbit, and Copilot carefully before responding.\n\n' + phases
});
console.log(`Claude triggered on PR #${pr}`);
# ================================================================
# Claude after Gemini — restores the trigger lost from the deleted
# chain-claude-after-copilot.yml workflow.
# Fires when Gemini posts a review comment on a PR or issue.
# ================================================================
claude-after-gemini:
if: |
github.event_name == 'issue_comment' &&
(
github.event.comment.user.login == 'gemini-code-assist[bot]' ||
contains(github.event.comment.body, 'Review completed by Gemini CLI') ||
contains(github.event.comment.body, 'The fix is ready for review. Please test')
)
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- name: Check if Claude already triggered
id: check_claude
uses: actions/github-script@v7
env:
TRIGGER_LOGINS: ${{ env.CLAUDE_TRIGGER_LOGINS }}
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const triggerLogins = JSON.parse(process.env.TRIGGER_LOGINS);
const comments = await github.rest.issues.listComments({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo
});
const alreadyPosted = comments.data.some(c =>
c.body.includes('@claude') && triggerLogins.includes(c.user.login)
);
core.setOutput('already_triggered', alreadyPosted ? 'true' : 'false');
- name: Post Claude analysis request (Lead Engineer)
if: steps.check_claude.outputs.already_triggered != 'true'
uses: actions/github-script@v7
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const scope = process.env.CLAUDE_UI_SCOPE;
const phases = process.env.CLAUDE_FINAL_PHASES_DETAILED;
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '@claude You are the Lead Engineer. If the branch is under MervinPraison/PraisonAIUI (not a fork), you are able to make modifications to this branch and push directly. ' + scope + ' Read ALL analysis and reviews above carefully (Gemini, CodeRabbit, Qodo, Copilot, etc).\n\n' + phases
});
# ================================================================
# Recovery: re-post FINAL @claude after push or when chain missed
# ================================================================
claude-review-recovery:
if: |
github.event_name == 'pull_request_target' &&
github.event.action == 'synchronize'
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: read
steps:
- uses: actions/checkout@v4
- name: Re-post FINAL Claude review when stale or missing
uses: actions/github-script@v7
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const path = require('path');
const mergeGate = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/merge-gate.js'));
const chain = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/pr-review-chain.js'));
const pr = context.payload.pull_request.number;
const owner = context.repo.owner;
const repo = context.repo.repo;
const comments = await mergeGate.listAllComments(github, owner, repo, pr);
const headPushedAt = (await mergeGate.getHeadCommitDate(github, owner, repo, pr))
|| context.payload.pull_request.updated_at;
const headPusher = context.payload.sender?.login || null;
const hasFinal = mergeGate.hasFinalClaudeReviewTrigger(comments);
const isStale = mergeGate.isStaleFinalAfterPush(comments, headPushedAt);
if (mergeGate.shouldSkipFinalRecovery(comments, headPushedAt)) {
core.info('Recent @claude within 35min and FINAL not stale — skip recovery');
return;
}
if (await mergeGate.hasInProgressClaudeAssistant(github, owner, repo, pr)) {
core.info('Claude workflow in progress — skip recovery');
return;
}
const finalBody = mergeGate.FINAL_CLAUDE_REVIEW_BODY;
const staleOpts = { allowStaleRepost: true, skipCopilot: true, optionalWaitMs: 0 };
const missingOpts = { allowCopilotTimeout: true, optionalWaitMs: 0 };
if (hasFinal && isStale) {
const gate = mergeGate.shouldSkipStaleFinalRecovery(comments, headPushedAt, headPusher);
if (gate.skip) {
core.info(`Skip stale-FINAL recovery: ${gate.reason}`);
return;
}
const result = await chain.maybeTriggerClaudeFinal(
github, owner, repo, pr, finalBody, core, staleOpts
);
if (result.posted) core.info(`Posted stale-FINAL recovery @claude on PR #${pr}`);
return;
}
if (hasFinal) {
core.info('FINAL Claude review current on HEAD — skip recovery');
return;
}
const result = await chain.maybeTriggerClaudeFinal(
github, owner, repo, pr, finalBody, core, missingOpts
);
if (result.posted) core.info(`Posted missing FINAL Claude review on PR #${pr}`);
- name: Sync pipeline status labels
uses: actions/github-script@v7
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const path = require('path');
const ps = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/pipeline-status.js'));
const pr = context.payload.pull_request.number;
await ps.ensurePipelineLabels(github, context.repo.owner, context.repo.repo, core);
await ps.syncPipelineLabels(github, context.repo.owner, context.repo.repo, pr, core);
# Scheduled + manual: post missing or stale FINAL @claude on all open PRs
post-missing-claude-final:
if: |
github.event_name == 'schedule' ||
(github.event_name == 'workflow_dispatch' && !inputs.pr_number)
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: read
steps:
- uses: actions/checkout@v4
- name: Post missing/stale FINAL @claude on open PRs
uses: actions/github-script@v7
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const path = require('path');
const mergeGate = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/merge-gate.js'));
const chain = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/pr-review-chain.js'));
const ps = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/pipeline-status.js'));
const owner = context.repo.owner;
const repo = context.repo.repo;
const prs = await github.paginate(github.rest.pulls.list, {
owner, repo, state: 'open', per_page: 100,
});
let posted = 0;
for (const pr of prs) {
if (pr.draft) continue;
const comments = await mergeGate.listAllComments(github, owner, repo, pr.number);
const headPushedAt = (await mergeGate.getHeadCommitDate(github, owner, repo, pr.number)) || pr.updated_at;
const hasFinal = mergeGate.hasFinalClaudeReviewTrigger(comments);
const isStale = mergeGate.isStaleFinalAfterPush(comments, headPushedAt);
if (hasFinal && !isStale) continue;
if (mergeGate.hasRecentClaudeTrigger(comments, 10)) {
core.info(`PR #${pr.number}: @claude within 10min — skip`);
continue;
}
if (await mergeGate.hasInProgressClaudeAssistant(github, owner, repo, pr.number)) {
core.info(`PR #${pr.number}: Claude in progress — skip`);
continue;
}
if (hasFinal && isStale) {
const gate = mergeGate.shouldSkipStaleFinalRecovery(comments, headPushedAt);
if (gate.skip) {
core.info(`PR #${pr.number}: skip stale — ${gate.reason}`);
continue;
}
}
const opts = hasFinal && isStale
? { allowStaleRepost: true, skipCopilot: true, optionalWaitMs: 0 }
: { allowCopilotTimeout: true, optionalWaitMs: 0 };
const result = await chain.maybeTriggerClaudeFinal(
github, owner, repo, pr.number,
mergeGate.FINAL_CLAUDE_REVIEW_BODY, core, opts
);
if (result.posted) {
posted++;
core.info(`Posted Claude FINAL on PR #${pr.number}`);
}
await ps.syncPipelineLabels(github, owner, repo, pr.number, core);
if (posted >= 10) break;
}
core.info(`Missing/stale Claude FINAL sweep complete (${posted} posted)`);
# ================================================================
# BOT PRs: CodeRabbit → Claude directly (skip Copilot when no user PAT)
# Copilot ignores github-actions[bot] comments; bot PRs use this path.
# ================================================================
claude-after-coderabbit-bot-pr:
if: |
github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
github.event.comment.user.login == 'coderabbitai[bot]' &&
contains(github.event.comment.body, 'summarize by coderabbit')
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: read
steps:
- name: Trigger Claude final review on bot PR
uses: actions/github-script@v7
env:
TRIGGER_LOGINS: ${{ env.CLAUDE_TRIGGER_LOGINS }}
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const pr = context.issue.number;
const { data: pull } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr,
});
const author = pull.user.login;
const isBot = author === 'github-actions[bot]' ||
author === 'praisonai-triage-agent[bot]' ||
pull.user.type === 'Bot';
if (!isBot) {
console.log('Human PR — Copilot chain handles Claude trigger');
return;
}
const triggerLogins = JSON.parse(process.env.TRIGGER_LOGINS);
const comments = await github.rest.issues.listComments({
issue_number: pr,
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100,
});
const alreadyPosted = comments.data.some(c =>
c.body.includes('@claude') && triggerLogins.includes(c.user.login)
);
if (alreadyPosted) {
console.log('Claude already triggered on PR #' + pr);
return;
}
await github.rest.issues.createComment({
issue_number: pr,
owner: context.repo.owner,
repo: context.repo.repo,
body: '@claude You are the FINAL architecture reviewer on this bot-authored PR. Push fixes directly to THIS branch (do NOT open a new PR). ' + process.env.CLAUDE_UI_SCOPE + ' Read ALL CodeRabbit/Qodo comments above.\n\n' + process.env.CLAUDE_FINAL_PHASES_COMPACT
});
console.log('Claude final review triggered on bot PR #' + pr);
# ================================================================
# Manual: trigger Claude final review on any PR
# ================================================================
claude-manual-dispatch:
if: github.event_name == 'workflow_dispatch' && inputs.pr_number
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Trigger Claude final review
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ inputs.pr_number }}
TRIGGER_LOGINS: ${{ env.CLAUDE_TRIGGER_LOGINS }}
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const pr = parseInt(process.env.PR_NUMBER, 10);
const triggerLogins = JSON.parse(process.env.TRIGGER_LOGINS);
const comments = await github.rest.issues.listComments({
issue_number: pr,
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100,
});
const alreadyPosted = comments.data.some(c =>
c.body.includes('@claude') && triggerLogins.includes(c.user.login)
);
if (alreadyPosted) {
console.log('Claude already triggered on PR #' + pr);
return;
}
await github.rest.issues.createComment({
issue_number: pr,
owner: context.repo.owner,
repo: context.repo.repo,
body: '@claude You are the FINAL architecture reviewer. If the branch is under MervinPraison/PraisonAIUI (not a fork), you are able to make modifications to this branch and push directly. ' + process.env.CLAUDE_UI_SCOPE + ' Read all prior reviewer comments.\n\n' + process.env.CLAUDE_FINAL_PHASES_COMPACT
});
console.log('Claude manually triggered on PR #' + pr);
# ================================================================
# BOT PRs: kick CodeRabbit + Qodo
# ================================================================
bot-pr-trigger-reviews:
if: |
github.event_name == 'pull_request' &&
github.event.action == 'opened' &&
(
github.event.pull_request.user.login == 'github-actions[bot]' ||
github.event.pull_request.user.login == 'praisonai-triage-agent[bot]' ||
github.event.pull_request.user.type == 'Bot'
)
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Trigger CodeRabbit and Qodo reviews
uses: actions/github-script@v7
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const path = require('path');
const chain = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/bot-pr-review-chain.js'));
const pr = context.payload.pull_request.number;
await chain.kickReviewChain(github, context.repo.owner, context.repo.repo, pr, core);
- name: Sync pipeline status labels
uses: actions/github-script@v7
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const path = require('path');
const ps = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/pipeline-status.js'));
const pr = context.payload.pull_request.number;
await ps.ensurePipelineLabels(github, context.repo.owner, context.repo.repo, core);
await ps.syncPipelineLabels(github, context.repo.owner, context.repo.repo, pr, core);
-102
View File
@@ -1,102 +0,0 @@
name: Auto CI Failure → Claude
# Detects internal PRs with failing CI and posts @claude with extracted failure details.
on:
workflow_run:
workflows: [CI]
types: [completed]
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
inputs:
pr_number:
description: 'Optional PR number to process (default: scan blocked PRs)'
required: false
type: string
schedule:
- cron: '15 */6 * * *'
concurrency:
group: ci-failure-scan-${{ github.repository }}-${{ github.event.pull_request.number || github.event.workflow_run.id || github.run_id }}
cancel-in-progress: true
env:
# PAT posts as MervinPraison so issue_comment triggers claude.yml (GITHUB_TOKEN cannot chain workflows)
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
permissions:
pull-requests: read
issues: write
actions: read
jobs:
detect-and-trigger:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Detect CI failures and trigger Claude
uses: actions/github-script@v7
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const path = require('path');
const ciFix = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/ci-failure-claude.js'));
const owner = context.repo.owner;
const repo = context.repo.repo;
const baseRepo = `${owner}/${repo}`;
async function processPR(prNumber) {
return ciFix.maybeTriggerCiFixClaude(github, owner, repo, prNumber, core);
}
let results = [];
if (context.eventName === 'workflow_run') {
const wr = context.payload.workflow_run;
const result = await ciFix.processWorkflowRunFailure(
github, owner, repo, wr, core
);
results.push({ event: 'workflow_run', workflow: wr.name, ...result });
} else if (context.eventName === 'pull_request') {
results.push({
pr: context.payload.pull_request.number,
...(await processPR(context.payload.pull_request.number)),
});
} else {
let prNumbers = [];
if (context.eventName === 'workflow_dispatch' && context.payload.inputs?.pr_number) {
prNumbers = [Number(context.payload.inputs.pr_number)];
} else {
const prs = await github.paginate(github.rest.pulls.list, {
owner,
repo,
state: 'open',
per_page: 100,
});
for (const pr of prs) {
if (pr.draft) continue;
const headRepo = pr.head?.repo?.full_name;
if (headRepo && headRepo !== baseRepo) continue;
const { data: issue } = await github.rest.issues.get({
owner,
repo,
issue_number: pr.number,
});
const labels = issue.labels.map((l) => l.name);
if (labels.includes('pipeline/blocked:ci') || labels.includes(ciFix.CI_FIX_LABEL)) {
prNumbers.push(pr.number);
}
}
}
for (const num of prNumbers) {
results.push({ pr: num, ...(await processPR(num)) });
}
}
core.summary.addRaw('```json\n' + JSON.stringify(results, null, 2) + '\n```');
await core.summary.write();
-67
View File
@@ -1,67 +0,0 @@
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
python:
name: python
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: pip install -e .[dev]
- name: Lint with ruff
run: ruff check src/praisonaiui
- name: Test with pytest
# Unit tests are the primary CI contract; integration smoke validates backends.
run: pytest tests/unit -v --no-cov --timeout=60
- name: Integration smoke tests
run: pytest tests/integration/test_agentic_roundtrip.py tests/test_feature_sdk_backends.py -q --no-cov --timeout=120
docs:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
permissions:
contents: write
pages: write
id-token: write
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install AIUI
run: pip install -e .
- name: Build docs with AIUI
run: |
aiui build --output site --minify
cp CNAME site/CNAME
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./site
-538
View File
@@ -1,538 +0,0 @@
name: Claude PR Merge Gate
# Read-only Claude assesses merge readiness; GH_TOKEN merges (no @claude, no gh pr review).
# Does not overlap with merge-conflict-claude.yml or auto-pr-comment @claude chains.
on:
schedule:
# Scan for merge-ready PRs every 10 minutes (assess runs only when candidates exist).
- cron: '*/10 * * * *'
workflow_dispatch:
inputs:
pr_number:
description: 'Optional PR number (scan all open internal PRs if empty)'
required: false
type: string
merge_method:
description: 'Merge method'
required: false
type: choice
default: merge
options:
- merge
- squash
- rebase
workflow_run:
workflows:
- Claude Assistant
- CI
types:
- completed
repository_dispatch:
types:
- claude-merge-gate
concurrency:
group: claude-merge-gate-${{ github.repository }}-${{ github.event.inputs.pr_number || github.event.client_payload.pr_number || github.event.workflow_run.id || 'scan' }}
cancel-in-progress: false
env:
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
MAX_CANDIDATES: 3
DISPATCH_PR_NUMBER: ${{ github.event.inputs.pr_number || github.event.client_payload.pr_number || '' }}
permissions:
contents: read
pull-requests: read
issues: read
actions: read
jobs:
auto-dispatch:
if: github.event_name == 'workflow_run'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
actions: write
id-token: write
steps:
- uses: actions/checkout@v4
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Dispatch merge gate when PR pipeline is ready
uses: actions/github-script@v7
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
const path = require('path');
const mergeGate = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/merge-gate.js'));
const wr = context.payload.workflow_run;
const owner = context.repo.owner;
const repo = context.repo.repo;
if (wr.conclusion !== 'success') {
core.info(`Skip dispatch: ${wr.name} conclusion=${wr.conclusion}`);
return;
}
const allowed = ['Claude Assistant', 'CI'];
if (!allowed.includes(wr.name)) {
core.info(`Skip dispatch: workflow ${wr.name}`);
return;
}
const prNumber = await mergeGate.resolvePrNumberFromWorkflowRun(github, owner, repo, wr);
if (!prNumber) {
core.info('Skip dispatch: could not resolve PR from workflow run');
return;
}
const fromClaude = wr.name === 'Claude Assistant';
const check = await mergeGate.evaluatePipelineQuiescent(
github, owner, repo, prNumber, core, {
skipGlobalClaudeRunCheck: fromClaude,
skipRecentClaudeCooldown: fromClaude,
}
);
if (!check.ready) {
core.info(`PR #${prNumber} not ready: ${check.reasons.join(', ')}`);
return;
}
await github.rest.repos.createDispatchEvent({
owner,
repo,
event_type: 'claude-merge-gate',
client_payload: { pr_number: prNumber },
});
core.info(`Dispatched merge gate for PR #${prNumber} after ${wr.name}`);
scan-candidates:
if: github.event_name != 'workflow_run'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: write
actions: read
id-token: write
outputs:
matrix: ${{ steps.scan.outputs.matrix }}
has_candidates: ${{ steps.scan.outputs.has_candidates }}
steps:
- uses: actions/checkout@v4
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Scan open PRs for merge gate eligibility
id: scan
uses: actions/github-script@v7
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
const path = require('path');
const mergeGate = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/merge-gate.js'));
const ps = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/pipeline-status.js'));
const owner = context.repo.owner;
const repo = context.repo.repo;
const maxCandidates = parseInt(process.env.MAX_CANDIDATES || '5', 10);
const inputPr = String(process.env.DISPATCH_PR_NUMBER || '').trim();
const candidates = [];
const skipped = [];
if (inputPr) {
const n = parseInt(inputPr, 10);
if (Number.isNaN(n)) {
throw new Error(`Invalid pr_number input: ${inputPr}`);
}
const result = await mergeGate.evaluatePipelineQuiescent(github, owner, repo, n, core);
if (result.ready) {
candidates.push({ pr_number: n, head_sha: result.headSha });
} else {
skipped.push({ pr: n, reasons: result.reasons });
}
} else {
const prNumbers = await mergeGate.listPrNumbersForMergeGateScan(
github, owner, repo, core
);
const selected = await mergeGate.selectMergeGateCandidates(
github, owner, repo, prNumbers, maxCandidates, core
);
candidates.push(...selected.candidates);
skipped.push(...selected.skipped);
}
core.info('Skipped: ' + JSON.stringify(skipped));
core.setOutput('matrix', JSON.stringify({ include: candidates }));
core.setOutput('has_candidates', candidates.length > 0 ? 'true' : 'false');
core.summary.addRaw('## Merge gate scan\n');
core.summary.addRaw(`Candidates: ${candidates.length}\n`);
core.summary.addRaw('```json\n' + JSON.stringify({ candidates, skipped }, null, 2) + '\n```');
await core.summary.write();
if (inputPr && skipped.length === 1 && skipped[0].pr === parseInt(inputPr, 10)) {
const reasons = skipped[0].reasons;
const body = [
'**Merge gate scan** — not eligible for auto-merge.',
'',
...reasons.map((r) => `- \`${r}\``),
'',
'**Actions:** wait for CI and the Claude review chain, or add label `needs-manual-review` and merge manually.',
'**Opt out:** label `no-auto-merge`.',
].join('\n');
await github.rest.issues.createComment({
owner, repo, issue_number: skipped[0].pr, body,
});
} else if (inputPr && candidates.length === 1) {
await github.rest.issues.createComment({
owner, repo, issue_number: candidates[0].pr_number,
body: '**Merge gate scan** — eligible for assessment. Claude merge gate will assess and may auto-merge if `MERGE_GATE_VERDICT: APPROVE`.',
});
}
await ps.syncOpenPullRequests(github, owner, repo, { maxPrs: 10 }, core);
claude-assess:
needs: scan-candidates
if: needs.scan-candidates.outputs.has_candidates == 'true'
runs-on: ubuntu-latest
timeout-minutes: 20
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.scan-candidates.outputs.matrix) }}
permissions:
contents: read
pull-requests: read
issues: write
actions: read
id-token: write
steps:
- name: Generate GitHub App Token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ steps.app-token.outputs.token }}
- name: Mark merge gate active
id: mark_active
uses: actions/github-script@v7
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
core.setOutput('started_at', new Date().toISOString());
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: ${{ matrix.pr_number }},
labels: ['claude-merge-gate-active'],
});
- name: Stash merge gate helpers
run: |
# Keep scripts together so require('./gate-config.js') works from /tmp
mkdir -p /tmp/merge-gate-scripts /tmp/gh-actions
cp .github/scripts/merge-gate.js .github/scripts/gate-config.js /tmp/merge-gate-scripts/
cp -R .github/actions/claude-code-action /tmp/gh-actions/
- name: Fetch PR branch
env:
PR_NUMBER: ${{ matrix.pr_number }}
run: |
git fetch origin "pull/${PR_NUMBER}/head:pr-${PR_NUMBER}"
git checkout "pr-${PR_NUMBER}"
mkdir -p .github/actions
rm -rf .github/actions/claude-code-action
cp -R /tmp/gh-actions/claude-code-action .github/actions/
- name: Claude merge gate assessment (read-only)
id: assess
uses: ./.github/actions/claude-code-action
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
CLAUDE_CODE_SUBAGENT_MODEL: inherit
ANTHROPIC_DEFAULT_SONNET_MODEL: claude-sonnet-4-6
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github_token: ${{ steps.app-token.outputs.token }}
model: claude-opus-4-8
trigger_phrase: '@claude-merge-gate-internal'
direct_prompt: |
You are the MERGE GATE reviewer for PraisonAI PR #${{ matrix.pr_number }}.
READ-ONLY: do not modify code, commit, push, rebase, or create branches.
CRITICAL OUTPUT RULE:
Post exactly one PR comment via GitHub MCP containing either:
MERGE_GATE_VERDICT: APPROVE
or
MERGE_GATE_VERDICT: BLOCK
followed by a short rationale on the next lines.
NEVER include @claude in any comment. NEVER mention merge conflict resolution.
Review checklist:
1. Read AGENTS.md and the PR diff on the current branch.
2. Read all PR comments and reviews (FINAL architecture reviewer / Lead Engineer must have run).
3. Confirm SDK value gate: change strengthens praisonaiagents (no scope creep).
4. Do not bloat the Agent class with additional params — only if absolutely required; we already support many params.
5. If agent.py adds >100 lines or new Agent __init__ params, respond MERGE_GATE_VERDICT: BLOCK (manual review required).
6. BLOCK if labels security/breaking-change/needs-manual-review/release, sensitive paths (.github/workflows, auth, pyproject.toml), secrets in diff, PR >800 lines or >30 files, or SDK changes without tests. Label `merge-gate-ci-only` exempts CI-only changes under `.github/workflows/`, `.github/actions/`, or merge-gate scripts.
7. Confirm no CHANGES_REQUESTED reviews and CI green on HEAD ${{ matrix.head_sha }}.
8. If ready to merge: MERGE_GATE_VERDICT: APPROVE. Otherwise: MERGE_GATE_VERDICT: BLOCK with reasons.
Do not approve or merge via GitHub UI/API — only post the verdict comment.
disallowed_tools: |
Bash
Edit
Write
Replace
allowed_tools: |
View
GlobTool
GrepTool
Read
timeout_minutes: 15
- name: Post fallback BLOCK if Opus did not comment
id: fallback_verdict
if: steps.assess.outcome != 'success'
uses: actions/github-script@v7
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
const mergeGate = require('/tmp/merge-gate-scripts/merge-gate.js');
const owner = context.repo.owner;
const repo = context.repo.repo;
const prNumber = ${{ matrix.pr_number }};
const ctx = await mergeGate.loadPrContext(github, owner, repo, prNumber);
const minCreatedAt = new Date(Date.now() - 25 * 60 * 1000).toISOString();
const existing = mergeGate.findMergeGateVerdict(
ctx.comments, minCreatedAt, ctx.headPushedAt, { excludeAutomatedFallback: true }
);
if (existing) {
core.info(`Opus verdict already posted: ${existing}`);
return;
}
const check = await mergeGate.evaluatePipelineQuiescent(
github, owner, repo, prNumber, core, { forMergeStep: true }
);
const lines = [
'MERGE_GATE_VERDICT: BLOCK',
'',
'Automated fallback — Opus merge gate assessment did not complete.',
];
if (check.ready) {
lines.push('Deterministic gates passed, but Opus MERGE_GATE_VERDICT is required before merge.');
} else {
lines.push('Blockers:', ...check.reasons.map((r) => `- ${r}`));
}
await github.rest.issues.createComment({
owner, repo, issue_number: prNumber,
body: lines.join('\n'),
});
core.info('Posted fallback BLOCK — Opus verdict required');
- name: Require Opus MERGE_GATE_VERDICT
uses: actions/github-script@v7
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
const mergeGate = require('/tmp/merge-gate-scripts/merge-gate.js');
const comments = await mergeGate.listAllComments(
github, context.repo.owner, context.repo.repo, ${{ matrix.pr_number }}
);
const ctx = await mergeGate.loadPrContext(
github, context.repo.owner, context.repo.repo, ${{ matrix.pr_number }}
);
const minCreatedAt = new Date(Date.now() - 25 * 60 * 1000).toISOString();
const verdict = mergeGate.findMergeGateVerdict(
comments, minCreatedAt, ctx.headPushedAt, { excludeAutomatedFallback: true }
);
if (!verdict) {
core.setFailed(
'Opus merge gate assessment must post MERGE_GATE_VERDICT on this PR (automated fallback APPROVE is not accepted).'
);
return;
}
core.info(`Opus merge gate verdict: ${verdict}`);
core.setOutput('verdict', verdict);
- name: Remove merge gate active label
if: always()
uses: actions/github-script@v7
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
const prNumber = ${{ matrix.pr_number }};
try {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
name: 'claude-merge-gate-active',
});
core.info(`Removed claude-merge-gate-active from PR #${prNumber}`);
} catch (e) {
core.info(`Label claude-merge-gate-active already removed or missing on PR #${prNumber}`);
}
- name: Fail job if assessment failed
if: steps.assess.outcome == 'failure'
run: exit 1
merge-only:
needs: [scan-candidates, claude-assess]
if: |
always() &&
needs.scan-candidates.outputs.has_candidates == 'true' &&
needs.claude-assess.result == 'success'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.scan-candidates.outputs.matrix) }}
permissions:
contents: write
pull-requests: write
issues: write
actions: read
id-token: write
steps:
- uses: actions/checkout@v4
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Re-check gates and merge
uses: actions/github-script@v7
env:
MERGE_METHOD: ${{ github.event.inputs.merge_method || 'merge' }}
SCAN_HEAD_SHA: ${{ matrix.head_sha }}
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
const path = require('path');
const mergeGate = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/merge-gate.js'));
const owner = context.repo.owner;
const repo = context.repo.repo;
const prNumber = ${{ matrix.pr_number }};
const scanHeadSha = process.env.SCAN_HEAD_SHA;
const removeLabels = async () => {
try {
await github.rest.issues.removeLabel({
owner, repo, issue_number: prNumber, name: 'claude-merge-gate-active',
});
} catch (e) {
core.info('Label claude-merge-gate-active already removed or missing');
}
};
try {
const ctx = await mergeGate.loadPrContext(github, owner, repo, prNumber);
const comments = ctx.comments;
const verdictMin = new Date(Date.now() - 25 * 60 * 1000).toISOString();
const verdict = mergeGate.findMergeGateVerdict(
comments, verdictMin, ctx.headPushedAt, { excludeAutomatedFallback: true }
);
if (verdict !== 'APPROVE') {
core.info(`Skip merge: verdict=${verdict || 'NONE'}`);
await removeLabels();
return;
}
const check = await mergeGate.evaluatePipelineQuiescent(
github, owner, repo, prNumber, core, { forMergeStep: true }
);
if (!check.ready) {
core.info(`Skip merge: ${check.reasons.join(', ')}`);
await removeLabels();
return;
}
if (check.headSha !== scanHeadSha) {
core.info(`Skip merge: HEAD moved ${scanHeadSha.slice(0, 7)} → ${check.headSha.slice(0, 7)}`);
await removeLabels();
return;
}
const method = process.env.MERGE_METHOD || 'merge';
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
let merged = false;
for (let attempt = 1; attempt <= 3; attempt++) {
try {
await github.rest.pulls.merge({
owner, repo, pull_number: prNumber, merge_method: method,
});
merged = true;
break;
} catch (e) {
const msg = (e.message || '').toLowerCase();
if (attempt < 3 && msg.includes('base branch was modified')) {
core.info(`Merge attempt ${attempt} failed (base moved), retrying in 8s...`);
await sleep(8000);
const recheck = await mergeGate.evaluatePipelineQuiescent(
github, owner, repo, prNumber, core, { forMergeStep: true }
);
if (!recheck.ready) {
core.info(`Skip merge retry: ${recheck.reasons.join(', ')}`);
await removeLabels();
return;
}
continue;
}
throw e;
}
}
if (!merged) {
core.info('Skip merge: exhausted retries');
await removeLabels();
return;
}
await github.rest.issues.addLabels({
owner, repo, issue_number: prNumber, labels: ['auto-merged-by-gate'],
});
await github.rest.issues.createComment({
owner, repo, issue_number: prNumber,
body: [
'Merged by **Claude PR merge gate** (`claude-merge-gate.yml`).',
`Verdict: MERGE_GATE_VERDICT: APPROVE`,
`SHA: \`${check.headSha.slice(0, 7)}\``,
`Method: ${method}`,
].join('\n'),
});
core.info(`Merged PR #${prNumber}`);
} finally {
await removeLabels();
}
-543
View File
@@ -1,543 +0,0 @@
name: Claude Assistant
# Triggers:
# - issues:opened → lightweight triage (labels + auto-claude for owner)
# - issues:labeled → full implementation when `claude` label applied
# - issues:assigned → full implementation when issue assigned to Claude
# - issue_comment → full implementation when @claude mentioned (issues + PRs)
# - pull_request_review → full implementation when @claude mentioned in review
# - pull_request_review_comment → full implementation when @claude mentioned inline
#
# Escalate an issue with the `claude` label OR an @claude comment — not both.
# If both fire within 3 minutes, the comment trigger is skipped (dedupe job).
#
# Focus: CLAUDE only. Copilot and CodeRabbit are GitHub Apps that react to PRs
# automatically — no workflow file needed. auto-pr-comment.yml orchestrates the
# CodeRabbit → Copilot → Claude review chain for PRs.
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, labeled, assigned]
pull_request_review:
types: [submitted]
workflow_dispatch:
inputs:
issue_number:
description: 'Issue number for Claude implementation'
required: true
type: string
jobs:
# ================================================================
# Job 1 — Issue triage (runs on ANY new issue, including external users)
# Posts welcome comment + triage labels. Auto-adds `claude` for owner issues.
# ================================================================
issue-triage:
if: |
github.event_name == 'issues' &&
github.event.action == 'opened' &&
!contains(toJSON(github.event.issue.labels), 'claude')
runs-on: ubuntu-latest
permissions:
issues: write
contents: read
steps:
- name: Generate GitHub App Token
id: app-token
continue-on-error: true
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Resolve GitHub token
id: github-token
run: |
if [ -n "${{ steps.app-token.outputs.token }}" ]; then
echo "token=${{ steps.app-token.outputs.token }}" >> "$GITHUB_OUTPUT"
else
echo "token=${{ secrets.GITHUB_TOKEN }}" >> "$GITHUB_OUTPUT"
fi
- name: Triage and acknowledge issue
uses: actions/github-script@v7
with:
github-token: ${{ steps.github-token.outputs.token }}
script: |
const issue = context.payload.issue;
const title = (issue.title || '').toLowerCase();
const body = (issue.body || '').toLowerCase();
const content = title + ' ' + body;
const isOwner = ['OWNER', 'MEMBER', 'COLLABORATOR'].includes(
issue.author_association
);
const labels = [];
if (content.includes('feature request') || content.includes('[feature')) {
labels.push('enhancement');
} else if (content.includes('bug') || content.includes('error') || content.includes('crash') || content.includes('traceback')) {
labels.push('bug');
} else if (content.includes('question') || content.includes('how do i') || content.includes('how to')) {
labels.push('question');
}
if (content.includes('security') || content.includes('cve') || content.includes('vulnerability')) {
labels.push('security');
}
if (content.includes('performance') || content.includes('slow') || content.includes('memory leak')) {
labels.push('performance');
}
if (content.includes('documentation') || content.includes('docs')) {
labels.push('documentation');
}
if (content.includes('typescript') || content.includes('javascript') || content.includes('npm')) {
labels.push('javascript');
}
if (content.includes('frontend') || content.includes('react') || content.includes('vite')) {
labels.push('frontend');
}
if (content.includes('example') || content.includes('yaml')) {
labels.push('examples');
}
if (labels.length > 0) {
await github.rest.issues.addLabels({
issue_number: issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels
});
}
if (!isOwner) {
await github.rest.issues.createComment({
issue_number: issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: [
`👋 Thanks for opening this issue, @${issue.user.login}!`,
'',
'A maintainer will review this shortly. In the meantime:',
'- Make sure you\'ve included steps to reproduce (for bugs)',
'- Check [existing issues](https://github.com/MervinPraison/PraisonAIUI/issues) for duplicates',
'- Review [AGENTS.md](https://github.com/MervinPraison/PraisonAIUI/blob/main/AGENTS.md) for project conventions',
'',
'_A maintainer can trigger deeper analysis by commenting `@claude` on this issue._'
].join('\n')
});
}
if (isOwner) {
await github.rest.issues.addLabels({
issue_number: issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['claude']
});
}
# ================================================================
# Job 2 — Full Claude Code implementation
# Triggers on: labeled `claude`, @claude comments, assignments
#
# Dedup: label + @claude comment on the same issue fires two events.
# Skip the comment trigger when `claude` was labelled within 3 minutes.
# ================================================================
claude-dedupe:
if: |
github.event_name == 'workflow_dispatch' ||
(
github.event.action != 'opened' &&
(github.event.action != 'labeled' || github.event.label.name == 'claude') &&
(github.event_name != 'issue_comment' || contains(github.event.comment.body, '@claude')) &&
(
!contains(github.actor, '[bot]') ||
github.actor == 'github-actions[bot]' ||
github.actor == 'praisonai-triage-agent[bot]'
) &&
github.actor != 'dependabot[bot]' &&
github.actor != 'cursor[bot]' &&
github.actor != 'renovate[bot]'
)
runs-on: ubuntu-latest
outputs:
proceed: ${{ steps.check.outputs.proceed }}
permissions:
issues: read
pull-requests: read
steps:
- name: Skip duplicate comment after fresh claude label
id: check
uses: actions/github-script@v7
with:
script: |
if (context.eventName === 'workflow_dispatch') {
core.setOutput('proceed', 'true');
return;
}
if (context.eventName !== 'issue_comment' || context.payload.issue?.pull_request) {
core.setOutput('proceed', 'true');
return;
}
const issue = context.payload.issue;
const hasClaude = (issue.labels || []).some(l => l.name === 'claude');
if (!hasClaude) {
core.setOutput('proceed', 'true');
return;
}
const events = await github.rest.issues.listEvents({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
per_page: 30,
});
const windowMs = 3 * 60 * 1000;
const recentLabel = events.data.find(e =>
e.event === 'labeled' &&
e.label?.name === 'claude' &&
(Date.now() - new Date(e.created_at).getTime()) < windowMs
);
if (recentLabel) {
core.info('Skipping: claude label was added within 3 minutes — label trigger already handles this issue.');
core.setOutput('proceed', 'false');
return;
}
core.setOutput('proceed', 'true');
claude-response:
needs: claude-dedupe
env:
ISSUE_NUMBER_RESOLVED: ${{ github.event.issue.number || github.event.pull_request.number || inputs.issue_number }}
if: needs.claude-dedupe.outputs.proceed == 'true'
concurrency:
group: claude-${{ github.event.issue.number || github.event.pull_request.number || inputs.issue_number || github.run_id }}
cancel-in-progress: true
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
actions: read
id-token: write
steps:
- name: Generate GitHub App Token
id: app-token
continue-on-error: true
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Resolve GitHub token
id: github-token
run: |
if [ -n "${{ steps.app-token.outputs.token }}" ]; then
echo "token=${{ steps.app-token.outputs.token }}" >> "$GITHUB_OUTPUT"
else
echo "token=${{ secrets.GITHUB_TOKEN }}" >> "$GITHUB_OUTPUT"
fi
- name: Check for Fork PR
id: check_fork
uses: actions/github-script@v7
with:
github-token: ${{ steps.github-token.outputs.token }}
script: |
const isPR = context.eventName === 'pull_request' ||
context.eventName === 'pull_request_review' ||
context.eventName === 'pull_request_review_comment' ||
(context.payload.issue && context.payload.issue.pull_request);
if (isPR) {
core.setOutput('is_pr_review', 'true');
const prNumber = context.payload.pull_request
? context.payload.pull_request.number
: context.payload.issue.number;
core.setOutput('pr_number', String(prNumber));
const pr = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
});
core.setOutput('pr_branch', pr.data.head.ref);
const headRepo = pr.data.head.repo?.full_name || context.repo.full_name;
core.setOutput('head_repo', headRepo);
let mergeState = '';
try {
const gql = await github.graphql(
`query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $number) { mergeStateStatus }
}
}`,
{ owner: context.repo.owner, repo: context.repo.repo, number: prNumber }
);
mergeState = (gql.repository.pullRequest.mergeStateStatus || '').toUpperCase();
} catch (e) {
core.warning(`GraphQL mergeStateStatus failed: ${e.message}`);
}
if (!mergeState) {
mergeState = (pr.data.mergeable_state || pr.data.merge_state_status || '').toUpperCase();
}
core.setOutput('merge_state', mergeState);
if (headRepo !== `${context.repo.owner}/${context.repo.repo}`) {
core.setOutput('is_fork', 'true');
core.setOutput('clone_url', pr.data.head.repo.clone_url);
core.setOutput('branch', pr.data.head.ref);
return;
}
core.setOutput('is_fork', 'false');
return;
}
core.setOutput('is_pr_review', 'false');
core.setOutput('is_fork', 'false');
core.setOutput('merge_state', '');
- name: Checkout repository
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 0
token: ${{ steps.github-token.outputs.token }}
ref: ${{ steps.check_fork.outputs.is_pr_review == 'true' && format('refs/pull/{0}/head', steps.check_fork.outputs.pr_number) || github.ref }}
- name: Checkout PR branch for edits
if: steps.check_fork.outputs.is_pr_review == 'true' && steps.check_fork.outputs.is_fork != 'true'
env:
PR_BRANCH: ${{ steps.check_fork.outputs.pr_branch }}
run: |
git checkout "${PR_BRANCH}"
git config --local user.name "MervinPraison"
git config --local user.email "[email protected]"
echo "On branch: $(git branch --show-current)"
- name: Fetch PR branch and Setup Remote
if: steps.check_fork.outputs.is_pr_review == 'true' && steps.check_fork.outputs.is_fork == 'true'
env:
PR_BRANCH: ${{ steps.check_fork.outputs.pr_branch }}
run: |
git fetch origin pull/${{ steps.check_fork.outputs.pr_number }}/head:"${PR_BRANCH}"
git checkout "${PR_BRANCH}"
git remote set-url origin file://$(pwd)
- name: Run Claude PR final review
if: steps.check_fork.outputs.is_pr_review == 'true'
uses: anthropics/claude-code-action@beta
env:
GH_TOKEN: ${{ steps.github-token.outputs.token }}
with:
allowed_bots: 'praisonai-triage-agent[bot]'
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github_token: ${{ steps.github-token.outputs.token }}
model: claude-opus-4-8
trigger_phrase: "@claude"
timeout_minutes: "30"
direct_prompt: |
${{ steps.check_fork.outputs.is_fork == 'true' && 'CRITICAL: FORK PR — comment only, do not push.\n\n' || 'PR on MervinPraison/PraisonAIUI — SAME REPO, NOT A FORK. You HAVE push permission to this branch. NEVER say this is a fork.\n\n' }}
${{ steps.check_fork.outputs.is_fork != 'true' && steps.check_fork.outputs.merge_state == 'DIRTY' && format('PRIORITY — RESOLVE MERGE CONFLICTS (branch: {0}, PR #{1}):\n- DO NOT create a new branch or PR\n- git fetch origin main && git rebase origin/main\n- Resolve conflicts: keep this PR intent, merge in main newer logic\n- git add -A && git rebase --continue (repeat until done)\n- git push --force-with-lease origin {0}\n- Run targeted pytest/ruff on changed paths\n- Comment files resolved and what you skipped\n- Only after conflicts are resolved, proceed with review phases below if still needed\n\n', steps.check_fork.outputs.pr_branch, steps.check_fork.outputs.pr_number) || '' }}
${{ steps.check_fork.outputs.merge_state != 'DIRTY' && format('CONTEXT: PR #{0} on branch {1}. merge_state={2}.\n\n', steps.check_fork.outputs.pr_number, steps.check_fork.outputs.pr_branch, steps.check_fork.outputs.merge_state) || '' }}
You are the Lead Engineer doing FINAL review on this open PR in MervinPraison/PraisonAIUI.
Read ALL reviewer comments (CodeRabbit, Gemini, Qodo, Copilot, human). Follow AGENTS.md.
SCOPE: src/praisonaiui, src/frontend, tests, docs only.
**Phase 1 — Review** architecture, security, tests, backward compat, import-time budget.
**Phase 2 — FIX (mandatory)** implement every VALID issue on THIS branch. Push commits before Phase 3.
Do NOT ask the author to fix. Do NOT open a new PR. Do NOT claim fork restrictions unless is_fork is true.
**Phase 3 — Verdict** approve only after fixes are pushed and tests pass; else request changes with specifics.
git config --global user.name "MervinPraison"
git config --global user.email "[email protected]"
gh auth setup-git
git status
git branch --show-current
allowed_tools: |
Bash(git:*)
Bash(python:*)
Bash(pip:*)
Bash(pytest:*)
Bash(ruff:*)
Bash(gh:*)
Bash(npm:*)
View
GlobTool
GrepTool
BatchTool
Edit
Replace
- name: Run Claude Code Action
if: steps.check_fork.outputs.is_pr_review != 'true'
uses: anthropics/claude-code-action@beta
env:
GH_TOKEN: ${{ steps.github-token.outputs.token }}
with:
allowed_bots: 'praisonai-triage-agent[bot]'
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
github_token: ${{ steps.github-token.outputs.token }}
model: claude-opus-4-8
mode: ${{ github.event_name == 'workflow_dispatch' && 'agent' || 'tag' }}
trigger_phrase: "@claude"
label_trigger: "claude"
timeout_minutes: "30"
direct_prompt: |
${{ steps.check_fork.outputs.is_fork == 'true' && 'CRITICAL: THIS IS A PULL REQUEST FROM A FORK. YOU DO NOT HAVE PUSH PERMISSIONS TO THIS REPOSITORY. ONLY READ FILES, VALIDATE CODE, AND PROVIDE YOUR COMMENTS/FEEDBACK DIRECTLY IN THIS PR VIA COMMENTS. DO NOT ATTEMPT TO PUSH OR CREATE PULL REQUESTS.\n\n' || 'NOTE: The branch is under MervinPraison/PraisonAIUI (not a fork). You are able to make modifications and push directly to this branch.\n\n' }}
You are implementing changes in **MervinPraison/PraisonAIUI** (YAML-driven server-driven UI with agentic chat).
Follow `AGENTS.md` at the repository root. If a conflict arises between this prompt and `AGENTS.md`, `AGENTS.md` wins.
═══════════════════════════════════════════════════════════════
STEP 0 — GIT & GITHUB CLI
═══════════════════════════════════════════════════════════════
git config --global user.name "MervinPraison"
git config --global user.email "[email protected]"
gh auth setup-git
═══════════════════════════════════════════════════════════════
STEP 1 — READ GUIDELINES
═══════════════════════════════════════════════════════════════
Read `AGENTS.md` and any `docs/principles.md`. Key invariants:
• Cold import of `praisonaiui` must stay under 200 ms; module count must not grow.
• Heavy / optional deps (`mcp`, `langchain`, `llama_index`, `semantic_kernel`,
`slack_sdk`, `discord.py`, `botbuilder.core`, `openai`, `anthropic`, `mistralai`,
`google.generativeai`) must be **lazy-imported** — never eager.
• Public API is verb-first. New classes in `src/praisonaiui/message.py` ending
in `Message` with a verb prefix (Ask*, Do*, Request*, …) are forbidden —
use a module-level `async def` verb helper instead (see `prompt`, `error`).
• Deprecations must emit a runtime `warnings.warn(..., DeprecationWarning, stacklevel=2)`
on first access, not only in the docstring.
• Deterministic serialisation in anything reaching the wire (sorted keys, stable field
order). See existing `to_dict` patterns.
• Multi-agent + async safe: no global mutable state without a lock.
═══════════════════════════════════════════════════════════════
STEP 2 — ARCHITECTURE VALIDATION & ROUTING (MANDATORY before any code)
═══════════════════════════════════════════════════════════════
Answer these questions inline in your response, then proceed only if you pass:
ROUTING:
1. **Core aiui** (`src/praisonaiui/`) — protocols, message types, server, features.
2. **Features** (`src/praisonaiui/features/`) — opt-in capabilities (MCP, platforms, lifecycle, audio, auth, sharing, etc.).
3. **UI builders** (`src/praisonaiui/ui.py`) — declarative component helpers.
4. **Frontend** (`src/frontend/`) — React components / stores / SSE handlers.
5. **Tests** (`tests/unit/`, `tests/integration/`) — new features require both smoke and real-agentic tests.
6. **Docs** (`docs/`) — canonical name per feature, migration table for renames.
EXTERNAL REPOS (do NOT edit from within this repo — route the work to the right place and stop):
• Core SDK: `MervinPraison/PraisonAI` (`praisonaiagents`, `praisonai`) — agent runtime.
• Tools: `MervinPraison/PraisonAI-Tools` — tool implementations.
• Docs site: `MervinPraison/PraisonAIDocs` — product docs.
If the requested change belongs in an external repo, comment on the issue explaining
where it should live and DO NOT open a PR in this repo.
CONCEPTUAL CHECKS (if ANY fails — add a comment, do NOT open a PR):
• Does it duplicate an existing public symbol in `src/praisonaiui/__init__.py`?
• Does it add new class-first message types (`class Ask*Message`, `class *Message`
with a verb in the name)? → Use a verb-first helper instead.
• Does it add a new hard dependency to `pyproject.toml` `[project] dependencies`?
→ Move to `[project.optional-dependencies]` and wrap imports lazily.
• Does it break backward compat (rename, signature change, removal)? → Add
a deprecation alias that emits `DeprecationWarning`; never hard-remove before the
documented removal version (e.g. `0.5.0`).
═══════════════════════════════════════════════════════════════
STEP 3 — IMPLEMENT
═══════════════════════════════════════════════════════════════
Single branch for the whole flow (reuse the same name in STEP 5):
BRANCH="claude/issue-${{ env.ISSUE_NUMBER_RESOLVED }}-$(date +%Y%m%d-%H%M%S)"
git checkout -b "$BRANCH"
Make minimal, focused changes:
• Stay within the files listed in the issue's "Scope" / "Files to change" section.
• Prefer extending existing modules over adding new ones.
• No emojis, no comments, no markdown except where the user asked for it.
• Python ≥ 3.10 style (`list[...]` not `List[...]`, `X | None` not `Optional[X]`).
═══════════════════════════════════════════════════════════════
STEP 4 — TEST / VERIFY
═══════════════════════════════════════════════════════════════
Run these targeted checks (NOT the full suite):
# 1. Lint on only the files you changed:
CHANGED=$(git diff --name-only origin/main...HEAD | grep -E '\.py$' | tr '\n' ' ')
[ -n "$CHANGED" ] && ruff check $CHANGED
# 2. Unit tests for the module(s) you touched:
pytest tests/unit/<your_new_test_file>.py -v --tb=short
# 3. Import-time invariant (MUST stay under 200 ms cold):
python -c "import time, sys; t=time.time(); import praisonaiui; dt=(time.time()-t)*1000; heavy=[m for m in sys.modules if any(h in m for h in ['langchain','llama_index','mcp','slack','discord','botbuilder','openai.','anthropic.','mistralai','google.generativeai'])]; print(f'{dt:.1f}ms modules={len(sys.modules)} leaked={heavy}'); assert heavy == [], f'Heavy deps leaked: {heavy}'"
If anything fails, fix the root cause (never skip, xfail, or delete the test).
═══════════════════════════════════════════════════════════════
STEP 5 — COMMIT, PUSH, OPEN PR (MANDATORY if you produced commits)
═══════════════════════════════════════════════════════════════
git add -A
git commit -m "feat: <short summary> (fixes #${{ env.ISSUE_NUMBER_RESOLVED }})"
git push -u origin "$BRANCH"
REPO="${{ github.repository }}"
COUNT=$(gh pr list --repo "$REPO" --head "$BRANCH" --json number --jq 'length')
if [ "$COUNT" -gt 0 ]; then
gh pr list --repo "$REPO" --head "$BRANCH" --json url --jq '.[0].url'
else
gh pr create --repo "$REPO" --base main --head "$BRANCH" \
--title "feat: <short title>" \
--body "Fixes #${{ env.ISSUE_NUMBER_RESOLVED }}
## Summary
<what changed in one paragraph>
## Acceptance criteria
<copy from the issue; tick boxes only with commit SHA + file path evidence>
## Test evidence
\`\`\`
<paste pytest output>
\`\`\`
"
fi
CRITICAL: Do NOT stop after `git push`. You MUST complete `gh pr create` (or print the
existing PR URL from the step above) and post that URL on the issue. Never ask a
human to open the PR manually.
═══════════════════════════════════════════════════════════════
STEP 6 — RESPOND TO REVIEW FEEDBACK (if this run was triggered by a review comment)
═══════════════════════════════════════════════════════════════
If you were invoked by a PR review comment, you are the Lead Engineer for this PR:
• Read ALL reviewer comments in chronological order (CodeRabbit → Copilot → human).
• Fix every VALID issue by pushing commits to THIS branch (do NOT open a new PR).
• Reply with a summary of which comments you addressed, which you disagreed with (and why).
• Never ship a fix that removes/weakens a test.
allowed_tools: |
Bash(git:*)
Bash(python:*)
Bash(pip:*)
Bash(pytest:*)
Bash(ruff:*)
Bash(gh:*)
Bash(npm:*)
Bash(npx:*)
Bash(python -m pytest:*)
Bash(python -m pip:*)
Bash(python -m ruff:*)
View
GlobTool
GrepTool
BatchTool
Edit
Replace
mcp__github__get_issue
mcp__github__get_issue_comments
mcp__github__update_issue
-183
View File
@@ -1,183 +0,0 @@
name: Auto Merge Conflict → Claude
# Detects internal PRs with mergeStateStatus=DIRTY and posts @claude to trigger claude.yml.
on:
push:
branches: [main]
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
schedule:
- cron: '0 */6 * * *'
concurrency:
group: merge-conflict-scan-${{ github.repository }}
cancel-in-progress: true
env:
# PAT posts as MervinPraison so issue_comment triggers claude.yml (GITHUB_TOKEN cannot chain workflows)
GH_TOKEN: ${{ secrets.GH_TOKEN || github.token }}
permissions:
pull-requests: write
issues: write
jobs:
detect-and-trigger:
runs-on: ubuntu-latest
steps:
- name: Detect conflicting PRs and trigger Claude
uses: actions/github-script@v7
with:
github-token: ${{ env.GH_TOKEN }}
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const baseRepo = `${owner}/${repo}`;
const COOLDOWN_MS = 12 * 60 * 60 * 1000;
const AUTO_ACTORS = ['github-actions[bot]', 'MervinPraison'];
const LABEL = 'claude-conflict-pending';
const COMMENT_BODY = [
'@claude this PR has merge conflicts with `main`.',
'Please rebase onto latest `main`, resolve conflicts (keep this PR\'s intent, merge in newer main logic),',
'run targeted tests, and force-push with `--force-with-lease`.',
'Comment which files you resolved.'
].join(' ');
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function getMergeState(prNumber) {
const query = `
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $number) {
mergeStateStatus
maintainerCanModify
isDraft
headRef { repository { nameWithOwner } }
}
}
}
`;
for (let attempt = 0; attempt < 3; attempt++) {
const result = await github.graphql(query, { owner, repo, number: prNumber });
const prGql = result.repository.pullRequest;
const status = (prGql?.mergeStateStatus || '').toUpperCase();
if (status && status !== 'UNKNOWN') {
return {
status,
isDraft: prGql.isDraft,
headRepo: prGql.headRef?.repository?.nameWithOwner,
maintainerCanModify: prGql.maintainerCanModify === true,
};
}
if (attempt < 2) await sleep(10000);
}
const pr = await github.rest.pulls.get({ owner, repo, pull_number: prNumber });
return {
status: (pr.data.mergeable_state || '').toUpperCase(),
isDraft: pr.data.draft,
headRepo: pr.data.head.repo?.full_name,
maintainerCanModify: pr.data.maintainer_can_modify === true,
};
}
function hasFinalClaudeReviewTrigger(comments) {
return comments.some((c) => {
const body = (c.body || '').toLowerCase();
if (!AUTO_ACTORS.includes(c.user.login)) return false;
if (!body.includes('@claude')) return false;
if (body.includes('merge conflict')) return false;
return body.includes('final architecture reviewer') || body.includes('lead engineer');
});
}
function hasRecentAutoComment(comments) {
const cutoff = Date.now() - COOLDOWN_MS;
return comments.some((c) => {
if (!AUTO_ACTORS.includes(c.user.login)) return false;
const body = (c.body || '').toLowerCase();
if (!body.includes('@claude') || !body.includes('merge conflict')) return false;
return new Date(c.created_at).getTime() > cutoff;
});
}
async function processPR(prNumber) {
const { status, isDraft, headRepo, maintainerCanModify } = await getMergeState(prNumber);
core.info(`PR #${prNumber}: mergeState=${status}, head=${headRepo}, draft=${isDraft}, maintainerCanModify=${maintainerCanModify}`);
const { data: issue } = await github.rest.issues.get({
owner,
repo,
issue_number: prNumber,
});
const labels = issue.labels.map((l) => l.name);
if (status !== 'DIRTY' && labels.includes(LABEL)) {
await github.rest.issues.removeLabel({
owner,
repo,
issue_number: prNumber,
name: LABEL,
});
core.info(`Removed ${LABEL} from PR #${prNumber}`);
}
if (status !== 'DIRTY') return { skipped: true, reason: 'not dirty' };
if (isDraft) return { skipped: true, reason: 'draft' };
if (headRepo && headRepo !== baseRepo && !maintainerCanModify) {
return { skipped: true, reason: 'fork without maintainer edits' };
}
if (labels.includes(LABEL)) {
return { skipped: true, reason: 'conflict resolution pending' };
}
const { data: comments } = await github.rest.issues.listComments({
owner,
repo,
issue_number: prNumber,
per_page: 100,
});
if (hasRecentAutoComment(comments)) {
return { skipped: true, reason: 'recent auto comment' };
}
if (!hasFinalClaudeReviewTrigger(comments)) {
return { skipped: true, reason: 'awaiting final claude review trigger' };
}
await github.rest.issues.addLabels({
owner,
repo,
issue_number: prNumber,
labels: [LABEL],
});
await github.rest.issues.createComment({
owner,
repo,
issue_number: prNumber,
body: COMMENT_BODY,
});
return { triggered: true };
}
let prNumbers = [];
if (context.eventName === 'pull_request') {
prNumbers = [context.payload.pull_request.number];
} else {
const prs = await github.paginate(github.rest.pulls.list, {
owner,
repo,
state: 'open',
per_page: 100,
});
prNumbers = prs.map((p) => p.number);
}
const results = [];
for (const num of prNumbers) {
results.push({ pr: num, ...(await processPR(num)) });
}
core.summary.addRaw('```json\n' + JSON.stringify(results, null, 2) + '\n```');
await core.summary.write();
-129
View File
@@ -1,129 +0,0 @@
name: Nightly Release Gate
# Preflight before PyPI Release (patch bump).
# Primary: CI success on main (workflow_run).
# Backstop: nightly cron at 00:00 UTC.
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
inputs:
dry_run:
description: 'Run preflight only; do not dispatch pypi-release.yml'
required: false
default: false
type: boolean
workflow_run:
workflows:
- CI
types:
- completed
branches:
- main
permissions:
contents: read
actions: write
concurrency:
group: nightly-release-gate
cancel-in-progress: false
jobs:
preflight:
if: |
github.event_name == 'workflow_dispatch' ||
github.event_name == 'schedule' ||
(
github.event_name == 'workflow_run' &&
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.head_branch == 'main' &&
github.event.workflow_run.event == 'push'
)
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
steps:
- name: Resolve trigger context
id: ctx
run: |
if [ "${{ github.event_name }}" = "workflow_run" ]; then
echo "checkout_sha=${{ github.event.workflow_run.head_sha }}" >> "$GITHUB_OUTPUT"
echo "source=ci" >> "$GITHUB_OUTPUT"
echo "is_ci=true" >> "$GITHUB_OUTPUT"
else
echo "checkout_sha=main" >> "$GITHUB_OUTPUT"
echo "source=nightly" >> "$GITHUB_OUTPUT"
echo "is_ci=false" >> "$GITHUB_OUTPUT"
fi
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: ${{ steps.ctx.outputs.checkout_sha }}
fetch-depth: 0
- name: Fetch main and tags
run: git fetch --tags origin main
- name: Preflight — path changes, CI SHA, dedupe
id: preflight
uses: actions/github-script@v7
env:
HEAD_SHA: ${{ steps.ctx.outputs.checkout_sha }}
IS_CI: ${{ steps.ctx.outputs.is_ci }}
with:
github-token: ${{ secrets.GH_TOKEN }}
script: |
const path = require('path');
const rg = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/release-gate.js'));
const owner = context.repo.owner;
const repo = context.repo.repo;
const headSha = process.env.HEAD_SHA;
const isCi = process.env.IS_CI === 'true';
const result = await rg.evaluateReleasePreflight(
github, owner, repo,
{ headSha, isCiTrigger: isCi, bump: 'patch' },
core
);
core.setOutput('should_release', result.ready ? 'true' : 'false');
core.setOutput('reason', result.reasons.join('; '));
core.setOutput('head_sha', result.headSha || headSha);
core.setOutput('last_tag', result.lastTag || '');
core.setOutput('target_version', result.targetVersion || '');
core.summary.addRaw('## Release gate preflight\n');
core.summary.addRaw(`Ready: ${result.ready}\n`);
core.summary.addRaw(`Reason: ${result.reasons.join('; ')}\n`);
if (result.targetVersion) {
core.summary.addRaw(`Target: aiui==${result.targetVersion}\n`);
}
await core.summary.write();
if (!result.ready) {
core.info(`Skip release: ${result.reasons.join('; ')}`);
}
- name: Dry run summary
if: inputs.dry_run == true
run: |
echo "Dry run — preflight only, no pypi-release dispatch."
echo "should_release=${{ steps.preflight.outputs.should_release }}"
echo "reason=${{ steps.preflight.outputs.reason }}"
- name: Dispatch PyPI Release (patch)
if: steps.preflight.outputs.should_release == 'true' && inputs.dry_run != true
run: |
set -euo pipefail
gh workflow run pypi-release.yml \
--repo "${GITHUB_REPOSITORY}" \
--ref main \
-f bump=patch \
-f source=${{ steps.ctx.outputs.source }} \
-f trigger_sha=${{ steps.preflight.outputs.head_sha }} \
-f dry_run=false
echo "Dispatched pypi-release.yml (patch, source=${{ steps.ctx.outputs.source }})"
echo "Uses pypi-auto environment for ci/nightly patch releases."
@@ -1,42 +0,0 @@
name: Pipeline Status Sync
# Sync pipeline/* stage and blocker labels on open internal PRs.
on:
schedule:
- cron: '*/10 * * * *'
workflow_dispatch:
permissions:
pull-requests: read
issues: write
actions: write
id-token: write
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
owner: ${{ github.repository_owner }}
- name: Sync pipeline labels on open PRs
uses: actions/github-script@v7
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
const path = require('path');
const ps = require(path.join(process.env.GITHUB_WORKSPACE, '.github/scripts/pipeline-status.js'));
await ps.syncOpenPullRequests(
github, context.repo.owner, context.repo.repo,
{ maxPrs: 30, dispatchMergeGate: true }, core
);
-232
View File
@@ -1,232 +0,0 @@
name: PyPI Release
# Requires GitHub Environment "pypi" (manual) or "pypi-auto" (ci/nightly patch).
# Secrets: PYPI_TOKEN (or PYPI_API_TOKEN), GH_TOKEN
on:
workflow_dispatch:
inputs:
bump:
description: 'Version bump type for aiui'
required: true
default: patch
type: choice
options:
- patch
- minor
- major
dry_run:
description: 'Preview versions and steps without publishing or pushing'
required: false
default: false
type: boolean
version:
description: 'Override version (empty = auto bump from pyproject.toml)'
required: false
default: ''
type: string
source:
description: 'Trigger source (audit trail)'
required: false
default: manual
type: string
trigger_sha:
description: 'SHA that triggered this release'
required: false
default: ''
type: string
permissions:
contents: write
concurrency:
group: pypi-release
cancel-in-progress: false
jobs:
release:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
environment: >-
${{
(inputs.source == 'ci' || inputs.source == 'nightly') &&
inputs.bump == 'patch' &&
'pypi-auto' || 'pypi'
}}
env:
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN || secrets.PYPI_API_TOKEN }}
GH_TOKEN: ${{ secrets.GH_TOKEN }}
PACKAGE: aiui
steps:
- name: Release audit
run: |
echo "Source: ${{ inputs.source }}"
echo "Trigger SHA: ${{ inputs.trigger_sha }}"
echo "Bump: ${{ inputs.bump }}"
echo "Environment: ${{ (inputs.source == 'ci' || inputs.source == 'nightly') && inputs.bump == 'patch' && 'pypi-auto' || 'pypi' }}"
- name: Checkout main
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
ref: main
fetch-depth: 0
token: ${{ secrets.GH_TOKEN }}
- name: Set up Python
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.11'
- name: Set up uv
uses: astral-sh/setup-uv@38f3f104447c67c051c4a08e39b64a148898af3a # v4
- name: Configure git
run: |
git config user.name "MervinPraison"
git config user.email "[email protected]"
gh auth setup-git
- name: Compute release version
id: versions
env:
BUMP: ${{ inputs.bump }}
VERSION_OVERRIDE: ${{ inputs.version }}
run: |
python <<'PY'
import os
import re
import sys
from pathlib import Path
SEMVER = re.compile(r"^\d+\.\d+\.\d+$")
bump = os.environ["BUMP"]
override = os.environ.get("VERSION_OVERRIDE", "").strip()
def bump_version(version: str) -> str:
parts = version.split(".")
if len(parts) != 3:
print(f"Invalid version: {version}", file=sys.stderr)
sys.exit(1)
maj, min_, patch = (int(parts[0]), int(parts[1]), int(parts[2]))
if bump == "major":
return f"{maj + 1}.0.0"
if bump == "minor":
return f"{maj}.{min_ + 1}.0"
return f"{maj}.{min_}.{patch + 1}"
pyproject = Path("pyproject.toml")
content = pyproject.read_text()
match = re.search(r'^version\s*=\s*"([^"]+)"', content, re.MULTILINE)
if not match:
print("Could not read version from pyproject.toml", file=sys.stderr)
sys.exit(1)
current = match.group(1)
if not SEMVER.match(current):
print(f"Invalid current version: {current}", file=sys.stderr)
sys.exit(1)
if override:
if not SEMVER.match(override):
print(f"Invalid version override: {override}", file=sys.stderr)
sys.exit(1)
new_version = override
else:
new_version = bump_version(current)
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as fh:
fh.write(f"current_version={current}\n")
fh.write(f"new_version={new_version}\n")
print(f"aiui: {current} -> {new_version}")
PY
- name: Dry run summary
if: inputs.dry_run
run: |
echo "Dry run — no publish, commit, or push."
echo "Package: ${{ env.PACKAGE }}"
echo "Version: ${{ steps.versions.outputs.current_version }} -> ${{ steps.versions.outputs.new_version }}"
echo "Would: bump pyproject.toml + __version__.py, uv publish, commit, tag, GitHub release"
- name: Bump version files
if: inputs.dry_run != true
env:
CURRENT: ${{ steps.versions.outputs.current_version }}
NEW_VERSION: ${{ steps.versions.outputs.new_version }}
run: |
set -euo pipefail
python <<'PY'
import os
import re
from pathlib import Path
current = os.environ["CURRENT"]
new = os.environ["NEW_VERSION"]
pyproject = Path("pyproject.toml")
content = pyproject.read_text()
pyproject.write_text(content.replace(f'version = "{current}"', f'version = "{new}"', 1))
version_py = Path("src/praisonaiui/__version__.py")
vcontent = version_py.read_text()
version_py.write_text(re.sub(
r'__version__ = "[^"]+"',
f'__version__ = "{new}"',
vcontent,
count=1,
))
PY
- name: Publish aiui to PyPI
if: inputs.dry_run != true
run: |
set -euo pipefail
rm -rf dist
uv lock
uv build
uv publish
- name: Wait for aiui on PyPI
if: inputs.dry_run != true
run: |
set -euo pipefail
VERSION="${{ steps.versions.outputs.new_version }}"
MAX_WAIT=600
INTERVAL=30
START=$(date +%s)
while true; do
if curl -fsSL "https://pypi.org/pypi/${PACKAGE}/${VERSION}/json" >/dev/null; then
echo "✅ ${PACKAGE}==${VERSION} is available on PyPI"
exit 0
fi
ELAPSED=$(( $(date +%s) - START ))
if [ "$ELAPSED" -ge "$MAX_WAIT" ]; then
echo "❌ Timeout waiting for ${PACKAGE}==${VERSION} on PyPI"
exit 1
fi
echo "⏳ Waiting for ${PACKAGE}==${VERSION} ($(( MAX_WAIT - ELAPSED ))s remaining...)"
sleep "$INTERVAL"
done
- name: Commit, tag, and release
if: inputs.dry_run != true
env:
VERSION: ${{ steps.versions.outputs.new_version }}
run: |
set -euo pipefail
TAG="v${VERSION}"
git add pyproject.toml uv.lock src/praisonaiui/__version__.py
git diff --cached --quiet && { echo "No version files to commit"; exit 0; }
git commit -m "Release ${TAG}"
git tag -f "${TAG}"
git pull --rebase origin main
git tag -f "${TAG}"
git push origin main
git push --tags -f
gh release create "${TAG}" \
--title "PraisonAIUI ${TAG}" \
--notes "Release ${TAG}" \
--latest
- name: Verify release
if: inputs.dry_run != true
run: echo "✅ ${{ env.PACKAGE }}==${{ steps.versions.outputs.new_version }}"
@@ -1,33 +0,0 @@
name: Sync Claude Secrets from PraisonAI
# GitHub does not allow reading secret values back via API.
# This workflow triggers the sync job in MervinPraison/PraisonAI, which copies:
# CLAUDE_APP_ID, CLAUDE_APP_PRIVATE_KEY, CLAUDE_CODE_OAUTH_TOKEN, GH_TOKEN
#
# Requires SECRETS_ADMIN_PAT in PraisonAI (repo Settings → Secrets).
# If sync fails, copy secrets manually:
# PraisonAI → Settings → Secrets → Actions
# PraisonAIUI → Settings → Secrets → Actions (same names)
on:
workflow_dispatch:
permissions:
contents: read
jobs:
trigger-sync:
runs-on: ubuntu-latest
steps:
- name: Trigger PraisonAI secret sync
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh workflow run sync-secrets-to-aiui.yml \
--repo MervinPraison/PraisonAI \
--ref main \
-f target_repo=MervinPraison/PraisonAIUI
echo "Triggered: https://github.com/MervinPraison/PraisonAI/actions/workflows/sync-secrets-to-aiui.yml"
echo ""
echo "If sync fails (401/403), refresh SECRETS_ADMIN_PAT in PraisonAI,"
echo "or copy CLAUDE_APP_ID + CLAUDE_APP_PRIVATE_KEY + GH_TOKEN manually."
-59
View File
@@ -1,59 +0,0 @@
# Python
__pycache__/
*.py[cod]
*$py.class
.venv/
venv/
env/
build/
dist/
*.egg-info/
.pytest_cache/
.coverage
coverage.xml
htmlcov/
.mypy_cache/
.ruff_cache/
# JavaScript / Node
node_modules/
.next/
dist/
.npm/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-lock.yaml
*.tsbuildinfo
# Environment
.env
.env.local
.env.*.local
# IDE
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
# Project specific
aiui/
*.log
.praison/
.gemini/
.internal/
# Generated
site/
docs/_build/
aiui-output/
_site
.praisonai
tmp/
*.db
File renamed without changes.
@@ -1,375 +0,0 @@
---
description: Comprehensive analysis workflow that produces a detailed GitHub issue — combines deep codebase analysis with issue creation for implementation-ready tickets
---
# Analysis → GitHub Issue Workflow
Deep Analysis → Gap Analysis → Critical Review → Plan → Create GitHub Issue.
> **When to use this:** You need to analyze a feature, integration, or system deeply and produce a GitHub issue that another agent/developer can implement immediately without asking follow-up questions.
> **When NOT to use this:** Use `/analysis` for analysis-only (no issue). Use `/local-fix` if you're implementing yourself.
---
## PRINCIPLES (apply throughout)
- **Agent-centric**: Agents, workflows, sessions, tools, memory, multi-agent safety.
- **Protocol-driven core**: praisonaiagents = lightweight, protocol-first (protocols/hooks/adapters only).
- **DRY**: identify reuse; avoid duplication.
- **No perf impact**: preserve import-time and hot-path; heavy deps optional + lazy.
- **Async-safe + multi-agent safe** by default.
- **Easy for non-developers**: "Few lines of code to do the task!"
- **No competitor names in public surfaces**: Never mention competitor product, company, or project names in GitHub issues, PRs, commit messages, release notes, docs, or any other public-facing content. Refer to capabilities generically (e.g., "self-improving agent pattern", "external agent framework").
---
## CANONICAL PATHS
```
UI Repo: /Users/praison/praisonaiui (praisonaiui)
SDK Core: /Users/praison/praisonai-package/src/praisonai-agents (praisonaiagents)
Docs: /Users/praison/PraisonAIDocs
Extension: src/praisonaiui/*, docs/*, tests/*
```
---
## Phase 1 — Acceptance Criteria
Translate the request into testable criteria:
- API expectations (classes, methods, signatures)
- CLI expectations (commands, flags, help text)
- Documentation expectations (pages, examples)
- Test expectations (unit, integration, smoke, real agentic)
- Performance constraints (import time, hot-path)
---
## Phase 2 — External Research (if applicable)
### 2a. Read official sources
If analyzing an external integration, research from primary sources:
```bash
# Use read_url_content tool for:
# - Official site / announcement pages
# - GitHub README and docs
# - Framework documentation
# - Third-party write-ups
```
**Capture:**
- What is it? Purpose and design goals
- Key terminology and concepts
- Architecture overview
- Current ecosystem state
- References list (all URLs)
### 2b. Clone & analyze external codebase (if applicable)
```bash
git clone <repo-url> ~/<repo-name> --depth=1
ls -la ~/<repo-name>/
```
Key files to read:
- `AGENTS.md` / `README.md` — architecture overview
- Base class files (abstract methods, signatures)
- Factory / registry files (registration pattern)
- Model/config files (data structures)
- Example implementations (minimal + full-featured)
- `pyproject.toml` / `package.json` — dependencies
---
## Phase 3 — PraisonAI Codebase Inventory
### 3a. Inventory with evidence
Go through ALL relevant files, understand current logic end-to-end.
```bash
# UI repo
ls /Users/praison/praisonaiui/src/praisonaiui/
ls /Users/praison/praisonaiui/tests/
ls /Users/praison/praisonaiui/docs/
# Optional cross-check against SDK only when needed
ls /Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/
```
**Document:**
- Public APIs: modules/classes/functions and exports
- Protocols/adapters/hooks and extension points
- CLI commands, options, help text
- Integrations (db/observability/tools)
- Tests (unit/integration), fixtures, CI config
- Docs (Mintlify), examples, recipes
Provide: **file paths + key symbols + grep counts + entry points**.
### 3b. Identify DRY opportunities
- Existing abstractions that can be reused
- Duplicated code that should be consolidated
- Existing protocols before creating new ones
---
## Phase 4 — Detailed Analysis
### 4a. Architecture and behavior
- Control flow and data flow
- Concurrency model (sync/async)
- Multi-agent interactions
- Dependency boundaries (core/wrapper/tools)
- Failure modes and error handling
### 4b. Invariants check
Verify these are preserved:
- [ ] Protocol-driven core (no heavy impls in praisonaiagents)
- [ ] Lazy imports (optional deps never at module level)
- [ ] Backward compatible (public API changes need deprecation)
- [ ] Safe defaults (new features opt-in)
---
## Phase 5 — Gap Analysis
Compare acceptance criteria vs current state.
### Checklist
| Area | Current State | Gap | Severity | Impact | Placement |
|------|---------------|-----|----------|--------|-----------|
| Core SDK | | | | | |
| Wrapper | | | | | |
| Tools/plugins | | | | | |
| CLI | | | | | |
| Docs | | | | | |
| Tests | | | | | |
| Exports | | | | | |
| Perf | | | | | |
| Multi-agent + async | | | | | |
### Gap severity levels
- **Critical**: Blocks functionality
- **High**: Significant limitation
- **Medium**: Missing feature
- **Low**: Nice-to-have
---
## Phase 6 — Critical Review
### 6a. Risks and footguns
- API ambiguity or edge cases
- Backward compatibility concerns
- Coupling violations
- Performance regressions
- Concurrency hazards
- Misuse risks
- Operational concerns
### 6b. Mitigation strategies
For each risk, document:
- "Safe by default" recommendation
- Explicit opt-in for dangerous behavior
- Documentation warnings
---
## Phase 7 — Implementation Plan
Step-by-step plan (DO NOT implement):
### 7a. Test-first (TDD)
1. Unit tests for new functionality
2. Integration tests for cross-component behavior
3. Smoke tests for quick validation
4. **Real agentic tests** (REQUIRED):
```python
from praisonaiagents import Agent
agent = Agent(name="test", instructions="You are helpful")
result = agent.start("Say hello in one sentence")
print(result) # Must call LLM and produce response
```
### 7b. Implementation order
1. Tests (TDD)
2. Core implementation
3. CLI integration
4. Documentation
5. Verification
### 7c. Files to change/create
| File | Action | Purpose |
|------|--------|---------|
| | | |
### 7d. Verification commands
```bash
# Unit tests
pytest tests/unit/test_<feature>.py -v
# Integration tests
pytest tests/integration/test_<feature>.py -v
# Smoke test
python -c "from praisonaiagents import <Feature>; print('OK')"
# Real agentic test
python examples/<feature>_example.py
```
---
## Phase 8 — Draft GitHub Issue
The issue must be **self-contained**. Another agent must be able to implement by reading only the issue.
### Required sections
```markdown
## Overview
One paragraph: what, why, and the end goal.
## Background
- Purpose and design goals
- Why this is valuable
- Current state / ecosystem
## Architecture Analysis
### Current Implementation
- Key files and their purposes
- Integration points
- Data flow
### Key File Locations
| File | Purpose | Lines |
|------|---------|-------|
## Gap Analysis Summary
### Critical Gaps
| Gap | Impact | Effort |
|-----|--------|--------|
### Feature Gaps
| Feature | Current Support | Gap |
|---------|-----------------|-----|
## Proposed Implementation
### Phase 1: Minimal
Working code example.
### Phase 2: Production
Working code example.
## Files to Create / Modify
### New files
| File | Purpose |
|------|---------|
### Modified files
| File | Change |
|------|--------|
## Technical Considerations
- Dependencies
- Performance impact
- Safety / approval
- Multi-agent safety
## Acceptance Criteria
- [ ] Verifiable checkbox list
## Implementation Notes
### Key Files to Read First
1. `path/to/file.py` (N lines) — purpose
### Critical Integration Points
1. Where X connects to Y
### Testing Commands
```bash
# Copy-pastable commands
```
## References
- [Link](url)
```
---
## Phase 9 — Create GitHub Issue
### 9a. Create via `gh` CLI
```bash
gh issue create \
--repo MervinPraison/PraisonAIUI \
--title "<Type>: <Descriptive Title>" \
--body "<issue body>"
```
**Title formats:**
- `Feature: <What>` — new functionality
- `Analysis: <Topic>` — analysis/research
- `Integration: <External System>` — external integration
- `Fix: <Problem>` — bug fix proposal
### 9b. Verify issue created
```bash
gh issue view <number> --repo MervinPraison/PraisonAIUI | head -20
```
---
## Checklist — Before Creating Issue
- [ ] Acceptance criteria defined and testable
- [ ] All relevant PraisonAI files read (not skimmed)
- [ ] External sources researched (if applicable)
- [ ] Gap analysis completed with severity ratings
- [ ] Critical review identifies risks and mitigations
- [ ] Implementation plan is step-by-step with file list
- [ ] Issue body has working code examples (not pseudocode)
- [ ] All file paths are absolute and verified
- [ ] CLI commands are copy-pastable
- [ ] Acceptance criteria are verifiable (not vague)
- [ ] References section includes all URLs
- [ ] Issue is self-contained — no "see docs" without details
---
## Quick Reference — Common Mistakes
| Mistake | Fix |
|---------|-----|
| Pseudocode in examples | Use real, runnable code with imports |
| Vague file paths | Use absolute paths |
| Skipping gap analysis | Every gap needs severity + impact |
| Missing real agentic test | Include `agent.start()` test, not just construction |
| No verification commands | Include copy-pastable pytest/python commands |
| Claiming "done" without evidence | Every claim references specific files/symbols |
| Implementing instead of analyzing | This workflow produces issues, not code |
---
## Hard Rules
1. **DO NOT implement** — this workflow produces analysis and issues only
2. **DO NOT claim done** without evidence
3. **Every claim must reference** specific files/symbols
4. **Issue must be self-contained** — implementer needs no follow-up questions
5. **Working code examples required** — no pseudocode
-104
View File
@@ -1,104 +0,0 @@
---
description: analysis
---
You are an expert AI engineer in the PraisonAI ecosystem.
Your job: produce ONLY (1) analysis, (2) review, (3) gap analysis, (4) critical review, (5) plan, (6) proposal.
Do NOT implement. Do NOT write code. Do NOT update docs. Do NOT run tests beyond discovery.
Be precise, evidence-based, and agent-centric.
PRINCIPLES (apply in all analysis/proposals):
- Agent-centric: Agents, workflows, sessions, tools, memory, multi-agent safety.
- Protocol-driven core: praisonaiagents = lightweight, protocol-first (protocols/hooks/adapters only).
- DRY: identify reuse; avoid duplication.
- No perf impact: preserve import-time and hot-path; heavy deps optional + lazy.
- Async-safe + multi-agent safe by default.
- Clear paid upgrade path (support/cloud/services) without restricting core.
- Easy for non-developers. "Few lines of code to do the task!"
CANONICAL PATHS:
- UI Repo: /Users/praison/praisonaiui (praisonaiui)
- SDK Core (reference): /Users/praison/praisonai-package/src/praisonai-agents (praisonaiagents)
- Docs: /Users/praison/PraisonAIDocs (JS: docs/js, Rust: docs/rust)
- Extension points: src/praisonaiui/*, docs/*, tests/*
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MANDATORY PROCESS (NO IMPLEMENTATION)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
STEP 1 — Acceptance Criteria
- Translate request into testable criteria: API, CLI, docs, test expectations, perf constraints.
STEP 2 — Repo Inventory (evidence-based)
- Go through ALL relevant files, understand current logic end-to-end.
- Inventory with evidence:
- Public APIs: modules/classes/functions and exports
- Protocols/adapters/hooks and extension points
- CLI commands, options, help text
- Integrations (db/observability/tools)
- Tests (unit/integration), fixtures, CI config
- Docs (Mintlify), examples, recipes
- Provide: file paths + key symbols + grep counts + entry points.
- Identify DRY opportunities.
STEP 3 — Detailed Analysis
- Architecture and behavior: control flow, data flow, concurrency (sync/async), multi-agent interactions, dependency boundaries (core/wrapper/tools), failure modes.
- Highlight invariants: protocol-driven core, lazy imports, optional deps.
STEP 4 — Detailed Review
- Evaluate against principles: agent-centricity, API simplicity, DRY, perf, optional deps + lazy imports, async/multi-agent safety, test coverage, CLI parity, docs clarity.
- Concrete evidence for each judgment.
STEP 5 — Gap Analysis
- Compare acceptance criteria vs current state. Checklist:
- UI Core, CLI, Docs, Tests, Exports, Perf, Multi-agent + async
- Each gap: severity, impact, risk, recommended location (core/wrapper/tools).
STEP 6 — Critical Review
- Risks, footguns, maintenance concerns:
- API ambiguity, edge cases, backward compat
- Coupling violations, perf regressions, concurrency hazards
- Misuse risks, operational concerns
- Mitigation strategies and "safe by default" recommendations.
STEP 7 — Plan
- Step-by-step (do not implement): tests (TDD) → implementation → CLI → docs → verification
- Exact files to change/create. Migration/compat plan. Rollback plan. Verification commands. Perf checks. Multi-agent + async test strategy.
REAL AGENTIC TEST definition (MUST include in every verification plan):
- A "real agentic test" = agent ACTUALLY RUNS and calls the LLM:
1. Create Agent with the feature being tested
2. Call `agent.start("a real task prompt")` — NOT just constructing the object
3. Agent MUST call LLM and produce text response
4. Print full output so dev can see it worked end-to-end
- Example:
```python
from praisonaiagents import Agent
agent = Agent(name="test", instructions="You are a helpful assistant")
result = agent.start("Say hello in one sentence")
print(result)
```
- Assert-only object construction = SMOKE TEST, not real agentic test.
- Both smoke AND real agentic tests required.
STEP 8 — Proposal
- Minimal, agent-centric design and API/CLI surface:
- protocols/hooks in core; implementations in wrapper/tools
- Clear defaults and explicit overrides
- Multi-agent resource isolation/sharing
- Error model and observability hooks
- Include: "Simple API" examples, CLI UX, docs outline, paid upgrade path.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
REQUIRED OUTPUT (in order):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1) Acceptance Criteria
2) Inventory (evidence: paths/symbols/exports/grep counts)
3) Detailed Analysis (architecture + flows + invariants)
4) Detailed Review (quality vs principles, evidence-based)
5) Gap Analysis (checklist + severity/impact/placement)
6) Critical Review (risks + mitigations)
7) Plan (step-by-step + file list + verification strategy)
8) Proposal (agent-centric design + API/CLI/docs outline)
Hard rules: DO NOT implement. DO NOT write code. DO NOT claim done. Every claim must reference specific files/symbols.
-228
View File
@@ -1,228 +0,0 @@
---
description: Audit existing docs against live code, then create a comprehensive GitHub issue in PraisonAIDocs with correct, tested information ready for a writer/agent to implement immediately
---
# Create PraisonAIDocs Issue Workflow
Audit code → Compare with existing docs → Draft correct content → Create issue.
> **When to use this:** A feature is already implemented in PraisonAI but the docs are missing, outdated, or wrong. You need to file a self-contained docs issue in `MervinPraison/PraisonAIDocs` that a writer or agent can act on without asking follow-up questions.
> **When NOT to use this:** Use `@[/create-github-issue]` for new integrations that need external research. Use `@[/local-fix]` if you are writing the docs yourself.
---
## Phase 1 — Identify the Feature & Existing Docs
### 1a. Find the relevant doc file
```bash
ls /Users/praison/PraisonAIDocs/docs/<section>/
cat /Users/praison/PraisonAIDocs/docs/<section>/<feature>.mdx
```
Key doc sections:
- `docs/observability/` — tracing providers (Langfuse, LangSmith, etc.)
- `docs/tools/` — tool integrations
- `docs/features/` — agent features
- `docs/cli/` — CLI commands
- `docs/guides/` — how-to guides
### 1b. Read the existing doc fully
Note every claim that needs verification:
- Install commands
- Import statements
- API method names and signatures
- Environment variable names
- CLI commands
---
## Phase 2 — Audit the Live Code
### 2a. Find the source implementation
```bash
# Search praisonaiagents core SDK
grep -rn "<feature>" /Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/ 2>&1 | grep -v ".pyc"
# Search praisonai wrapper (CLI, integrations)
grep -rn "<feature>" /Users/praison/praisonai-package/src/praisonai/praisonai/ 2>&1 | grep -v ".pyc"
# Search praisonai-tools
grep -rn "<feature>" /Users/praison/PraisonAI-tools/ 2>&1 | grep -v ".pyc"
```
### 2b. Read all relevant source files end-to-end
Read every file that implements the feature. For each file capture:
- Actual class/function names and signatures
- Required vs optional parameters
- Environment variables read (exact names)
- What gets called internally (trace the call chain)
- Any version-specific behavior
Key files to always check:
| File pattern | What to look for |
|---|---|
| `praisonaiagents/obs/__init__.py` | `_LazyObsModule`, factory methods, `auto()` |
| `praisonai_tools/observability/providers/<name>_provider.py` | `init()`, `is_available()`, `shutdown()`, `flush()` |
| `praisonai/observability/<name>.py` | CLI sink adapter, event handling |
| `praisonai/cli/commands/<name>.py` | All CLI sub-commands and options |
| `praisonai/__init__.py` | Global env var overrides that may interfere |
### 2c. Test the feature live
Run minimal test scripts to verify the actual behavior:
```bash
# Test the import works
python3 -c "from praisonaiagents.obs import obs; provider = obs.<name>(); print(type(provider).__name__, provider._initialized)"
# Test CLI commands
praisonai <feature> --help
praisonai <feature> <subcommand>
# Verify traces/output appear
timeout 30 praisonai <feature> <subcommand> --limit 5
```
### 2d. Build a "What's Wrong" table
For each doc claim that is incorrect, record:
| Current Doc (Wrong) | Correct |
|---|---|
| wrong install command | correct install |
| wrong import | correct import |
| non-existent method | actual method |
| wrong env var name | actual env var |
---
## Phase 3 — Draft the Issue
The issue body must be **self-contained and implementation-ready**. A writer should be able to update the doc by reading only the issue — no follow-up questions.
### Required sections:
```markdown
## Overview
One paragraph: what doc file needs updating, why it's wrong, and the end goal.
State explicitly: "All code in this issue has been tested and verified working."
## What's Wrong With the Current Docs
Table: Current (Wrong) | Correct
Cover: install commands, imports, API methods, env vars, missing sections.
## Correct Architecture (How It Actually Works)
Explain the actual internal call chain so the writer understands context.
Include a text diagram if helpful.
## Required Install
Exact pip commands, nothing more.
## Environment Variables
Table: Variable | Required | Description
Show bash export examples for both cloud and self-hosted.
## Python Usage
### Quickstart (Recommended)
Full working code with correct imports, init, agent run, and flush.
### Auto-Detection
Document obs.auto() or equivalent if applicable.
### Additional Patterns
Any other valid usage patterns (explicit provider, multi-agent, etc.).
## CLI Usage (if applicable)
All sub-commands with flags and examples.
Include an end-to-end CLI session example.
## Configuration File (if applicable)
Document any config files that are auto-created or auto-read.
## What Output Looks Like
Show what traces/output actually look like after a successful run.
## Version Compatibility Notes
Document any breaking changes between SDK versions that affect usage.
## Files to Update
Table: File | Change
## Acceptance Criteria
- [ ] Checkbox list — each item must be specific and verifiable
## References
List all source files read (with absolute paths).
```
---
## Phase 4 — Create the Issue
### 4a. Write body to a temp file
```bash
cat > /tmp/docs_issue_<feature>.md << 'EOF'
<issue body>
EOF
```
### 4b. Create via `gh` CLI
```bash
gh issue create \
--repo MervinPraison/PraisonAIDocs \
--title "Docs: <action verb> <feature> page — <one-line summary of what's wrong>" \
--label "documentation" \
--body-file /tmp/docs_issue_<feature>.md
```
**Title format:** `Docs: Rewrite/Update/Add <Feature> page — <what's wrong or missing>`
Examples:
- `Docs: Rewrite Langfuse integration page with correct Langfuse v4 API and CLI commands`
- `Docs: Add obs.auto() documentation to observability overview`
- `Docs: Fix LangSmith install command and update import paths`
### 4c. Verify
```bash
gh issue view <number> --repo MervinPraison/PraisonAIDocs | head -30
```
Confirm the URL: `https://github.com/MervinPraison/PraisonAIDocs/issues/<number>`
---
## Checklist — Before Creating the Issue
- [ ] Existing doc file read completely
- [ ] All source files implementing the feature read end-to-end (not skimmed)
- [ ] Feature tested live — not just code-read
- [ ] "What's Wrong" table is complete and specific
- [ ] All code examples in the issue are copy-pastable and tested
- [ ] All env var names are verified against source (not guessed)
- [ ] All CLI commands verified with `--help` and live run
- [ ] Acceptance criteria are specific and verifiable (not vague)
- [ ] References list includes all source file paths read
- [ ] Issue is self-contained — writer needs no follow-up
---
## Quick Reference — Common Mistakes
| Mistake | Fix |
|---|---|
| Documenting what the code *should* do, not what it *does* | Run it. Test it. Document the actual behavior. |
| Copying import paths from docs being replaced | Always verify imports against source files |
| Missing the "What's Wrong" table | This is the most important section — be explicit |
| Vague acceptance criteria like "docs are updated" | Write specific, testable criteria: "install command is `pip install langfuse`" |
| Not checking for interfering globals (e.g. `OTEL_SDK_DISABLED`) | Always grep `__init__.py` files for env var overrides |
| Forgetting `provider.flush()` in examples | Async buffers need explicit flush before process exit |
| Not testing with a real API key | Code-reading alone misses runtime errors |
| Using `timeout` too short for first-run (downloads, auth) | Use `timeout 120` for agent runs, `timeout 30` for CLI |
-308
View File
@@ -1,308 +0,0 @@
---
description: Research a topic in-depth, analyze both external and local codebases, and create a comprehensive GitHub issue — ready for another agent/developer to act on immediately
---
# Create GitHub Issue Workflow
Research → Clone & Analyze → PraisonAI Analysis → Draft → Create Issue.
> **When to use this:** You need to create a detailed, implementation-ready GitHub issue for a new integration, feature, or benchmark. The issue must contain enough context that another agent or developer can implement it without asking further questions.
> **When NOT to use this:** Use `@[/local-fix]` if you are implementing the change yourself, not just filing an issue.
---
## Phase 1 — Online Research
### 1a. Read official sources
Research the topic from all primary sources: official site, GitHub repo, documentation, blog posts.
```bash
# Example searches (adapt to your topic)
# - Official site / announcement pages
# - GitHub README and docs
# - Third-party write-ups (e.g. Snorkel AI, Epoch AI)
# - Framework documentation (core concepts, agents, running)
```
URLs to read for each source (use `read_url_content` tool):
- Official announcement / news page
- GitHub repository README (multiple chunks if large)
- Framework/integration documentation pages
- Any relevant blog posts or analysis
**Capture for the issue:**
- What is it? Purpose and design goals
- Key terminology and concepts (with definitions)
- Architecture overview
- Current leaderboard / ecosystem state
- References list (all URLs)
### 1b. Read paginated content
For large pages, read additional chunks:
```
view_content_chunk(document_id=<url>, position=2)
view_content_chunk(document_id=<url>, position=3)
view_content_chunk(document_id=<url>, position=4)
```
Continue until all relevant sections are read (core concepts, agent types, running instructions, integration API).
---
## Phase 2 — Clone & Analyze External Codebase
### 2a. Clone the repository
```bash
git clone <repo-url> ~/<repo-name> --depth=1
```
### 2b. Explore structure
```bash
ls -la ~/<repo-name>/
ls -la ~/<repo-name>/src/
```
Key files to read (adapt paths to repo):
- `AGENTS.md` / `CLAUDE.md` / `README.md` — architecture overview
- Base class files (e.g. `base.py` for agents, environments)
- Factory / registry files (how things are registered)
- Model/config files (data structures agents must populate)
- Enum files (valid names, types)
- Example agent implementations (minimal + full-featured)
- `pyproject.toml` — Python version, dependencies
**Capture for the issue:**
- Repository structure diagram
- Key file paths with line counts
- Base class interface (all abstract methods with signatures)
- How to register a new agent (enum + factory pattern)
- Data models the agent must populate (`AgentContext`, etc.)
- Example agent implementations (minimal and production)
- CLI commands to run the integration
- Environment variables required
### 2c. Read base classes end-to-end
Read every relevant base class completely. For agent integrations:
```
read_file(base.py) # BaseAgent / BaseInstalledAgent
read_file(factory.py) # AgentFactory registration
read_file(models/agent/name.py) # AgentName enum
read_file(models/agent/context.py) # AgentContext fields
read_file(examples/agents/minimal_agent.py) # Minimal example
read_file(agents/installed/reference_agent.py) # Full example
```
### 2d. Read a reference implementation
Pick the most complete existing agent implementation (e.g. `codex.py`, `gemini_cli.py`) and read it fully. This reveals:
- Install pattern (system packages → user packages)
- Version detection (`get_version_command` / `parse_version`)
- `@with_prompt_template` decorator usage
- `populate_context_post_run` for token tracking
- ATIF trajectory support (`SUPPORTS_ATIF`)
- `CliFlag` / `EnvVar` declarative config
- `exec_as_root` vs `exec_as_agent` usage
---
## Phase 3 — Analyze PraisonAI Codebase
### 3a. Identify relevant components
```bash
ls /Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/
ls /Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/tools/
ls /Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/agent/
```
Key files to read for agent integration issues:
| File | What to look for |
|------|-----------------|
| `praisonaiagents/tools/shell_tools.py` | `execute_command`, approval decorators |
| `praisonaiagents/agent/agent.py` | `Agent.start()`, `Agent.chat()`, token tracking |
| `praisonaiagents/approval/` | `@require_approval`, auto-approval backend |
| `praisonaiagents/eval/` | Evaluation framework hooks |
| `praisonaiagents/agents/agents.py` | `AgentTeam` multi-agent |
| `pyproject.toml` | Current version, optional dependencies |
### 3b. Map integration points
For each PraisonAI component, document:
- What it does
- How it maps to the external system's interface
- What needs bridging (e.g. wrapping `environment.exec()` as a tool)
- Known gotchas (e.g. `@require_approval` must be bypassed in containers)
---
## Phase 4 — Draft the Issue
The issue body must be self-contained. Another agent must be able to implement the feature by reading only the issue — no follow-up questions.
### Required sections:
```markdown
## Overview
One paragraph: what, why, and the end goal.
## Background: What is <X>?
- Purpose and design goals
- Key statistics (task count, solve rates, etc.)
- Why <X> + PraisonAI is valuable
- Current ecosystem / leaderboard state
## <X> Architecture (Codebase Analysis)
> Repo analyzed locally: `~/<repo-name>` (cloned at `~/<repo-name>`)
### Core Concepts
Table: Concept | Description
### Two (or N) Integration Types
Code examples for each type with full signatures.
### Key File Locations in <X> Codebase
Directory tree with annotations for each important file.
### Data Models
Full class definitions the agent must populate.
### How to Run (CLI)
All relevant CLI commands with flags and examples.
## PraisonAI Architecture (Relevant to This Integration)
Table: Component | Location | Relevance
### PraisonAI Execution Model
How PraisonAI currently handles the relevant operations, and what must be adapted.
## Proposed Implementation Plan
### Approach: <Recommended> (with justification)
### Phase 1: Minimal Proof-of-Concept
Full working code example.
### Phase 2: Production Implementation
Full working code example.
### Phase N: Advanced Features
(ATIF, multi-agent, etc.)
## Files to Create / Modify
### New files (praisonai-package)
Table: File | Purpose
### Modifications to <External Repo> (PR upstream)
Table: File | Change
## Technical Considerations
Subsections for:
- Container/environment dependencies
- API key forwarding
- Safety/approval bypass
- Token tracking
- Parallel execution safety
## Job / Config Example
Working YAML config + CLI invocation.
## Use Cases Unlocked
Table: Use Case | How
## Acceptance Criteria
- [ ] Checkbox list of verifiable outcomes
## Implementation Notes for the Assigned Agent/Developer
### Key <X> Files to Read First
Numbered list with file paths and line counts.
### Key PraisonAI Files to Read
Numbered list with file paths.
### Critical Integration Points
Numbered list of the exact code-level bridges needed.
### Architecture Decision
Why the chosen approach (installed vs external, etc.) with trade-offs.
### Installation & Testing Commands
Copy-pastable commands to install, verify, and run.
### Upstream PR
What to submit upstream and where.
## References
Bullet list of all URLs used.
```
---
## Phase 5 — Create the Issue
### 5a. Create via `gh` CLI
```bash
gh issue create \
--repo <org>/<repo> \
--title "Feature: <Descriptive Title>" \
--label "enhancement" \
--body "<issue body>"
```
**Title format:** `Feature: <What> with <Integration> (<Framework/Version>)`
Example:
```bash
gh issue create \
--repo MervinPraison/PraisonAI \
--title "Feature: Integrate PraisonAI Agents with Terminal-Bench 2.0 (Harbor Framework)" \
--label "enhancement" \
--body "..."
```
### 5b. Verify the issue was created
```bash
gh issue view <issue-number> --repo <org>/<repo> | head -20
```
The output URL confirms success: `https://github.com/<org>/<repo>/issues/<number>`
---
## Checklist — Before Creating the Issue
- [ ] All primary documentation URLs read (including paginated chunks)
- [ ] External repo cloned locally and analyzed
- [ ] Base classes read end-to-end (not just skimmed)
- [ ] At least one reference implementation read fully
- [ ] PraisonAI codebase analyzed for integration points
- [ ] Issue body has working code examples (not pseudocode)
- [ ] All file paths are absolute and verified to exist
- [ ] CLI commands are copy-pastable and complete
- [ ] Acceptance criteria are verifiable (not vague)
- [ ] References section includes all URLs used
- [ ] Issue is self-contained — no "see docs for details" without the details
---
## Quick Reference — Common Mistakes
| Mistake | Fix |
|---------|-----|
| Pseudocode in examples | Use real, runnable code with imports |
| Vague file paths like `agents/` | Use absolute paths like `~/harbor/src/harbor/agents/base.py` |
| Missing `--depth=1` on clone | Large repos take forever; always use shallow clone |
| Only reading chunk 0 of a URL | Read chunks 1–4+ for paginated content |
| Skipping the factory/registry file | This is where registration happens; always read it |
| Not reading a reference agent | Pattern is not obvious from base class alone |
| Forgetting API key forwarding section | Always document how secrets are passed to containers |
| Skipping `populate_context_post_run` | Harbor uses this for token tracking and leaderboard data |
| Missing upstream PR instructions | Specify exact files to modify upstream for first-class support |
-190
View File
@@ -1,190 +0,0 @@
---
description: create and publish a post on mer.vin using praisonaiwp
---
## Config
- Server: `default` → `https://mer.vin`
- Config: `~/.praisonaiwp/config.yaml`
- Category for PraisonAI features: `PraisonAI`
---
## Step 1 — Compose the content
Structure every post as:
1. **Intro paragraph** — one sentence, what the feature solves
2. **Mermaid diagram** — architecture/flow (see block format below)
3. **Sections** — H2 headings, tables > prose, code blocks for usage
4. **Performance/summary** — table with concrete numbers
Keep it technical. Lead with diagrams and tables, not paragraphs.
---
## Step 2 — Mermaid block format (merpress)
> **Creating merpress:** Install the [Merpress – Mermaid for WordPress](https://wordpress.org/plugins/merpress/) plugin via `wp plugin install merpress --activate --allow-root` on the server. It adds the `wp:merpress/mermaidjs` block used below.
All posts use the native `wp:merpress/mermaidjs` block. Use this exact format:
```
<!-- wp:merpress/mermaidjs {"align":"full"} -->
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid alignfull"><pre class="mermaid">%%{init: {"theme": "base", "themeVariables": {"background": "transparent", "lineColor": "#000000"}}}%%
graph TD
A[Input] --> B[Agent]
B --> C[Tool]
C --> D[Output]
classDef hook fill:#189AB4,color:#fff
classDef agent fill:#8B0000,color:#fff
classDef decision fill:#444,color:#fff
class B agent
class C hook
</pre></div>
<!-- /wp:merpress/mermaidjs -->
```
**Do NOT use:** `[mermaid]...[/mermaid]` shortcode — that is the wrong format.
Color scheme:
- `#8B0000` (dark red) — agents, inputs, outputs
- `#189AB4` (teal) — tools, hooks
- `#444` — decisions/conditionals
---
## Step 2a — SVG/image upload via SSH
`praisonaiwp media upload` correctly SFTPs the file to `/tmp/` on the server, but
`_execute_wp()` in `~/praisonaiwp-cli/praisonaiwp/core/wp_client.py` never appends
`--allow-root`. Use direct SSH instead.
**SVG upload (Safe SVG plugin active on mer.vin):**
```bash
# 1. SCP SVG to server
scp -i ~/.ssh/id_ed25519 /path/to/diagram.svg <SSH_USER>@<SERVER_IP>:/tmp/
# 2. Import via WP-CLI — must pass --user=<admin> so Safe SVG capability check passes
ssh -i ~/.ssh/id_ed25519 <SSH_USER>@<SERVER_IP> \
"cd <WP_ROOT> && \
wp media import /tmp/diagram.svg --post_id=<POST_ID> \
--title='Title' --alt='Alt' --user=praison --allow-root --porcelain"
# → returns media ID
# 3. Get the URL
ssh -i ~/.ssh/id_ed25519 <SSH_USER>@<SERVER_IP> \
"cd <WP_ROOT> && \
wp post get <MEDIA_ID> --field=guid --allow-root"
```
> **Key:** `--user=praison` is required — Safe SVG checks upload capability against the
> current WP user. Without it, even with the plugin active, SVG imports are blocked.
**PNG fallback (if Safe SVG not available):**
```bash
rsvg-convert -w 1360 /path/to/diagram.svg -o /tmp/diagram_2x.png
# Then follow the same SSH steps above using the .png file (no --user needed)
```
Use this Gutenberg image block in the post content:
```
<!-- wp:image {"id":<MEDIA_ID>,"sizeSlug":"full","linkDestination":"none"} -->
<figure class="wp-block-image size-full"><img src="<IMAGE_URL>" alt="Alt text" class="wp-image-<MEDIA_ID>"/></figure>
<!-- /wp:image -->
```
---
## Step 3 — Create the post
```bash
praisonaiwp create "Post Title" \
--status publish \
--content '<FULL GUTENBERG CONTENT>'
```
Note the returned **Post ID** from the output.
---
## Step 4 — Set category
```bash
praisonaiwp update <POST_ID> --category "PraisonAI"
```
---
## Step 5 — Validate mermaid format
```bash
ssh -i ~/.ssh/id_ed25519 <SSH_USER>@<SERVER_IP> \
"cd <WP_ROOT> && \
wp post get <POST_ID> --field=post_content --allow-root | grep -i mermaid"
```
Expected output must contain `wp:merpress/mermaidjs`, not `[mermaid]`.
---
## Key Gutenberg blocks reference
```
<!-- wp:paragraph --><p>text</p><!-- /wp:paragraph -->
<!-- wp:heading --><h2 class="wp-block-heading">Title</h2><!-- /wp:heading -->
<!-- wp:heading {"level":3} --><h3 class="wp-block-heading">Sub</h3><!-- /wp:heading -->
<!-- wp:code --><pre class="wp-block-code"><code>code here</code></pre><!-- /wp:code -->
<!-- wp:table -->
<figure class="wp-block-table"><table>
<thead><tr><th>Col</th></tr></thead>
<tbody><tr><td>Val</td></tr></tbody>
</table></figure>
<!-- /wp:table -->
<!-- wp:list --><ul class="wp-block-list"><li>item</li></ul><!-- /wp:list -->
<!-- wp:separator --><hr class="wp-block-separator has-alpha-channel-opacity"/><!-- /wp:separator -->
```
---
## Full example command
```bash
praisonaiwp create "Feature Name: What It Does" \
--status publish \
--content '<!-- wp:paragraph -->
<p>One sentence intro.</p>
<!-- /wp:paragraph -->
<!-- wp:heading -->
<h2 class="wp-block-heading">Architecture</h2>
<!-- /wp:heading -->
<!-- wp:merpress/mermaidjs {"align":"full"} -->
<div class="wp-block-merpress-mermaidjs diagram-source-mermaid alignfull"><pre class="mermaid">%%{init: {"theme": "base", "themeVariables": {"background": "transparent", "lineColor": "#000000"}}}%%
graph TD
A[Start] --> B[Agent]
class B agent
classDef agent fill:#8B0000,color:#fff
</pre></div>
<!-- /wp:merpress/mermaidjs -->
<!-- wp:code -->
<pre class="wp-block-code"><code>from praisonaiagents import Agent
agent = Agent(name="example")
result = agent.start("task")</code></pre>
<!-- /wp:code -->'
# Then set category:
praisonaiwp update <ID> --category "PraisonAI"
```
@@ -1,677 +0,0 @@
---
description: End-to-end workflow — deep analysis → GitHub issue → wait for implementing agents → create PR if missing → wait for reviewing agents → review PR locally → feedback to @claude → merge to main when robust per AGENTS.md
---
# End-to-End: Analysis → Issue → PR → Review → Merge
Deep Analysis → Gap Analysis → Critical Review → Plan → Create Issue → **Wait for implementing agents** → **Create PR if missing** → **Wait for reviewers** → **Validate PR locally** → **Feedback to @claude** → **Re-review after fixes** → **Merge to main if robust**.
> **When to use this:** You want a fully hands-off delivery loop. You describe a feature/integration/fix; this workflow produces the issue, monitors implementation by other agents (Claude, Copilot, CodeRabbit), validates their PR locally against `AGENTS.md` principles, loops feedback until the PR is robust, and merges to `main`.
> **When NOT to use this:** Use `/analysis-github-issue-create` if you only want the issue (no PR/merge). Use `/local-fix` if you are the implementer.
---
## PRINCIPLES (apply throughout)
- **Agent-centric**: Agents, workflows, sessions, tools, memory, multi-agent safety.
- **Protocol-driven core**: `praisonaiagents` = lightweight, protocol-first (protocols/hooks/adapters only).
- **DRY**: identify reuse; avoid duplication.
- **No perf impact**: preserve import-time and hot-path; heavy deps optional + lazy.
- **Async-safe + multi-agent safe** by default.
- **Easy for non-developers**: "Few lines of code to do the task!"
- **No competitor names in public surfaces**: Never mention competitor product, company, or project names in GitHub issues, PRs, commit messages, release notes, docs, or any other public-facing content. Refer to capabilities generically (e.g., "self-improving agent pattern", "external agent framework").
- **Test before merge**: never merge unvalidated PRs. Always clone the branch locally and run the tests.
- **Minimal code change**: prefer upstream one-line fixes over downstream workarounds.
- **Autonomous polling — NEVER ask the user to "check now"**: after posting feedback to `@claude`, submitting a trigger comment, or any state that requires an external agent to push commits, the assistant itself waits ~10 minutes (`sleep 600`) and then re-checks. Do not stop and wait for the human to type "check now". Only surface control back to the human when a round is fully complete (PR merged or 3-round feedback cap hit) or a blocking decision is required (e.g. rebase strategy, conflicting feature intent).
---
## CANONICAL PATHS
```
Core SDK: /Users/praison/praisonai-package/src/praisonai-agents (praisonaiagents)
Wrapper: /Users/praison/praisonai-package/src/praisonai (praisonai)
Tools: /Users/praison/PraisonAI-tools
Docs: /Users/praison/PraisonAIDocs
TypeScript: /Users/praison/praisonai-package/src/praisonai-ts
AGENTS.md: /Users/praison/praisonai-package/src/praisonai-agents/AGENTS.md
```
---
# PART A — ANALYSIS & ISSUE (Phases 1–9)
These phases are identical to `/analysis-github-issue-create`. Execute them in order. **Do not implement any code** in these phases — they produce analysis and an issue only.
## Phase 1 — Acceptance Criteria
Translate the request into testable criteria:
- API expectations (classes, methods, signatures)
- CLI expectations (commands, flags, help text)
- Documentation expectations (pages, examples)
- Test expectations (unit, integration, smoke, real agentic)
- Performance constraints (import time, hot-path)
---
## Phase 2 — External Research (if applicable)
### 2a. Read official sources
If analyzing an external integration, research from primary sources:
```bash
# Use read_url_content tool for:
# - Official site / announcement pages
# - GitHub README and docs
# - Framework documentation
# - Third-party write-ups
```
**Capture:**
- What is it? Purpose and design goals
- Key terminology and concepts
- Architecture overview
- Current ecosystem state
- References list (all URLs)
### 2b. Clone & analyze external codebase (if applicable)
```bash
git clone <repo-url> ~/<repo-name> --depth=1
ls -la ~/<repo-name>/
```
Key files to read:
- `AGENTS.md` / `README.md` — architecture overview
- Base class files (abstract methods, signatures)
- Factory / registry files (registration pattern)
- Model/config files (data structures)
- Example implementations (minimal + full-featured)
- `pyproject.toml` / `package.json` — dependencies
---
## Phase 3 — PraisonAI Codebase Inventory
### 3a. Inventory with evidence
Go through ALL relevant files, understand current logic end-to-end.
```bash
# Core SDK
ls /Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/
grep -r "class.*Protocol" praisonaiagents/ --include="*.py" | wc -l
# Wrapper
ls /Users/praison/praisonai-package/src/praisonai/praisonai/
ls /Users/praison/praisonai-package/src/praisonai/praisonai/cli/commands/
# TypeScript
ls /Users/praison/praisonai-package/src/praisonai-ts/src/
```
**Document:**
- Public APIs: modules/classes/functions and exports
- Protocols/adapters/hooks and extension points
- CLI commands, options, help text
- Integrations (db/observability/tools)
- Tests (unit/integration), fixtures, CI config
- Docs (Mintlify), examples, recipes
Provide: **file paths + key symbols + grep counts + entry points**.
### 3b. Identify DRY opportunities
- Existing abstractions that can be reused
- Duplicated code that should be consolidated
- Existing protocols before creating new ones
---
## Phase 4 — Detailed Analysis
### 4a. Architecture and behavior
- Control flow and data flow
- Concurrency model (sync/async)
- Multi-agent interactions
- Dependency boundaries (core/wrapper/tools)
- Failure modes and error handling
### 4b. Invariants check
Verify these are preserved:
- [ ] Protocol-driven core (no heavy impls in `praisonaiagents`)
- [ ] Lazy imports (optional deps never at module level)
- [ ] Backward compatible (public API changes need deprecation)
- [ ] Safe defaults (new features opt-in)
---
## Phase 5 — Gap Analysis
Compare acceptance criteria vs current state.
### Checklist
| Area | Current State | Gap | Severity | Impact | Placement |
|------|---------------|-----|----------|--------|-----------|
| Core SDK | | | | | |
| Wrapper | | | | | |
| Tools/plugins | | | | | |
| CLI | | | | | |
| Docs | | | | | |
| Tests | | | | | |
| Exports | | | | | |
| Perf | | | | | |
| Multi-agent + async | | | | | |
### Gap severity levels
- **Critical**: Blocks functionality
- **High**: Significant limitation
- **Medium**: Missing feature
- **Low**: Nice-to-have
---
## Phase 6 — Critical Review
### 6a. Risks and footguns
- API ambiguity or edge cases
- Backward compatibility concerns
- Coupling violations
- Performance regressions
- Concurrency hazards
- Misuse risks
- Operational concerns
### 6b. Mitigation strategies
For each risk, document:
- "Safe by default" recommendation
- Explicit opt-in for dangerous behavior
- Documentation warnings
---
## Phase 7 — Implementation Plan
Step-by-step plan (DO NOT implement):
### 7a. Test-first (TDD)
1. Unit tests for new functionality
2. Integration tests for cross-component behavior
3. Smoke tests for quick validation
4. **Real agentic tests** (REQUIRED):
```python
from praisonaiagents import Agent
agent = Agent(name="test", instructions="You are helpful")
result = agent.start("Say hello in one sentence")
print(result) # Must call LLM and produce response
```
### 7b. Implementation order
1. Tests (TDD)
2. Core implementation
3. CLI integration
4. Documentation
5. Verification
### 7c. Files to change/create
| File | Action | Purpose |
|------|--------|---------|
| | | |
### 7d. Verification commands
```bash
# Unit tests
pytest tests/unit/test_<feature>.py -v
# Integration tests
pytest tests/integration/test_<feature>.py -v
# Smoke test
python -c "from praisonaiagents import <Feature>; print('OK')"
# Real agentic test
python examples/<feature>_example.py
```
---
## Phase 8 — Draft GitHub Issue
The issue must be **self-contained**. Another agent must be able to implement by reading only the issue.
### Required sections
```markdown
## Overview
One paragraph: what, why, and the end goal.
## Background
- Purpose and design goals
- Why this is valuable
- Current state / ecosystem
## Architecture Analysis
### Current Implementation
- Key files and their purposes
- Integration points
- Data flow
### Key File Locations
| File | Purpose | Lines |
|------|---------|-------|
## Gap Analysis Summary
### Critical Gaps
| Gap | Impact | Effort |
|-----|--------|--------|
### Feature Gaps
| Feature | Current Support | Gap |
|---------|-----------------|-----|
## Proposed Implementation
### Phase 1: Minimal
Working code example.
### Phase 2: Production
Working code example.
## Files to Create / Modify
### New files
| File | Purpose |
|------|---------|
### Modified files
| File | Change |
|------|--------|
## Technical Considerations
- Dependencies
- Performance impact
- Safety / approval
- Multi-agent safety
## Acceptance Criteria
- [ ] Verifiable checkbox list
## Implementation Notes
### Key Files to Read First
1. `path/to/file.py` (N lines) — purpose
### Critical Integration Points
1. Where X connects to Y
### Testing Commands
```bash
# Copy-pastable commands
```
## References
- [Link](url)
```
---
## Phase 9 — Create GitHub Issue
### 9a. Create via `gh` CLI
```bash
gh issue create \
--repo MervinPraison/PraisonAI \
--title "<Type>: <Descriptive Title>" \
--body-file /tmp/issue-body.md
```
**Title formats:**
- `Feature: <What>` — new functionality
- `Integration: <External System>` — external integration
- `Fix: <Problem>` — bug fix proposal
### 9b. Record the issue number
```bash
ISSUE_NUM=$(gh issue view <number> --repo MervinPraison/PraisonAI --json number --jq '.number')
echo "Tracking issue #$ISSUE_NUM"
```
---
# PART B — IMPLEMENTATION MONITORING (Phases 10–15)
After the issue is filed, other agents (`@claude`, GitHub Copilot agent, CodeRabbit) pick it up automatically. This part watches, shepherds, validates, and merges.
## Phase 10 — Wait ~10 min for implementing agents
After `gh issue create`, Claude and Copilot typically start work within seconds and finish a first pass in 5–15 minutes.
```bash
echo "Waiting 10 minutes for implementing agents..."
echo "Start: $(date)"
sleep 600
echo "End: $(date)"
```
### Then check: did they open a PR?
```bash
REPO=MervinPraison/PraisonAI
ISSUE_NUM=<number>
# Check for PRs that reference the issue
gh pr list --repo $REPO --state open --search "fixes #$ISSUE_NUM OR closes #$ISSUE_NUM" --json number,title,headRefName
# Also check for branches matching claude/issue-<N>-* naming convention
gh api repos/$REPO/branches --paginate --jq ".[] | select(.name | startswith(\"claude/issue-$ISSUE_NUM\")) | .name"
```
---
## Phase 11 — Create PR if none exists
If Claude pushed a branch but did not open a PR, open one yourself.
```bash
REPO=MervinPraison/PraisonAI
ISSUE_NUM=<number>
BRANCH=$(gh api repos/$REPO/branches --paginate --jq ".[] | select(.name | startswith(\"claude/issue-$ISSUE_NUM\")) | .name" | head -1)
if [ -n "$BRANCH" ]; then
TITLE=$(gh api repos/$REPO/commits/$BRANCH --jq '.commit.message' | head -1)
gh pr create --repo $REPO --head "$BRANCH" --base main \
--title "$TITLE" \
--body "Automated PR from Claude's work on issue #$ISSUE_NUM.
Branch: \`$BRANCH\`
Closes #$ISSUE_NUM"
fi
```
### If no branch exists after 10 minutes
Re-trigger Claude by commenting on the issue, then wait another 10 minutes and re-check:
```bash
gh issue comment $ISSUE_NUM --repo $REPO \
--body "@claude please pick up this issue — full analysis and plan are in the issue body."
sleep 600
```
---
## Phase 12 — Wait ~10 min for reviewing agents
Once a PR exists, `CodeRabbit`, `Copilot`, and CI pipelines run. Give them time to complete.
```bash
echo "Waiting 10 minutes for PR reviewers and CI..."
sleep 600
```
### Collect status
```bash
PR=<pr-number>
gh pr view $PR --repo $REPO --json state,mergeable,mergeStateStatus,updatedAt,commits,files \
| python -c "
import json,sys
d=json.load(sys.stdin)
print(f\" State: {d['state']} Mergeable: {d['mergeable']} MergeState: {d['mergeStateStatus']}\")
print(f\" Commits: {len(d['commits'])}\")
for f in d['files']:
print(f\" {f['path']}: +{f['additions']} -{f['deletions']}\")
"
# CI & review checks
gh pr view $PR --repo $REPO --json statusCheckRollup > /tmp/pr-checks.json
python -c "
import json
for c in json.load(open('/tmp/pr-checks.json'))['statusCheckRollup']:
s = c.get('conclusion') or c.get('status','?')
name = c.get('name') or c.get('context','?')
if s and s not in ('SKIPPED',):
print(f' {name}: {s}')
"
```
---
## Phase 13 — Validate the PR locally
**Never merge an unvalidated PR.** Always clone the branch and run tests.
```bash
REPO_URL=https://github.com/MervinPraison/PraisonAI.git
BRANCH=<branch-name>
WORKDIR=/tmp/pr-validate
rm -rf $WORKDIR
git clone --depth 1 --branch "$BRANCH" $REPO_URL $WORKDIR
cd $WORKDIR
# Files touched by the PR
gh pr view $PR --repo $REPO --json files --jq '.files[].path'
# Run the tests for changed files — ALWAYS use timeout (user global rule)
timeout 120 python -m pytest <test-paths> -v --tb=short
# Critical invariant checks (adapt per feature):
# 1) Lazy-import: heavy deps never imported at module level
timeout 30 python - <<'PY'
import sys
from praisonai.observability import <NewThing> # example
assert 'heavy_dep' not in sys.modules, "eager import — violates AGENTS.md §4.2"
print("OK: lazy import preserved")
PY
# 2) Cold-import benchmark (no regression)
timeout 30 python -c "import time; t=time.time(); import praisonaiagents; print(f'{(time.time()-t)*1000:.1f} ms')"
```
### Mergeability gate
A PR is **ready to merge only if ALL of these are true**:
- [ ] `gh pr view` reports `mergeable=MERGEABLE` and `mergeStateStatus` in `CLEAN`/`UNSTABLE` (not `DIRTY`/`BLOCKED`).
- [ ] All `test (3.x)` matrix jobs report `SUCCESS`.
- [ ] Local `pytest` on the changed test files passes with **zero failures** (skipped/xfailed tests are OK).
- [ ] Lazy-import invariant preserved (if the feature adds an optional dep).
- [ ] Cold-import time within ±2 % of `main` (AGENTS.md §4.2).
- [ ] No files outside the issue's declared scope were changed.
- [ ] The diff respects all invariants in AGENTS.md §4.6.
If **any** is false → go to Phase 14 (feedback). Do not merge.
---
## Phase 14 — Feedback to `@claude` when issues found
When validation fails, post a precise, actionable comment tagging `@claude`, referencing the exact test name, error, file, and the AGENTS.md principle violated.
```bash
gh pr comment $PR --repo $REPO --body "$(cat <<'EOF'
Hold on merge: validated locally on HEAD `<short-sha>` and found these issues:
**Test failures:**
```
FAILED tests/.../test_x.py::TestY::test_z
AssertionError: <actual-message>
```
**Root cause:** <one-line diagnosis referencing the exact file and line>.
**AGENTS.md violation(s):**
- §<section>: <principle>
**Requested fix (minimal):**
- Change `<file>:<line>` to `<what>`.
- Or update the test assertion to `<what>` (if the test is wrong, not the code).
**What already passes:**
- N/M tests pass.
- Lazy-import invariant preserved ✅ (or not — state explicitly).
@claude please push a fix. Follow AGENTS.md principles: minimal change, protocol-driven, no perf impact, lazy imports, backward-compatible, safe defaults. Make sure the PR is robust — run the tests locally before force-pushing.
EOF
)"
```
### Loop
After commenting:
```bash
echo "Waiting 10 minutes for Claude to push fixes..."
sleep 600
# → return to Phase 12 (fetch new commits, re-run checks)
```
**The assistant runs this `sleep 600` itself — it does NOT pause the loop to ask the user "check now".** After the 10-minute wait completes, the assistant immediately re-fetches the PR, re-runs the test suite, and either merges, posts the next feedback round, or reports a final status. The human is only prompted when:
- The PR merges successfully (report + move to next issue).
- The 3-round feedback cap is hit (escalate).
- A design decision is needed that the assistant cannot make unilaterally (e.g. "should `allow` policy persist or not?").
Repeat Phases 12 → 13 → 14 until the mergeability gate in Phase 13 is fully green, or escalate to a human after 3 failed rounds.
### When the PR has merge conflicts
If `mergeStateStatus=DIRTY`, ask Claude to rebase rather than resolving conflicts yourself on non-trivial logic:
```bash
gh pr comment $PR --repo $REPO --body "@claude this PR has merge conflicts with \`main\` (PR #<X> was merged, touching the same regions). Please rebase onto latest \`main\`, re-run \`pytest <paths>\`, and force-push."
```
---
## Phase 15 — Merge to `main`
Once Phase 13's gate is fully green:
### 15a. Final diff review against AGENTS.md
```bash
gh pr diff $PR --repo $REPO | less
```
**Hard gate — every box must be ticked before merge:**
- [ ] **Protocol-driven core (§4.1)**: no heavy implementations leaked into `praisonaiagents`.
- [ ] **No perf impact (§4.2)**: lazy imports confirmed; import benchmark within ±2 %.
- [ ] **DRY (§4.3)**: no new duplication; existing protocols/adapters reused where possible.
- [ ] **Agent-centric (§4.4)**: API centers on agents/sessions/tools/memory.
- [ ] **Async-safe + multi-agent safe (§4.5)**: no shared mutable globals; locks where needed.
- [ ] **Invariants preserved (§4.6)**: backward compatible, safe defaults, deterministic tests.
- [ ] **Naming conventions (§4.9)**: `XProtocol` for interfaces, `XAdapter` for impls, `add_*`/`get_*`/`save`/`load` verbs.
- [ ] No `.md` files added beyond those explicitly requested (per user global rule).
- [ ] Tests run locally with `timeout` — never hang (per user global rule).
### 15b. Merge
```bash
gh pr merge $PR --repo $REPO --squash --delete-branch
# --squash preserves linear main; --delete-branch keeps the repo clean
```
### 15c. Verify
```bash
gh pr view $PR --repo $REPO --json state,mergedAt,mergeCommit
gh issue view $ISSUE_NUM --repo $REPO --json state # should auto-close
```
---
# Orchestration Snippet (one-shot reference)
For a single end-to-end invocation, chain Part B phases:
```bash
#!/usr/bin/env bash
set -euo pipefail
REPO=MervinPraison/PraisonAI
ISSUE_NUM=<fill>
# Phase 10: wait for implementing agents
sleep 600
# Phase 11: ensure PR exists
BRANCH=$(gh api repos/$REPO/branches --paginate \
--jq ".[] | select(.name | startswith(\"claude/issue-$ISSUE_NUM\")) | .name" | head -1)
PR=$(gh pr list --repo $REPO --state open --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null || true)
if [ -z "$PR" ] && [ -n "$BRANCH" ]; then
TITLE=$(gh api repos/$REPO/commits/$BRANCH --jq '.commit.message' | head -1)
gh pr create --repo $REPO --head "$BRANCH" --base main \
--title "$TITLE" --body "Closes #$ISSUE_NUM"
PR=$(gh pr list --repo $REPO --state open --head "$BRANCH" --json number --jq '.[0].number')
fi
echo "Tracking PR #$PR"
# Phase 12: wait for reviewers + CI
sleep 600
# Phases 13–14: validate + feedback loop (cap at 3 rounds)
for round in 1 2 3; do
echo "=== Validation round $round ==="
# clone + pytest (per feature) — if green break; else gh pr comment + sleep 600
break # placeholder
done
# Phase 15: merge
gh pr merge $PR --repo $REPO --squash --delete-branch
gh issue view $ISSUE_NUM --repo $REPO --json state
```
---
## Checklist — Before Merging
- [ ] Issue exists and describes the work
- [ ] PR exists and references the issue (`Closes #N`)
- [ ] Branch was fetched and tests were run **locally** — not just CI-trusted
- [ ] All PR-relevant tests pass with zero failures
- [ ] CI matrix (3.10 / 3.11 / 3.12) is all green
- [ ] Lazy-import / cold-import invariants verified if optional deps added
- [ ] Diff reviewed against every AGENTS.md §4 principle
- [ ] `mergeStateStatus` in `CLEAN`/`UNSTABLE`, never `DIRTY`/`BLOCKED`
- [ ] No files outside the issue's scope were changed
- [ ] If feedback was given, `@claude` had a chance to respond and fixed everything
---
## Quick Reference — Common Mistakes
| Mistake | Fix |
|---------|-----|
| Merging without running tests locally | Always `git clone` the branch and run `pytest` |
| Resolving complex conflicts manually | Ask `@claude` to rebase instead |
| Trusting CI alone | CI jobs can be skipped / out-of-date; local validation is source of truth |
| Vague feedback to `@claude` | Every comment must cite file, line, test name, error, and AGENTS.md section |
| Waiting forever | Cap loops at 3 rounds, then escalate to a human |
| Running commands without `timeout` | Always `timeout 60 ...` per user global rule |
| Creating `.md` docs proactively | Don't — user rule forbids unrequested `.md` files |
| Skipping diff review | Every merge needs a full-diff AGENTS.md pass |
---
## Hard Rules
1. **Never merge without local test validation.**
2. **Never merge when `mergeStateStatus = DIRTY` or `BLOCKED`.**
3. **Every `@claude` comment must be actionable** — file, line, exact fix, AGENTS.md ref.
4. **Cap feedback loops at 3 rounds** — escalate after that, don't spin forever.
5. **Use `--squash --delete-branch`** to keep `main` linear and the repo clean.
6. **Always verify** the issue auto-closed after merge.
7. **All `run_command` calls use `timeout`** to avoid hangs (user global rule).
8. **No proactive `.md` creation** beyond this workflow file (user global rule).
9. **Never ask the user "check now"**: between rounds the assistant runs `sleep 600` itself and keeps driving. Only return control to the human on merge, 3-round cap, or an irresolvable design decision.
-771
View File
@@ -1,771 +0,0 @@
---
description: Gap Implementation Prompts — Sequential agent tasks for PraisonAIUI feature gaps
---
# Gap Implementation Prompts
Execute these prompts **sequentially**, one at a time. Each prompt is self-contained with context, analysis steps, and implementation instructions. Complete one fully (analysis → implementation → verification) before starting the next.
Reference: gap_analysis.md in the project's brain directory for full context.
---
---
## PROMPT 1: Channel Management Tab (G1 — Phase 1, Critical)
You are an expert AI engineer. Your task: **Add a Channel Management dashboard tab to PraisonAIUI** that surfaces the existing bot channel infrastructure from the PraisonAI package.
### Context
PraisonAI package already has a full channel/bot system:
- **Bots directory**: `~/praisonai-package/src/praisonai/praisonai/bots/` (26 files)
- Discord bot: `discord.py`, `_discord_approval.py`
- Slack bot: `slack.py`, `_slack_approval.py`
- Telegram bot: `telegram.py`, `_telegram_approval.py`
- WhatsApp bot: `whatsapp.py`, `_whatsapp_web_adapter.py`
- Base infra: `bot.py`, `_session.py`, `_rate_limit.py`, `_resilience.py`, `_approval.py`, `_approval_base.py`, `_http_approval.py`, `_webhook_approval.py`, `media.py`, `_commands.py`, `_debounce.py`, `_ack.py`, `_chunk.py`, `_protocol_mixin.py`, `_config_schema.py`, `_registry.py`
- **Gateway**: `~/praisonai-package/src/praisonai/praisonai/gateway/server.py` (1102 lines, 41KB)
- `WebSocketGateway.health()` — returns per-channel bot health status
- `WebSocketGateway.start_channels(channels_cfg)` — starts bot instances from config
- `WebSocketGateway._create_bot(channel_type, token, agent, config, ch_cfg)` — creates bot per channel
- `WebSocketGateway._run_bot_safe(name, bot)` — runs with error isolation
- `WebSocketGateway._inject_routing_handler(channel_name, bot)` — routing-aware handlers
PraisonAIUI server: `~/PraisonAIUI/src/praisonaiui/server.py` — Starlette app with SSE streaming, existing dashboard tabs via `/api/*` endpoints and `@page()` decorator.
PraisonAIUI frontend dashboard: `~/PraisonAIUI/src/praisonaiui/templates/frontend/plugins/` — JavaScript plugins for dashboard tabs (e.g., `topnav.js` for tab rendering).
### PHASE 1 — Analysis (MUST complete before implementing)
1. **Inventory the bot system**: Read every file in `~/praisonai-package/src/praisonai/praisonai/bots/`. Understand:
- How each bot is initialized (constructor params, tokens, agent binding)
- What status/health information each bot exposes
- How `_resilience.py` tracks bot health
- How `_config_schema.py` defines channel configuration
- How `_registry.py` registers available channels
2. **Inventory the gateway**: Read `~/praisonai-package/src/praisonai/praisonai/gateway/server.py`. Understand:
- `WebSocketGateway.health()` — what data it returns about channels
- `start_channels()` — how channels are started from YAML config
- `_create_bot()` — bot factory pattern
- Channel routing: `_determine_routing_context()`, `_resolve_agent_for_message()`
3. **Inventory PraisonAIUI dashboard**: Read `~/PraisonAIUI/src/praisonaiui/server.py`. Understand:
- How existing `/api/*` endpoints work (pattern for adding new ones)
- How `@page()` decorator registers dashboard pages
- How `_registered_pages` dict works
- How dashboard tabs are rendered in the frontend
4. **Inventory the frontend**: Read `~/PraisonAIUI/src/praisonaiui/templates/frontend/plugins/topnav.js` and other dashboard plugins. Understand:
- How tabs are dynamically rendered
- How tab data is fetched from `/api/*` endpoints
- The pattern for adding a new dashboard tab
5. **Gap Analysis**: Document exactly what's missing:
- Backend: API endpoint to query channel status
- Frontend: Dashboard tab component for channels
- Integration: How PraisonAIUI will communicate with the gateway for channel health
6. **Plan**: Produce a step-by-step implementation plan listing exact files to create/modify.
### PHASE 2 — Implementation (MUST)
1. **Backend — Add `/api/channels` endpoint** in `~/PraisonAIUI/src/praisonaiui/server.py`:
- `GET /api/channels` — Returns list of configured channels with status (name, type, health, connected, last_active)
- `POST /api/channels/{name}/restart` — Restart a specific channel bot
- The endpoint should integrate with the gateway's `health()` method or maintain its own channel registry
- Follow the exact pattern of existing `/api/overview`, `/api/config` endpoints
2. **Frontend — Add Channels dashboard page**:
- Create a new dashboard plugin or add to existing dashboard rendering
- Show a card/table for each channel: icon, name, status (online/offline/error), message count, last activity
- Add status indicators (green/yellow/red dots)
- Add restart button per channel
- Follow the existing dashboard tab rendering pattern from `topnav.js`
3. **Register the tab**: Ensure the Channels tab appears in the dashboard navigation alongside existing tabs (Agents, Config, Logs)
### PHASE 3 — Verification (MUST)
1. Run the PraisonAIUI dev server and verify the Channels tab appears
2. Verify `/api/channels` returns correct data
3. Verify the UI renders channel cards with accurate status
4. Test with at least one bot configured and verify status updates
5. Verify no regressions in existing dashboard tabs
6. Document what was implemented and what remains
---
---
## PROMPT 2: Scheduler/Cron Tab (G2 — Phase 1, Critical)
You are an expert AI engineer. Your task: **Add a Scheduler dashboard tab to PraisonAIUI** that surfaces the existing AgentScheduler from the PraisonAI package.
### Context
PraisonAI package has a complete scheduler system:
- **Scheduler directory**: `~/praisonai-package/src/praisonai/praisonai/scheduler/` (7 files)
- `agent_scheduler.py` (21KB) — `AgentScheduler` class:
- `__init__(agent, task, config, on_success, on_failure, timeout, max_cost)`
- `start(schedule_expr, max_retries, run_immediately)` — schedule expressions: `"hourly"`, `"daily"`, `"*/6h"`, `"3600"` (seconds)
- `stop()` — graceful shutdown
- `get_stats()` — execution stats including cost
- `execute_once()` — one-time run
- `from_yaml(yaml_path, ...)` — create from agents.yaml
- `from_recipe(recipe_name, ...)` — create from recipe
- `start_from_yaml_config()` — start using YAML schedule config
- `daemon_manager.py` (7KB) — background process lifecycle
- `state_manager.py` (4KB) — persistent execution state
- `base.py` (4KB) — `ScheduleParser`, `PraisonAgentExecutor` base classes
- `yaml_loader.py` (6KB) — YAML schedule config loading
- **Top-level**: `~/praisonai-package/src/praisonai/praisonai/agent_scheduler.py` (11KB) — convenience wrapper
PraisonAIUI: `~/PraisonAIUI/src/praisonaiui/server.py` — Starlette app. Existing pattern: API endpoints return JSON, dashboard renders tabs.
### PHASE 1 — Analysis (MUST complete before implementing)
1. **Read the full scheduler system**: Go through every file in `~/praisonai-package/src/praisonai/praisonai/scheduler/`:
- `agent_scheduler.py` — understand the full `AgentScheduler` lifecycle (init → start → _run_schedule → _execute_with_retry → stop)
- `base.py` — understand `ScheduleParser.parse()` for schedule expression formats
- `daemon_manager.py` — understand how daemon processes are managed (start/stop/status)
- `state_manager.py` — understand how execution state is persisted (where, format)
- `yaml_loader.py` — understand YAML config format for schedules
2. **Understand the data model**: What data does a scheduled agent have?
- Schedule expression, agent identity, task description, max retries, timeout, max cost
- Execution stats: total_runs, successful_runs, failed_runs, total_cost, last_run, next_run
3. **Inventory PraisonAIUI**: Read `server.py` to understand the pattern for adding CRUD API endpoints.
4. **Gap Analysis**: Document exactly what's needed:
- API: CRUD endpoints for schedules (list, create, update, delete, run-now, get-stats)
- Storage: Where to persist schedule definitions (YAML file? database? in-memory?)
- Frontend: Scheduler tab with schedule list, create/edit form, run history
5. **Plan**: Step-by-step with exact files to create/modify.
### PHASE 2 — Implementation (MUST)
1. **Backend — Add Scheduler API endpoints** in `~/PraisonAIUI/src/praisonaiui/server.py`:
- `GET /api/schedules` — List all scheduled agents with status and stats
- `POST /api/schedules` — Create a new schedule (agent, task, schedule_expr, max_retries, timeout, max_cost)
- `PUT /api/schedules/{id}` — Update schedule configuration
- `DELETE /api/schedules/{id}` — Remove a schedule
- `POST /api/schedules/{id}/run` — Trigger immediate execution
- `POST /api/schedules/{id}/stop` — Stop a running schedule
- `GET /api/schedules/{id}/stats` — Get execution statistics
- Integrate with `AgentScheduler` class from praisonai-package, importing it appropriately
2. **Backend — Schedule persistence**:
- Store schedule definitions in a YAML/JSON file alongside the existing config
- Load schedules on server startup and start them automatically
- Track run history in-memory with periodic flush
3. **Frontend — Add Scheduler dashboard page**:
- Schedule list: table/cards showing each schedule (name, expression, status, last run, next run, cost)
- Create/Edit form: agent selector, task input, schedule expression picker (presets: hourly/daily/weekly + custom cron), retry/timeout/cost settings
- Run history: expandable section per schedule showing past executions with results
- Action buttons: Start, Stop, Run Now, Edit, Delete
- Status indicators: Running (green pulse), Stopped (gray), Failed (red)
4. **Register the tab**: Add Scheduler tab to dashboard navigation.
### PHASE 3 — Verification (MUST)
1. Create a test schedule with a simple agent task and verify it appears in the UI
2. Test start/stop/run-now actions
3. Verify execution stats update after runs
4. Verify schedules persist across server restarts
5. Verify no regressions in existing functionality
6. Document what was implemented
---
---
## PROMPT 3: Jobs Management Tab (G3 — Phase 1, Critical)
You are an expert AI engineer. Your task: **Add a Jobs Management dashboard tab to PraisonAIUI** that surfaces the existing async Jobs API from the PraisonAI package.
### Context
PraisonAI package has a complete async jobs system:
- **Jobs directory**: `~/praisonai-package/src/praisonai/praisonai/jobs/` (6 files)
- `executor.py` (14KB) — `JobExecutor` class:
- `__init__(store, max_concurrent, default_timeout, cleanup_interval)`
- `submit(job)` — submit job for execution
- `cancel(job_id)` — cancel running job
- `start()` / `stop()` — executor lifecycle
- `register_progress_callback(job_id, callback)` — real-time progress
- `_run_agent(job)` / `_run_recipe(job)` / `_run_praisonai_agents(job)` — multiple execution modes
- `_send_webhook(job)` — webhook notifications on completion
- `get_stats()` — executor statistics
- `router.py` (11KB) — FastAPI router (`create_router(store, executor)`):
- `POST /jobs` → `submit_job` (returns 202 + Location header + Retry-After)
- `GET /jobs` → `list_jobs` (filter by status, session_id, pagination)
- `GET /jobs/{id}/status` → `get_job_status`
- `GET /jobs/{id}/result` → `get_job_result` (409 if not complete)
- `DELETE /jobs/{id}/cancel` → `cancel_job` (409 if already complete)
- `DELETE /jobs/{id}` → `delete_job` (only completed)
- `GET /jobs/{id}/stream` → `stream_job` (SSE: status/progress/result/error events)
- Supports idempotency via `Idempotency-Key` header
- `models.py` (10KB) — `Job`, `JobStatus`, `JobSubmitRequest`, `JobSubmitResponse`, `JobStatusResponse`, `JobResultResponse`, `JobListResponse`
- `store.py` (7KB) — `JobStore` — in-memory + persistent storage
- `server.py` (5KB) — standalone server mounting the router
### PHASE 1 — Analysis (MUST complete before implementing)
1. **Read the full jobs system**: Go through every file in `~/praisonai-package/src/praisonai/praisonai/jobs/`:
- `models.py` — understand all DTOs and status enum
- `store.py` — understand storage backend (how jobs are persisted, queried)
- `executor.py` — understand execution lifecycle (submit → execute → complete/fail)
- `router.py` — understand all HTTP endpoints and their contracts
- `server.py` — understand how the standalone server mounts the router
2. **Determine integration approach**: The jobs router is a FastAPI router. PraisonAIUI uses Starlette. Determine:
- Can the jobs router be mounted directly in PraisonAIUI's Starlette app?
- Or do we need to adapt the endpoints?
- How to share the `JobStore` and `JobExecutor` instances with the main app
3. **Gap Analysis**: Document what's needed:
- Backend: Mount or adapt the jobs router into PraisonAIUI
- Frontend: Jobs dashboard showing job list, status, progress, results with real-time SSE updates
4. **Plan**: Step-by-step with exact files.
### PHASE 2 — Implementation (MUST)
1. **Backend — Mount Jobs API** in PraisonAIUI:
- Initialize `JobStore` and `JobExecutor` in `create_app()`
- Mount the jobs router at `/api/jobs/*` or adapt endpoints to Starlette
- Ensure the executor starts when the app starts and stops when it stops
2. **Frontend — Add Jobs dashboard page**:
- Jobs list: table with columns (ID, agent, status, progress %, submitted, duration, cost)
- Status badges: Pending (gray), Running (blue pulse), Completed (green), Failed (red), Cancelled (yellow)
- Real-time progress: Use SSE from `/jobs/{id}/stream` to update progress bars
- Job detail view: expandable row showing full result, error message, webhook status
- Actions: Submit new job (form), Cancel running job, Delete completed job
- Filters: by status, date range, agent
3. **Register the tab**: Add Jobs tab to dashboard navigation.
### PHASE 3 — Verification (MUST)
1. Submit a test job via the UI and verify it appears in the list
2. Verify real-time progress updates via SSE
3. Test cancel and delete actions
4. Verify job results are displayed correctly after completion
5. Verify no regressions
6. Document what was implemented
---
---
## PROMPT 4: Usage Analytics Upgrade (G6 — Phase 1, Critical)
You are an expert AI engineer. Your task: **Upgrade PraisonAIUI's usage analytics** from basic token counters to per-model cost tracking with time-series charts.
### Context
Current state in PraisonAIUI (`~/PraisonAIUI/src/praisonaiui/server.py`):
- `_usage_stats` — simple in-memory dict tracking basic token counts
- `GET /api/usage` — returns this dict as JSON
- No cost calculation, no per-model breakdown, no time-series data, no charts
OpenClaw comparison: ~80KB of usage view code with per-model costs, per-session breakdown, time-series charts, export functionality.
### PHASE 1 — Analysis (MUST complete before implementing)
1. **Read PraisonAIUI usage tracking**: Read `server.py` and search for `_usage_stats`, understand:
- Where/when usage is tracked (during `run_agent`, on SSE events)
- What data is currently captured (input_tokens, output_tokens, total_tokens)
- How the data flows from agent execution to the stats dict
2. **Research model pricing**: Understand common LLM pricing models:
- OpenAI: per-1K tokens, different rates for input vs output, varies by model
- Anthropic: per-1K tokens, input vs output
- Google: per-1K tokens
- Design a cost table data structure
3. **Design time-series storage**: Plan how to store usage data over time:
- In-memory ring buffer with periodic flush to disk? SQLite? JSON file?
- Granularity: per-request? per-minute? per-hour?
- Retention: how much history to keep?
4. **Plan**: Step-by-step with exact files.
### PHASE 2 — Implementation (MUST)
1. **Backend — Enhanced usage tracking**:
- Create a `UsageTracker` class (or enhance the existing tracking in `server.py`):
- Track per-request: model, input_tokens, output_tokens, cost, timestamp, session_id, agent_name
- Maintain aggregations: by model, by session, by agent, by time period
- Cost calculation: configurable cost table (price per 1K input/output tokens per model)
- Update `/api/usage` to return rich data:
- `GET /api/usage` — summary (total cost, total tokens, by model, by period)
- `GET /api/usage/details` — detailed time-series data for charts
- `GET /api/usage/models` — per-model breakdown
- `GET /api/usage/sessions` — per-session breakdown
2. **Backend — Cost table**:
- Default cost table with common LLM model pricing
- Configurable via YAML config (`cost_per_model` section)
- Auto-detect model from provider responses
3. **Frontend — Usage analytics dashboard**:
- Summary cards: Total cost ($), Total tokens, Requests count, Avg cost per request
- Chart: Token/cost usage over time (line chart, selectable time range: 1h/24h/7d/30d)
- Model breakdown: Bar chart or table showing cost per model
- Session breakdown: Table showing per-session usage
- Use a lightweight charting library (e.g., Chart.js via CDN, or SVG-based inline charts)
4. **Persistence**: Save usage data to a JSON/SQLite file so it survives server restarts.
### PHASE 3 — Verification (MUST)
1. Run an agent chat and verify usage data is captured with model and cost
2. Verify `/api/usage` returns enriched data
3. Verify charts render correctly in the dashboard
4. Verify data persists across server restarts
5. Verify no performance impact on chat response times
6. Document what was implemented
---
---
## PROMPT 5: Skills/Tools Management Tab (G4 — Phase 2, High)
You are an expert AI engineer. Your task: **Add a Skills/Tools Management dashboard tab to PraisonAIUI** that surfaces available tools and allows enable/disable/configuration.
### Context
PraisonAI package has tool infrastructure:
- **Capabilities**: `~/praisonai-package/src/praisonai/praisonai/capabilities/` (27 files)
- `skills.py` (3KB) — skills endpoint
- `completions.py`, `responses.py`, `assistants.py`, `files.py`, `images.py`, `audio.py`, `embeddings.py`, `fine_tuning.py`, `batches.py`, `guardrails.py`, `moderations.py`, `ocr.py`, `rag.py`, `realtime.py`, `rerank.py`, `search.py`, `videos.py`, `mcp.py`, `a2a.py`, `messages.py`, `vector_stores.py`, `container_files.py`, `containers.py`, `passthrough.py`
- **Tool resolver**: `~/praisonai-package/src/praisonai/praisonai/tool_resolver.py` (14KB) — dynamic tool resolution by name
- **Tools directory**: `~/praisonai-package/src/praisonai/praisonai/tools/` — audio.py, glob_tool.py, grep_tool.py, multiedit.py
- **Inbuilt tools**: `~/praisonai-package/src/praisonai/praisonai/inbuilt_tools/` — autogen_tools.py
- **Skills examples**: `~/praisonai-package/examples/skills/` — basic_skill_usage.py, create_skill_example.py, custom_skill_example.py
### PHASE 1 — Analysis (MUST complete before implementing)
1. **Read the tool/skills system**:
- `capabilities/skills.py` — understand the skills endpoint interface
- `tool_resolver.py` — understand how tools are discovered, resolved, loaded
- `tools/` directory — understand the built-in tool pattern
- `capabilities/__init__.py` — understand how capabilities are registered and discovered
- Skills examples — understand the user-facing skill creation pattern
2. **Understand capability registration**: How does PraisonAI know which capabilities are available?
- Are they auto-discovered? Explicitly registered? Config-driven?
- Can individual capabilities be enabled/disabled?
3. **Gap Analysis**: Document what's needed:
- API: Endpoint to list tools, get tool details, enable/disable, set API keys
- Frontend: Skills tab with tool catalog, status toggles, API key configuration
- Integration: How to wire capability enable/disable to the provider system
4. **Plan**: Step-by-step with exact files.
### PHASE 2 — Implementation (MUST)
1. **Backend — Skills API** in PraisonAIUI:
- `GET /api/skills` — List all available tools/skills with status (name, type, enabled, description, required_keys)
- `PUT /api/skills/{name}` — Enable/disable a skill
- `PUT /api/skills/{name}/config` — Set API keys or configuration for a skill
- `GET /api/skills/{name}` — Get detailed info about a specific skill
2. **Frontend — Skills dashboard page**:
- Tool catalog: Grid/list of available tools with icons, names, descriptions
- Status toggles: Enable/disable switch per tool
- Configuration: Expandable config section per tool for API keys and settings
- Categories: Group by type (built-in, capabilities, custom)
- Search/filter: Find tools by name or category
3. **Register the tab**: Add Skills tab to dashboard navigation.
### PHASE 3 — Verification (MUST)
1. Verify the skills list loads with correct tool inventory
2. Test enable/disable toggle and verify it affects agent tool availability
3. Test API key configuration
4. Verify no regressions
5. Document what was implemented
---
---
## PROMPT 6: Agent CRUD from Dashboard (G7 — Phase 2, High)
You are an expert AI engineer. Your task: **Add full Agent CRUD (Create, Update, Delete) to the PraisonAIUI dashboard**, extending beyond the current read-only agent listing.
### Context
Current state:
- PraisonAIUI `server.py`: `GET /agents` returns a list of registered agents (read-only)
- PraisonAI gateway: `WebSocketGateway.register_agent(agent, agent_id)` and `unregister_agent(agent_id)` exist
- Agents are currently registered programmatically via Python code, not from the UI
OpenClaw comparison: Full agent CRUD with file editing (system prompt, instructions), tool profile overrides (allow/deny lists), identity management (name, avatar).
### PHASE 1 — Analysis (MUST complete before implementing)
1. **Read the agent system end-to-end**:
- `~/PraisonAIUI/src/praisonaiui/server.py` — how agents are registered, listed, used during `run_agent`
- `~/praisonai-package/src/praisonai/praisonai/gateway/server.py` — `register_agent()`, `unregister_agent()`, `get_agent()`, `list_agents()`, `_create_agents_from_config()`
- Understand the Agent class from praisonaiagents: what properties can be configured?
2. **Understand agent configuration format**:
- How are agents defined in YAML? What fields?
- System prompt, instructions, tool lists, model selection, temperature, etc.
- How are agents loaded from config at startup?
3. **Design the CRUD model**: What data does agent create/update need?
- Name, description, system prompt, instructions, model, temperature
- Tool allow/deny lists
- Avatar/icon
4. **Plan**: Step-by-step with exact files.
### PHASE 2 — Implementation (MUST)
1. **Backend — Agent CRUD endpoints** in PraisonAIUI:
- `GET /agents` — (existing) List agents with full details
- `POST /agents` — Create a new agent (name, description, system_prompt, instructions, model, tools, config)
- `PUT /agents/{id}` — Update agent configuration
- `DELETE /agents/{id}` — Remove an agent
- `GET /agents/{id}` — Get detailed agent info including system prompt and tools
- Persist agent definitions to a YAML/JSON file
2. **Frontend — Agent editor**:
- Agent list with Create New button
- Agent editor form: name, description, model selector, temperature slider
- System prompt editor: multi-line text area with syntax highlighting
- Instructions editor: multi-line text area
- Tool configuration: checkbox list of available tools
- Save/Cancel/Delete buttons
- Inline validation
3. **Integration**: New/updated agents should be live-registerable without server restart.
### PHASE 3 — Verification (MUST)
1. Create a new agent from the dashboard and verify it appears in the list
2. Edit an agent's system prompt and verify the change takes effect in chat
3. Delete an agent and verify it's removed
4. Verify agents persist across server restarts
5. Document what was implemented
---
---
## PROMPT 7: Exec Approval Dashboard (G5 — Phase 2, High)
You are an expert AI engineer. Your task: **Add an Execution Approval dashboard to PraisonAIUI** that surfaces the existing approval system from the PraisonAI package bots.
### Context
PraisonAI package has a comprehensive approval system:
- **Approval infrastructure** in `~/praisonai-package/src/praisonai/praisonai/bots/`:
- `_approval.py` — Core approval logic
- `_approval_base.py` — Base class for approval backends
- `_discord_approval.py` — Discord-specific approval flow
- `_slack_approval.py` — Slack-specific approval flow
- `_telegram_approval.py` — Telegram-specific approval flow
- `_http_approval.py` — HTTP webhook-based approvals
- `_webhook_approval.py` — Webhook notification for approvals
The approval system allows agents to request human approval before executing certain actions (tool calls, external API calls, destructive operations).
### PHASE 1 — Analysis (MUST complete before implementing)
1. **Read the full approval system**:
- `_approval_base.py` — understand the base protocol/interface for approvals
- `_approval.py` — understand the core approval lifecycle (request → pending → approve/deny)
- `_http_approval.py` — understand the HTTP-based approval mechanism (this is most relevant for UI integration)
- Each channel-specific approval file — understand how they present approval requests
2. **Understand the approval data model**:
- What information is in an approval request? (agent, tool, arguments, risk level, timestamp)
- What are the possible actions? (approve, deny, approve-always, deny-always)
- How are policies stored? (auto-approve lists, always-deny lists)
3. **Determine integration approach**:
- Can `_http_approval.py` be extended to serve as the UI backend?
- Or do we need a separate approval queue accessible from PraisonAIUI?
- Real-time: WebSocket for instant approval notifications?
4. **Plan**: Step-by-step with exact files.
### PHASE 2 — Implementation (MUST)
1. **Backend — Approval API** in PraisonAIUI:
- `GET /api/approvals` — List pending approval requests
- `POST /api/approvals/{id}/approve` — Approve a request
- `POST /api/approvals/{id}/deny` — Deny a request
- `GET /api/approvals/policies` — List approval policies (auto-approve, always-deny)
- `PUT /api/approvals/policies` — Update policies
- `GET /api/approvals/history` — Past approval decisions
- WebSocket or SSE endpoint for real-time approval notifications
2. **Frontend — Approval dashboard page**:
- Pending queue: Cards showing each pending request with agent name, action, arguments, risk level, timestamp
- Approve/Deny buttons with optional "always" checkbox
- Policy editor: Configure auto-approve/deny rules per tool, per agent
- History: Table of past approvals with decision, timestamp, details
- Real-time: New approvals appear instantly via WebSocket/SSE
- Notification badge on the tab showing pending count
3. **Register the tab**: Add Approvals tab to dashboard navigation with badge.
### PHASE 3 — Verification (MUST)
1. Configure an agent with an approval-required tool
2. Trigger the tool and verify an approval request appears in the dashboard
3. Approve it and verify the agent continues execution
4. Deny a request and verify the agent handles it gracefully
5. Test auto-approve policy and verify it works
6. Document what was implemented
---
---
## PROMPT 8: OpenAI-Compatible API Routes (G — Phase 2, High)
You are an expert AI engineer. Your task: **Mount PraisonAI's 27 OpenAI-compatible capability endpoints in PraisonAIUI** so they are accessible via `/v1/*` routes.
### Context
PraisonAI package has 27 OpenAI-compatible capability endpoints:
- **Directory**: `~/praisonai-package/src/praisonai/praisonai/capabilities/` (27 files)
- Key endpoints: `completions.py`, `responses.py`, `assistants.py`, `files.py`, `images.py`, `audio.py`, `embeddings.py`, `fine_tuning.py`, `batches.py`, `guardrails.py`, `moderations.py`, `ocr.py`, `rag.py`, `realtime.py`, `rerank.py`, `search.py`, `skills.py`, `videos.py`, `mcp.py`, `a2a.py`, `messages.py`, `vector_stores.py`, `container_files.py`, `containers.py`, `passthrough.py`
- `__init__.py` (9KB) — likely contains registration/routing logic
PraisonAIUI uses Starlette. The capabilities likely use FastAPI routers.
### PHASE 1 — Analysis (MUST complete before implementing)
1. **Read `capabilities/__init__.py`**: Understand how capabilities are registered, what router/app they expose
2. **Read `completions.py`**: Understand the endpoint pattern (request/response format, OpenAI compatibility)
3. **Read `responses.py`**: Understand the responses API endpoint
4. **Understand the mount pattern**: How to integrate FastAPI routers into Starlette apps
5. **Plan**: Determine which capabilities to mount, routing prefix (`/v1/`), authentication, and configuration
### PHASE 2 — Implementation (MUST)
1. **Mount capabilities in PraisonAIUI**:
- Import the capabilities router/app from praisonai-package
- Mount at `/v1/` prefix in PraisonAIUI's Starlette app (in `create_app()`)
- Ensure proper CORS, authentication, and error handling
- Key routes: `/v1/chat/completions`, `/v1/responses`, `/v1/embeddings`, `/v1/images/generations`, etc.
2. **Configuration**: Add capability enable/disable flags in PraisonAIUI config YAML
3. **Documentation**: Add API docs endpoint or link to capability documentation
### PHASE 3 — Verification (MUST)
1. Test `/v1/chat/completions` with a standard OpenAI SDK client
2. Test `/v1/responses` endpoint
3. Verify compatibility with OpenAI Python SDK
4. Verify no regressions in existing PraisonAIUI functionality
5. Document the available endpoints
---
---
## PROMPT 9: Real-Time Log Streaming (G9 — Phase 3, Polish)
You are an expert AI engineer. Your task: **Upgrade PraisonAIUI's log viewer from polling to real-time WebSocket streaming**.
### Context
Current state in PraisonAIUI (`~/PraisonAIUI/src/praisonaiui/server.py`):
- `_log_buffer` — in-memory deque (500 entries max)
- `GET /api/logs` — returns the entire buffer as JSON (polling-based)
- Frontend polls this endpoint periodically
Goal: Real-time log tailing via WebSocket, with level filtering and search.
### PHASE 1 — Analysis (MUST complete before implementing)
1. **Read current logging implementation**: Search `server.py` for `_log_buffer`, understand how logs are captured and stored
2. **Understand Python logging integration**: How are Python logger messages routed to `_log_buffer`?
3. **Design WebSocket approach**: Plan the WebSocket endpoint, message format, filtering protocol
4. **Plan**: Step-by-step with exact files.
### PHASE 2 — Implementation (MUST)
1. **Backend — WebSocket log endpoint**:
- `WS /api/logs/stream` — WebSocket endpoint that streams log entries in real-time
- Support filter parameters: `level` (DEBUG/INFO/WARNING/ERROR), `search` (text match)
- Keep the existing `GET /api/logs` for backward compatibility
- Use Python logging handler that broadcasts to connected WebSocket clients
2. **Frontend — Enhanced log viewer**:
- Real-time log display with auto-scroll
- Level filter buttons (DEBUG, INFO, WARNING, ERROR) with color coding
- Search box for text filtering
- Pause/resume button to stop auto-scroll
- Clear button
- Timestamp formatting
- Log level color coding (gray=DEBUG, blue=INFO, yellow=WARNING, red=ERROR)
### PHASE 3 — Verification (MUST)
1. Connect to the WebSocket and verify real-time log streaming
2. Test level filtering
3. Test search filtering
4. Verify auto-scroll and pause/resume
5. Verify backward compatibility of `GET /api/logs`
6. Document what was implemented
---
---
## PROMPT 10: Config Form Editor (G8 — Phase 3, Polish)
You are an expert AI engineer. Your task: **Upgrade PraisonAIUI's config editor from raw YAML to a schema-driven form editor**.
### Context
Current state:
- PraisonAIUI `server.py`: `GET /api/config` returns raw YAML, `POST /api/config` writes raw YAML
- PraisonAI package: `bots/_config_schema.py` — configuration schema definition
- No form rendering, no validation, no guided editing
OpenClaw comparison: Full schema-validated form rendering with live apply.
### PHASE 1 — Analysis (MUST complete before implementing)
1. **Read current config handling**: `server.py` → `api_config_handler`, `load_config_from_yaml`
2. **Read `_config_schema.py`**: Understand the config schema format (JSON Schema? Custom?)
3. **Understand the config structure**: What sections exist? (provider, model, channels, agents, scheduler, etc.)
4. **Design form rendering**: Plan how to render schema-driven forms in the frontend
5. **Plan**: Step-by-step with exact files.
### PHASE 2 — Implementation (MUST)
1. **Backend — Config schema endpoint**:
- `GET /api/config/schema` — Return the config schema (JSON Schema format)
- `POST /api/config/validate` — Validate config changes before applying
- `POST /api/config/apply` — Apply config changes with validation and live reload
2. **Frontend — Form editor**:
- Tab within the Config page: "Form View" vs "YAML View" toggle
- Auto-generated form from JSON Schema:
- Text inputs for strings, number inputs for numbers
- Toggle switches for booleans
- Dropdowns for enums (model selection, provider selection)
- Nested sections with collapsible panels
- Validation: Real-time validation with error messages
- Save button with confirmation
- Reset to defaults button
- Keep raw YAML editor as alternative view
### PHASE 3 — Verification (MUST)
1. Verify the form renders all config sections correctly
2. Test editing a config value via form and verify it's saved
3. Test validation with invalid values
4. Verify toggle between form and YAML views
5. Verify config changes take effect without restart (where possible)
6. Document what was implemented
---
---
## PROMPT 11: Session Advanced Operations (G10 — Phase 3, Polish)
You are an expert AI engineer. Your task: **Add advanced session operations to PraisonAIUI**: reset context, compact memory, and session preview.
### Context
Current state in PraisonAIUI (`server.py`):
- `GET /sessions` — List sessions
- `GET /sessions/{id}` — Get session detail
- `GET /sessions/{id}/runs` — Get message history
- `DELETE /sessions/{id}` — Delete session
- `PATCH /sessions/{id}` — Rename/tag session
- `POST /sessions` — Create session
Missing (present in OpenClaw): Reset context (clear memory but keep session), Compact memory (summarize old messages to reduce context), Preview (rich preview of session content).
### PHASE 1 — Analysis (MUST complete before implementing)
1. **Read current session system** in `server.py`: Understand how sessions store messages, how context is managed
2. **Read session system in praisonai-package**: `bots/_session.py` — understand session state management
3. **Design**: Plan reset (clear messages, keep metadata), compact (LLM-summarize old messages), preview (formatted message display)
4. **Plan**: Step-by-step with exact files.
### PHASE 2 — Implementation (MUST)
1. **Backend — Advanced session endpoints**:
- `POST /sessions/{id}/reset` — Clear all messages but keep session metadata
- `POST /sessions/{id}/compact` — Summarize old messages using the LLM, replace them with a summary message
- `GET /sessions/{id}/preview` — Return formatted preview (first/last messages, total count, token estimate)
2. **Frontend — Enhanced session management**:
- Add action buttons to session list: Reset, Compact, Preview
- Reset confirmation dialog
- Compact: Show before/after message count and token savings
- Preview: Modal showing session summary without loading full history
### PHASE 3 — Verification (MUST)
1. Test reset: verify messages are cleared, session metadata preserved
2. Test compact: verify old messages are replaced with a summary
3. Test preview: verify formatted preview is returned
4. Verify no regressions in existing session operations
5. Document what was implemented
---
---
## PROMPT 12: Auth Enhancements (G11 — Phase 3, Polish)
You are an expert AI engineer. Your task: **Enhance PraisonAIUI's authentication** from a single `require_auth` flag to multi-mode auth support.
### Context
Current state in PraisonAIUI (`server.py`):
- `require_auth: bool` parameter in `create_app()` — single flag
- No token management, no API key support, no user-level access control
OpenClaw comparison: Token + password + trusted-proxy + device auth modes.
PraisonAI package security: `~/praisonai-package/src/praisonai/praisonai/security/` — security module (read this first).
### PHASE 1 — Analysis (MUST complete before implementing)
1. **Read current auth**: `server.py` → understand how `require_auth` is implemented
2. **Read praisonai-package security**: `~/praisonai-package/src/praisonai/praisonai/security/` — understand what security infrastructure exists
3. **Design multi-mode auth**:
- API key auth (for programmatic access)
- Token/session auth (for dashboard users)
- Optional password auth (for initial setup)
4. **Plan**: Step-by-step with exact files.
### PHASE 2 — Implementation (MUST)
1. **Backend — Auth middleware**:
- API key authentication: `X-API-Key` header or `?api_key=` query param
- Session token authentication: JWT or session cookie for dashboard
- Configurable auth mode in YAML config
- Auth middleware in Starlette that checks configured mode
2. **Frontend — Auth UI**:
- Login page (if password auth enabled)
- API key display/rotation in settings
- Session management (logout, token refresh)
3. **Configuration**: Auth section in YAML config with mode selection and credentials
### PHASE 3 — Verification (MUST)
1. Test API key auth with curl
2. Test session auth via dashboard login
3. Verify unauthenticated requests are rejected
4. Verify auth can be disabled for development
5. Document auth configuration options
-81
View File
@@ -1,81 +0,0 @@
---
description: PraisonAIUI product categories and differentiation
---
# UI Product Categories
PraisonAIUI supports three distinct styles, each serving a different use case:
## 1. Chat (`style: chat`)
- Full-screen conversational interface (like ChatGPT)
- Sidebar with session/conversation history
- Streaming responses, thinking indicators, tool calls
- Best for: single-agent chat, customer support, Q&A bots
## 2. Playground (`style: playground`)
- Input/output panel layout
- Agent selection, model switching, endpoint configuration
- Session management with agent profiles
- Best for: multi-agent experimentation, developer testing, agent debugging
## 3. UI Components (Widget mode)
- Embeddable components (copilot widget, sidebar panel, floating button)
- Integrates into existing apps/docs sites
- Configurable position: bottom-right, bottom-left, top-right, top-left
- Best for: adding AI to existing products, documentation copilots
## Key Differentiators
- **Chat** = conversation-first, full-page, session history
- **Playground** = multi-agent, experimentation, side-by-side panels
- **Components** = embeddable widgets for existing apps
When using AI, we mainly and primarily use PraisonAI as the backend ~/praisonai-package
When using Platform, we mainly and primarily use PraisonAI (Gateway) as the backend ~/praisonai-package
We will also support other providers, but PraisonAI will be the primary.
PraisonAI already has memory, knowledge, session management, and more. So where possible we will use PraisonAI's features.
## PraisonAI Backend Capabilities (~/praisonai-package)
The backend (`praisonaiagents`) already provides these features. The UI's job is to surface them:
- **Gateway**: EventType enum (20 types), GatewayEvent, GatewayMessage, GatewaySessionProtocol, GatewayClientProtocol
- **Streaming**: StreamEventType (REQUEST_START, FIRST_TOKEN, DELTA_TEXT, DELTA_TOOL_CALL, TOOL_CALL_END, STREAM_END, ERROR), StreamEvent, StreamMetrics, StreamEventEmitter
- **Memory**: Short-term, long-term, user-specific, auto-memory, file memory, rules, workflows (76KB+ implementation)
- **Knowledge**: RAG, vector store, chunking, query engine, rerankers, readers (41KB+ knowledge.py)
- **Sessions**: Full Session API with state persistence, agent chat history, memory/knowledge integration
- **Hooks**: Registry, middleware, runner, events, types (65KB+ system)
- **Approval**: Full human-in-the-loop approval with backends, registry, protocols
- **Bots/Channels**: Telegram (via gateway.yaml channel routing), extensible to Slack/Discord/WhatsApp etc. (Via Gateway)
- **Other**: MCP, guardrails, planning, sandbox, plugins, tools, thinking, escalation, checkpoints
## Goal of PraisonAIUI
One of the primary goals is: **make the web UI enable and surface these existing PraisonAI backend features**.
Except for the web UI itself, PraisonAI supports everything. This project fills that gap.
## Provider Protocol Architecture (Extensibility)
PraisonAIUI is **provider-agnostic**. The architecture uses a protocol-driven design so any AI backend can be swapped in:
- **`BaseProvider`** (`src/praisonaiui/provider.py`): Abstract base class any backend implements. Only `run()` is required — yields `RunEvent` objects.
- **`RunEvent`**: Structured dataclass with `type` (27 `RunEventType` values), optional fields for content, tool calls, reasoning, errors, agent info, and arbitrary `extra_data`.
- **`PraisonAIProvider`** (`src/praisonaiui/providers/__init__.py`): Default implementation wrapping the `@aiui.reply` callback system. Maps legacy queue events to `RunEvent`.
### Swapping Providers
```python
import praisonaiui
# Use any custom provider:
praisonaiui.set_provider(MyLangChainProvider())
# or
praisonaiui.set_provider(MyCrewAIProvider())
```
### Design Principles
- **Protocol-first**: All communication between UI and backend goes through `RunEvent` protocol — no tight coupling
- **PraisonAI primary, others welcome**: PraisonAI is the default, but the architecture doesn't lock you in
- **Frontend already ready**: The frontend `useSSE.ts` hook and components (`ToolCallDisplay`, `ThinkingSteps`, `MultimediaElements`) already handle all 27 `RunEventType` values — swapping the backend requires no frontend changes
Aim is by default it need to be protocol driven, so we can easily extend, or replace any providers or function accordingly. At the same time it also need to be capable of handling clients, and the clients will be of config driven, same like chainlit or yaml config and it should work.
-839
View File
@@ -1,839 +0,0 @@
---
description: Update install.sh and deploy PraisonAI to Kubernetes via Helm (CI/CD Pipeline)
---
# Install.sh Update & Helm Deployment Workflow
Complete guide for updating the PraisonAI install script and deploying to Kubernetes via the full CI/CD pipeline.
**⚠️ CRITICAL**: This workflow contains **NO SECRETS**. All sensitive values (tokens, passwords) must be passed via environment variables or external secret management.
## 📁 Key Locations (MUST KNOW)
### Scripts
| File/Resource | Absolute Path | Purpose |
|---------------|---------------|----------|
| **install.sh** | `/Users/praison/praisonai-package/src/praisonai/scripts/install.sh` | Main bash installer |
| **install.ps1** | `/Users/praison/praisonai-package/src/praisonai/scripts/install.ps1` | PowerShell installer |
### CI/CD Pipeline (GitHub → ACR → Helm → K8s)
| File/Resource | Absolute Path | Purpose |
|---------------|---------------|----------|
| **GitHub Workflow** | `/Users/praison/Sites/localhost/praisonai/.github/workflows/azure-pipeline.yaml` | CI/CD pipeline triggered on git push |
| **Dockerfile.php** | `/Users/praison/Sites/localhost/praisonai/Dockerfile.php` | PHP container build |
| **Dockerfile.nginx** | `/Users/praison/Sites/localhost/praisonai/Dockerfile.nginx` | Nginx container build |
| **Dockerfile.init** | `/Users/praison/Sites/localhost/praisonai/Dockerfile.init` | Init container build |
### Helm Deployment
| File/Resource | Absolute Path | Purpose |
|---------------|---------------|----------|
| **Helm Charts** | `/Users/praison/repos/person/helmcharts/` | All Kubernetes deployments |
| **wb_azure Chart** | `/Users/praison/repos/person/helmcharts/charts/wb_azure/` | PraisonAI WordPress deployment |
| **Production Values** | `/Users/praison/Sites/localhost/praisonai/values-praisonai-production.yaml` | Production Helm config |
| **Local Values** | `/Users/praison/Sites/localhost/praisonai/values-local.yaml` | Local development config |
| **Deployment Docs** | `/Users/praison/Sites/localhost/praisonai/DEPLOYMENT.md` | Deployment documentation |
| **Deployment Makefile** | `/Users/praison/Sites/localhost/praisonai/Makefile` | Deployment automation |
---
## 🔄 Full CI/CD Pipeline Overview
```
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Git Push │────▶│ GitHub Actions │────▶│ Azure ACR │
│ (master) │ │ azure-pipeline │ │ Image Build │
└─────────────────┘ └──────────────────┘ └────────┬────────┘
│
▼
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Kubernetes │◀────│ Helm Upgrade │◀────│ Update Image │
│ Deployment │ │ (values.yaml) │ │ Tag in Values │
└─────────────────┘ └──────────────────┘ └─────────────────┘
```
### Pipeline Steps:
1. **Git push** to master branch
2. **GitHub Actions** triggers (`.github/workflows/azure-pipeline.yaml`)
3. **Build** Docker images (nginx, php, init)
4. **Push** to Azure Container Registry (ACR)
5. **Update** Helm values with new image tag
6. **Deploy** using Helm upgrade
---
## 🚀 Phase 0 - Fully Automated CI/CD Pipeline
### Complete Auto-Deploy Architecture
```
Git Push ──▶ Build Images ──▶ Trigger Deploy ──▶ Helm Upgrade ──▶ Production
│ │ │ │
│ ▼ ▼ ▼
│ ACR Push helmcharts wb_azure chart
│ (pa-php:SHA) repository (K8s deploy)
│
└─── install.sh ────────────────────────────────────────────────▶ praison.ai/install.sh
```
### Step 0.1: Build Workflow (Automatic on Git Push)
**File**: `/Users/praison/Sites/localhost/praisonai/.github/workflows/azure-pipeline.yaml`
**Repository**: `https://github.com/MervinPraison/praison.ai`
This workflow triggers on every push to `master`:
```yaml
on:
push:
branches: [master]
```
**What it does:**
1. **Syncs install.sh** from PraisonAI repository (only if changed!)
- Checks out `MervinPraison/PraisonAI`
- Compares `install.sh` and `install.ps1` with existing web files
- **Only copies if files have actually changed** (avoids unnecessary redeploys)
- This ensures `https://praison.ai/install.sh` is always latest
2. Downloads env files from Azure Storage
3. Builds multi-arch Docker images (linux/amd64, linux/arm64)
4. Pushes to Azure Container Registry: `praison.azurecr.io/pa/`
5. **Triggers Helm deployment** via `repository_dispatch` event
**Key Step - Automatic Deploy Trigger:**
```yaml
- name: Trigger Helm Deployment
run: |
SHORT_SHA=$(git rev-parse --short HEAD)
curl -X POST \
-H "Authorization: token ${{ secrets.HELM_REPO_TOKEN }}" \
-d '{
"event_type": "deploy_wb_azure",
"client_payload": {
"image_tag": "'"$SHORT_SHA"'",
"source_repo": "'"${{ github.repository }}"'",
"source_commit": "'"${{ github.sha }}"'"
}
}' \
https://api.github.com/repos/praison/helmcharts/dispatches
```
### Step 0.2: Deploy Workflow (Triggered Automatically)
**File**: `/Users/praison/repos/person/helmcharts/.github/workflows/helm-upgrade-with-image.yml`
Listens for `repository_dispatch` events:
```yaml
on:
repository_dispatch:
types: [deploy_wb_azure, deploy_tcs_azure, deploy_tamilmanna_azure]
```
**What it does:**
1. Receives image tag from build workflow
2. Runs `helm upgrade --install wb_azure` with new image tag
3. Waits for rollout to complete
4. Verifies deployment
**Result**: Every git push automatically builds AND deploys!
### Required GitHub Secrets
For the automated CI/CD to work, you need these secrets configured:
**In praisonai site repository** (`https://github.com/MervinPraison/praison.ai`):
| Secret | Purpose |
|--------|---------|
| `AZURE_CREDENTIALS` | Azure login for ACR and AKS |
| `AZURE_USERNAME` | ACR username |
| `AZURE_PASSWORD` | ACR password |
| `AZURE_STORAGE_KEY` | Download env files from Azure Storage |
| `HELM_REPO_TOKEN` | **NEW**: Trigger deploy workflow in helmcharts repo |
**In helmcharts repository** (`/Users/praison/repos/person/helmcharts/.github/workflows/`):
| Secret | Purpose |
|--------|---------|
| `AZURE_CREDENTIALS` | Azure login for AKS |
| `AKS_CLUSTER_NAME` | Kubernetes cluster name |
| `AKS_RESOURCE_GROUP` | Azure resource group |
**To add HELM_REPO_TOKEN**:
1. Go to GitHub Settings → Developer settings → Personal access tokens
2. Create token with `repo` scope
3. Add as secret `HELM_REPO_TOKEN` in https://github.com/MervinPraison/praison.ai
**Current status**: ✅ Already configured (set via `gh secret set`)!
**Images built:**
- `praison.azurecr.io/pa/pa-nginx:SHORT_SHA`
- `praison.azurecr.io/pa/pa-nginx:master`
- `praison.azurecr.io/pa/pa-php:SHORT_SHA`
- `praison.azurecr.io/pa/pa-php:master`
- `praison.azurecr.io/pa/pa-init:SHORT_SHA`
- `praison.azurecr.io/pa/pa-init:master`
### Step 0.2: Update Helm Values with New Image Tag
After the ACR build completes, update the Helm values file to use the new image:
```bash
cd /Users/praison/Sites/localhost/praisonai
# Get the short SHA from the latest commit (matches the Docker tag)
SHORT_SHA=$(git rev-parse --short HEAD)
# Update values file with new image tag
helm upgrade praisonai /Users/praison/repos/person/helmcharts/charts/wb_azure \
-f values-praisonai-production.yaml \
--set image.tag=$SHORT_SHA \
--namespace default \
--timeout 10m
```
**Alternative**: Update values file permanently:
```bash
# Edit values-praisonai-production.yaml to set image.tag
sed -i "s/tag: \".*\"/tag: \"$SHORT_SHA\"/" values-praisonai-production.yaml
# Then commit and push the updated values
git add values-praisonai-production.yaml
git commit -m "ci: update image tag to $SHORT_SHA"
git push origin master
```
### Step 0.3: Full Automated Script (For CI/CD Integration)
```bash
#!/bin/bash
# deploy-after-build.sh - Run after ACR build completes
set -e
SHORT_SHA=$(git rev-parse --short HEAD)
NAMESPACE=default
RELEASE_NAME=praisonai
CHART_PATH=/Users/praison/repos/person/helmcharts/charts/wb_azure
VALUES_FILE=/Users/praison/Sites/localhost/praisonai/values-praisonai-production.yaml
echo "🚀 Deploying PraisonAI with image tag: $SHORT_SHA"
# Update Helm deployment with new image tag
helm upgrade --install $RELEASE_NAME $CHART_PATH \
-f $VALUES_FILE \
--set image.tag=$SHORT_SHA \
--namespace $NAMESPACE \
--timeout 10m \
--atomic
echo "✅ Deployment complete!"
echo ""
echo "Verify with:"
echo " kubectl get pods -n $NAMESPACE -l app.kubernetes.io/instance=$RELEASE_NAME"
echo " helm status $RELEASE_NAME -n $NAMESPACE"
```
---
### Step 0.4: Extend GitHub Actions for Automatic Helm Deployment
To make the CI/CD fully automated (build → deploy), extend the GitHub Actions workflow:
**File to edit**: `/Users/praison/Sites/localhost/praisonai/.github/workflows/azure-pipeline.yaml`
Add a new job after the `build` job:
```yaml
deploy:
needs: build # Wait for build to complete
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Setup kubectl
uses: azure/setup-kubectl@v3
with:
version: 'v1.28.0'
- name: Setup Helm
uses: azure/setup-helm@v3
with:
version: 'v3.13.0'
- name: Get AKS credentials
run: |
az aks get-credentials \
--resource-group your-resource-group \
--name your-aks-cluster-name \
--overwrite-existing
- name: Deploy with Helm
run: |
SHORT_SHA=$(git rev-parse --short HEAD)
helm upgrade --install praisonai \
/Users/praison/repos/person/helmcharts/charts/wb_azure \
-f values-praisonai-production.yaml \
--set image.tag=$SHORT_SHA \
--namespace default \
--timeout 10m \
--atomic
- name: Verify deployment
run: |
kubectl rollout status deployment/php-nginx -n default
helm status praisonai -n default
```
**Requirements for automatic deploy:**
1. GitHub repository secrets configured:
- `AZURE_CREDENTIALS` - Azure service principal credentials
- `AZURE_STORAGE_KEY` - For downloading env files
- `AZURE_USERNAME` / `AZURE_PASSWORD` - ACR login
2. AKS cluster access configured in Azure
3. Helm and kubectl available in GitHub Actions runner
---
## 🔧 Phase 1 — Update install.sh (Manual, When Needed)
### When to Update
- New PraisonAI version released
- New dependency requirements
- New OS support needed
- Bug fixes in installation process
### Step 1: Read Current install.sh
```bash
# View the install script
cat /Users/praison/praisonai-package/src/praisonai/scripts/install.sh
```
Key sections in install.sh:
- **Lines 1-50**: Header, usage, environment variables documentation
- **Lines 51-150**: OS detection (macOS, Linux, Windows/WSL)
- **Lines 151-300**: Python installation (version checks, package managers)
- **Lines 301-450**: Virtual environment setup
- **Lines 451-550**: PraisonAI package installation
- **Lines 551-637**: PATH configuration, shell integration, verification
### Step 2: Make Changes
**Common Changes:**
#### Update Default Version
```bash
# Find this line (around line 70):
PRAISONAI_VERSION="${PRAISONAI_VERSION:-latest}"
# Change to specific version if needed:
PRAISONAI_VERSION="${PRAISONAI_VERSION:-1.5.0}"
```
#### Add New Environment Variable
```bash
# Add to header section (after line 10, in the comment block):
# PRAISONAI_NEW_FEATURE - Description (default: value)
# Add to actual code (around line 75):
export PRAISONAI_NEW_FEATURE="${PRAISONAI_NEW_FEATURE:-default_value}"
```
#### Update Python Version Requirements
```bash
# Find Python version check (around line 100-120):
PYTHON_MIN_VERSION="3.9"
# Update if needed:
PYTHON_MIN_VERSION="3.10"
```
### Step 3: Test Changes
```bash
# Test locally (dry run)
cd /Users/praison/praisonai-package/src/praisonai/scripts
bash install.sh --dry-run
# Test in Docker (full test)
bash /Users/praison/praisonai-package/src/praisonai/scripts/test-install-smoke.sh
```
### Step 4: Verify Both Scripts
```bash
# Check install.sh syntax
bash -n /Users/praison/praisonai-package/src/praisonai/scripts/install.sh
# Check install.ps1 syntax (if pwsh available)
pwsh -Command "Get-Command /Users/praison/praisonai-package/src/praisonai/scripts/install.ps1"
```
---
## 🚀 Phase 2 — Deploy to Kubernetes (Helm)
### Pre-Deployment Checklist
```bash
# 1. Verify kubectl connection
kubectl get nodes
# 2. Check current Helm releases
helm list -n default
# 3. Verify chart exists
ls /Users/praison/repos/person/helmcharts/charts/wb_azure/
```
### Deployment Types
#### A. Fresh Deployment (First Time)
```bash
cd /Users/praison/Sites/localhost/praisonai
# Option 1: Using Makefile
make deploy
# Option 2: Manual helm command
helm upgrade --install praisonai /Users/praison/repos/person/helmcharts/charts/wb_azure \
-f values-praisonai-production.yaml \
--namespace default \
--timeout 10m \
--atomic
```
#### B. Update Existing Deployment
```bash
cd /Users/praison/Sites/localhost/praisonai
# Edit values file first
vim values-praisonai-production.yaml
# Then apply
make upgrade
# Or manually:
helm upgrade praisonai /Users/praison/repos/person/helmcharts/charts/wb_azure \
-f values-praisonai-production.yaml \
--namespace default \
--timeout 10m
```
#### C. Local Development Deployment
```bash
cd /Users/praison/Sites/localhost/praisonai
make local-deploy
```
### Values File Structure
```yaml
# /Users/praison/Sites/localhost/praisonai/values-praisonai-production.yaml
# Core settings
replicaCount: 2
# Database
dbHost: "10.0.0.11"
dbUser: "bible_4"
dbPassword: "changeme" # Override via --set
# OpenAI tokens (for plugin verification)
openaiVerificationToken: "token-here"
# Feature toggles
praisonai:
enabled: true
domain: praison.ai
whiteboard:
enabled: true
domain: whiteboard.gallery
# Disable other sites
bible: { enabled: false }
music: { enabled: false }
save: { enabled: false }
# Resources
resources:
requests:
cpu: 800m
memory: 1024Mi
limits:
cpu: 2000m
memory: 2048Mi
# Auto-scaling
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
# Ingress
ingress:
enabled: true
className: nginx
```
---
## 📊 Phase 3 — Verify Deployment
### Check Deployment Status
```bash
# Using Makefile
make status
# Manual checks
helm status praisonai -n default
kubectl get pods -l app.kubernetes.io/instance=praisonai -n default
kubectl get svc -l app.kubernetes.io/instance=praisonai -n default
```
### Verify All Resources
```bash
# Pods should be Running
kubectl get pods -n default | grep praisonai
# Services should be Active
kubectl get svc -n default | grep praisonai
# Ingress should exist
kubectl get ingress -n default | grep praisonai
# ConfigMaps
kubectl get configmap -n default | grep nginx-config
# Secrets
kubectl get secret -n default | grep db-password
```
### Check Application Health
```bash
# Port forward and test
echo "Visit http://127.0.0.1:8080"
kubectl port-forward svc/php-nginx 8080:80 -n default
# In another terminal:
curl http://127.0.0.1:8080/test.php
```
---
## 🔄 Phase 4 — Rollback (If Needed)
```bash
# View revision history
make history
# Rollback to previous revision
make rollback
# Or manually:
helm rollback praisonai 1 -n default
```
---
## 🛠️ Phase 5 — Troubleshooting
### Problem: "Resource exists and cannot be imported"
**Cause**: Existing Kubernetes resources not managed by Helm.
**Solution**: Adopt resources into Helm
```bash
cd /Users/praison/Sites/localhost/praisonai
./scripts/adopt-resources.sh praisonai default
```
Or manually annotate:
```bash
# For any resource type
kubectl annotate <resource-type> <name> \
meta.helm.sh/release-name=praisonai \
meta.helm.sh/release-namespace=default
kubectl label <resource-type> <name> \
app.kubernetes.io/managed-by=Helm
```
### Problem: Pods Not Starting
```bash
# Check events
kubectl get events -n default --sort-by='.lastTimestamp' | tail -20
# Check pod logs
kubectl logs -l app.kubernetes.io/instance=praisonai -n default
# Describe pod for details
kubectl describe pod <pod-name> -n default
```
### Problem: Image Pull Errors
```bash
# Check image pull secrets
kubectl get secret acr-auth -n default
# Verify ACR auth exists
kubectl create secret docker-registry acr-auth \
--docker-server=praison.azurecr.io \
--docker-username=<username> \
--docker-password=<password> \
-n default
```
---
## 📋 Phase 6 — Post-Deployment
### Update Documentation
If install.sh changed, update:
1. `/Users/praison/PraisonAIDocs/docs/installation.mdx` — Installation docs
2. `/Users/praison/praisonai-package/src/praisonai/scripts/README.md` — Script docs (if exists)
### Verify Website
```bash
# Check praison.ai is accessible
curl -I https://praison.ai
# Check whiteboard.gallery
curl -I https://whiteboard.gallery
```
### Monitor
```bash
# Watch pods
kubectl get pods -l app.kubernetes.io/instance=praisonai -n default -w
# Check resource usage
kubectl top pods -l app.kubernetes.io/instance=praisonai -n default
```
---
## 📚 Reference: Helm Chart Structure
```
/Users/praison/repos/person/helmcharts/charts/wb_azure/
├── Chart.yaml # Chart metadata (name: wb, version: 1.0.1)
├── values.yaml # Default values (fallback)
├── templates/
│ ├── deployment.yaml # Main php-nginx deployment
│ ├── service.yaml # NodePort service
│ ├── ingress.yaml # TLS + routing
│ ├── nginx-configMap.yaml # Server configs
│ ├── db-password-secret.yaml # DB credentials
│ ├── pdb.yaml # Pod disruption budget
│ ├── autoscalar.yml # HPA
│ ├── cert-manager.yaml # TLS certificates
│ └── _helpers.tpl # Template helpers
```
---
## 🎯 Quick Commands Reference
| Task | Command |
|------|---------|
| Deploy | `make deploy` |
| Update | `make upgrade` |
| Status | `make status` |
| History | `make history` |
| Rollback | `make rollback` |
| Logs | `make logs` |
| Restart | `make restart` |
| Local dev | `make local-deploy` |
| Dry run | `make dry-run` |
| Lint | `make lint` |
---
## ⚠️ Critical Rules
1. **Never commit SQL dumps**: `.gitignore` already excludes `*.sql` files
2. **Never commit secrets**: Use `--set` or external secret management
3. **Always test install.sh** after changes (use test-install-smoke.sh)
4. **Always verify deployment** with `make status` after Helm operations
5. **Use Infrastructure as Code**: All changes via Helm values files, never manual kubectl
6. **Version control**: Commit values files (without secrets), never commit generated manifests
---
## 🆘 Getting Help
If stuck:
1. Check `/Users/praison/Sites/localhost/praisonai/DEPLOYMENT.md` for detailed docs
2. Check `/Users/praison/Sites/localhost/praisonai/INFRASTRUCTURE_AS_CODE_SUMMARY.md` for quick reference
3. Run `helm status praisonai -n default` for deployment status
4. Run `kubectl get events -n default` for cluster events
5. View install.sh comments for usage examples (lines 1-50)
---
## 🔄 CI/CD Pipeline Summary (For New Agents)
### Complete Workflow (Fully Automated!)
```
Developer Push ──────────────────────────────────────────────▶ Production
│ │
▼ ▼
┌─────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ 1. Git Push to │───▶│ 2. GitHub Actions │───▶│ 3. Sync │
│ master │ │ Trigger │ │ install.sh │
└─────────────────┘ └──────────────────┘ └────────┬─────────┘
│
┌────────────────────────┘
▼
┌──────────────────┐
│ 4. Azure ACR │
│ Build Images │
│ + Push │
└────────┬─────────┘
│
──────▶┌──────────────────┐
│ 5. Trigger Deploy│
│ (repository_ │
│ dispatch) │
└────────┬─────────┘
│
┌─────────────────┐ ┌──────────────────┐ │
│ 7. Production │◀───│ 6. Helm Upgrade │◀──┘
│ Running │ │ Deploy │
│ (includes │ │ │
│ install.sh) │ │ │
└─────────────────┘ └──────────────────┘
```
**🎉 Fully Automated**: Git push → Build → Deploy (No manual steps!)
### Automatic install.sh Sync
**Key Point**: The workflow automatically syncs `install.sh` from `MervinPraison/PraisonAI` repository **only if changed**:
```yaml
- name: Checkout PraisonAI for install.sh
uses: actions/checkout@v2
with:
repository: MervinPraison/PraisonAI
path: praisonai-package
- name: Sync install.sh to web folder (if changed)
run: |
# Only sync if files have actually changed
if ! diff -q praisonai-package/src/praisonai/scripts/install.sh ./web/install.sh; then
cp praisonai-package/src/praisonai/scripts/install.sh ./web/install.sh
fi
```
**Optimization**: Uses `diff` to compare files - only copies when install.sh or install.ps1 have actually changed. This avoids unnecessary Docker layer rebuilds and deployments.
**Result**: `https://praison.ai/install.sh` is automatically updated **only when the source files change**!
### How install.sh is Served
The `web/install.sh` file is copied into the Docker image at `/var/www/html/web/install.sh` and served by nginx:
```nginx
# In nginx-config, requests to praison.ai/install.sh
# are served from /var/www/html/web/install.sh
location / {
root /var/www/html/web;
try_files $uri $uri/ =404;
}
```
**URL Mapping**:
| File in Repo | URL |
|--------------|-----|
| `web/install.sh` | `https://praison.ai/install.sh` |
| `web/install.ps1` | `https://praison.ai/install.ps1` |
### What Files to Edit
| To Change | Edit File |
|-----------|-----------|
| Application code | `/Users/praison/Sites/localhost/praisonai/` (PHP files) |
| Docker images | `Dockerfile.php`, `Dockerfile.nginx`, `Dockerfile.init` |
| CI/CD pipeline | `.github/workflows/azure-pipeline.yaml` |
| Helm deployment config | `values-praisonai-production.yaml` |
| Install script | `/Users/praison/praisonai-package/src/praisonai/scripts/install.sh` |
### Common Tasks
**Task 1: Deploy new code**
```bash
cd /Users/praison/Sites/localhost/praisonai
git add .
git commit -m "feat: new feature"
git push origin master
# CI/CD automatically builds and deploys
```
**Task 2: Update install.sh and deploy**
```bash
# 1. Update install.sh
vim /Users/praison/praisonai-package/src/praisonai/scripts/install.sh
# 2. Test install.sh
bash /Users/praison/praisonai-package/src/praisonai/scripts/install.sh --dry-run
# 3. Commit and push
git add /Users/praison/praisonai-package/src/praisonai/scripts/install.sh
git commit -m "fix: update install script"
git push origin main
# 4. Deploy website (if needed)
cd /Users/praison/Sites/localhost/praisonai
make upgrade
```
**Task 3: Rollback deployment**
```bash
cd /Users/praison/Sites/localhost/praisonai
make rollback
# Or: helm rollback praisonai 1 -n default
```
### Architecture
| Layer | Technology | Purpose |
|-------|------------|---------|
| Source Control | Git/GitHub | Code repository |
| CI/CD | GitHub Actions | Automated build/deploy |
| Container Registry | Azure ACR | Docker image storage |
| Orchestration | Kubernetes (AKS) | Container management |
| Deployment | Helm | K8s package management |
| Ingress | NGINX Ingress + cert-manager | Traffic routing + TLS |
### Security Notes
- **No secrets in workflow files** - All tokens/passwords via env vars
- **ACR authentication** - Uses `acr-auth` secret in Kubernetes
- **GitHub Secrets** - `AZURE_CREDENTIALS`, `AZURE_USERNAME`, `AZURE_PASSWORD`
- **Never commit** `.env` files, SQL dumps, or credentials
-181
View File
@@ -1,181 +0,0 @@
---
description: instruction
---
Create multiple TODOs and sub-TODOs, get all things done.
First: detailed analysis, plan, and gap analysis. Go through all files, understand current logic. Search if needed.
Then: implement, fix, test (TDD, Agent-Centric, no perf impact, DRY). praisonaiagents is protocol-driven. Run unit, integration, smoke, and real agentic tests.
After: re-do detailed analysis/plan to find remaining gaps and propose fixes.
Docs: beginner-friendly, for non-developers. Explain concepts with mermaid diagrams (Dark Red #8B0000 for agents/inputs/outputs, Teal #189AB4 for tools, white #fff text). Less descriptive, more interactive. Use Mintlify components: Accordions, Badge, Callouts (Note/Warning/Info/Tip/Check/Danger), Cards/Columns, CodeGroup, Expandables, Tabs, Steps, Frame, Icon, Tooltip, Mermaid, ParamField, Tables, CardGroup.
You are an expert AI engineer in the PraisonAI ecosystem.
Production-quality code, zero regressions, full verification. Make PraisonAI the best agent framework.
### Core Philosophy
```
Simpler • More extensible • Faster • Agent-centric
```
| Principle | Rule |
|---|---|
| Agent-Centric | Design centers on Agents, workflows, sessions, tools, memory |
| Protocol-Driven | Core SDK: protocols/hooks/adapters only; heavy code in wrapper/tools |
| Minimal API | Fewer params, sensible defaults, explicit overrides |
| Performance-First | Lazy loading, optional deps, no hot-path regressions |
| Production-Ready | Safe by default, multi-agent safe, async-safe |
- Powerful, lightweight, reliable. Easy for non-developers.
- "Few lines of code to do the task!" — SDK and docs must feel this way.
- Each feature runs 3 ways: CLI, YAML, Python.
- Open source, developer-first. Core free, clear upgrade path to paid (support/cloud/services).
- Simple to adopt, hard to misuse, safe by default.
- Prioritise time saved, reduced risk, and operational confidence.
- Reduce production friction, not just add functionality.
- All features must have CLI integration. Agent-first naming and ergonomics.
ENGINEERING PRINCIPLES (MUST)
- DRY: reuse abstractions, no duplication.
- Protocol-driven core: protocols/hooks in core; heavy impl in wrapper/tools.
- No perf impact: lazy imports, optional deps, no global singletons, no heavy module-level work.
- TDD mandatory: tests first.
- Multi-agent + async safe by default.
- AGENTS.md is not for documentation.
CRITICAL REQUIREMENTS
- EXECUTE + VERIFY mode. No guessing. Proof for "done."
- Optional deps only; lazy import everything heavy.
- Every feature/fix: Python + CLI + docs/examples.
- Any core change must be justified: simpler client API, measurable benefit, NO perf regression.
- If TypeScript parity required: update praisonai-ts, but never at cost of Python core performance.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
CANONICAL PATHS (MUST use these)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- Core SDK: /Users/praison/praisonai-package/src/praisonai-agents → praisonaiagents
- Wrapper: /Users/praison/praisonai-package/src/praisonai → praisonai
- Tools: /Users/praison/PraisonAI-tools → praisonai-tools
- Docs: /Users/praison/PraisonAIDocs (read AGENTS.md first before updating docs)
- Docs JS: /Users/praison/PraisonAIDocs/docs/js | Rust: docs/rust
- Examples: /Users/praison/praisonai-package/examples/
- TypeScript: /Users/praison/praisonai-package/src/praisonai-ts
- Rust: /Users/praison/praisonai-package/src/praisonai-rust (follow praisonai-ts/AGENTS.md)
- UI (this repo): /Users/praison/praisonaiui → praisonaiui
- Extension points: tools/base.py, tools/decorator.py, db/*
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ARCHITECTURE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Core (praisonaiagents): protocol-driven, lightweight. No heavy imports. Only protocols/hooks/adapters.
Wrapper (praisonai): real integrations (DBs, observability, CLI). Lazy imports, optional deps.
Tools (PraisonAI-tools): pluggable, never overload core/wrapper.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
MANDATORY EXECUTION FLOW
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PHASE 1 — ANALYSIS (before writing code)
1.1 Acceptance Criteria — testable bullets for API, CLI, docs, tests, perf.
1.2 Repo Inventory — scan relevant files end-to-end:
- modules/classes/APIs/exports, CLI commands, tests, docs/examples
- Evidence: paths + symbols + grep counts. Identify DRY opportunities.
1.3 Gap Analysis — what exists vs what's needed:
- Missing: core SDK, wrapper, tools, CLI, docs, tests, exports
- Risks: perf, API breaks, optional deps, async, multi-agent
1.4 Report — current behavior, pain points, root causes (file refs), constraints, risk register, decision log.
1.5 Plan — step-by-step: tests → impl → CLI → docs → verify. Files to change. Compat/rollback/perf strategy.
1.6 Proposal — minimal agent-centric design. Protocols in core, impl in wrapper. Upgrade-path notes.
1.7 TODO Tree — granular, executable. Python + CLI + TDD + docs + perf.
- Second-to-last: "Verify all changes end-to-end"
- Last: "Implement remaining gaps (missing=0), re-verify" or "Final scan, confirm missing=0"
PHASE 2 — EXECUTE
2.1 TDD — write failing tests first. Deterministic and fast.
2.2 Implement — DRY, agent-centric, protocol-driven. Heavy code in wrapper/tools. Multi-agent + async safe.
2.3 CLI parity — add/extend CLI commands. Scriptable, clear help, proper exit codes.
2.4 Docs — Mintlify pages (SDK="Module", API="API"). Copy-paste runnable examples.
2.5 Verification:
- Run tests (unit/integration), show results.
- Smoke: `python3 -c "..."` + CLI help/run.
- Optional deps graceful degradation.
- Perf: no heavy core imports, import-time sanity.
- Provide evidence for every claim.
- dont use Sending termination request to command to terminate a process, kill port instead when terminating
REAL AGENTIC TEST (MANDATORY — not replaceable by smoke tests)
- After unit/smoke tests, MUST run at least one REAL agent execution:
1. Create Agent with the feature being tested
2. Call `agent.start("a real task prompt")` — NOT just constructing the object
3. Agent MUST call LLM and produce text response
4. Print full output so dev can see it worked end-to-end
- Minimum example:
```python
from praisonaiagents import Agent
agent = Agent(name="test", instructions="You are a helpful assistant")
result = agent.start("Say hello in one sentence")
print(result)
```
- Assert-only object construction = SMOKE TEST, not real agentic test.
- Both smoke AND real agentic tests required.
PHASE 3 — POST-IMPLEMENTATION ANALYSIS
3.1 Re-scan files, summarize final behavior/architecture.
3.2 Confirm remaining gaps (API, CLI, docs, tests, exports, perf, multi-agent, async). If gaps exist, treat as required work until missing=0.
3.3 Report: what changed, why, validation evidence, tradeoffs.
3.4 Plan: close remaining gaps or maintenance plan.
3.5 Proposal: refinements for UX, safety, perf, extensibility. Label: implemented vs out-of-scope.
Final rule: conclude only when evidence shows missing = 0.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PUBLISH WORKFLOW (reference)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
GitHub Actions (recommended):
GitHub → Actions → "PyPI Release" → Run workflow → bump: patch
Requires repo secrets: PYPI_TOKEN, GH_TOKEN
Requires GitHub Environment "pypi" with required reviewers (Settings → Environments)
Manual — Publish aiui (PraisonAIUI):
cd /Users/praison/PraisonAIUI
# Bump version in pyproject.toml and src/praisonaiui/__version__.py
rm -rf dist && uv lock && uv build && uv publish --token "$PYPI_TOKEN"
git add pyproject.toml uv.lock src/praisonaiui/__version__.py
git commit -m "Release vX.Y.Z" && git tag vX.Y.Z && git push && git push --tags
gh release create vX.Y.Z --title "PraisonAIUI vX.Y.Z" --notes "Release vX.Y.Z" --latest
PyPI package name: aiui
Verify: pip index versions aiui | head -1
PraisonAI stack (separate repo — publish SDK before wrapper):
cd /Users/praison/praisonai-package/src/praisonai-agents
praisonai publish pypi
# Uses uv internally: uv lock → uv build → uv publish
# Auto-bumps patch version, requires PYPI_TOKEN env var
Step 2 — Publish praisonai (Wrapper):
cd /Users/praison/praisonai-package/src/praisonai
python scripts/bump_and_release.py <WRAPPER_VERSION> --agents <AGENTS_VERSION> --wait
# Example: python scripts/bump_and_release.py 4.5.90 --agents 1.5.91 --wait
# Waits for agents to be available on PyPI, bumps all version files,
# runs uv lock, builds, commits, tags, pushes, creates GitHub release
# Then: uv publish (from src/praisonai with clean dist/)
If bump_and_release published already, just verify:
pip index versions praisonai | head -1
If uv publish fails with "File already exists", it means the version is already on PyPI — success.
Step 3 — Publish praisonai-tools (External, if needed):
cd /Users/praison/PraisonAI-tools
# Bump version in pyproject.toml, then:
python3.13 -m build && uv run twine upload dist/*
PraisonAI PRs: NEVER merge automatically — user merges manually.
-223
View File
@@ -1,223 +0,0 @@
---
description: Implement, fix, and test code changes locally — for when the agent IS the implementer
---
# Local Fix Workflow
You are the implementer. Analyze → Plan → Implement → Test → Verify → PR.
> **When to use this:** The user explicitly asks you to fix something locally, or delegates a task that cannot be handled by the GitHub cloud agents.
> **When NOT to use this:** If given an Issue URL, prefer `@[/pr-review]` Step 8d — delegate to cloud agents first.
---
## Phase 1 — Analysis (before writing ANY code)
### 1a. Understand the problem
// turbo
```bash
cd /Users/praison/praisonai-package && git checkout main && git pull origin main
```
Read all relevant source files end-to-end. Use `grep`, `view_file`, and code navigation.
- Identify root cause with **file paths and line numbers**
- Trace the full code path (caller → callee → side effects)
- Assess blast radius (what else could break)
- Check for existing abstractions before creating new ones (DRY)
### 1b. Create TODO tree
Break work into granular, executable items:
```
- [ ] Write failing test(s)
- [ ] Implement fix (file:line references)
- [ ] CLI parity (if applicable)
- [ ] Docs update (if applicable)
- [ ] Run unit + integration tests
- [ ] Run real agentic test
- [ ] Verify end-to-end
```
---
## Phase 2 — Implement
### 2a. TDD — tests first
Write the failing test before touching implementation code.
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents && \
python -m pytest tests/<relevant_test>.py -x -v --tb=short
```
### 2b. Implement the fix
**Architecture rules (MUST follow):**
| Layer | What goes here | What does NOT go here |
|-------|---------------|----------------------|
| **Core SDK** (`praisonaiagents/`) | Protocols, hooks, adapters, base classes, decorators, dataclasses | Heavy implementations, optional deps at module level |
| **Wrapper** (`praisonai/`) | CLI commands, integrations, heavy impls, DB adapters, UI | Core logic |
| **Tools** (`PraisonAI-tools/`) | Pluggable tools, community extensions | Core or wrapper logic |
**Coding standards:**
- **Lazy imports**: Optional deps imported inside functions, never at module level
- **DRY**: Reuse existing abstractions; refactor if duplication found
- **Naming**: `add_X()`, `get_X()`, `XConfig`, `XProtocol`, `XAdapter`
- **Async-safe**: No blocking I/O in async context; use asyncio primitives
- **Multi-agent safe**: No shared mutable globals without `threading.Lock`
- **Security**: No hardcoded secrets; `hmac.compare_digest` for comparisons; sandboxed `exec()`
- **Backward compat**: Public API changes require deprecation cycle
**Canonical paths:**
| What | Where |
|------|-------|
| Core SDK | `/Users/praison/praisonai-package/src/praisonai-agents/praisonaiagents/` |
| Wrapper | `/Users/praison/praisonai-package/src/praisonai/praisonai/` |
| Tools | `/Users/praison/PraisonAI-tools/` |
| Docs | `/Users/praison/PraisonAIDocs/` (read AGENTS.md first) |
| Examples | `/Users/praison/praisonai-package/examples/` |
| TypeScript | `/Users/praison/praisonai-package/src/praisonai-ts/` |
### 2c. CLI parity
Every feature must work 3 ways: **Python, CLI, YAML**. If your change adds or modifies a feature, ensure CLI support exists.
---
## Phase 3 — Test & Verify
### 3a. Unit + Integration tests
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents && \
python -m pytest tests/ -x -q \
--ignore=tests/integration/test_whatsapp_web_real.py \
--ignore=tests/unit/tools/test_profiles.py \
--tb=short 2>&1 | tail -20
```
### 3b. Real agentic test (MANDATORY)
Unit tests alone are NOT sufficient. You MUST run at least one real agent execution:
```python
from praisonaiagents import Agent
agent = Agent(name="test", instructions="You are a helpful assistant")
result = agent.start("Say hello in one sentence")
print(result)
```
**Rules:**
- Agent MUST call `agent.start()` with a real prompt
- Agent MUST call the LLM and produce a text response
- Print full output — assert-only object construction is a SMOKE test, not agentic
- Both smoke AND real agentic tests required
### 3c. Security checks (if touching sensitive code)
```bash
# Hardcoded secrets
grep -rn "secret\|password\|token\|api_key" --include="*.py" <changed-files> | \
grep -v "test_\|#\|environ\|getenv\|config"
# Timing attacks
grep -rn "==.*api_key\|==.*secret\|==.*token" --include="*.py" <changed-files>
# Sandbox escapes
grep -rn "exec(\|eval(" --include="*.py" <changed-files>
```
### 3d. Performance sanity
```bash
# Verify no heavy imports at module level
python -c "import time; t=time.time(); import praisonaiagents; print(f'{(time.time()-t)*1000:.0f}ms')"
```
Target: < 200ms package import time.
---
## Phase 4 — Post-implementation scan
Re-scan changed files. Confirm:
- [ ] No remaining gaps (API, CLI, docs, tests, exports, perf)
- [ ] No regressions introduced
- [ ] All acceptance criteria met with evidence
If gaps remain → loop back to Phase 2. Conclude only when `missing = 0`.
---
## Phase 5 — Submit
### 5a. Create branch and PR
```bash
cd /Users/praison/praisonai-package && \
git checkout -b <type>/<descriptive-name> && \
git add -A && \
git commit -m "<type>: <description>" && \
git push origin <type>/<descriptive-name>
```
```bash
cd /Users/praison/praisonai-package && \
gh pr create \
--title "<type>: <description>" \
--body '## Summary
<what and why>
### Changes
- <file>: <what changed>
### Testing
- Unit tests: ✅
- Agentic test: ✅
- Security: ✅ (if applicable)' \
--head <type>/<descriptive-name> \
--base main
```
**Commit prefixes:** `fix:`, `feat:`, `security:`, `refactor:`, `docs:`, `test:`
> **Do NOT merge automatically** — user merges manually unless explicitly told otherwise.
### 5b. Verify PR state
// turbo
```bash
cd /Users/praison/praisonai-package && gh pr view --json state,title,url | cat
```
---
## Publish (only when user requests)
```bash
# Core SDK
cd /Users/praison/praisonai-package/src/praisonai-agents && praisonai publish pypi
# Wrapper
cd /Users/praison/praisonai-package/src/praisonai && \
python scripts/bump_and_release.py <VERSION> --agents <AGENTS_VERSION> --wait
```
---
## Quick Reference — Red Flags
| Red Flag | Fix |
|----------|-----|
| Module-level `import chromadb` | Move inside function with `try/except ImportError` |
| `exec(user_input)` without sandbox | Use `RestrictedPython` or sandbox module |
| `if token == secret:` | Use `hmac.compare_digest(token, secret)` |
| Shared mutable global `_cache = {}` | Add `threading.Lock`, or make per-agent |
| `debug=True` in production path | Remove or gate behind env var |
| Missing `async` variant for I/O | Add async version, wrap for sync callers |
-275
View File
@@ -1,275 +0,0 @@
---
description: Review, validate, and merge GitHub pull requests or triage issues
---
# PR / Issue Review Workflow
When given a GitHub PR or Issue URL, follow this procedure end-to-end.
---
## Step 0 — Determine Type
Parse the URL to identify whether it is a **Pull Request** or an **Issue**.
```
https://github.com/MervinPraison/PraisonAI/pull/<NUMBER> → PR
https://github.com/MervinPraison/PraisonAI/issues/<NUMBER> → Issue
```
- **PR** → go to Step 1
- **Issue** → go to Step 8
---
## Step 1 — Fetch PR Metadata
// turbo
```bash
cd /Users/praison/praisonai-package && \
gh pr view <NUMBER> --json title,body,author,state,additions,deletions,changedFiles,headRefName,baseRefName,labels
```
Record: title, author, branch, file count, +/- lines.
---
## Step 2 — Read the Full Diff
// turbo
```bash
cd /Users/praison/praisonai-package && gh pr diff <NUMBER>
```
If the diff is very large (>500 lines), pipe through `head -500` first, then read remaining chunks.
---
## Step 3 — Review the Diff
For each changed file, evaluate against **PraisonAI engineering principles** (from AGENTS.md):
| Principle | What to Check |
|-----------|---------------|
| **Protocol-driven core** | No heavy implementations in `praisonaiagents/` (core SDK) |
| **Lazy imports** | Optional deps imported inside functions, not at module level |
| **DRY** | No code duplication; reuse existing abstractions |
| **Naming conventions** | `add_X()`, `get_X()`, `XConfig`, `XProtocol`, `XAdapter` |
| **Async-safe** | No blocking I/O in async context; asyncio primitives used |
| **Multi-agent safe** | No shared mutable global state without locks |
| **Thread safety** | Double-checked locking for lazy caches; `threading.Lock` for mutables |
| **Security** | No hardcoded secrets; `hmac.compare_digest` for comparisons; restricted `exec()` |
| **Backward compat** | Public API changes require deprecation cycle |
| **Test coverage** | Tests included; TDD pattern; both unit + agentic tests |
**Red flags to catch:**
- Module-level imports of optional deps (chromadb, litellm, etc.)
- Hardcoded credentials or `debug=True` in production paths
- Direct string comparison for secrets (timing attacks)
- `exec()`/`eval()` without sandbox
- Shared mutable globals without `threading.Lock`
- Missing error handling or swallowed exceptions
---
## Step 4 — Checkout and Run Tests Locally
// turbo
```bash
cd /Users/praison/praisonai-package && git checkout main && git pull origin main
```
// turbo
```bash
cd /Users/praison/praisonai-package && gh pr checkout <NUMBER>
```
Run targeted tests for changed files first:
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents && \
python -m pytest tests/ -x -q \
--ignore=tests/integration/test_whatsapp_web_real.py \
--ignore=tests/unit/tools/test_profiles.py \
--tb=short 2>&1 | tail -20
```
For PRs touching security-sensitive code, also run:
```bash
# Sandbox tests
python -m pytest tests/unit/tools/test_python_tools_sandbox.py -v
# CWE-78 env injection tests
python -m pytest src/praisonai/tests/unit/test_cwe78_env_injection.py -v
# Thread-safety tests
python -m pytest tests/unit/test_thread_safety.py -v
```
---
## Step 5 — Verify No Regressions
Run the full test suite:
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents && \
python -m pytest tests/ -q \
--ignore=tests/integration/test_whatsapp_web_real.py \
--ignore=tests/unit/tools/test_profiles.py \
--tb=no 2>&1 | tail -5
```
**Acceptable result:** All tests pass, or only pre-existing flaky tests fail (e.g., `test_file_memory.py::test_memory_persistence_across_agent_instances`).
**Unacceptable:** Any NEW failure introduced by the PR.
---
## Step 6 — Approve or Request Changes
**If the PR is good:**
```bash
cd /Users/praison/praisonai-package && \
gh pr review <NUMBER> --approve --body "LGTM — reviewed diff, tests pass, follows PraisonAI engineering principles."
```
**If changes are needed:**
```bash
cd /Users/praison/praisonai-package && \
gh pr review <NUMBER> --request-changes --body "Requesting changes: <specific feedback>"
```
---
## Step 7 — Merge
```bash
cd /Users/praison/praisonai-package && \
gh pr merge <NUMBER> --merge --subject "<PR title>"
```
Verify merge:
// turbo
```bash
cd /Users/praison/praisonai-package && gh pr view <NUMBER> --json state,mergedAt
```
Then return to main:
// turbo
```bash
cd /Users/praison/praisonai-package && git checkout main && git pull origin main
```
---
## Step 8 — Issue Triage (if URL is an Issue)
### 8a. Fetch issue details
// turbo
```bash
cd /Users/praison/praisonai-package && \
gh issue view <NUMBER> --json title,body,author,state,labels,comments
```
### 8b. Classify severity
| Tier | Criteria | Examples |
|------|----------|---------|
| **Tier 1 — Critical** | Security vuln, data loss, crash in hot path | exec() without sandbox, hardcoded secrets, unprotected globals |
| **Tier 2 — High** | Performance regression, broken feature, wrong output | Duplicate API calls, memory leak, silent failure |
| **Tier 3 — Medium** | DX issue, missing validation, doc gap | Bad error messages, missing CLI parity, stale docs |
| **Tier 4 — Low** | Cosmetic, code style, minor refactor | Trailing whitespace, naming inconsistency |
### 8c. Deep analysis (for Tier 1-2)
1. Read ALL relevant source files end-to-end
2. Trace the code path that the issue describes
3. Identify root cause with file paths and line numbers
4. Assess blast radius (what else could be affected)
5. Determine if the issue is **actually what it claims** (re-classify if needed)
### 8d. Delegate Implementation to GitHub Workflow Agents
> **KEY PHILOSOPHY: We act as the Manager, GitHub Actions execute the Workflow.**
**DO NOT implement the fix yourself locally.** PraisonAI uses autonomous GitHub Action workflows (such as `gemini-issue-review.yml` and `claude.yml`) to automatically resolve issues and create PRs. Your job as the local agent is to supervise, analyze gaps, and trigger these cloud agents to do the heavy lifting. If there is a gap (e.g. strict test violations), provide detailed relevant information in the PR/Issue and trigger the agents again.
1. Issue the command to trigger the cloud agent on the issue:
```bash
cd /Users/praison/praisonai-package && \
gh issue comment <NUMBER> --body "@gemini please review and fix this issue"
```
*(Note: You can use `@claude` or `@gemini` depending on preference or active bots).*
2. Check the GitHub Actions logs (`gh run list`) and wait for the cloud agent to open a Pull Request (`gh pr list`).
3. Once the cloud bot opens a Pull Request for the issue, return to **Step 1** to review the PR, test the branch locally, and merge it if it passes the checks.
---
## Step 9 — (Skipped) Local PR Creation
> **Note:** As the local agent, you should delegate code fixes to the cloud agents. Only implement code locally and create a PR if the USER explicitly forces you to bypass the cloud agents. If forced, use standard prefixes: `fix:`, `feat:`, `security:`, `refactor:`, `docs:`, `test:`.
---
## Step 10 — Security-Specific Checks
When reviewing security-related PRs, additionally verify:
### Credentials / Secrets
```bash
# Check for hardcoded secrets
grep -rn "secret\|password\|token\|api_key" --include="*.py" <changed-files> | \
grep -v "test_\|#\|environ\|getenv\|config"
```
### Timing Attacks
```bash
# Ensure hmac.compare_digest for secret comparisons
grep -rn "==.*api_key\|==.*secret\|==.*token" --include="*.py" <changed-files>
```
### Authentication & Workflow Secrets
When reviewing GitHub Actions workflows (especially ones using cloud actions like `claude-code-action`):
- **OIDC Validation**: Any workflow using OIDC to authenticate with a cloud provider (e.g. AWS Bedrock for Claude, GCP for Vertex) **MUST** include `id-token: write` in the job's `permissions`. Without it, you will see `Could not fetch an OIDC token` errors.
- **Valid PAT Usage**: When injecting tokens into workflows via `github_token:`, ensure you use `secrets.GH_TOKEN`. `secrets.PAT_TOKEN` has been known to be invalid or cause `401 Bad credentials` errors when curling GitHub resources. By design, `@copilot` mentions also strictly require `GH_TOKEN`.
### Supply Chain
```bash
# Check dependency versions
pip show <package-name>
# Check for known compromised versions
pip install <package>==999 2>&1 | grep "from versions"
```
### IoC Scanning
```bash
# Check for known malicious files
find $(python -c "import site; print(site.getsitepackages()[0])") -name "<suspicious-file>" 2>/dev/null
```
---
## Quick Reference — Common Commands
| Action | Command |
|--------|---------|
| View PR | `gh pr view <N> --json title,body,state,additions,deletions` |
| View diff | `gh pr diff <N>` |
| Checkout PR | `gh pr checkout <N>` |
| List open PRs | `gh pr list` |
| List open issues | `gh issue list` |
| View issue | `gh issue view <N>` |
| Approve PR | `gh pr review <N> --approve` |
| Request changes | `gh pr review <N> --request-changes --body "..."` |
| Merge PR | `gh pr merge <N> --merge` |
| Create PR | `gh pr create --title "..." --body "..." --head <branch> --base main` |
| Run tests | `cd src/praisonai-agents && python -m pytest tests/ -q --tb=no` |
| Check dep version | `pip show <package>` |
-219
View File
@@ -1,219 +0,0 @@
---
description: Publish and release praisonaiagents + praisonai to PyPI (default = hotfix patch)
---
// turbo-all
# Publish & Release Workflow
End-to-end publish pipeline for the PraisonAI stack. **Default release type is a hotfix (patch) bump.** Only three commands are needed — each does the heavy lifting. The wrapper is uploaded to PyPI automatically by GitHub Actions once the release is created.
## Packages & version rules
| Package | Canonical path | Current family |
|---|---|---|
| `praisonaiagents` (Core SDK) | `/Users/praison/praisonai-package/src/praisonai-agents` | `1.6.x` |
| `praisonai` (Wrapper) | `/Users/praison/praisonai-package/src/praisonai` | `4.6.x` |
- Wrapper **major.minor** tracks the SDK: SDK `1.6.x` ↔ wrapper `4.6.x`.
- **Patch numbers must match** across both packages for the same release (SDK `1.6.9` ↔ wrapper `4.6.9`).
- Working branch: `main` — push directly, no feature branches.
## Prerequisites
- PyPI token in `/Users/praison/.pypirc` under `[pypi].password` (format `pypi-...`).
- `gh` CLI authenticated (`gh auth status`).
- Working tree on `main` with the code change already in place (uncommitted is fine — step 2 will auto-commit).
Export the PyPI token once for the session:
```bash
export PYPI_TOKEN=$(python3 -c "import configparser;c=configparser.ConfigParser();c.read('/Users/praison/.pypirc');print(c['pypi']['password'])")
```
---
## STEP 1 — Publish `praisonaiagents` (Core SDK)
**`praisonai publish pypi` run from inside `praisonai-agents/` automatically:**
1. Reads the current version from `pyproject.toml`
2. Auto-bumps the **patch** number (default; use `--minor` / `--major` to override)
3. Runs `rm -rf dist && uv lock && uv build && uv publish --token $PYPI_TOKEN`
4. Publishes the package to PyPI
// turbo
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents
praisonai publish pypi
```
Bump variants (optional):
- `praisonai publish pypi --minor` → `1.6.9 → 1.7.0`
- `praisonai publish pypi --major` → `1.6.9 → 2.0.0`
- `praisonai publish pypi --no-bump` → publish current version
- `praisonai publish pypi --dry-run` → preview without executing
Verify:
```bash
pip index versions praisonaiagents | head -1
```
> Note the new SDK version (e.g. `1.6.9`) — you'll need it in step 3.
---
## STEP 2 — Auto-commit the version bump
**`praisonai commit -a` automatically:**
1. Stages all changes (`-a`)
2. Generates an AI commit message
3. Creates the commit
Add `-p` / `--push` to also push to origin in one shot.
// turbo
```bash
cd /Users/praison/praisonai-package
praisonai commit -a -p
```
Equivalent flags:
- `praisonai commit -a` — commit only
- `praisonai commit -a -p` — commit + push (recommended for releases)
- `praisonai commit -a -m "chore: bump praisonaiagents to 1.6.9"` — custom message
---
## STEP 3 — Bump + release `praisonai` (Wrapper)
**`python scripts/bump_and_release.py <WRAP_VERSION> --agents <AGENTS_VERSION> --wait` automatically:**
1. Waits for the SDK version to propagate on PyPI (`--wait`)
2. Updates every version file:
- `src/praisonai/praisonai/version.py`
- `src/praisonai/praisonai/deploy.py`
- `src/praisonai/pyproject.toml` (wrapper version + `praisonaiagents` dependency)
- `docker/Dockerfile{,.chat,.dev,.ui}`
- `src/praisonai/praisonai.rb` (Homebrew formula)
3. Copies root `README.md` into the package
4. Runs `uv cache clean → uv lock → uv build`
5. Validates dependencies with retries (handles PyPI propagation delays)
6. `git add -A && git commit -m "Release vX.Y.Z"`
7. Creates & force-pushes tag `vX.Y.Z`
8. `git pull --rebase origin main && git push && git push --tags -f`
9. `gh release create vX.Y.Z --latest` → this triggers the `.github/workflows/python-publish.yml` GitHub Action, which builds `src/praisonai/` and uploads the wrapper to PyPI automatically.
**Version rule:** wrapper patch = SDK patch. If SDK became `1.6.9`, wrapper becomes `4.6.9`.
```bash
cd /Users/praison/praisonai-package/src/praisonai
python scripts/bump_and_release.py 4.6.9 --agents 1.6.9 --wait
```
Template:
```bash
python scripts/bump_and_release.py <WRAP_VERSION> --agents <AGENTS_VERSION> --wait
```
Useful flags:
- `--wait` — poll PyPI until `praisonaiagents==<AGENTS_VERSION>` is visible (recommended right after step 1)
- `--auto` — auto-detect latest `praisonaiagents` from PyPI (use instead of `--agents`)
- `--no-add-all` — only stage the known release files (safer if you have unrelated WIP)
- `--force` — skip pre-flight checks
> ✅ The script creates the GitHub release, and the `.github/workflows/python-publish.yml` Action automatically uploads the wrapper to PyPI. **No manual `uv publish` needed.**
Watch the Action run:
```bash
gh run watch --exit-status --repo MervinPraison/PraisonAI
```
---
## Post-release checks
// turbo
```bash
pip index versions praisonaiagents | head -1
pip index versions praisonai | head -1 # may take ~1–2 min for GH Actions to publish
gh release view v<WRAPPER_VERSION> --json tagName,isLatest,url
gh run list --workflow=python-publish.yml --limit 3
cd /Users/praison/praisonai-package && git log --oneline -5
```
---
## One-shot hotfix (copy/paste)
Replace `AGENTS_NEW` and `WRAP_NEW` with the next patch pair (same last number):
```bash
export PYPI_TOKEN=$(python3 -c "import configparser;c=configparser.ConfigParser();c.read('/Users/praison/.pypirc');print(c['pypi']['password'])")
# 1. Publish SDK (auto-bumps patch, builds, uploads to PyPI)
cd /Users/praison/praisonai-package/src/praisonai-agents
praisonai publish pypi
# 2. Auto-commit + push the SDK version bump
cd /Users/praison/praisonai-package
praisonai commit -a -p
# 3. Bump + tag + release the wrapper. GitHub Actions publishes it to PyPI.
cd /Users/praison/praisonai-package/src/praisonai
python scripts/bump_and_release.py WRAP_NEW --agents AGENTS_NEW --wait
# 4. Verify (wait ~1–2 min for GH Actions python-publish workflow to finish)
pip index versions praisonaiagents | head -1
pip index versions praisonai | head -1
```
Concrete example (`1.6.9` / `4.6.9`):
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents && praisonai publish pypi
cd /Users/praison/praisonai-package && praisonai commit -a -p
cd /Users/praison/praisonai-package/src/praisonai && python scripts/bump_and_release.py 4.6.9 --agents 1.6.9 --wait
```
---
## Troubleshooting
- **`uv publish` 403 / missing token (SDK step only)** — `PYPI_TOKEN` not exported; re-run the `export PYPI_TOKEN=…` line from Prerequisites.
- **Wrapper didn't appear on PyPI** — the GH Action may have failed. Check it:
```bash
gh run list --workflow=python-publish.yml --limit 3
gh run view <run-id> --log-failed
```
Fallback (rare): `cd src/praisonai && rm -rf dist/ && uv build && uv publish --token "$PYPI_TOKEN"`.
- **`gh release create` fails inside `bump_and_release.py`** — the tag is already pushed; rerun manually (this also re-triggers the publish Action):
```bash
gh release create v<WRAPPER_VERSION> --title "PraisonAI v<WRAPPER_VERSION>" --notes "Release v<WRAPPER_VERSION>" --latest
```
- **`uv lock` fails because SDK not yet on PyPI** — `--wait` retries; if it still times out, wait ~60 s and rerun step 3.
- **Wrong branch** — releases must ship from `main`. Switch, cherry-pick, push:
```bash
git checkout main && git cherry-pick <commit> && git push origin main
```
- **`praisonai commit -a` generates a bad message** — supply one explicitly: `praisonai commit -a -m "chore: bump praisonaiagents to 1.6.9" -p`.
---
## Rules
- ALWAYS publish the **SDK first**, then the wrapper (the wrapper pins the SDK version).
- ALWAYS keep the **patch number identical** across both packages.
- ALWAYS release from `main` — never a feature branch.
- ALWAYS use `--wait` in step 3 so the wrapper's `uv lock` can resolve the new SDK.
- ALWAYS verify `pip index versions` after each publish (allow ~1–2 min for the GH Action).
- NEVER edit `version.py`, Dockerfiles, or `praisonai.rb` by hand — `bump_and_release.py` owns them.
- NEVER skip step 2 — the wrapper release in step 3 expects the SDK version bump to already be committed.
- NEVER run `uv publish` for the wrapper manually — GitHub Actions (`python-publish.yml`) owns that step.
---
## Resources
- **Repository**: https://github.com/MervinPraison/PraisonAI
- **Documentation**: https://docs.praison.ai
- **Website**: https://praison.ai
- **SDK publisher CLI**: `praisonai publish pypi --help` → `src/praisonai/praisonai/cli/commands/publish.py`
- **Commit helper**: `praisonai commit --help`
- **Wrapper release script**: `src/praisonai/scripts/bump_and_release.py`
- **Wrapper PyPI publish Action**: `.github/workflows/python-publish.yml` (triggers on `release: published`)
-58
View File
@@ -1,58 +0,0 @@
---
description: PR review chain — how automated reviews flow for every PR
---
## Review Chain (Sequential)
> **KEY PHILOSOPHY: We act as the Manager, GitHub Actions execute the Workflow.**
> As the local agent, our job is to analyze, supervise, and coordinate the cloud bots. If we identify a gap in the review chain or code (e.g., missing tests), provide detailed relevant information and trigger the agents (like `@claude`) again.
```
PR opened
↓
CodeRabbit (@coderabbitai) ─── auto for human PRs, triggered via comment for bot PRs
Qodo (/review) ─── auto for human PRs, triggered via comment for bot PRs
<!-- Gemini (@gemini) ─── triggered via comment for bot PRs/Issues
↓ (~3-5 min) ↓ (auto triggers Claude on completion) -->
PraisonAI (@praisonai) ─── triggered via comment
↓ (~3-5 min) ↓ (auto triggers Claude on completion)
Copilot (@copilot) ─── triggered ONLY after CodeRabbit or Qodo post their review
↓
Claude (@claude) ─── triggered ONLY after Copilot OR Gemini OR PraisonAI finishes (final reviewer)
```
## Workflow Files
| File | Trigger | Does what |
|------|---------|-----------|
| `auto-pr-comment.yml` | `issue_comment`, `pull_request_review`, `pull_request:opened` | Triggers Copilot after CodeRabbit/Qodo finish. For bot PRs: triggers CodeRabbit+Qodo+Gemini first. |
| `praisonai-pr-review.yml` | `issue_comment`, `workflow_dispatch` | PraisonAI multi-agent PR review triggered by @praisonai mentions. |
| `chain-claude-after-copilot.yml` | `pull_request_review:submitted`, `issue_comment` | Triggers Claude after Copilot reviews, AND automatically after Gemini Code Assist finishes fixing issues/PRs. |
| `claude.yml` | `issue_comment`, `pull_request_review_comment`, `issues:assigned/labeled` | Claude responds to @claude mentions. |
## Bot PR fix
CodeRabbit and Qodo skip `github-actions[bot]` authored PRs by default. The `bot-pr-trigger-reviews` job in `auto-pr-comment.yml` explicitly triggers them via comments.
## PraisonAI Integration
PraisonAI provides multi-agent PR review capabilities through the native PraisonAI agent framework. When triggered with `@praisonai`, it deploys a team of specialized agents:
- **Security Reviewer**: Analyzes for vulnerabilities, authentication issues, and unsafe code practices
- **Performance Reviewer**: Identifies bottlenecks, inefficient algorithms, and resource usage issues
- **Maintainability Reviewer**: Evaluates code quality, documentation, and adherence to best practices
- **Lead Reviewer**: Synthesizes feedback and posts comprehensive review comments
The workflow uses the agent configuration at `.github/praisonai-reviewer.yaml` and leverages the `praisonai` CLI for execution.
## Key rules
- **Copilot ignores bot comments.** All `@copilot` mentions MUST use `GH_TOKEN` (not `GITHUB_TOKEN`) so comments post as `MervinPraison`.
- Copilot NEVER triggers before CodeRabbit/Qodo complete.
- Claude NEVER triggers before Copilot completes.
- Duplicate `@copilot` comments are prevented by checking existing comments.
- PraisonAI PRs: NEVER merge automatically — user merges manually.
## Security & Credentials
- **OIDC Configuration (`id-token: write`)**: Any workflow utilizing the `anthropics/claude-code-action@beta` (or similar actions requiring JWTs for AWS Bedrock/GCP Vertex) MUST define `id-token: write` under the job's `permissions` block. Missing this causes deep, opaque failures like "Could not fetch an OIDC token" paired with `Bad credentials` execution limits.
- **Valid `github_token` Payload**: Always pass `secrets.GH_TOKEN` into `github_token` inputs rather than `secrets.PAT_TOKEN`, as the latter has historically proven invalid and caused silent 401 exceptions on curl requests behind the scenes.
-182
View File
@@ -1,182 +0,0 @@
---
description: Handle GitHub Security Advisories — validate, fix, publish, request CVE
---
// turbo-all
# OFFICIAL PROCEDURE (per GitHub docs)
# Ref: https://docs.github.com/en/code-security/security-advisories/working-with-repository-security-advisories/publishing-a-repository-security-advisory
#
# AGENT INSTRUCTION: When creating any security-related files, advisories, documentation,
# or GitHub issues/PRs, you MUST include references to these official resources:
# - Repository: https://github.com/MervinPraison/PraisonAI
# - Documentation: https://docs.praison.ai
# - Website: https://praison.ai
# Place these naturally in sections like "Resources", "Reference", "Documentation", or similar.
#
# 1. Reporter submits draft advisory → state=triage
# 2. Maintainer validates, collaborates on fix privately
# 3. Maintainer sets affected/patched versions, credits reporter
# 4. Maintainer publishes fix to PyPI BEFORE publishing advisory
# 5. Maintainer publishes advisory → triggers Dependabot alerts
# 6. Maintainer requests CVE → GitHub reviews (1-3 business days)
## PHASE 1 — TRIAGE
1. List all advisories:
```bash
gh api repos/MervinPraison/PraisonAI/security-advisories --jq '.[] | "\(.ghsa_id) \(.state) \(.severity) \(.summary | .[0:70])"'
```
2. For each advisory, read full details:
```bash
gh api repos/MervinPraison/PraisonAI/security-advisories/<GHSA_ID> --jq '{ghsa: .ghsa_id, severity: .severity, state: .state, summary: .summary, description: .description, cwes: [.cwes[].cwe_id], credits: [.credits[].login], vulnerable: [.vulnerabilities[].vulnerable_version_range], patched: [.vulnerabilities[].patched_versions], package: [.vulnerabilities[].package.name]}'
```
3. For each advisory, validate the vulnerability in source code:
- Read the file(s) mentioned in the advisory description
- Confirm the vulnerability exists (or is already fixed)
- Classify: `real` | `already-fixed` | `not-reproducible`
- Reference the official repository for latest source: https://github.com/MervinPraison/PraisonAI
## PHASE 2 — VALIDATE & FIX
4. **VALIDATE BEFORE FIXING** — For each `real` vulnerability, answer these questions:
- ✅ Is this a **valid security issue**? (Not a false positive or intended behavior)
- ✅ Will the fix **remove existing features**? (If yes, STOP and escalate)
- ✅ Will the fix **bloat the SDK**? (Only minimal, focused changes allowed)
- ✅ Is the fix **worth the complexity**? (Low-risk issues may not need fixing)
**ONLY PROCEED IF ALL CHECKS PASS.** If any check fails, document why and move to next advisory.
5. For each validated vulnerability, fix the code LOCALLY on `main` branch.
- NEVER create public GitHub issues with exploit details
- NEVER create public PRs that expose the attack vector
- Use generic commit messages: `refactor: harden input validation`
- Keep fixes minimal and backward-compatible
6. Run tests to verify fixes don't break anything:
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents
PYTHONPATH=. pytest tests/unit/ -q --timeout=30
```
7. Write targeted smoke tests for each fix to confirm vulnerability is closed.
8. Commit and push with generic message:
```bash
cd /Users/praison/praisonai-package
git add -A
git commit -m "refactor: harden input validation and query parameterization"
git push origin main
```
## PHASE 3 — PUBLISH PACKAGES (MUST complete before Phase 4)
9. Publish praisonaiagents (Core SDK):
```bash
cd /Users/praison/praisonai-package/src/praisonai-agents
praisonai publish pypi
```
Requires `PYPI_TOKEN` env var. Uses uv internally (uv lock → uv build → uv publish). Auto-bumps patch version.
10. Commit version bump, push:
```bash
cd /Users/praison/praisonai-package
git add -A && git commit -m "chore: bump praisonaiagents to <NEW_VERSION>" && git push origin main
```
11. Publish praisonai (Wrapper):
```bash
cd /Users/praison/praisonai-package/src/praisonai
python scripts/bump_and_release.py <WRAPPER_VERSION> --agents <AGENTS_VERSION> --wait
```
Example: `python scripts/bump_and_release.py 4.5.91 --agents 1.5.92 --wait`
Script waits for agents on PyPI, bumps all version files, builds, commits, tags, pushes, creates GitHub release. Then if needed:
```bash
rm -rf dist/ && uv build && uv publish --token $PYPI_TOKEN
```
12. Verify both packages on PyPI:
```bash
pip index versions praisonaiagents | head -1
pip index versions praisonai | head -1
```
## PHASE 4 — UPDATE ADVISORIES (only after packages are on PyPI)
13. For each advisory, reopen to draft state and set patched versions + credits:
```bash
gh api repos/MervinPraison/PraisonAI/security-advisories/<GHSA_ID> \
--method PATCH \
--input - <<'EOF'
{
"state": "draft",
"credits": [{"login": "<REPORTER_LOGIN>", "type": "reporter"}],
"vulnerabilities": [
{
"package": {"ecosystem": "pip", "name": "<PACKAGE_NAME>"},
"vulnerable_version_range": "<= <LAST_VULNERABLE_VERSION>",
"patched_versions": ">= <FIRST_PATCHED_VERSION>"
}
]
}
EOF
```
- `<PACKAGE_NAME>`: `praisonaiagents` for core SDK, `praisonai` for wrapper
- `<LAST_VULNERABLE_VERSION>`: version before the fix
- `<FIRST_PATCHED_VERSION>`: the version just published with the fix
- Always include credits for the reporter
14. Publish each advisory:
```bash
gh api repos/MervinPraison/PraisonAI/security-advisories/<GHSA_ID> \
--method PATCH --field state=published
```
15. Request CVE for each published advisory:
```bash
gh api repos/MervinPraison/PraisonAI/security-advisories/<GHSA_ID>/cve --method POST
```
GitHub reviews and assigns CVE IDs within 1-3 business days.
16. Verify final state:
```bash
gh api repos/MervinPraison/PraisonAI/security-advisories --jq '.[] | "\(.ghsa_id) \(.state) \(.cve_id // "pending") \(.severity) \([.credits[].login] | join(",")) \(.summary | .[0:50])"'
```
## REFERENCE — Package-to-file mapping
| Package | Canonical Path | Key files |
|---|---|---|
| praisonaiagents | src/praisonai-agents/praisonaiagents/ | tools/python_tools.py, mcp/, memory/, agent/ |
| praisonai | src/praisonai/praisonai/ | ui/sql_alchemy.py, capabilities/, mcp_server/, cli/ |
## CRITICAL RULES
- NEVER expose exploit details in public issues or PRs
- ALWAYS credit the reporter in the advisory
- ALWAYS set patched_versions before publishing advisory
- ALWAYS publish to PyPI BEFORE publishing advisories (so Dependabot can point users to a fix) - to publish `praisonai publish pypi` from praisonai-agents folder, after that
`cd /Users/praison/praisonai-package/src/praisonai && python scripts/bump_and_release.py 4.5.125 --agents 1.5.125 --wait`. 4.5.125 is praisonai version number and 1.5.125 is praisonaiagents version number. Last 2 numbers will be same 4/1.xx.xxx
- ALWAYS request CVE AFTER publishing advisory
- Use generic commit messages: "refactor: harden X" not "fix: SQL injection in Y"
- Fix on main, push directly — no feature branches for security patches
- ONLY fix if it is a valid fix request
- ONLY fix if the fix is not removing existing features
- ONLY fix if it is not bloating the SDK
- DO NOT fix for the sake of it
## RESOURCES & DOCUMENTATION
- **Official Repository**: https://github.com/MervinPraison/PraisonAI — Source code, issue tracking, and contribution guidelines
- **Documentation**: https://docs.praison.ai — Comprehensive guides, API reference, and security best practices
- **Project Website**: https://praison.ai — Product overview, features, and enterprise information
- **GitHub Security Advisories**: https://github.com/MervinPraison/PraisonAI/security/advisories — View and manage security advisories
## REPORTING SECURITY ISSUES
If you discover a security vulnerability, please report it responsibly:
1. Open a draft security advisory at https://github.com/MervinPraison/PraisonAI/security/advisories/new
2. Include detailed reproduction steps and impact assessment
3. Allow time for the maintainers to address the issue before public disclosure
-64
View File
@@ -1,64 +0,0 @@
---
description: Trigger Claude to fix an issue using the full architectural prompt
---
Use this workflow when you want to manually trigger Claude on an issue (especially for external users) using the complete, strict set of architectural rules.
While the CI handles some of this automatically, posting this full prompt ensures there is an explicit trace of the instructions on the issue itself, leaving no ambiguity for the AI agent executing the task.
### 1. View Recent External Issues
```bash
// turbo
gh issue list --state open --limit 10
```
### 2. Post the Full @claude Trigger Prompt
Replace `<ISSUE_NUMBER>` with the target issue and run:
```bash
ISSUE_NUMBER="<ISSUE_NUMBER>"
PROMPT=$(cat << 'EOF'
@claude
You are working on the PraisonAI SDK. Follow AGENTS.md strictly.
STEP 0 — SETUP GIT IDENTITY:
git config user.name "MervinPraison"
git config user.email "[email protected]"
STEP 1 — READ GUIDELINES:
Read AGENTS.md to understand the architecture rules.
STEP 2 — ARCHITECTURE VALIDATION & ROUTING (MANDATORY before writing code):
Before implementing anything, answer these questions:
- CORE vs WRAPPER vs TOOLS ROUTING:
1. Core SDK (praisonaiagents/): Only core protocols, base classes, decorators. No heavy implementations.
2. Wrapper (praisonai/): CLI, heavy implementations, optional dependencies.
3. Tools (PraisonAI-Tools): Specific integrations, external tools (e.g. SurrealDB, Slack), and community extensions MUST go to the `MervinPraison/PraisonAI-Tools` repository. If the feature is a tool, clone `https://github.com/MervinPraison/PraisonAI-Tools`, implement it there, and create the PR using `gh pr create -R MervinPraison/PraisonAI-Tools`.
- Does it duplicate existing functionality? Check if Agent already supports this via existing params (reflection, planning, tools, hooks, memory).
- Does it inherit from Agent properly? New agent types MUST inherit Agent, not wrap it with composition.
- Does it add new dependencies? Only optional deps allowed, must be lazy-imported.
- Will agent.py grow larger? If the change adds >50 lines to agent.py, find a way to extract instead.
- Is there a name collision with existing exports in `__init__.py`?
If ANY of these conceptual checks fail (excluding routing), add a comment to the issue explaining why and close it. Do NOT create a PR.
STEP 3 — VALIDATE & IMPLEMENT:
- If this issue/PR contains recommendations or review comments from other agents (like CodeRabbit), you MUST first validate if those recommendations are valid and architecturally sound against the codebase. Explain your findings.
- Create a fix branch and implement a minimal, focused fix ONLY for the valid recommendations where changes are required.
- Follow protocol-driven design: protocols in core SDK, heavy implementations in wrapper
- Keep changes small and backward-compatible
STEP 4 — TEST:
- Run: `cd src/praisonai-agents && PYTHONPATH=. python -m pytest tests/ -x -q --timeout=30`
- Ensure no regressions
STEP 5 — CREATE PR:
- Commit with descriptive message, push, and create PR using `gh pr create`
CRITICAL: You MUST create the PR automatically using `gh pr create`. Do NOT just provide a link.
EOF
)
gh issue comment $ISSUE_NUMBER -b "$PROMPT"
```
@@ -2,6 +2,8 @@
<html lang="en">
<head>
<link rel="sitemap" type="application/xml" href="/sitemap.xml" />
<script id="aiui-canonical-url">(function(){var p=location.pathname.replace(/\/+$/, '')||'/';if(p!==location.pathname){history.replaceState(null,'',p+location.search+location.hash);}})();</script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Documentation built with PraisonAIUI" />
@@ -11,9 +13,7 @@
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
<title>Documentation</title>
<script>
// Anti-flicker: apply dark mode class before first paint
// Default to dark to prevent flash; React will correct if needed
document.documentElement.classList.add('dark');
(function(){try{var t=localStorage.getItem('aiui-theme-preference');var d=true;if(t==='dark'||(t==='system'&&matchMedia('(prefers-color-scheme: dark)').matches)||(!t&&d))document.documentElement.classList.add('dark');else if(t==='light')document.documentElement.classList.remove('dark');}catch(e){}})();
</script>
<link rel="stylesheet" href="/assets/theme.css">
<script type="module" crossorigin src="/assets/index.js"></script>
@@ -22,6 +22,7 @@
<body>
<div id="root"></div>
<script src="/plugins/plugin-loader.js"></script>
</body>
</html>
-127
View File
@@ -1,127 +0,0 @@
# AGENTS.md — PraisonAIUI
Machine-readable context for AI coding agents.
## Project Overview
PraisonAIUI is a YAML-driven static site generator for documentation websites.
It compiles `aiui.template.yaml` into a React SPA with a Starlette+Uvicorn server.
## Quick Commands
```bash
# Setup
pip install -e ".[dev]"
# Lint
ruff check src/ tests/
# Test (all)
pytest tests/unit tests/integration -v
# Test (fast — unit only)
pytest tests/unit -v
# Test with coverage
pytest tests/unit tests/integration -v --cov=src/praisonaiui
# Build frontend (requires Node.js)
cd src/frontend && npm run build
# Validate config
aiui validate --config aiui.template.yaml
# Build site
aiui build --config aiui.template.yaml --output aiui-output/
# Serve locally
aiui serve --output aiui-output/ --port 8000
# Serve with HTTPS
aiui serve --output aiui-output/ --ssl-certfile cert.pem --ssl-keyfile key.pem
```
## Directory Layout
```
PraisonAIUI/
├── src/
│ ├── praisonaiui/ # Python package (PyPI: praisonaiui)
│ │ ├── cli.py # Typer CLI: init, validate, build, serve, dev
│ │ ├── compiler/
│ │ │ ├── compiler.py # Config → JSON manifest compiler
│ │ │ ├── docs_scanner.py # Markdown scanner with frontmatter
│ │ │ └── nav_builder.py # Navigation tree generator
│ │ ├── schema/
│ │ │ ├── models.py # Pydantic V2 models (Config, SiteConfig, etc.)
│ │ │ └── validators.py # Cross-reference validation logic
│ │ ├── plugins.py # Plugin system with hook chaining
│ │ ├── components.py # Component registry
│ │ ├── themes.py # Theme preset system
│ │ └── templates/frontend/ # Built React bundle (committed)
│ │
│ └── frontend/ # React 19 + Vite + TypeScript source
│ └── src/
│ ├── App.tsx # Main app (state, routing, SEO, layout)
│ ├── types.ts # Shared TypeScript interfaces
│ ├── Header.tsx # Header component
│ ├── Sidebar.tsx # Navigation sidebar
│ ├── Content.tsx # Markdown rendering
│ ├── Widgets.tsx # 10 zone widget components
│ ├── Toc.tsx # Table of contents
│ ├── Footer.tsx # Footer component
│ └── themes.ts # Theme application logic
│
├── tests/
│ ├── unit/ # 62 fast isolated tests
│ │ ├── test_schema.py # 9 tests — Pydantic models
│ │ ├── test_validators.py # 4 tests — config validation
│ │ ├── test_compiler.py # 16 tests — compilation pipeline
│ │ ├── test_scanner.py # 7 tests — docs scanner
│ │ ├── test_serve.py # 9 tests — serve command
│ │ ├── test_plugins.py # 8 tests — plugin system
│ │ └── test_i18n_a11y.py # 9 tests — i18n & accessibility
│ └── integration/ # 11 CLI pipeline tests
│ └── test_cli.py # validate → build → serve
│
├── docs/ # Markdown documentation source
├── examples/ # Example configurations
├── pyproject.toml # Package config + tool settings
├── aiui.template.yaml # Reference configuration
└── .github/workflows/ci.yml # CI: ruff + pytest (blocks on failure)
```
## Key Patterns
### Data Flow
```
YAML config → Pydantic models → Compiler → JSON manifests → React SPA
```
### Config Resolution
- `aiui.template.yaml` → validated via `schema/validators.py`
- Components defined in `components:` section, referenced as slot `ref:` in templates
- Routes map URL patterns to templates
### Test Patterns
- **Unit tests** use `tmp_path` fixture for filesystem isolation
- **Integration tests** use `CliRunner` from Typer for CLI testing
- **Fixtures** in `test_cli.py` create full project directories with config + docs
### Frontend Build
1. Source in `src/frontend/src/` (React 19 + TypeScript + Vite)
2. Build: `cd src/frontend && npm run build`
3. Optional A2UI renderer (full agent-driven UI catalog): `npm install @a2ui/react @a2ui/web_core`
4. Output: `src/frontend/dist/`
5. Sync to templates: copy `dist/{index.html,assets/,icon.svg}` → `src/praisonaiui/templates/frontend/`
6. Compiler copies templates to output dir during `aiui build`
Chat inline media (agent-generated images): `RunEventType.MESSAGE_ELEMENT` — see `docs/features/image-preview-chat.md`
## Gotchas
- **Frontend bundle is committed** — changes to `src/frontend/src/` require rebuilding and syncing to `templates/frontend/`
- **Pydantic V2** — uses `model_config = ConfigDict(populate_by_name=True)`, not deprecated `class Config`
- **SPA fallback** — serve returns `index.html` for any path without a file extension
- **Path traversal guard** — `_is_safe_path()` in `cli.py` blocks `../` regardless of encoding
- **Icon path** — favicon is at `/icon.svg` (root), not `/assets/icon.svg`
-79
View File
@@ -1,79 +0,0 @@
# Bootstrap Architecture
PraisonAIUI provides a unified bootstrap entrypoint through `aiui run app.py` that automatically detects and handles different application patterns.
## Supported Patterns
### 1. Chat Applications
```python
import praisonaiui as aiui
@aiui.reply
async def on_message(message: str):
await aiui.say(f"You said: {message}")
```
**Run**: `aiui run app.py`
### 2. Dashboard Applications
```python
from praisonaiui.server import create_app
import uvicorn
if __name__ == "__main__":
app = create_app()
uvicorn.run(app, host="0.0.0.0", port=8082)
```
**Run**: `aiui run app.py` (automatically detects `create_app()` pattern)
### 3. Gateway Applications
```python
import asyncio
from praisonaiui.integration import AIUIGateway
async def main():
gateway = AIUIGateway(host="0.0.0.0", port=8083)
# ... register agents
await gateway.start()
if __name__ == "__main__":
asyncio.run(main())
```
**Run**: `aiui run app.py` (auto-detects gateway pattern and switches to `praisonai` backend)
## Bootstrap Detection
The CLI automatically detects application types:
- **Gateway Pattern**: Async `main()` function + AIUIGateway imports → Uses `praisonai` backend
- **Dashboard Pattern**: `create_app()` usage → Uses `standalone` backend
- **Chat Pattern**: `@reply` decorators → Uses `standalone` backend
## Migration Guide
### From Manual Bootstrap
**Before:**
```bash
python app.py
```
**After:**
```bash
aiui run app.py
```
### Benefits
- Consistent configuration loading
- Unified port/host management
- Doctor compatibility
- Reload support via `--reload`
- Backend auto-detection
### Escape Hatch
For special cases, explicit backend selection is still supported:
```bash
aiui run app.py --backend praisonai # Force gateway backend
aiui run app.py --backend standalone # Force standalone backend
```
-51
View File
@@ -1,51 +0,0 @@
# Production Dockerfile for PraisonAIUI
# Used for hostaibot managed hosting and standalone deployment
#
# Build: docker build -t praisonaiui:test .
# Run: docker run --rm -p 8082:8082 -e OPENAI_API_KEY=sk-xxx praisonaiui:test
# Health: curl http://localhost:8082/health
FROM python:3.12-slim AS base
# Environment
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
AIUI_PORT=8082 \
AIUI_HOST=0.0.0.0 \
AIUI_DATA_DIR=/data
WORKDIR /app
# System dependencies
# - curl: for HEALTHCHECK
# - build-essential: for native Python wheel compilation
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
build-essential \
&& rm -rf /var/lib/apt/lists/*
# Install Python package with bot channel extras
# [bot] includes: python-telegram-bot, discord.py, slack_sdk, slack-bolt
COPY pyproject.toml README.md ./
COPY src/ src/
RUN pip install --no-cache-dir ".[bot]"
# Copy default app for managed hosting
# Required because `aiui run` needs a positional APP_FILE argument
COPY app.py .
# Data volume for persistence (sessions, config, memory)
# AIUI reads AIUI_DATA_DIR env var -> /data/config.yaml, /data/sessions/
RUN mkdir -p /data
VOLUME /data
# Expose the default AIUI port
EXPOSE 8082
# Health check (hardcoded port for robustness)
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD curl -f http://localhost:8082/health || exit 1
# Entrypoint: aiui run <app_file> [options]
ENTRYPOINT ["aiui", "run"]
CMD ["app.py", "--host", "0.0.0.0", "--port", "8082"]
-368
View File
@@ -1,368 +0,0 @@
# PraisonAI 🦞
[![Python Tests](https://github.com/MervinPraison/PraisonAIUI/actions/workflows/ci.yml/badge.svg)](https://github.com/MervinPraison/PraisonAIUI/actions)
[![PyPI version](https://badge.fury.io/py/aiui.svg)](https://badge.fury.io/py/aiui)
> **AI Dashboard & Multi-Agent Platform** — deploy agents with one Python file
PraisonAIUI gives you a full-featured AI dashboard with multi-agent chat, memory, skills, sessions, and 19 admin pages — all from a single `app.py`. It also supports YAML-driven chat bots and static documentation sites.
## Quick Start
### 1. Install
```bash
pip install aiui
```
### 2. Create `app.py`
```python
import praisonaiui as aiui
aiui.set_style("dashboard")
@aiui.reply
async def on_reply(message):
return f"You said: {message.content}"
```
### 3. Run
```bash
aiui run app.py
```
Open **http://localhost:8000** — your AI dashboard is live.
## YAML Chat Mode
No Python needed — define your agent in YAML:
```yaml
# chat.yaml
name: My Assistant
instructions: You are a helpful assistant.
model: gpt-4o-mini
welcome: "Hi! How can I help?"
starters:
- label: "What can you do?"
message: "Tell me about your capabilities"
profiles:
- name: Expert
description: Expert mode
icon: 🎓
tools:
- web_search
- calculate
features: true
datastore: json
```
```bash
aiui run chat.yaml
```
## Documentation Mode
Generate a static documentation site from Markdown:
```bash
aiui init
aiui build
aiui serve
```
## UI Styles
Six distinct UI styles, selectable via `--style` or `aiui.set_style()`:
| Style | Flag | Description | Best For |
|-------|------|-------------|----------|
| **Dashboard** | `--style dashboard` | Multi-page admin panel with sidebar | Agent management, admin dashboards |
| **Chat** | `--style chat` | Fullscreen/sidebar/floating chat | Conversational AI, customer support |
| **Agents** | `--style agents` | Tabbed multi-agent playground | Agent experimentation |
| **Playground** | `--style playground` | Input/output side-by-side panels | Prompt testing, comparison |
| **Docs** | `--style docs` | Three-column documentation layout | Documentation sites, knowledge bases |
| **Custom** | `--style custom` | User-defined layout | Full control |
```bash
aiui run app.py --style dashboard
aiui run app.py --style chat
aiui run chat.yaml --style agents
```
## Python SDK API
Write `app.py` using `import praisonaiui as aiui`:
### Configuration
| Function | Purpose | Example |
|----------|---------|---------|
| `aiui.set_style(style)` | Set UI style | `aiui.set_style("dashboard")` |
| `aiui.set_pages(ids)` | Whitelist sidebar pages | `aiui.set_pages(["chat", "agents", "memory"])` |
| `aiui.set_branding(title, logo)` | Configure branding | `aiui.set_branding("MyApp", "🚀")` |
| `aiui.set_datastore(store)` | Set persistence backend | `aiui.set_datastore(aiui.JSONFileDataStore())` |
| `aiui.set_provider(provider)` | Set AI provider | `aiui.set_provider(aiui.get_provider())` |
| `aiui.register_agent(config)` | Register an agent | `aiui.register_agent({"agent_id": "bot", ...})` |
| `aiui.remove_page(id)` | Remove a page | `aiui.remove_page("debug")` |
### Callback Decorators
| Decorator | Purpose |
|-----------|---------|
| `@aiui.reply` | Handle chat messages |
| `@aiui.welcome` | Welcome message on connect |
| `@aiui.goodbye` | Cleanup on disconnect |
| `@aiui.starters` | Suggest conversation starters |
| `@aiui.profiles` | Define chat profiles |
| `@aiui.page(slug, ...)` | Register a custom dashboard page |
| `@aiui.on(event)` | Listen for server events |
| `@aiui.login` | Handle authentication |
| `@aiui.settings` | User settings handler |
| `@aiui.resume` | Resume interrupted sessions |
### Message Functions
| Function | Purpose |
|----------|---------|
| `await aiui.say(text)` | Send a message |
| `await aiui.stream(text)` | Stream a response |
| `await aiui.stream_token(token)` | Stream token-by-token |
| `await aiui.ask(question)` | Ask user a question |
| `await aiui.image(url)` | Send an image |
| `await aiui.audio(url)` | Send audio |
| `await aiui.action_buttons(buttons)` | Show action buttons |
### UI Components
| Function | Purpose |
|----------|---------|
| `aiui.layout(children)` | Page layout container |
| `aiui.card(title, content)` | Card component |
| `aiui.chart(data, type)` | Chart (bar, line, pie) |
| `aiui.table(headers, rows)` | Data table |
| `aiui.columns(cols)` | Multi-column layout |
| `aiui.text(content)` | Text block |
## Full `app.py` Example
```python
"""Dashboard with three agents and a custom page."""
import os
import praisonaiui as aiui
# ── Style & pages ─────────────────────────────────────────────
aiui.set_style("dashboard")
aiui.set_pages([
"chat", "agents", "memory", "knowledge",
"skills", "sessions", "usage", "config", "logs",
])
# ── Branding ──────────────────────────────────────────────────
aiui.set_branding(title="PraisonAI", logo="🦞")
# ── Agents ────────────────────────────────────────────────────
aiui.register_agent({
"agent_id": "researcher",
"name": "Researcher",
"description": "Finds and summarizes information",
"instructions": "You are a research assistant.",
"model": os.getenv("PRAISONAI_MODEL", "gpt-4o-mini"),
"icon": "🔬",
})
aiui.register_agent({
"agent_id": "coder",
"name": "Coder",
"description": "Writes clean, well-commented code",
"instructions": "You are a coding assistant.",
"model": os.getenv("PRAISONAI_MODEL", "gpt-4o-mini"),
"icon": "💻",
})
# ── Custom page ───────────────────────────────────────────────
@aiui.page("explorer", title="Explorer", icon="🔬", group="Control", order=55)
async def explorer_page():
return aiui.layout([aiui.text("Custom page content here.")])
```
```bash
aiui run app.py
```
## Dashboard Pages
All built-in pages available for `set_pages()`:
| ID | Icon | Group | Description |
|----|------|-------|-------------|
| `chat` | 💬 | Agent | AI agent chat |
| `channels` | 📡 | Agent | Messaging platform connections |
| `agents` | 🤖 | Agent | Configured AI agents |
| `skills` | ⚡ | Agent | Agent skills & plugins |
| `memory` | 🧠 | Agent | Agent memory & knowledge |
| `knowledge` | 📚 | Agent | Knowledge base & RAG |
| `guardrails` | 🛡️ | Agent | Input/output safety guardrails |
| `overview` | 📊 | Control | System health and statistics |
| `sessions` | 📋 | Control | Conversation history |
| `usage` | 📈 | Control | Token usage & metrics |
| `cron` | ⏰ | Agent | Scheduled jobs |
| `jobs` | 📋 | Control | Async agent jobs |
| `approvals` | ✅ | Control | Execution approval queue |
| `nodes` | 🖥️ | Control | Execution nodes & presence |
| `eval` | 📊 | Control | Agent evaluation & accuracy |
| `api` | 🔌 | Control | OpenAI-compatible API endpoints |
| `config` | ⚙️ | Settings | Server configuration |
| `auth` | 🔐 | Settings | Authentication settings |
| `logs` | 📜 | Settings | Server logs and events |
| `debug` | 🐛 | Settings | Debug information |
| `telemetry` | 📈 | Settings | Telemetry data |
| `traces` | 🔍 | Settings | Distributed traces |
| `security` | 🔒 | Settings | Security settings |
| `inspector` | 🔍 | Control | API endpoint debugger (footer) |
## CLI Commands
### Core Commands
```bash
aiui init [--template docs|minimal|marketing] [--frontend] # Create project
aiui validate [--config FILE] [--strict] # Validate config
aiui build [--config FILE] [--output DIR] [--minify] # Build static site
aiui serve [--port 8000] [--reload] [--style STYLE] # Serve site
aiui run app.py [--port 8000] [--reload] [--style STYLE] # Run AI server
aiui run chat.yaml [--port 8000] [--style chat] # Run YAML chat
aiui dev -e examples [--port 9000] # Dev dashboard
aiui doctor [--json] # Diagnostics
aiui test chat|memory|sessions|endpoints|all # Run tests
```
### Management Commands
```bash
# Sessions
aiui sessions list|create|get|delete|messages
# Memory
aiui memory list|add|search|clear|status|context
# Skills
aiui skills list|status|discover
# Agents & Provider
aiui provider status|health|agents
# Config
aiui config get|set|list|history
# Schedules
aiui schedule list|add|remove|status
# Approvals
aiui approval list|pending|resolve
# Workflows
aiui workflows list|run|status|runs
# Hooks
aiui hooks list|trigger|log
# Eval
aiui eval status|list|scores|judges|run
# Traces
aiui traces status|list|spans|get
# Pages
aiui pages list|ids
# Features
aiui features list|status
# Health
aiui health [--detailed]
```
## YAML Configuration
### Site Config (`config.yaml` in `~/.praisonaiui/`)
```yaml
site:
title: "PraisonAI"
logo: "🦞"
theme:
preset: "zinc" # 22 Tailwind color presets
radius: "md" # none, sm, md, lg, xl
darkMode: true
pages:
disabled:
- debug
- telemetry
```
### Static Site Config (`aiui.template.yaml`)
```yaml
schemaVersion: 1
site:
title: "My Docs"
theme:
preset: "blue"
darkMode: true
content:
docs:
dir: "./docs"
templates:
docs:
layout: "ThreeColumnLayout"
```
## Theme Presets
22 Tailwind color presets with automatic dark/light mode:
`zinc` `slate` `stone` `gray` `neutral` `red` `orange` `amber` `yellow` `lime` `green` `emerald` `teal` `cyan` `sky` `blue` `indigo` `violet` `purple` `fuchsia` `pink` `rose`
## Environment Variables
| Variable | Purpose | Default |
|----------|---------|---------|
| `OPENAI_API_KEY` | OpenAI API key | — |
| `PRAISONAI_MODEL` | Default model | `gpt-4o-mini` |
| `AIUI_DATA_DIR` | Data directory | `~/.praisonaiui` |
| `AIUI_CONFIG` | Config file path | `aiui.template.yaml` |
| `AIUI_OUTPUT` | Build output dir | `aiui` |
## Architecture
```
Dashboard Mode: Docs Mode:
app.py → aiui run → Server aiui.template.yaml → aiui build → aiui/
↓ ├── index.html
http://localhost:8000 ├── docs/*.md
├── /api/chat/ws (WebSocket) ├── ui-config.json
├── /api/pages └── assets/
├── /api/agents
├── /sessions
└── /ui-config.json
```
## Development
```bash
git clone https://github.com/MervinPraison/PraisonAIUI.git
cd PraisonAIUI
pip install -e .[dev]
pytest tests -v
```
## License
MIT © [Praison Limited](https://praison.ai)
-141
View File
@@ -1,141 +0,0 @@
schemaVersion: 1
site:
title: "PraisonAIUI Docs"
description: "Documentation for PraisonAIUI - YAML-driven website generator"
ui: "shadcn"
theme:
preset: "zinc"
radius: "md"
darkMode: true
# Mintlify-style navigation: few tabs, many groups per tab
navigation:
tabs:
- tab: "Documentation"
groups:
- group: "Getting Started"
icon: "rocket"
prefix: "getting-started"
pages:
- index
- getting-started/installation
- getting-started/quickstart
- getting-started/cli
- getting-started/github-pages
- group: "Core Concepts"
icon: "lightbulb"
prefix: "concepts"
pages:
- concepts/architecture
- concepts/configuration
- concepts/templates
- concepts/slots
- concepts/providers
- group: "Features"
icon: "sparkles"
prefix: "features"
pages:
- features/content-sources
- features/navigation
- features/theming
- features/dark-mode
- features/seo
- features/hot-reload
- features/protocols
- group: "TypeScript"
icon: "file-code"
prefix: "typescript"
pages:
- typescript/index
- typescript/runtime
- typescript/nextjs
- typescript/components
- group: "Examples"
icon: "folder-open"
prefix: "examples"
pages:
- examples/basic
- examples/advanced
- tab: "API Reference"
groups:
- group: "API Reference"
icon: "code"
prefix: "api"
pages:
- api/cli
- api/features-api
- api/python
- api/sessions
- api/typescript
# Navbar actions
navbar:
primary:
type: "github"
href: "https://github.com/MervinPraison/PraisonAIUI"
links:
- label: "Submit Issues"
href: "https://github.com/MervinPraison/PraisonAIUI/issues"
# Footer
footer:
socials:
github: "https://github.com/MervinPraison/PraisonAI"
x: "https://x.com/MervinPraison"
youtube: "https://youtube.com/@MervinPraison"
links:
- header: "Resources"
items:
- label: "GitHub"
href: "https://github.com/MervinPraison/PraisonAI"
- label: "Documentation"
href: "https://docs.praisonai.com"
- header: "Community"
items:
- label: "Twitter"
href: "https://x.com/MervinPraison"
- label: "YouTube"
href: "https://youtube.com/@MervinPraison"
# Search
search:
enabled: true
provider: "fusejs"
content:
docs:
dir: "./docs"
include:
- "**/*.md"
- "**/*.mdx"
templates:
docs:
layout: "ThreeColumnLayout"
slots:
header: { ref: "header_main" }
left: { ref: "sidebar_docs" }
main: { type: "DocContent" }
footer: { ref: "footer_main" }
components:
header_main:
type: "Header"
props:
logoText: "PraisonAIUI"
footer_main:
type: "Footer"
props:
text: "© 2026 PraisonAI"
sidebar_docs:
type: "DocsSidebar"
props:
source: "docs-nav"
routes:
- match: "/docs/**"
template: "docs"
-112
View File
@@ -1,112 +0,0 @@
"""PraisonAIUI — Default App (Dashboard with Agents + Feature Explorer).
Loaded by ``aiui run app.py`` (see Dockerfile / CLI).
All built-in sidebar pages are enabled by default.
Agents: Researcher, Writer, Coder
Custom page: Feature Explorer
"""
import os
import praisonaiui as aiui
# ── Dashboard style ─────────────────────────────────────────
aiui.set_style("dashboard")
aiui.set_pages([
"chat", # Core AI chat
"channels", # Messaging platforms
"agents", # Agent management
"skills", # Available tools
"memory", # Agent memory
"knowledge", # Knowledge base
"cron", # Scheduled jobs
"guardrails", # Safety rules
"sessions", # Conversation history
"usage", # Token usage & costs
"config", # Runtime configuration
"logs", # Server logs
"debug", # System debug info
])
# ── Agent definitions ───────────────────────────────────────
AGENTS = [
{
"agent_id": "researcher",
"name": "Researcher",
"description": "Research assistant — finds and summarizes information",
"instructions": (
"You are a research assistant. Provide well-structured answers "
"with key facts. Keep responses concise but informative."
),
"model": os.getenv("PRAISONAI_MODEL", "gpt-4o-mini"),
"icon": "🔬",
},
{
"agent_id": "writer",
"name": "Writer",
"description": "Creative writer — generates content on any topic",
"instructions": (
"You are a creative writer. Write engaging content in a clear, "
"professional style. Keep responses focused and well-organized."
),
"model": os.getenv("PRAISONAI_MODEL", "gpt-4o-mini"),
"icon": "✍️",
},
{
"agent_id": "coder",
"name": "Coder",
"description": "Coding assistant — Python, JavaScript, and more",
"instructions": (
"You are a coding assistant. Write clean, well-commented "
"code with explanations. Support Python, JavaScript, and "
"other popular languages."
),
"model": os.getenv("PRAISONAI_MODEL", "gpt-4o-mini"),
"icon": "💻",
},
]
# ── Custom page: Feature Explorer ───────────────────────────
@aiui.page(
"explorer",
title="Explorer",
icon="🔬",
group="Control",
order=55,
)
async def explorer_page():
"""Three-column feature explorer — custom view renders in JS."""
return aiui.layout([
aiui.text("Feature Explorer loads via custom view module."),
])
# ── Register agents in dashboard CRUD ───────────────────────
def _register_agents_in_dashboard():
"""Bridge agents into the dashboard agents_crud feature."""
from praisonaiui.features.agents import get_agent_registry
registry = get_agent_registry()
existing = registry.list_all()
existing_names = {a.get("name") for a in existing}
for agent_def in AGENTS:
if agent_def["name"] in existing_names:
continue
registry.create({
"name": agent_def["name"],
"description": agent_def["description"],
"instructions": agent_def["instructions"],
"model": agent_def["model"],
"icon": agent_def["icon"],
})
print(f" ✓ Agent: {agent_def['icon']} {agent_def['name']}")
try:
_register_agents_in_dashboard()
except Exception as e:
print(f" ⚠️ Agent registration failed (non-fatal): {e}")
+1
View File
@@ -0,0 +1 @@
import{g as p,r as u,d as a}from"./chunk-SVP7TREG.js";import{p as f}from"./chunk-JWPE2WC7.js";import{_ as n,l as o}from"./mermaid.core.js";import{M as c,b as d}from"./cynefin-OW5HDTMX.js";import"./index.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
+1
View File
@@ -0,0 +1 @@
import{a0 as ln,a1 as an,a2 as H,a3 as q,a4 as B,a5 as un,a6 as y,a7 as tn,a8 as L,a9 as _,aa as rn,ab as o,ac as on,ad as sn,ae as fn}from"./mermaid.core.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,C,a){var O=I-l,i=D-h,n=C-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function W(l,h,I,D,v,A,C){var a=l-I,O=h-D,i=(C?A:-A)/L(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,F=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*L(on(0,T*T*R-P*P)),j=(P*g-m*S)/R,z=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=j-F,e=z-t,r=w-F,G=p-t;return x*x+e*e>r*r+G*G&&(j=w,z=p),{cx:j,cy:z,x01:-n,y01:-d,x11:j*(v/T-1),y11:z*(v/T-1)}}function hn(){var l=cn,h=yn,I=B(0),D=null,v=gn,A=dn,C=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,F=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(F>tn-y)a.moveTo(s*H(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*H(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=F,S=F,j=C.apply(this,arguments)/2,z=j>y&&(D?+D.apply(this,arguments):L(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if(z>y){var G=sn(z/u*q(j)),M=sn(z/s*q(j));(P-=G*2)>y?(G*=t?1:-1,R+=G,T-=G):(P=0,R=T=(f+c)/2),(S-=M*2)>y?(M*=t?1:-1,m+=M,g-=M):(S=0,m=g=(f+c)/2)}var J=s*H(m),K=s*q(m),N=u*H(T),Q=u*q(T);if(w>y){var U=s*H(g),V=s*q(g),X=u*H(R),Y=u*q(R),E;if(F<an)if(E=pn(J,K,X,Y,U,V,N,Q)){var Z=J-E[0],$=K-E[1],b=U-E[0],k=V-E[1],nn=1/q(fn((Z*b+$*k)/(L(Z*Z+$*$)*L(b*b+k*k)))/2),en=L(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=W(X,Y,J,K,s,x,t),r=W(U,V,N,Q,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(J,K),a.arc(0,0,s,m,g,!t)):a.moveTo(J,K),!(u>y)||!(P>y)?a.lineTo(N,Q):p>y?(e=W(N,Q,U,V,u,-p,t),r=W(J,K,X,Y,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[H(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:B(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:B(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:B(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:B(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:B(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:B(+n),i):A},i.padAngle=function(n){return arguments.length?(C=typeof n=="function"?n:B(+n),i):C},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
+36
View File
@@ -0,0 +1,36 @@
import{p as qe}from"./chunk-JWPE2WC7.js";import{_ as ct,D as Qe,Y as Je,l as Fe,b as Ke,a as je,n as _e,o as tr,g as er,s as rr,p as ir,A as ar,y as nr,B as or,c as Ee,b5 as Te,ak as pe,i as sr,j as hr,q as lr,al as fr,b6 as cr}from"./mermaid.core.js";import{p as gr}from"./cynefin-OW5HDTMX.js";import{c as be}from"./cytoscape.esm.js";import{g as ur}from"./index.js";var he={exports:{}},le={exports:{}},fe={exports:{}},dr=fe.exports,De;function vr(){return De||(De=1,(function(x,M){(function(R,T){x.exports=T()})(dr,function(){return(function(w){var R={};function T(v){if(R[v])return R[v].exports;var l=R[v]={i:v,l:!1,exports:{}};return w[v].call(l.exports,l,l.exports,T),l.l=!0,l.exports}return T.m=w,T.c=R,T.i=function(v){return v},T.d=function(v,l,i){T.o(v,l)||Object.defineProperty(v,l,{configurable:!1,enumerable:!0,get:i})},T.n=function(v){var l=v&&v.__esModule?function(){return v.default}:function(){return v};return T.d(l,"a",l),l},T.o=function(v,l){return Object.prototype.hasOwnProperty.call(v,l)},T.p="",T(T.s=28)})([(function(w,R,T){function v(){}v.QUALITY=1,v.DEFAULT_CREATE_BENDS_AS_NEEDED=!1,v.DEFAULT_INCREMENTAL=!1,v.DEFAULT_ANIMATION_ON_LAYOUT=!0,v.DEFAULT_ANIMATION_DURING_LAYOUT=!1,v.DEFAULT_ANIMATION_PERIOD=50,v.DEFAULT_UNIFORM_LEAF_NODE_SIZES=!1,v.DEFAULT_GRAPH_MARGIN=15,v.NODE_DIMENSIONS_INCLUDE_LABELS=!1,v.SIMPLE_NODE_SIZE=40,v.SIMPLE_NODE_HALF_SIZE=v.SIMPLE_NODE_SIZE/2,v.EMPTY_COMPOUND_NODE_SIZE=40,v.MIN_EDGE_LENGTH=1,v.WORLD_BOUNDARY=1e6,v.INITIAL_WORLD_BOUNDARY=v.WORLD_BOUNDARY/1e3,v.WORLD_CENTER_X=1200,v.WORLD_CENTER_Y=900,w.exports=v}),(function(w,R,T){var v=T(2),l=T(8),i=T(9);function r(f,e,d){v.call(this,d),this.isOverlapingSourceAndTarget=!1,this.vGraphObject=d,this.bendpoints=[],this.source=f,this.target=e}r.prototype=Object.create(v.prototype);for(var a in v)r[a]=v[a];r.prototype.getSource=function(){return this.source},r.prototype.getTarget=function(){return this.target},r.prototype.isInterGraph=function(){return this.isInterGraph},r.prototype.getLength=function(){return this.length},r.prototype.isOverlapingSourceAndTarget=function(){return this.isOverlapingSourceAndTarget},r.prototype.getBendpoints=function(){return this.bendpoints},r.prototype.getLca=function(){return this.lca},r.prototype.getSourceInLca=function(){return this.sourceInLca},r.prototype.getTargetInLca=function(){return this.targetInLca},r.prototype.getOtherEnd=function(f){if(this.source===f)return this.target;if(this.target===f)return this.source;throw"Node is not incident with this edge"},r.prototype.getOtherEndInGraph=function(f,e){for(var d=this.getOtherEnd(f),t=e.getGraphManager().getRoot();;){if(d.getOwner()==e)return d;if(d.getOwner()==t)break;d=d.getOwner().getParent()}return null},r.prototype.updateLength=function(){var f=new Array(4);this.isOverlapingSourceAndTarget=l.getIntersection(this.target.getRect(),this.source.getRect(),f),this.isOverlapingSourceAndTarget||(this.lengthX=f[0]-f[2],this.lengthY=f[1]-f[3],Math.abs(this.lengthX)<1&&(this.lengthX=i.sign(this.lengthX)),Math.abs(this.lengthY)<1&&(this.lengthY=i.sign(this.lengthY)),this.length=Math.sqrt(this.lengthX*this.lengthX+this.lengthY*this.lengthY))},r.prototype.updateLengthSimple=function(){this.lengthX=this.target.getCenterX()-this.source.getCenterX(),this.lengthY=this.target.getCenterY()-this.source.getCenterY(),Math.abs(this.lengthX)<1&&(this.lengthX=i.sign(this.lengthX)),Math.abs(this.lengthY)<1&&(this.lengthY=i.sign(this.lengthY)),this.length=Math.sqrt(this.lengthX*this.lengthX+this.lengthY*this.lengthY)},w.exports=r}),(function(w,R,T){function v(l){this.vGraphObject=l}w.exports=v}),(function(w,R,T){var v=T(2),l=T(10),i=T(13),r=T(0),a=T(16),f=T(5);function e(t,s,o,c){o==null&&c==null&&(c=s),v.call(this,c),t.graphManager!=null&&(t=t.graphManager),this.estimatedSize=l.MIN_VALUE,this.inclusionTreeDepth=l.MAX_VALUE,this.vGraphObject=c,this.edges=[],this.graphManager=t,o!=null&&s!=null?this.rect=new i(s.x,s.y,o.width,o.height):this.rect=new i}e.prototype=Object.create(v.prototype);for(var d in v)e[d]=v[d];e.prototype.getEdges=function(){return this.edges},e.prototype.getChild=function(){return this.child},e.prototype.getOwner=function(){return this.owner},e.prototype.getWidth=function(){return this.rect.width},e.prototype.setWidth=function(t){this.rect.width=t},e.prototype.getHeight=function(){return this.rect.height},e.prototype.setHeight=function(t){this.rect.height=t},e.prototype.getCenterX=function(){return this.rect.x+this.rect.width/2},e.prototype.getCenterY=function(){return this.rect.y+this.rect.height/2},e.prototype.getCenter=function(){return new f(this.rect.x+this.rect.width/2,this.rect.y+this.rect.height/2)},e.prototype.getLocation=function(){return new f(this.rect.x,this.rect.y)},e.prototype.getRect=function(){return this.rect},e.prototype.getDiagonal=function(){return Math.sqrt(this.rect.width*this.rect.width+this.rect.height*this.rect.height)},e.prototype.getHalfTheDiagonal=function(){return Math.sqrt(this.rect.height*this.rect.height+this.reLine truncated
.edge {
stroke-width: ${x.archEdgeWidth};
stroke: ${x.archEdgeColor};
fill: none;
}
.arrow {
fill: ${x.archEdgeArrowColor};
}
.node-bkg {
fill: none;
stroke: ${x.archGroupBorderColor};
stroke-width: ${x.archGroupBorderWidth};
stroke-dasharray: 8;
}
.node-icon-text {
display: flex;
align-items: center;
}
.node-icon-text > div {
color: #fff;
margin: 1px;
height: fit-content;
text-align: center;
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
}
`,"getStyles"),Fr=Sr;function me(x,M){if(x===0)return M();const w=Math.random;let R=x>>>0;Math.random=function(){R=R+1831565813>>>0;let T=R;return T=Math.imul(T^T>>>15,T|1),T^=T+Math.imul(T^T>>>7,T|61),((T^T>>>14)>>>0)/4294967296};try{return M()}finally{Math.random=w}}ct(me,"withSeededRandom");var re=ct(x=>`<g><rect width="80" height="80" style="fill: #087ebf; stroke-width: 0px;"/>${x}</g>`,"wrapIcon"),ne={prefix:"mermaid-architecture",height:80,width:80,icons:{database:{body:re('<path id="b" data-name="4" d="m20,57.86c0,3.94,8.95,7.14,20,7.14s20-3.2,20-7.14" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><path id="c" data-name="3" d="m20,45.95c0,3.94,8.95,7.14,20,7.14s20-3.2,20-7.14" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><path id="d" data-name="2" d="m20,34.05c0,3.94,8.95,7.14,20,7.14s20-3.2,20-7.14" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><ellipse id="e" data-name="1" cx="40" cy="22.14" rx="20" ry="7.14" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><line x1="20" y1="57.86" x2="20" y2="22.14" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><line x1="60" y1="57.86" x2="60" y2="22.14" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/>')},server:{body:re('<rect x="17.5" y="17.5" width="45" height="45" rx="2" ry="2" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><line x1="17.5" y1="32.5" x2="62.5" y2="32.5" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><line x1="17.5" y1="47.5" x2="62.5" y2="47.5" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><g><path d="m56.25,25c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z" style="fill: #fff; stroke-width: 0px;"/><path d="m56.25,25c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z" style="fill: none; stroke: #fff; stroke-miterlimit: 10;"/></g><g><path d="m56.25,40c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z" style="fill: #fff; stroke-width: 0px;"/><path d="m56.25,40c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z" style="fill: none; stroke: #fff; stroke-miterlimit: 10;"/></g><g><path d="m56.25,55c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z" style="fill: #fff; stroke-width: 0px;"/><path d="m56.25,55c0,.27-.45.5-1,.5h-10.5c-.55,0-1-.23-1-.5s.45-.5,1-.5h10.5c.55,0,1,.23,1,.5Z" style="fill: none; stroke: #fff; stroke-miterlimit: 10;"/></g><g><circle cx="32.5" cy="25" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"/><circle cx="27.5" cy="25" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"/><circle cx="22.5" cy="25" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"/></g><g><circle cx="32.5" cy="40" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"/><circle cx="27.5" cy="40" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"/><circle cx="22.5" cy="40" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"/></g><g><circle cx="32.5" cy="55" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"/><circle cx="27.5" cy="55" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"/><circle cx="22.5" cy="55" r=".75" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10;"/></g>')},disk:{body:re('<rect x="20" y="15" width="40" height="50" rx="1" ry="1" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><ellipse cx="24" cy="19.17" rx=".8" ry=".83" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><ellipse cx="56" cy="19.17" rx=".8" ry=".83" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><ellipse cx="24" cy="60.83" rx=".8" ry=".83" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><ellipse cx="56" cy="60.83" rx=".8" ry=".83" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><ellipse cx="40" cy="33.75" rx="14" ry="14.58" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><ellipse cx="40" cy="33.75" rx="4" ry="4.17" style="fill: #fff; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><path d="m37.51,42.52l-4.83,13.22c-.26.71-1.1,1.02-1.76.64l-4.18-2.42c-.66-.38-.81-1.26-.33-1.84l9.01-10.8c.88-1.05,2.56-.08,2.09,1.2Z" style="fill: #fff; stroke-width: 0px;"/>')},internet:{body:re('<circle cx="40" cy="40" r="22.5" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><line x1="40" y1="17.5" x2="40" y2="62.5" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><line x1="17.5" y1="40" x2="62.5" y2="40" style="fill: none; stroke: #fff; stroke-miterlimit: 10; stroke-width: 2px;"/><path d="m39.99,17.51c-15.28,11.1-15.28,33.88,0,44.98" style="fill: none; sLine truncated
translate(${L}, ${F-E.height/2})
translate(${p*y.width/2}, ${m*y.height/2})
rotate(${-1*p*m*45}, 0, ${E.height/2})
`)}}}}}))},"drawEdges"),Pr=ct(async function(x,M,w,R){const v=w.getConfigField("padding")*.75,l=w.getConfigField("fontSize"),r=w.getConfigField("iconSize")/2;await Promise.all(M.nodes().map(async a=>{const f=ie(a);if(f.type==="group"){const{h:e,w:d,x1:t,y1:s}=a.boundingBox(),o=x.append("rect");o.attr("id",`${R}-group-${f.id}`).attr("x",t+r).attr("y",s+r).attr("width",d).attr("height",e).attr("class","node-bkg");const c=x.append("g");let h=t,N=s;if(f.icon){const g=c.append("g");g.html(`<g>${await pe(f.icon,{height:v,width:v,fallbackPrefix:ne.prefix})}</g>`),g.attr("transform","translate("+(h+r+1)+", "+(N+r+1)+")"),h+=v,N+=l/2-1-2}if(f.label){const g=c.append("g");await Te(g,f.label,{useHtmlLabels:!1,width:d,classes:"architecture-service-label"},Ee()),g.attr("dy","1em").attr("alignment-baseline","middle").attr("dominant-baseline","start").attr("text-anchor","start"),g.attr("transform","translate("+(h+r+4)+", "+(N+r+2)+")")}w.setElementForId(f.id,o)}}))},"drawGroups"),Gr=ct(async function(x,M,w,R){const T=Ee();for(const v of w){const l=M.append("g"),i=x.getConfigField("iconSize");if(v.title){const e=l.append("g");await Te(e,v.title,{useHtmlLabels:!1,width:i*1.5,classes:"architecture-service-label"},T),e.attr("dy","1em").attr("alignment-baseline","middle").attr("dominant-baseline","middle").attr("text-anchor","middle"),e.attr("transform","translate("+i/2+", "+i+")")}const r=l.append("g");if(v.icon)r.html(`<g>${await pe(v.icon,{height:i,width:i,fallbackPrefix:ne.prefix})}</g>`);else if(v.iconText){r.html(`<g>${await pe("blank",{height:i,width:i,fallbackPrefix:ne.prefix})}</g>`);const t=r.append("g").append("foreignObject").attr("width",i).attr("height",i).append("div").attr("class","node-icon-text").attr("style",`height: ${i}px;`).append("div").html(sr(v.iconText,T)),s=parseInt(window.getComputedStyle(t.node(),null).getPropertyValue("font-size").replace(/\D/g,""))??16;t.attr("style",`-webkit-line-clamp: ${Math.floor((i-2)/s)};`)}else r.append("path").attr("class","node-bkg").attr("id",`${R}-node-${v.id}`).attr("d",`M0,${i} V5 Q0,0 5,0 H${i-5} Q${i},0 ${i},5 V${i} Z`);l.attr("id",`${R}-service-${v.id}`).attr("class","architecture-service");const{width:a,height:f}=l.node().getBBox();v.width=a,v.height=f,x.setElementForId(v.id,l)}return 0},"drawServices"),Ur=ct(function(x,M,w,R){w.forEach(T=>{const v=M.append("g"),l=x.getConfigField("iconSize");v.append("g").append("rect").attr("id",`${R}-node-${T.id}`).attr("fill-opacity","0").attr("width",l).attr("height",l),v.attr("class","architecture-junction");const{width:r,height:a}=v._groups[0][0].getBBox();v.width=r,v.height=a,x.setElementForId(T.id,v)})},"drawJunctions");fr([{name:ne.prefix,icons:ne}]);be.use(Nr);function Xe(x,M,w){x.forEach(R=>{M.add({group:"nodes",data:{type:"service",id:R.id,icon:R.icon,label:R.title,parent:R.in,width:w.getConfigField("iconSize"),height:w.getConfigField("iconSize")},classes:"node-service"})})}ct(Xe,"addServices");function He(x,M,w){x.forEach(R=>{M.add({group:"nodes",data:{type:"junction",id:R.id,parent:R.in,width:w.getConfigField("iconSize"),height:w.getConfigField("iconSize")},classes:"node-junction"})})}ct(He,"addJunctions");function We(x,M){M.nodes().map(w=>{const R=ie(w);if(R.type==="group")return;R.x=w.position().x,R.y=w.position().y,x.getElementById(R.id).attr("transform","translate("+(R.x||0)+","+(R.y||0)+")")})}ct(We,"positionNodes");function Ve(x,M){x.forEach(w=>{M.add({group:"nodes",data:{type:"group",id:w.id,icon:w.icon,label:w.title,parent:w.in},classes:"node-group"})})}ct(Ve,"addGroups");function $e(x,M){x.forEach(w=>{const{lhsId:R,rhsId:T,lhsInto:v,lhsGroup:l,rhsInto:i,lhsDir:r,rhsDir:a,rhsGroup:f,title:e}=w,d=Ne(w.lhsDir,w.rhsDir)?"segments":"straight",t={id:`${R}-${T}`,label:e,source:R,sourceDir:r,sourceArrow:v,sourceGroup:l,sourceEndpoint:r==="L"?"0 50%":r==="R"?"100% 50%":r==="T"?"50% 0":"50% 100%",target:T,targetDir:a,targetArrow:i,targetGroup:f,targetEndpoint:a==="L"?"0 50%":a==="R"?"100% 50%":a==="T"?"50% 0":"50% 100%"};M.add({group:"edges",data:t,classes:d})})}ct($e,"addEdges");function ze(x,M,w,R=[]){const T=ct((d,t)=>{const s=new Map;for(const[o,c]of d.entries()){const h=`${o}`;let N=0;const g=[...c.entries()];if(g.length===1){s.set(h,g[0][1]);continue}for(let u=0;u<g.length-1;u++)for(let L=u+1;L<g.length;L++){const[F,C]=g[u],[G,V]=g[L];if(w.get(Pe(F,G))===t)s.set(h,[...s.get(h)??[],...C,...V]);else if(F==="default"||G==="default")s.set(h,[...s.get(h)??[],...C,...V]);else{const $=`${h}-${N++}`;s.set($,C);const A=`${h}-${N++}`;s.set(A,V)}}}return s},"flattenAlignments"),v=M.map(d=>{const t=new Map,s=new Map;return d.forEach(([o,c],h)=>{const N=x.getNode(h)?.in??"default",g=t.get(c)??new Map;t.has(c)||t.set(c,g);const u=s.get(o)??new Map;s.has(o)||s.set(o,u);for(const L of[g,u]){const F=L.get(N)??[];L.has(N)||L.set(N,F),F.push(h)}}),{horiz:[...T(t,"horizontal").values()].filter(o=>o.length>1),vert:[...T(s,"vertical").values()].filter(o=>o.length>1)}}),[l,i]=v.reduce(([d,t],{horiz:s,vert:o})=>[[...d,Line truncated
+129
View File
@@ -0,0 +1,129 @@
import{g as Pe}from"./chunk-5VM5RSS4.js";import{aD as Fe,aE as xe,aF as Me,aG as Ke,aH as Ye,aI as We,aJ as Ve,aK as Ue,aL as He,aM as Xe,aN as je,aO as Ge,aP as qe,aQ as Je,aR as Ze,aS as Qe,aT as $e,aU as et,aV as tt,aW as st,aX as rt,aY as it,aZ as at,a_ as nt,a$ as ot,_ as u,y as Y,j as X,b0 as ct,d as lt,l as m,p as ut,r as gt,c as Le,Q as ht,az as dt,ay as pt,aA as ft,k as bt,b1 as St,ag as ye,ah as xt}from"./mermaid.core.js";import{c as Lt}from"./channel.js";import"./index.js";function yt(e){return Array.isArray(e)}function mt(e){if(Fe(e))return e;const a=xe(e);if(!wt(e))return{};if(yt(e)){const r=Array.from(e);return e.length>0&&typeof e[0]=="string"&&Object.hasOwn(e,"index")&&(r.index=e.index,r.input=e.input),r}if(Me(e)){const r=e,l=r.constructor;return new l(r.buffer,r.byteOffset,r.length)}if(a==="[object ArrayBuffer]")return new ArrayBuffer(e.byteLength);if(a==="[object DataView]"){const r=e,l=r.buffer,d=r.byteOffset,s=r.byteLength,h=new ArrayBuffer(s),x=new Uint8Array(l,d,s);return new Uint8Array(h).set(x),new DataView(h)}if(a==="[object Boolean]"||a==="[object Number]"||a==="[object String]"){const r=e.constructor,l=new r(e.valueOf());return a==="[object String]"?_t(l,e):se(l,e),l}if(a==="[object Date]")return new Date(Number(e));if(a==="[object RegExp]"){const r=e,l=new RegExp(r.source,r.flags);return l.lastIndex=r.lastIndex,l}if(a==="[object Symbol]")return Object(Symbol.prototype.valueOf.call(e));if(a==="[object Map]"){const r=e,l=new Map;return r.forEach((d,s)=>{l.set(s,d)}),l}if(a==="[object Set]"){const r=e,l=new Set;return r.forEach(d=>{l.add(d)}),l}if(a==="[object Arguments]"){const r=e,l={};return se(l,r),l.length=r.length,l[Symbol.iterator]=r[Symbol.iterator],l}const o={};return kt(o,e),se(o,e),Et(o,e),o}function wt(e){switch(xe(e)){case ot:case nt:case at:case it:case rt:case st:case tt:case et:case $e:case Qe:case Ze:case Je:case qe:case Ge:case je:case Xe:case He:case Ue:case Ve:case We:case Ye:case Ke:return!0;default:return!1}}function se(e,a){for(const o in a)Object.hasOwn(a,o)&&(e[o]=a[o])}function Et(e,a){const o=Object.getOwnPropertySymbols(a);for(let r=0;r<o.length;r++){const l=o[r];Object.prototype.propertyIsEnumerable.call(a,l)&&(e[l]=a[l])}}function _t(e,a){const o=a.valueOf().length;for(const r in a)Object.hasOwn(a,r)&&(Number.isNaN(Number(r))||Number(r)>=o)&&(e[r]=a[r])}function kt(e,a){const o=Object.getPrototypeOf(a);o!==null&&typeof a.constructor=="function"&&Object.setPrototypeOf(e,o)}var ie=(function(){var e=u(function(v,g,i,c){for(i=i||{},c=v.length;c--;i[v[c]]=g);return i},"o"),a=[1,15],o=[1,7],r=[1,13],l=[1,14],d=[1,19],s=[1,16],h=[1,17],x=[1,18],y=[8,30],S=[8,10,21,28,29,30,31,39,43,46],f=[1,23],L=[1,24],w=[8,10,15,16,21,28,29,30,31,39,43,46],b=[8,10,15,16,21,27,28,29,30,31,39,43,46],k=[1,49],_={trace:u(function(){},"trace"),yy:{},symbols_:{error:2,spaceLines:3,SPACELINE:4,NL:5,separator:6,SPACE:7,EOF:8,start:9,BLOCK_DIAGRAM_KEY:10,document:11,stop:12,statement:13,link:14,LINK:15,START_LINK:16,LINK_LABEL:17,STR:18,nodeStatement:19,columnsStatement:20,SPACE_BLOCK:21,blockStatement:22,classDefStatement:23,cssClassStatement:24,styleStatement:25,node:26,SIZE:27,COLUMNS:28,"id-block":29,end:30,NODE_ID:31,nodeShapeNLabel:32,dirList:33,DIR:34,NODE_DSTART:35,NODE_DEND:36,BLOCK_ARROW_START:37,BLOCK_ARROW_END:38,classDef:39,CLASSDEF_ID:40,CLASSDEF_STYLEOPTS:41,DEFAULT:42,class:43,CLASSENTITY_IDS:44,STYLECLASS:45,style:46,STYLE_ENTITY_IDS:47,STYLE_DEFINITION_DATA:48,$accept:0,$end:1},terminals_:{2:"error",4:"SPACELINE",5:"NL",7:"SPACE",8:"EOF",10:"BLOCK_DIAGRAM_KEY",15:"LINK",16:"START_LINK",17:"LINK_LABEL",18:"STR",21:"SPACE_BLOCK",27:"SIZE",28:"COLUMNS",29:"id-block",30:"end",31:"NODE_ID",34:"DIR",35:"NODE_DSTART",36:"NODE_DEND",37:"BLOCK_ARROW_START",38:"BLOCK_ARROW_END",39:"classDef",40:"CLASSDEF_ID",41:"CLASSDEF_STYLEOPTS",42:"DEFAULT",43:"class",44:"CLASSENTITY_IDS",45:"STYLECLASS",46:"style",47:"STYLE_ENTITY_IDS",48:"STYLE_DEFINITION_DATA"},productions_:[0,[3,1],[3,2],[3,2],[6,1],[6,1],[6,1],[9,3],[12,1],[12,1],[12,2],[12,2],[11,1],[11,2],[14,1],[14,4],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[19,3],[19,2],[19,1],[20,1],[22,4],[22,3],[26,1],[26,2],[33,1],[33,2],[32,3],[32,4],[23,3],[23,3],[24,3],[25,3]],performAction:u(function(g,i,c,p,E,t,M){var n=t.length-1;switch(E){case 4:p.getLogger().debug("Rule: separator (NL) ");break;case 5:p.getLogger().debug("Rule: separator (Space) ");break;case 6:p.getLogger().debug("Rule: separator (EOF) ");break;case 7:p.getLogger().debug("Rule: hierarchy: ",t[n-1]),p.setHierarchy(t[n-1]);break;case 8:p.getLogger().debug("Stop NL ");break;case 9:p.getLogger().debug("Stop EOF ");break;case 10:p.getLogger().debug("Stop NL2 ");break;case 11:p.getLogger().debug("Stop EOF2 ");break;case 12:p.getLogger().debug("Rule: statement: ",t[n]),typeof t[n].length=="number"?this.$=t[n]:this.$=[t[n]];break;case 13:p.getLogger().debug("Rule: statement #2: ",t[n-1]),this.$=[t[n-1]].concat(t[n]);break;case 14:p.getLogger().debug("Rule: link: ",Line truncated
`+D.showPosition()+`
Expecting `+H.join(", ")+", got '"+(this.terminals_[N]||N)+"'":te="Parse error on line "+(P+1)+": Unexpected "+(N==V?"end of input":"'"+(this.terminals_[N]||N)+"'"),this.parseError(te,{text:D.match,token:this.terminals_[N]||N,line:D.yylineno,loc:$,expected:H})}if(C[0]instanceof Array&&C.length>1)throw new Error("Parse Error: multiple actions possible at state: "+R+", token: "+N);switch(C[0]){case 1:c.push(N),E.push(D.yytext),t.push(D.yylloc),c.push(C[1]),N=null,W=D.yyleng,n=D.yytext,P=D.yylineno,$=D.yylloc;break;case 2:if(B=this.productions_[C[1]][1],F.$=E[E.length-B],F._$={first_line:t[t.length-(B||1)].first_line,last_line:t[t.length-1].last_line,first_column:t[t.length-(B||1)].first_column,last_column:t[t.length-1].last_column},Be&&(F._$.range=[t[t.length-(B||1)].range[0],t[t.length-1].range[1]]),ee=this.performAction.apply(F,[n,W,P,A.yy,C[1],E,t].concat(Z)),typeof ee<"u")return ee;B&&(c=c.slice(0,-1*B*2),E=E.slice(0,-1*B),t=t.slice(0,-1*B)),c.push(this.productions_[C[1]][0]),E.push(F.$),t.push(F._$),pe=M[c[c.length-2]][c[c.length-1]],c.push(pe);break;case 3:return!0}}return!0},"parse")},T=(function(){var v={EOF:1,parseError:u(function(i,c){if(this.yy.parser)this.yy.parser.parseError(i,c);else throw new Error(i)},"parseError"),setInput:u(function(g,i){return this.yy=i||this.yy||{},this._input=g,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:u(function(){var g=this._input[0];this.yytext+=g,this.yyleng++,this.offset++,this.match+=g,this.matched+=g;var i=g.match(/(?:\r\n?|\n).*/g);return i?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),g},"input"),unput:u(function(g){var i=g.length,c=g.split(/(?:\r\n?|\n)/g);this._input=g+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-i),this.offset-=i;var p=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),c.length-1&&(this.yylineno-=c.length-1);var E=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:c?(c.length===p.length?this.yylloc.first_column:0)+p[p.length-c.length].length-c[0].length:this.yylloc.first_column-i},this.options.ranges&&(this.yylloc.range=[E[0],E[0]+this.yyleng-i]),this.yyleng=this.yytext.length,this},"unput"),more:u(function(){return this._more=!0,this},"more"),reject:u(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:u(function(g){this.unput(this.match.slice(g))},"less"),pastInput:u(function(){var g=this.matched.substr(0,this.matched.length-this.match.length);return(g.length>20?"...":"")+g.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:u(function(){var g=this.match;return g.length<20&&(g+=this._input.substr(0,20-g.length)),(g.substr(0,20)+(g.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:u(function(){var g=this.pastInput(),i=new Array(g.length+1).join("-");return g+this.upcomingInput()+`
`+i+"^"},"showPosition"),test_match:u(function(g,i){var c,p,E;if(this.options.backtrack_lexer&&(E={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(E.yylloc.range=this.yylloc.range.slice(0))),p=g[0].match(/(?:\r\n?|\n).*/g),p&&(this.yylineno+=p.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:p?p[p.length-1].length-p[p.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+g[0].length},this.yytext+=g[0],this.match+=g[0],this.matches=g,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(g[0].length),this.matched+=g[0],c=this.performAction.call(this,this.yy,this,i,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),c)return c;if(this._backtrack){for(var t in E)this[t]=E[t];return!1}return!1},"test_match"),next:u(function(){if(this.done)return this.EOF;this._input||(this.done=!0);var g,i,c,p;this._more||(this.yytext="",this.match="");for(var E=this._currentRules(),t=0;t<E.length;t++)if(c=this._input.match(this.rules[E[t]]),c&&(!i||c[0].length>i[0].length)){if(i=c,p=t,this.options.backtrack_lexer){if(g=this.test_match(c,E[t]),g!==!1)return g;if(this._backtrack){i=!1;continue}else return!1}else if(!this.options.flex)break}return i?(g=this.test_match(i,E[p]),g!==!1?g:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text.
`+this.showPosition(),{text:"",token:null,line:this.yylineno})},"next"),lex:u(function(){var i=this.next();return i||this.lex()},"lex"),begin:u(function(i){this.conditionStack.push(i)},"begin"),popState:u(function(){var i=this.conditionStack.length-1;return i>0?this.conditionStack.pop():this.conditionStack[0]},"popState"),_currentRules:u(function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},"_currentRules"),topState:u(function(i){return i=this.conditionStack.length-1-Math.abs(i||0),i>=0?this.conditionStack[i]:"INITIAL"},"topState"),pushState:u(function(i){this.begin(i)},"pushState"),stateStackSize:u(function(){return this.conditionStack.length},"stateStackSize"),options:{},performAction:u(function(i,c,p,E){switch(p){case 0:return i.getLogger().debug("Found block-beta"),10;case 1:return i.getLogger().debug("Found id-block"),29;case 2:return i.getLogger().debug("Found block"),10;case 3:i.getLogger().debug(".",c.yytext);break;case 4:i.getLogger().debug("_",c.yytext);break;case 5:return 5;case 6:return c.yytext=-1,28;case 7:return c.yytext=c.yytext.replace(/columns\s+/,""),i.getLogger().debug("COLUMNS (LEX)",c.yytext),28;case 8:this.pushState("md_string");break;case 9:return"MD_STR";case 10:this.popState();break;case 11:this.pushState("string");break;case 12:i.getLogger().debug("LEX: POPPING STR:",c.yytext),this.popState();break;case 13:return i.getLogger().debug("LEX: STR end:",c.yytext),"STR";case 14:return c.yytext=c.yytext.replace(/space\:/,""),i.getLogger().debug("SPACE NUM (LEX)",c.yytext),21;case 15:return c.yytext="1",i.getLogger().debug("COLUMNS (LEX)",c.yytext),21;case 16:return 42;case 17:return"LINKSTYLE";case 18:return"INTERPOLATE";case 19:return this.pushState("CLASSDEF"),39;case 20:return this.popState(),this.pushState("CLASSDEFID"),"DEFAULT_CLASSDEF_ID";case 21:return this.popState(),this.pushState("CLASSDEFID"),40;case 22:return this.popState(),41;case 23:return this.pushState("CLASS"),43;case 24:return this.popState(),this.pushState("CLASS_STYLE"),44;case 25:return this.popState(),45;case 26:return this.pushState("STYLE_STMNT"),46;case 27:return this.popState(),this.pushState("STYLE_DEFINITION"),47;case 28:return this.popState(),48;case 29:return this.pushState("acc_title"),"acc_title";case 30:return this.popState(),"acc_title_value";case 31:return this.pushState("acc_descr"),"acc_descr";case 32:return this.popState(),"acc_descr_value";case 33:this.pushState("acc_descr_multiline");break;case 34:this.popState();break;case 35:return"acc_descr_multiline_value";case 36:return 30;case 37:return this.popState(),i.getLogger().debug("Lex: (("),"NODE_DEND";case 38:return this.popState(),i.getLogger().debug("Lex: (("),"NODE_DEND";case 39:return this.popState(),i.getLogger().debug("Lex: ))"),"NODE_DEND";case 40:return this.popState(),i.getLogger().debug("Lex: (("),"NODE_DEND";case 41:return this.popState(),i.getLogger().debug("Lex: (("),"NODE_DEND";case 42:return this.popState(),i.getLogger().debug("Lex: (-"),"NODE_DEND";case 43:return this.popState(),i.getLogger().debug("Lex: -)"),"NODE_DEND";case 44:return this.popState(),i.getLogger().debug("Lex: (("),"NODE_DEND";case 45:return this.popState(),i.getLogger().debug("Lex: ]]"),"NODE_DEND";case 46:return this.popState(),i.getLogger().debug("Lex: ("),"NODE_DEND";case 47:return this.popState(),i.getLogger().debug("Lex: ])"),"NODE_DEND";case 48:return this.popState(),i.getLogger().debug("Lex: /]"),"NODE_DEND";case 49:return this.popState(),i.getLogger().debug("Lex: /]"),"NODE_DEND";case 50:return this.popState(),i.getLogger().debug("Lex: )]"),"NODE_DEND";case 51:return this.popState(),i.getLogger().debug("Lex: )"),"NODE_DEND";case 52:return this.popState(),i.getLogger().debug("Lex: ]>"),"NODE_DEND";case 53:return this.popState(),i.getLogger().debug("Lex: ]"),"NODE_DEND";case 54:return i.getLogger().debug("Lexa: -)"),this.pushState("NODE"),35;case 55:return i.getLogger().debug("Lexa: (-"),this.pushState("NODE"),35;case 56:return i.getLogger().debug("Lexa: ))"),this.pushState("NODE"),35;case 57:return i.getLogger().debug("Lexa: )"),this.pushState("NODE"),35;case 58:return i.getLogger().debug("Lex: ((("),this.pushState("NODE"),35;case 59:return i.getLogger().debug("Lexa: )"),this.pushState("NODE"),35;case 60:return i.getLogger().debug("Lexa: )"),this.pushState("NODE"),35;case 61:return i.getLogger().debug("Lexa: )"),this.pushState("NODE"),35;case 62:return i.getLogger().debug("Lexc: >"),this.pushState("NODE"),35;case 63:return i.getLogger().debug("Lexa: (["),this.pushState("NODE"),35;case 64:return i.getLogger().debug("Lexa: )"),this.pushState("NODE"),35;case 65:return this.pushState("NODE"),35;case 66:return this.pushState("NODE"),35;case 67:return this.pushState("NODE"),35;case 68:return this.pushState("NODE"),35;case 69:return this.pushState("NODE"),35;case 70:return this.pushState("NODE"),35;case 71:return this.p Line truncated
font-family: ${e.fontFamily};
color: ${e.nodeTextColor||e.textColor};
}
.cluster-label text {
fill: ${e.titleColor};
}
.cluster-label span {
color: ${e.titleColor};
}
.label text,span {
fill: ${e.nodeTextColor||e.textColor};
color: ${e.nodeTextColor||e.textColor};
}
.node rect,
.node circle,
.node ellipse,
.node polygon,
.node path {
fill: ${e.mainBkg};
stroke: ${e.nodeBorder};
stroke-width: 1px;
}
.flowchart-label text {
text-anchor: middle;
}
// .flowchart-label .text-outer-tspan {
// text-anchor: middle;
// }
// .flowchart-label .text-inner-tspan {
// text-anchor: start;
// }
.node .label {
text-align: center;
}
.node.clickable {
cursor: pointer;
}
.arrowheadPath {
fill: ${e.arrowheadColor};
}
.edgePaths .path {
stroke: ${e.lineColor};
stroke-width: 2.0px;
}
.flowchart-link {
stroke: ${e.lineColor};
fill: none;
}
.edgeLabel {
background-color: ${e.edgeLabelBackground};
/*
* This is for backward compatibility with existing code that didn't
* add a \`<p>\` around edge labels.
*
* TODO: We should probably remove this in a future release.
*/
p {
margin: 0;
padding: 0;
display: inline;
}
rect {
opacity: 0.5;
background-color: ${e.edgeLabelBackground};
fill: ${e.edgeLabelBackground};
}
text-align: center;
}
/* For html labels only */
.labelBkg {
background-color: ${e.edgeLabelBackground};
}
.node .cluster {
// fill: ${re(e.mainBkg,.5)};
fill: ${re(e.clusterBkg,.5)};
stroke: ${re(e.clusterBorder,.2)};
box-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px, rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
stroke-width: 1px;
}
.cluster text {
fill: ${e.titleColor};
}
.cluster span {
color: ${e.titleColor};
}
/* .cluster div {
color: ${e.titleColor};
} */
div.mermaidTooltip {
position: absolute;
text-align: center;
max-width: 200px;
padding: 2px;
font-family: ${e.fontFamily};
font-size: 12px;
background: ${e.tertiaryColor};
border: 1px solid ${e.border2};
border-radius: 2px;
pointer-events: none;
z-index: 100;
}
.flowchartTitleText {
text-anchor: middle;
font-size: 18px;
fill: ${e.textColor};
}
${Pe()}
`,"getStyles"),Gt=jt;function ne(e,a){if(e===0||!Number.isInteger(e))throw new Error("Columns must be an integer !== 0.");if(a<0||!Number.isInteger(a))throw new Error("Position must be a non-negative integer."+a);if(e<0)return{px:a,py:0};if(e===1)return{px:0,py:a};const o=a%e,r=Math.floor(a/e);return{px:o,py:r}}u(ne,"calculateBlockPosition");var qt=u(e=>{let a=0,o=0;for(const r of e.children){const{width:l,height:d,x:s,y:h}=r.size??{width:0,height:0,x:0,y:0};if(m.debug("getMaxChildSize abc95 child:",r.id,"width:",l,"height:",d,"x:",s,"y:",h,r.type),r.type==="space")continue;const x=l/(r.widthInColumns??1);x>a&&(a=x),d>o&&(o=d)}return{width:a,height:o}},"getMaxChildSize");function G(e,a,o=0,r=0,l=8){m.debug("setBlockSizes abc95 (start)",e.id,e?.size?.x,"block width =",e?.size,"siblingWidth",o),e?.size?.width||(e.size={width:o,height:r,x:0,y:0});let d=0,s=0;if(e.children?.length>0){for(const b of e.children)G(b,a,0,0,l);const h=qt(e);d=h.width,s=h.height,m.debug("setBlockSizes abc95 maxWidth of",e.id,":s children is ",d,s);for(const b of e.children)b.size&&(m.debug(`abc95 Setting size of children of ${e.id} id=${b.id} ${d} ${s} ${JSON.stringify(b.size)}`),b.size.width=d*(b.widthInColumns??1)+l*((b.widthInColumns??1)-1),b.size.height=s,b.size.x=0,b.size.y=0,m.debug(`abc95 updating size of ${e.id} children child:${b.id} maxWidth:${d} maxHeight:${s}`));for(const b of e.children)G(b,a,d,s,l);const x=e.columns??-1;let y=0;for(const b of e.children)y+=b.widthInColumns??1;let S=e.children.length;x>0&&x<y&&(S=x);const f=Math.ceil(y/S);let L=S*(d+l)+l,w=f*(s+l)+l;if(L<o){m.debug(`Detected to small sibling: abc95 ${e.id} siblingWidth ${o} siblingHeight ${r} width ${L}`),L=o,w=r;const b=(o-S*l-l)/S,k=(r-f*l-l)/f;m.debug("Size indata abc88",e.id,"childWidth",b,"maxWidth",d),m.debug("Size indata abc88",e.id,"childHeight",k,"maxHeight",s),m.debug("Size indata abc88 xSize",S,"padding",l);for(const _ of e.children)_.size&&(_.size.width=b,_.size.height=k,_.size.x=0,_.size.y=0)}if(m.debug(`abc95 (finale calc) ${e.id} xSize ${S} ySize ${f} columns ${x}${e.children.length} width=${Math.max(L,e.size?.width||0)}`),L<(e?.size?.width||0)){L=e?.size?.width||0;const b=x>0?Math.min(e.children.length,x):e.children.length;if(b>0){const k=(L-b*l-l)/b;m.debug("abc95 (growing to fit) width",e.id,L,e.size?.width,k);for(const _ of e.children)_.size&&(_.size.width=k)}}e.size={width:L,height:w,x:0,y:0}}m.debug("setBlockSizes abc94 (done)",e.id,e?.size?.x,e?.size?.width,e?.size?.y,e?.size?.height)}u(G,"setBlockSizes");function ue(e,a,o=8){m.debug(`abc85 layout blocks (=>layoutBlocks) ${e.id} x: ${e?.size?.x} y: ${e?.size?.y} width: ${e?.size?.width}`);const r=e.columns??-1;if(m.debug("layoutBlocks columns abc95",e.id,"=>",r,e),e.children&&e.children.length>0){const l=e?.children[0]?.size?.width??0,d=e.children.length*l+(e.children.length-1)*o;m.debug("widthOfChildren 88",d,"posX");const s=new Map;{let f=0;for(const L of e.children){if(!L.size)continue;const{py:w}=ne(r,f),b=s.get(w)??0;L.size.height>b&&s.set(w,L.size.height);let k=L?.widthInColumns??1;r>0&&(k=Math.min(k,r-f%r)),f+=k}}const h=new Map;{let f=0;const L=[...s.keys()].sort((w,b)=>w-b);for(const w of L)h.set(w,f),f+=(s.get(w)??0)+o}let x=0;m.debug("abc91 block?.size?.x",e.id,e?.size?.x);let y=e?.size?.x?e?.size?.x+(-e?.size?.width/2||0):-o,S=0;for(const f of e.children){const L=e;if(!f.size)continue;const{width:w,height:b}=f.size,{px:k,py:_}=ne(r,x);if(_!=S&&(S=_,y=e?.size?.x?e?.size?.x+(-e?.size?.width/2||0):-o,m.debug("New row in layout for block",e.id," and child ",f.id,S)),m.debug(`abc89 layout blocks (child) id: ${f.id} Pos: ${x} (px, py) ${k},${_} (${L?.size?.x},${L?.size?.y}) parent: ${L.id} width: ${w}${o}`),L.size){const O=w/2;f.size.x=y+o+O,m.debug(`abc91 layout blocks (calc) px, pyid:${f.id} startingPos=X${y} new startingPosX${f.size.x} ${O} padding=${o} width=${w} halfWidth=${O} => x:${f.size.x} y:${f.size.y} ${f.widthInColumns} (width * (child?.w || 1)) / 2 ${w*(f?.widthInColumns??1)/2}`),y=f.size.x+O;const v=h.get(_)??0,g=s.get(_)??b;f.size.y=L.size.y-L.size.height/2+v+g/2+o,m.debug(`abc88 layout blocks (calc) px, pyid:${f.id}startingPosX${y}${o}${O}=>x:${f.size.x}y:${f.size.y}${f.widthInColumns}(width * (child?.w || 1)) / 2${w*(f?.widthInColumns??1)/2}`)}f.children&&ue(f,a,o);let T=f?.widthInColumns??1;r>0&&(T=Math.min(T,r-x%r)),x+=T,m.debug("abc88 columnsPos",f,x)}}m.debug(`layout blocks (<==layoutBlocks) ${e.id} x: ${e?.size?.x} y: ${e?.size?.y} width: ${e?.size?.width}`)}u(ue,"layoutBlocks");function ge(e,{minX:a,minY:o,maxX:r,maxY:l}={minX:0,minY:0,maxX:0,maxY:0}){if(e.size&&e.id!=="root"){const{x:d,y:s,width:h,height:x}=e.size;d-h/2<a&&(a=d-h/2),s-x/2<o&&(o=s-x/2),d+h/2>r&&(r=d+h/2),s+x/2>l&&(l=s+x/2)}if(e.children)for(const d of e.children)({minX:a,minY:o,maxX:r,maxY:l}=ge(d,{minX:a,minY:o,maxX:r,maxY:l}));return{minX:a,minY:o,maxX:r,maxY:l}}u(ge,"findBounds");function Ie(e){const a=e.getBlock("root");if(!a)return;const o=Le()?.block?.padding??8;G(a,e,0,0,o),ue(a, Line truncated
+38
View File
@@ -0,0 +1,38 @@
import{d as Le}from"./chunk-F27PBJKO.js";import{s as Ie,g as Me,a as Be,b as Ve,_ as d,c as wt,l as he,d as Ye,e as Fe,f as Dt,h as Ue,i as be,j as Jt,w as je,k as $t,m as de}from"./mermaid.core.js";import"./index.js";var Ut=(function(){var t=d(function(yt,m,x,E){for(x=x||{},E=yt.length;E--;x[yt[E]]=m);return x},"o"),e=[1,24],s=[1,25],a=[1,26],u=[1,27],i=[1,28],n=[1,63],l=[1,64],r=[1,65],h=[1,66],y=[1,67],f=[1,68],b=[1,69],v=[1,29],w=[1,30],N=[1,31],O=[1,32],P=[1,33],I=[1,34],W=[1,35],X=[1,36],q=[1,37],H=[1,38],Q=[1,39],K=[1,40],G=[1,41],J=[1,42],Z=[1,43],$=[1,44],tt=[1,45],et=[1,46],nt=[1,47],st=[1,48],rt=[1,50],at=[1,51],it=[1,52],ot=[1,53],lt=[1,54],ct=[1,55],ut=[1,56],ht=[1,57],dt=[1,58],pt=[1,59],ft=[1,60],kt=[14,42],Wt=[14,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],Ot=[12,14,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],S=[1,82],k=[1,83],T=[1,84],C=[1,85],R=[12,14,42],ie=[12,14,33,42],Mt=[12,14,33,42,76,77,79,80],gt=[12,33],Xt=[34,36,37,38,39,40,41,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],qt={trace:d(function(){},"trace"),yy:{},symbols_:{error:2,start:3,mermaidDoc:4,direction:5,direction_tb:6,direction_bt:7,direction_rl:8,direction_lr:9,graphConfig:10,C4_CONTEXT:11,NEWLINE:12,statements:13,EOF:14,C4_CONTAINER:15,C4_COMPONENT:16,C4_DYNAMIC:17,C4_DEPLOYMENT:18,otherStatements:19,diagramStatements:20,otherStatement:21,title:22,accDescription:23,acc_title:24,acc_title_value:25,acc_descr:26,acc_descr_value:27,acc_descr_multiline_value:28,boundaryStatement:29,boundaryStartStatement:30,boundaryStopStatement:31,boundaryStart:32,LBRACE:33,ENTERPRISE_BOUNDARY:34,attributes:35,SYSTEM_BOUNDARY:36,BOUNDARY:37,CONTAINER_BOUNDARY:38,NODE:39,NODE_L:40,NODE_R:41,RBRACE:42,diagramStatement:43,PERSON:44,PERSON_EXT:45,SYSTEM:46,SYSTEM_DB:47,SYSTEM_QUEUE:48,SYSTEM_EXT:49,SYSTEM_EXT_DB:50,SYSTEM_EXT_QUEUE:51,CONTAINER:52,CONTAINER_DB:53,CONTAINER_QUEUE:54,CONTAINER_EXT:55,CONTAINER_EXT_DB:56,CONTAINER_EXT_QUEUE:57,COMPONENT:58,COMPONENT_DB:59,COMPONENT_QUEUE:60,COMPONENT_EXT:61,COMPONENT_EXT_DB:62,COMPONENT_EXT_QUEUE:63,REL:64,BIREL:65,REL_U:66,REL_D:67,REL_L:68,REL_R:69,REL_B:70,REL_INDEX:71,UPDATE_EL_STYLE:72,UPDATE_REL_STYLE:73,UPDATE_LAYOUT_CONFIG:74,attribute:75,STR:76,STR_KEY:77,STR_VALUE:78,ATTRIBUTE:79,ATTRIBUTE_EMPTY:80,$accept:0,$end:1},terminals_:{2:"error",6:"direction_tb",7:"direction_bt",8:"direction_rl",9:"direction_lr",11:"C4_CONTEXT",12:"NEWLINE",14:"EOF",15:"C4_CONTAINER",16:"C4_COMPONENT",17:"C4_DYNAMIC",18:"C4_DEPLOYMENT",22:"title",23:"accDescription",24:"acc_title",25:"acc_title_value",26:"acc_descr",27:"acc_descr_value",28:"acc_descr_multiline_value",33:"LBRACE",34:"ENTERPRISE_BOUNDARY",36:"SYSTEM_BOUNDARY",37:"BOUNDARY",38:"CONTAINER_BOUNDARY",39:"NODE",40:"NODE_L",41:"NODE_R",42:"RBRACE",44:"PERSON",45:"PERSON_EXT",46:"SYSTEM",47:"SYSTEM_DB",48:"SYSTEM_QUEUE",49:"SYSTEM_EXT",50:"SYSTEM_EXT_DB",51:"SYSTEM_EXT_QUEUE",52:"CONTAINER",53:"CONTAINER_DB",54:"CONTAINER_QUEUE",55:"CONTAINER_EXT",56:"CONTAINER_EXT_DB",57:"CONTAINER_EXT_QUEUE",58:"COMPONENT",59:"COMPONENT_DB",60:"COMPONENT_QUEUE",61:"COMPONENT_EXT",62:"COMPONENT_EXT_DB",63:"COMPONENT_EXT_QUEUE",64:"REL",65:"BIREL",66:"REL_U",67:"REL_D",68:"REL_L",69:"REL_R",70:"REL_B",71:"REL_INDEX",72:"UPDATE_EL_STYLE",73:"UPDATE_REL_STYLE",74:"UPDATE_LAYOUT_CONFIG",76:"STR",77:"STR_KEY",78:"STR_VALUE",79:"ATTRIBUTE",80:"ATTRIBUTE_EMPTY"},productions_:[0,[3,1],[3,1],[5,1],[5,1],[5,1],[5,1],[4,1],[10,4],[10,4],[10,4],[10,4],[10,4],[13,1],[13,1],[13,2],[19,1],[19,2],[19,3],[21,1],[21,1],[21,2],[21,2],[21,1],[29,3],[30,3],[30,3],[30,4],[32,2],[32,2],[32,2],[32,2],[32,2],[32,2],[32,2],[31,1],[20,1],[20,2],[20,3],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,1],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[35,1],[35,2],[75,1],[75,2],[75,1],[75,1]],performAction:d(function(m,x,E,_,D,o,Pt){var p=o.length-1;switch(D){case 3:_.setDirection("TB");break;case 4:_.setDirection("BT");break;case 5:_.setDirection("RL");break;case 6:_.setDirection("LR");break;case 8:case 9:case 10:case 11:case 12:_.setC4Type(o[p-3]);break;case 19:_.setTitle(o[p].substring(6)),this.$=o[p].substring(6);break;case 20:_.setAccDescription(o[p].substring(15)),this.$=o[p].substring(15);break;case 21:this.$=o[p].trim(),_.setTitle(this.$);break;case 22:case 23:this.$=o[p].trim(),_.setAccDescription(this.$);break;case 28:o[p].splice(2,0,"ENTERPRISE"),_.addPersonOrSystemBoundary(...o[p]),this.$=o[p];break;case 29:o[p].splice(2,0,"SYSTEM"),_.addPersonOrSystemBoundary(...o[p]),this.$=o[p];break;case 30:_.addPersonOrSystemBoundary(...o[p]),this.$=o[p];break;case 31:o[p].splice(2,0,"CONTAINER"),_.addContainerBoundary(...o[p]),this.$=o[p];break;case 32:_.addDeploymentNode("node",...Line truncated
`+A.showPosition()+`
Expecting `+Yt.join(", ")+", got '"+(this.terminals_[M]||M)+"'":Gt="Parse error on line "+(xt+1)+": Unexpected "+(M==le?"end of input":"'"+(this.terminals_[M]||M)+"'"),this.parseError(Gt,{text:A.match,token:this.terminals_[M]||M,line:A.yylineno,loc:Qt,expected:Yt})}if(V[0]instanceof Array&&V.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Et+", token: "+M);switch(V[0]){case 1:E.push(M),D.push(A.yytext),o.push(A.yylloc),E.push(V[1]),M=null,oe=A.yyleng,p=A.yytext,xt=A.yylineno,Qt=A.yylloc;break;case 2:if(j=this.productions_[V[1]][1],Tt.$=D[D.length-j],Tt._$={first_line:o[o.length-(j||1)].first_line,last_line:o[o.length-1].last_line,first_column:o[o.length-(j||1)].first_column,last_column:o[o.length-1].last_column},Ne&&(Tt._$.range=[o[o.length-(j||1)].range[0],o[o.length-1].range[1]]),Kt=this.performAction.apply(Tt,[p,oe,xt,vt.yy,V[1],D,o].concat(De)),typeof Kt<"u")return Kt;j&&(E=E.slice(0,-1*j*2),D=D.slice(0,-1*j),o=o.slice(0,-1*j)),E.push(this.productions_[V[1]][0]),D.push(Tt.$),o.push(Tt._$),ue=Pt[E[E.length-2]][E[E.length-1]],E.push(ue);break;case 3:return!0}}return!0},"parse")},Oe=(function(){var yt={EOF:1,parseError:d(function(x,E){if(this.yy.parser)this.yy.parser.parseError(x,E);else throw new Error(x)},"parseError"),setInput:d(function(m,x){return this.yy=x||this.yy||{},this._input=m,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:d(function(){var m=this._input[0];this.yytext+=m,this.yyleng++,this.offset++,this.match+=m,this.matched+=m;var x=m.match(/(?:\r\n?|\n).*/g);return x?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),m},"input"),unput:d(function(m){var x=m.length,E=m.split(/(?:\r\n?|\n)/g);this._input=m+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-x),this.offset-=x;var _=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),E.length-1&&(this.yylineno-=E.length-1);var D=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:E?(E.length===_.length?this.yylloc.first_column:0)+_[_.length-E.length].length-E[0].length:this.yylloc.first_column-x},this.options.ranges&&(this.yylloc.range=[D[0],D[0]+this.yyleng-x]),this.yyleng=this.yytext.length,this},"unput"),more:d(function(){return this._more=!0,this},"more"),reject:d(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:d(function(m){this.unput(this.match.slice(m))},"less"),pastInput:d(function(){var m=this.matched.substr(0,this.matched.length-this.match.length);return(m.length>20?"...":"")+m.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:d(function(){var m=this.match;return m.length<20&&(m+=this._input.substr(0,20-m.length)),(m.substr(0,20)+(m.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:d(function(){var m=this.pastInput(),x=new Array(m.length+1).join("-");return m+this.upcomingInput()+`
`+x+"^"},"showPosition"),test_match:d(function(m,x){var E,_,D;if(this.options.backtrack_lexer&&(D={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(D.yylloc.range=this.yylloc.range.slice(0))),_=m[0].match(/(?:\r\n?|\n).*/g),_&&(this.yylineno+=_.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:_?_[_.length-1].length-_[_.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+m[0].length},this.yytext+=m[0],this.match+=m[0],this.matches=m,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(m[0].length),this.matched+=m[0],E=this.performAction.call(this,this.yy,this,x,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),E)return E;if(this._backtrack){for(var o in D)this[o]=D[o];return!1}return!1},"test_match"),next:d(function(){if(this.done)return this.EOF;this._input||(this.done=!0);var m,x,E,_;this._more||(this.yytext="",this.match="");for(var D=this._currentRules(),o=0;o<D.length;o++)if(E=this._input.match(this.rules[D[o]]),E&&(!x||E[0].length>x[0].length)){if(x=E,_=o,this.options.backtrack_lexer){if(m=this.test_match(E,D[o]),m!==!1)return m;if(this._backtrack){x=!1;continue}else return!1}else if(!this.options.flex)break}return x?(m=this.test_match(x,D[_]),m!==!1?m:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text.
`+this.showPosition(),{text:"",token:null,line:this.yylineno})},"next"),lex:d(function(){var x=this.next();return x||this.lex()},"lex"),begin:d(function(x){this.conditionStack.push(x)},"begin"),popState:d(function(){var x=this.conditionStack.length-1;return x>0?this.conditionStack.pop():this.conditionStack[0]},"popState"),_currentRules:d(function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},"_currentRules"),topState:d(function(x){return x=this.conditionStack.length-1-Math.abs(x||0),x>=0?this.conditionStack[x]:"INITIAL"},"topState"),pushState:d(function(x){this.begin(x)},"pushState"),stateStackSize:d(function(){return this.conditionStack.length},"stateStackSize"),options:{},performAction:d(function(x,E,_,D){switch(_){case 0:return 6;case 1:return 7;case 2:return 8;case 3:return 9;case 4:return 22;case 5:return 23;case 6:return this.begin("acc_title"),24;case 7:return this.popState(),"acc_title_value";case 8:return this.begin("acc_descr"),26;case 9:return this.popState(),"acc_descr_value";case 10:this.begin("acc_descr_multiline");break;case 11:this.popState();break;case 12:return"acc_descr_multiline_value";case 13:break;case 14:c;break;case 15:return 12;case 16:break;case 17:return 11;case 18:return 15;case 19:return 16;case 20:return 17;case 21:return 18;case 22:return this.begin("person_ext"),45;case 23:return this.begin("person"),44;case 24:return this.begin("system_ext_queue"),51;case 25:return this.begin("system_ext_db"),50;case 26:return this.begin("system_ext"),49;case 27:return this.begin("system_queue"),48;case 28:return this.begin("system_db"),47;case 29:return this.begin("system"),46;case 30:return this.begin("boundary"),37;case 31:return this.begin("enterprise_boundary"),34;case 32:return this.begin("system_boundary"),36;case 33:return this.begin("container_ext_queue"),57;case 34:return this.begin("container_ext_db"),56;case 35:return this.begin("container_ext"),55;case 36:return this.begin("container_queue"),54;case 37:return this.begin("container_db"),53;case 38:return this.begin("container"),52;case 39:return this.begin("container_boundary"),38;case 40:return this.begin("component_ext_queue"),63;case 41:return this.begin("component_ext_db"),62;case 42:return this.begin("component_ext"),61;case 43:return this.begin("component_queue"),60;case 44:return this.begin("component_db"),59;case 45:return this.begin("component"),58;case 46:return this.begin("node"),39;case 47:return this.begin("node"),39;case 48:return this.begin("node_l"),40;case 49:return this.begin("node_r"),41;case 50:return this.begin("rel"),64;case 51:return this.begin("birel"),65;case 52:return this.begin("rel_u"),66;case 53:return this.begin("rel_u"),66;case 54:return this.begin("rel_d"),67;case 55:return this.begin("rel_d"),67;case 56:return this.begin("rel_l"),68;case 57:return this.begin("rel_l"),68;case 58:return this.begin("rel_r"),69;case 59:return this.begin("rel_r"),69;case 60:return this.begin("rel_b"),70;case 61:return this.begin("rel_index"),71;case 62:return this.begin("update_el_style"),72;case 63:return this.begin("update_rel_style"),73;case 64:return this.begin("update_layout_config"),74;case 65:return"EOF_IN_STRUCT";case 66:return this.begin("attribute"),"ATTRIBUTE_EMPTY";case 67:this.begin("attribute");break;case 68:this.popState(),this.popState();break;case 69:return 80;case 70:break;case 71:return 80;case 72:this.begin("string");break;case 73:this.popState();break;case 74:return"STR";case 75:this.begin("string_kv");break;case 76:return this.begin("string_kv_key"),"STR_KEY";case 77:this.popState(),this.begin("string_kv_value");break;case 78:return"STR_VALUE";case 79:this.popState(),this.popState();break;case 80:return"STR";case 81:return"LBRACE";case 82:return"RBRACE";case 83:return"SPACE";case 84:return"EOL";case 85:return 14}},"anonymous"),rules:[/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:title\s[^#\n;]+)/,/^(?:accDescription\s[^#\n;]+)/,/^(?:accTitle\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*\{\s*)/,/^(?:[\}])/,/^(?:[^\}]*)/,/^(?:%%(?!\{)*[^\n]*(\r?\n?)+)/,/^(?:%%[^\n]*(\r?\n)*)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:C4Context\b)/,/^(?:C4Container\b)/,/^(?:C4Component\b)/,/^(?:C4Dynamic\b)/,/^(?:C4Deployment\b)/,/^(?:Person_Ext\b)/,/^(?:Person\b)/,/^(?:SystemQueue_Ext\b)/,/^(?:SystemDb_Ext\b)/,/^(?:System_Ext\b)/,/^(?:SystemQueue\b)/,/^(?:SystemDb\b)/,/^(?:System\b)/,/^(?:Boundary\b)/,/^(?:Enterprise_Boundary\b)/,/^(?:System_Boundary\b)/,/^(?:ContainerQueue_Ext\b)/,/^(?:ContainerDb_Ext\b)/,/^(?:Container_Ext\b)/,/^(?:ContainerQueue\b)/,/^(?:ContainerDb\b)/,/^(?:Container\b)/,/^(?:Container_Boundary\b)/,/^(?:ComponentQueue_Ext\b)/,/^(?:ComponentDb_Ext\b)/,/^(?:Component_Ext\b)/,/^(?:ComponentQueue\b)/,/^(?:ComponentDb\b)/,/^(?:Component\bLine truncated
`)},"elementFontStyles"),W0=d(t=>`.person {
stroke: ${t.personBorder};
fill: ${t.personBkg};
}
${z0()}
/* The element font colour is set inline per element (default white); the
label text takes it via currentColor. */
.c4-shape .label,
.c4-shape .label text {
color: inherit;
fill: currentColor;
}
/* Structurizr typography: bold name, smaller stereotype/type and description lines. */
.c4-shape .label .c4-name {
font-weight: bold;
}
.c4-shape .label .c4-type {
font-size: 0.75em;
}
.c4-shape .label .c4-descr {
font-size: 0.82em;
}
.c4-shape .basic,
.c4-shape rect,
.c4-shape path,
.c4-shape circle,
.c4-shape ellipse,
.c4-shape line {
stroke-width: 2px;
}
`,"getStyles"),X0=W0,K0={parser:ze,db:te,renderer:_e,styles:X0,init:d(({c4:t,wrap:e})=>{_e.setConf(t),te.setWrap(e)},"init")};export{K0 as diagram};
+1
View File
@@ -0,0 +1 @@
import{ai as o,aj as n}from"./mermaid.core.js";const t=(a,r)=>o.lang.round(n.parse(a)[r]);export{t as c};
+1
View File
@@ -0,0 +1 @@
import{_ as s}from"./mermaid.core.js";var t,e=(t=class{constructor(i){this.init=i,this.records=this.init()}reset(){this.records=this.init()}},s(t,"ImperativeState"),t);export{e as I};
+15
View File
@@ -0,0 +1,15 @@
import{_ as e}from"./mermaid.core.js";var l=e(()=>`
/* Font Awesome icon styling - consolidated */
.label-icon {
display: inline-block;
height: 1em;
overflow: visible;
vertical-align: -0.125em;
}
.node .label-icon path {
fill: currentColor;
stroke: revert;
stroke-width: revert;
}
`,"getIconStyles");export{l as g};
+1
View File
@@ -0,0 +1 @@
import{_ as i,j as l,U as d,G as o}from"./mermaid.core.js";var x=i((r,t)=>{const e=r.append("rect");if(e.attr("x",t.x),e.attr("y",t.y),e.attr("fill",t.fill),e.attr("stroke",t.stroke),e.attr("width",t.width),e.attr("height",t.height),t.name&&e.attr("name",t.name),t.rx&&e.attr("rx",t.rx),t.ry&&e.attr("ry",t.ry),t.attrs!==void 0)for(const s in t.attrs)e.attr(s,t.attrs[s]);return t.class&&e.attr("class",t.class),e},"drawRect"),p=i((r,t)=>{const e={x:t.startx,y:t.starty,width:t.stopx-t.startx,height:t.stopy-t.starty,fill:t.fill,stroke:t.stroke,class:"rect"};x(r,e).lower()},"drawBackgroundRect"),y=i((r,t)=>{const e=t.text.replace(d," "),s=r.append("text");s.attr("x",t.x),s.attr("y",t.y),s.attr("class","legend"),s.style("text-anchor",t.anchor),t.class&&s.attr("class",t.class);const a=s.append("tspan");return a.attr("x",t.x+t.textMargin*2),a.text(e),s},"drawText"),m=i((r,t,e,s)=>{const a=r.append("image");a.attr("x",t),a.attr("y",e);const n=o.sanitizeUrl(s);a.attr("xlink:href",n)},"drawImage"),g=i((r,t,e,s)=>{const a=r.append("use");a.attr("x",t),a.attr("y",e);const n=o.sanitizeUrl(s);a.attr("xlink:href",`#${n}`)},"drawEmbeddedImage"),h=i(()=>({x:0,y:0,width:100,height:100,fill:"#EDF2AE",stroke:"#666",anchor:"start",rx:0,ry:0}),"getNoteRect"),f=i(()=>({x:0,y:0,width:100,height:100,"text-anchor":"start",style:"#666",textMargin:0,rx:0,ry:0,tspan:!0}),"getTextObj"),w=i(()=>{let r=l(".mermaidTooltip");return r.empty()&&(r=l("body").append("div").attr("class","mermaidTooltip").style("opacity",0).style("position","absolute").style("text-align","center").style("max-width","200px").style("padding","2px").style("font-size","12px").style("background","#ffffde").style("border","1px solid #333").style("border-radius","2px").style("pointer-events","none").style("z-index","100")),r},"createTooltip");export{p as a,h as b,g as c,x as d,m as e,w as f,f as g,y as h};
+231
View File
@@ -0,0 +1,231 @@
import{g as ee}from"./chunk-XXDRQBXY.js";import{s as se}from"./chunk-POPQ4Y6H.js";import{_ as p,l as b,c as $,v as ie,x as re,a as ae,b as ne,g as oe,s as le,n as ce,o as he,T as ue,k as j,p as de,j as kt,O as fe}from"./mermaid.core.js";import{f as pe}from"./chunk-F27PBJKO.js";var Ct=(function(){var t=p(function(V,o,h,a){for(h=h||{},a=V.length;a--;h[V[a]]=o);return h},"o"),e=[1,2],s=[1,3],n=[1,4],r=[2,4],c=[1,9],u=[1,11],S=[1,16],d=[1,17],T=[1,18],E=[1,19],m=[1,33],L=[1,20],D=[1,21],f=[1,22],I=[1,23],R=[1,24],C=[1,26],F=[1,27],A=[1,28],P=[1,29],w=[1,30],z=[1,31],rt=[1,32],at=[1,35],nt=[1,36],ot=[1,37],lt=[1,38],K=[1,34],y=[1,4,5,16,17,19,21,22,24,25,26,27,28,29,33,35,37,38,41,45,48,51,52,53,54,57],ct=[1,4,5,14,15,16,17,19,21,22,24,25,26,27,28,29,33,35,37,38,39,40,41,45,48,51,52,53,54,57],Lt=[4,5,16,17,19,21,22,24,25,26,27,28,29,33,35,37,38,41,45,48,51,52,53,54,57],gt={trace:p(function(){},"trace"),yy:{},symbols_:{error:2,start:3,SPACE:4,NL:5,SD:6,document:7,line:8,statement:9,classDefStatement:10,styleStatement:11,cssClassStatement:12,idStatement:13,DESCR:14,"-->":15,HIDE_EMPTY:16,scale:17,WIDTH:18,COMPOSIT_STATE:19,STRUCT_START:20,STRUCT_STOP:21,STATE_DESCR:22,AS:23,ID:24,FORK:25,JOIN:26,CHOICE:27,CONCURRENT:28,note:29,notePosition:30,NOTE_TEXT:31,direction:32,acc_title:33,acc_title_value:34,acc_descr:35,acc_descr_value:36,acc_descr_multiline_value:37,CLICK:38,STRING:39,HREF:40,classDef:41,CLASSDEF_ID:42,CLASSDEF_STYLEOPTS:43,DEFAULT:44,style:45,STYLE_IDS:46,STYLEDEF_STYLEOPTS:47,class:48,CLASSENTITY_IDS:49,STYLECLASS:50,direction_tb:51,direction_bt:52,direction_rl:53,direction_lr:54,eol:55,";":56,EDGE_STATE:57,STYLE_SEPARATOR:58,left_of:59,right_of:60,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NL",6:"SD",14:"DESCR",15:"-->",16:"HIDE_EMPTY",17:"scale",18:"WIDTH",19:"COMPOSIT_STATE",20:"STRUCT_START",21:"STRUCT_STOP",22:"STATE_DESCR",23:"AS",24:"ID",25:"FORK",26:"JOIN",27:"CHOICE",28:"CONCURRENT",29:"note",31:"NOTE_TEXT",33:"acc_title",34:"acc_title_value",35:"acc_descr",36:"acc_descr_value",37:"acc_descr_multiline_value",38:"CLICK",39:"STRING",40:"HREF",41:"classDef",42:"CLASSDEF_ID",43:"CLASSDEF_STYLEOPTS",44:"DEFAULT",45:"style",46:"STYLE_IDS",47:"STYLEDEF_STYLEOPTS",48:"class",49:"CLASSENTITY_IDS",50:"STYLECLASS",51:"direction_tb",52:"direction_bt",53:"direction_rl",54:"direction_lr",56:";",57:"EDGE_STATE",58:"STYLE_SEPARATOR",59:"left_of",60:"right_of"},productions_:[0,[3,2],[3,2],[3,2],[7,0],[7,2],[8,2],[8,1],[8,1],[9,1],[9,1],[9,1],[9,1],[9,2],[9,3],[9,4],[9,1],[9,2],[9,1],[9,4],[9,3],[9,6],[9,1],[9,1],[9,1],[9,1],[9,4],[9,4],[9,1],[9,2],[9,2],[9,1],[9,5],[9,5],[10,3],[10,3],[11,3],[12,3],[32,1],[32,1],[32,1],[32,1],[55,1],[55,1],[13,1],[13,1],[13,3],[13,3],[30,1],[30,1]],performAction:p(function(o,h,a,g,_,i,B){var l=i.length-1;switch(_){case 3:return g.setRootDoc(i[l]),i[l];case 4:this.$=[];break;case 5:i[l]!="nl"&&(i[l-1].push(i[l]),this.$=i[l-1]);break;case 6:case 7:this.$=i[l];break;case 8:this.$="nl";break;case 12:this.$=i[l];break;case 13:const Z=i[l-1];Z.description=g.trimColon(i[l]),this.$=Z;break;case 14:this.$={stmt:"relation",state1:i[l-2],state2:i[l]};break;case 15:const Tt=g.trimColon(i[l]);this.$={stmt:"relation",state1:i[l-3],state2:i[l-1],description:Tt};break;case 19:this.$={stmt:"state",id:i[l-3],type:"default",description:"",doc:i[l-1]};break;case 20:var Y=i[l],X=i[l-2].trim();if(i[l].match(":")){var ut=i[l].split(":");Y=ut[0],X=[X,ut[1]]}this.$={stmt:"state",id:Y,type:"default",description:X};break;case 21:this.$={stmt:"state",id:i[l-3],type:"default",description:i[l-5],doc:i[l-1]};break;case 22:this.$={stmt:"state",id:i[l],type:"fork"};break;case 23:this.$={stmt:"state",id:i[l],type:"join"};break;case 24:this.$={stmt:"state",id:i[l],type:"choice"};break;case 25:this.$={stmt:"state",id:g.getDividerId(),type:"divider"};break;case 26:this.$={stmt:"state",id:i[l-1].trim(),note:{position:i[l-2].trim(),text:i[l].trim()}};break;case 29:this.$=i[l].trim(),g.setAccTitle(this.$);break;case 30:case 31:this.$=i[l].trim(),g.setAccDescription(this.$);break;case 32:this.$={stmt:"click",id:i[l-3],url:i[l-2],tooltip:i[l-1]};break;case 33:this.$={stmt:"click",id:i[l-3],url:i[l-1],tooltip:""};break;case 34:case 35:this.$={stmt:"classDef",id:i[l-1].trim(),classes:i[l].trim()};break;case 36:this.$={stmt:"style",id:i[l-1].trim(),styleClass:i[l].trim()};break;case 37:this.$={stmt:"applyClass",id:i[l-1].trim(),styleClass:i[l].trim()};break;case 38:g.setDirection("TB"),this.$={stmt:"dir",value:"TB"};break;case 39:g.setDirection("BT"),this.$={stmt:"dir",value:"BT"};break;case 40:g.setDirection("RL"),this.$={stmt:"dir",value:"RL"};break;case 41:g.setDirection("LR"),this.$={stmt:"dir",value:"LR"};break;case 44:case 45:this.$={stmt:"state",id:i[l].trim(),type:"default",description:""};break;case 46:this.$={stmt:"state",id:i[l-2].trim(),classes:[i[l].trim()],type:"default",description:""};break;case 47:this.$={stmt:"state",id:i[l-2].trim(),classes:[i[l].trim()],type:"default",description:""};break}Line truncated
`+k.showPosition()+`
Expecting `+ft.join(", ")+", got '"+(this.terminals_[x]||x)+"'":bt="Parse error on line "+(Y+1)+": Unexpected "+(x==Z?"end of input":"'"+(this.terminals_[x]||x)+"'"),this.parseError(bt,{text:k.match,token:this.terminals_[x]||x,line:k.yylineno,loc:_t,expected:ft})}if(N[0]instanceof Array&&N.length>1)throw new Error("Parse Error: multiple actions possible at state: "+W+", token: "+x);switch(N[0]){case 1:a.push(x),_.push(k.yytext),i.push(k.yylloc),a.push(N[1]),x=null,X=k.yyleng,l=k.yytext,Y=k.yylineno,_t=k.yylloc;break;case 2:if(G=this.productions_[N[1]][1],J.$=_[_.length-G],J._$={first_line:i[i.length-(G||1)].first_line,last_line:i[i.length-1].last_line,first_column:i[i.length-(G||1)].first_column,last_column:i[i.length-1].last_column},Zt&&(J._$.range=[i[i.length-(G||1)].range[0],i[i.length-1].range[1]]),mt=this.performAction.apply(J,[l,X,Y,U.yy,N[1],_,i].concat(Tt)),typeof mt<"u")return mt;G&&(a=a.slice(0,-1*G*2),_=_.slice(0,-1*G),i=i.slice(0,-1*G)),a.push(this.productions_[N[1]][0]),_.push(J.$),i.push(J._$),wt=B[a[a.length-2]][a[a.length-1]],a.push(wt);break;case 3:return!0}}return!0},"parse")},Qt=(function(){var V={EOF:1,parseError:p(function(h,a){if(this.yy.parser)this.yy.parser.parseError(h,a);else throw new Error(h)},"parseError"),setInput:p(function(o,h){return this.yy=h||this.yy||{},this._input=o,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:p(function(){var o=this._input[0];this.yytext+=o,this.yyleng++,this.offset++,this.match+=o,this.matched+=o;var h=o.match(/(?:\r\n?|\n).*/g);return h?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),o},"input"),unput:p(function(o){var h=o.length,a=o.split(/(?:\r\n?|\n)/g);this._input=o+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-h),this.offset-=h;var g=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),a.length-1&&(this.yylineno-=a.length-1);var _=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:a?(a.length===g.length?this.yylloc.first_column:0)+g[g.length-a.length].length-a[0].length:this.yylloc.first_column-h},this.options.ranges&&(this.yylloc.range=[_[0],_[0]+this.yyleng-h]),this.yyleng=this.yytext.length,this},"unput"),more:p(function(){return this._more=!0,this},"more"),reject:p(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:p(function(o){this.unput(this.match.slice(o))},"less"),pastInput:p(function(){var o=this.matched.substr(0,this.matched.length-this.match.length);return(o.length>20?"...":"")+o.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:p(function(){var o=this.match;return o.length<20&&(o+=this._input.substr(0,20-o.length)),(o.substr(0,20)+(o.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:p(function(){var o=this.pastInput(),h=new Array(o.length+1).join("-");return o+this.upcomingInput()+`
`+h+"^"},"showPosition"),test_match:p(function(o,h){var a,g,_;if(this.options.backtrack_lexer&&(_={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(_.yylloc.range=this.yylloc.range.slice(0))),g=o[0].match(/(?:\r\n?|\n).*/g),g&&(this.yylineno+=g.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:g?g[g.length-1].length-g[g.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+o[0].length},this.yytext+=o[0],this.match+=o[0],this.matches=o,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(o[0].length),this.matched+=o[0],a=this.performAction.call(this,this.yy,this,h,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),a)return a;if(this._backtrack){for(var i in _)this[i]=_[i];return!1}return!1},"test_match"),next:p(function(){if(this.done)return this.EOF;this._input||(this.done=!0);var o,h,a,g;this._more||(this.yytext="",this.match="");for(var _=this._currentRules(),i=0;i<_.length;i++)if(a=this._input.match(this.rules[_[i]]),a&&(!h||a[0].length>h[0].length)){if(h=a,g=i,this.options.backtrack_lexer){if(o=this.test_match(a,_[i]),o!==!1)return o;if(this._backtrack){h=!1;continue}else return!1}else if(!this.options.flex)break}return h?(o=this.test_match(h,_[g]),o!==!1?o:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text.
`+this.showPosition(),{text:"",token:null,line:this.yylineno})},"next"),lex:p(function(){var h=this.next();return h||this.lex()},"lex"),begin:p(function(h){this.conditionStack.push(h)},"begin"),popState:p(function(){var h=this.conditionStack.length-1;return h>0?this.conditionStack.pop():this.conditionStack[0]},"popState"),_currentRules:p(function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},"_currentRules"),topState:p(function(h){return h=this.conditionStack.length-1-Math.abs(h||0),h>=0?this.conditionStack[h]:"INITIAL"},"topState"),pushState:p(function(h){this.begin(h)},"pushState"),stateStackSize:p(function(){return this.conditionStack.length},"stateStackSize"),options:{"case-insensitive":!0},performAction:p(function(h,a,g,_){function i(){const B=a.yytext.indexOf("%%");if(B===0)return!1;if(B>0){const l=a.yytext.slice(0,B),Y=a.yytext.slice(B);Y&&h.lexer.unput(Y),a.yytext=l}return!0}switch(p(i,"processId"),g){case 0:return 38;case 1:return 40;case 2:return 39;case 3:return 44;case 4:return 51;case 5:return 52;case 6:return 53;case 7:return 54;case 8:return 5;case 9:break;case 10:break;case 11:break;case 12:break;case 13:return this.pushState("SCALE"),17;case 14:return 18;case 15:this.popState();break;case 16:return this.begin("acc_title"),33;case 17:return this.popState(),"acc_title_value";case 18:return this.begin("acc_descr"),35;case 19:return this.popState(),"acc_descr_value";case 20:this.begin("acc_descr_multiline");break;case 21:this.popState();break;case 22:return"acc_descr_multiline_value";case 23:return this.pushState("CLASSDEF"),41;case 24:return this.popState(),this.pushState("CLASSDEFID"),"DEFAULT_CLASSDEF_ID";case 25:return this.popState(),this.pushState("CLASSDEFID"),42;case 26:return this.popState(),43;case 27:return this.pushState("CLASS"),48;case 28:return this.popState(),this.pushState("CLASS_STYLE"),49;case 29:return this.popState(),50;case 30:return this.pushState("STYLE"),45;case 31:return this.popState(),this.pushState("STYLEDEF_STYLES"),46;case 32:return this.popState(),47;case 33:return this.pushState("SCALE"),17;case 34:return 18;case 35:this.popState();break;case 36:this.pushState("STATE");break;case 37:return this.popState(),a.yytext=a.yytext.slice(0,-8).trim(),25;case 38:return this.popState(),a.yytext=a.yytext.slice(0,-8).trim(),26;case 39:return this.popState(),a.yytext=a.yytext.slice(0,-10).trim(),27;case 40:return this.popState(),a.yytext=a.yytext.slice(0,-8).trim(),25;case 41:return this.popState(),a.yytext=a.yytext.slice(0,-8).trim(),26;case 42:return this.popState(),a.yytext=a.yytext.slice(0,-10).trim(),27;case 43:return 51;case 44:return 52;case 45:return 53;case 46:return 54;case 47:this.pushState("STATE_STRING");break;case 48:return this.pushState("STATE_ID"),"AS";case 49:return i()?(this.popState(),"ID"):void 0;case 50:this.popState();break;case 51:return"STATE_DESCR";case 52:throw new Error('Error: State name must be a single word. Found: "'+a.yytext.trim()+'"');case 53:return 19;case 54:this.popState();break;case 55:return this.popState(),this.pushState("struct"),20;case 56:return this.popState(),21;case 57:break;case 58:return this.begin("NOTE"),29;case 59:return this.popState(),this.pushState("NOTE_ID"),59;case 60:return this.popState(),this.pushState("NOTE_ID"),60;case 61:this.popState(),this.pushState("FLOATING_NOTE");break;case 62:return this.popState(),this.pushState("FLOATING_NOTE_ID"),"AS";case 63:break;case 64:return"NOTE_TEXT";case 65:return i()?(this.popState(),"ID"):void 0;case 66:return i()?(this.popState(),this.pushState("NOTE_TEXT"),24):void 0;case 67:return this.popState(),a.yytext=a.yytext.substr(2).trim(),31;case 68:return this.popState(),a.yytext=a.yytext.slice(0,-8).trim(),31;case 69:return 6;case 70:return 6;case 71:return 16;case 72:return 57;case 73:return i()?24:void 0;case 74:return a.yytext=a.yytext.trim(),14;case 75:return 15;case 76:return 28;case 77:return 58;case 78:return 5;case 79:return"INVALID"}},"anonymous"),rules:[/^(?:click\b)/i,/^(?:href\b)/i,/^(?:"[^"]*")/i,/^(?:default\b)/i,/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*direction\s+BT[^\n]*)/i,/^(?:.*direction\s+RL[^\n]*)/i,/^(?:.*direction\s+LR[^\n]*)/i,/^(?:[\n]+)/i,/^(?:[\s]+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:scale\s+)/i,/^(?:\d+)/i,/^(?:\s+width\b)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:classDef\s+)/i,/^(?:DEFAULT\s+)/i,/^(?:\w+\s+)/i,/^(?:[^\n]*)/i,/^(?:class\s+)/i,/^(?:(\w+)+((,\s*\w+)*))/i,/^(?:[^\n]*)/i,/^(?:style\s+)/i,/^(?:[\w,]+\s+)/i,/^(?:[^\n]*)/i,/^(?:scale\s+)/i,/^(?:\d+)/i,/^(?:\s+width\b)/i,/^(?:state\s+)/i,/^(?:.*<<fork>>)/i,/^(?:.*<<join>>)/i,/^(?:.*<<choice>>)/i,/^(?:.*\[\[fork\]\])/i,/^(?:.*\[\[join\]\])/i,/^(?:.*\[\[choice\]\])/i,/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*directio Line truncated
defs [id$="-barbEnd"] {
fill: ${t.transitionColor};
stroke: ${t.transitionColor};
}
g.stateGroup text {
fill: ${t.nodeBorder};
stroke: none;
font-size: 10px;
}
g.stateGroup text {
fill: ${t.textColor};
stroke: none;
font-size: 10px;
}
g.stateGroup .state-title {
font-weight: bolder;
fill: ${t.stateLabelColor};
}
g.stateGroup rect {
fill: ${t.mainBkg};
stroke: ${t.nodeBorder};
}
g.stateGroup line {
stroke: ${t.lineColor};
stroke-width: ${t.strokeWidth||1};
}
.transition {
stroke: ${t.transitionColor};
stroke-width: ${t.strokeWidth||1};
fill: none;
}
.stateGroup .composit {
fill: ${t.background};
border-bottom: 1px
}
.stateGroup .alt-composit {
fill: #e0e0e0;
border-bottom: 1px
}
.state-note {
stroke: ${t.noteBorderColor};
fill: ${t.noteBkgColor};
text {
fill: ${t.noteTextColor};
stroke: none;
font-size: 10px;
}
}
.stateLabel .box {
stroke: none;
stroke-width: 0;
fill: ${t.mainBkg};
opacity: 0.5;
}
.edgeLabel .label rect {
fill: ${t.labelBackgroundColor};
opacity: 0.5;
}
.edgeLabel {
background-color: ${t.edgeLabelBackground};
p {
background-color: ${t.edgeLabelBackground};
}
rect {
opacity: 0.5;
background-color: ${t.edgeLabelBackground};
fill: ${t.edgeLabelBackground};
}
text-align: center;
}
.edgeLabel .label text {
fill: ${t.transitionLabelColor||t.tertiaryTextColor};
}
.label div .edgeLabel {
color: ${t.transitionLabelColor||t.tertiaryTextColor};
}
.stateLabel text {
fill: ${t.stateLabelColor};
font-size: 10px;
font-weight: bold;
}
.node circle.state-start {
fill: ${t.specialStateColor};
stroke: ${t.specialStateColor};
}
.node .fork-join {
fill: ${t.specialStateColor};
stroke: ${t.specialStateColor};
}
.node circle.state-end {
fill: ${t.innerEndBackground};
stroke: ${t.background};
stroke-width: 1.5
}
.end-state-inner {
fill: ${t.compositeBackground||t.background};
// stroke: ${t.background};
stroke-width: 1.5
}
.node rect {
fill: ${t.stateBkg||t.mainBkg};
stroke: ${t.stateBorder||t.nodeBorder};
stroke-width: ${t.strokeWidth||1}px;
}
.node polygon {
fill: ${t.mainBkg};
stroke: ${t.stateBorder||t.nodeBorder};;
stroke-width: ${t.strokeWidth||1}px;
}
[id$="-barbEnd"] {
fill: ${t.lineColor};
}
.statediagram-cluster rect {
fill: ${t.compositeTitleBackground};
stroke: ${t.stateBorder||t.nodeBorder};
stroke-width: ${t.strokeWidth||1}px;
}
.cluster-label, .nodeLabel {
color: ${t.stateLabelColor};
// line-height: 1;
}
.statediagram-cluster rect.outer {
rx: 5px;
ry: 5px;
}
.statediagram-state .divider {
stroke: ${t.stateBorder||t.nodeBorder};
}
.statediagram-state .title-state {
rx: 5px;
ry: 5px;
}
.statediagram-cluster.statediagram-cluster .inner {
fill: ${t.compositeBackground||t.background};
}
.statediagram-cluster.statediagram-cluster-alt .inner {
fill: ${t.altBackground?t.altBackground:"#efefef"};
}
.statediagram-cluster .inner {
rx:0;
ry:0;
}
.statediagram-state rect.basic {
rx: 5px;
ry: 5px;
}
.statediagram-state rect.divider {
stroke-dasharray: 10,10;
fill: ${t.altBackground?t.altBackground:"#efefef"};
}
.note-edge {
stroke-dasharray: 5;
}
.statediagram-note rect {
fill: ${t.noteBkgColor};
stroke: ${t.noteBorderColor};
stroke-width: 1px;
rx: 0;
ry: 0;
}
.statediagram-note rect {
fill: ${t.noteBkgColor};
stroke: ${t.noteBorderColor};
stroke-width: 1px;
rx: 0;
ry: 0;
}
.statediagram-note text {
fill: ${t.noteTextColor};
}
.statediagram-note .nodeLabel {
color: ${t.noteTextColor};
}
.statediagram .edgeLabel {
color: red; // ${t.noteTextColor};
}
[id$="-dependencyStart"], [id$="-dependencyEnd"] {
fill: ${t.lineColor};
stroke: ${t.lineColor};
stroke-width: ${t.strokeWidth||1};
}
.statediagramTitleText {
text-anchor: middle;
font-size: 18px;
fill: ${t.textColor};
}
[data-look="neo"].statediagram-cluster rect {
fill: ${t.mainBkg};
stroke: ${t.useGradient?"url("+t.svgId+"-gradient)":t.stateBorder||t.nodeBorder};
stroke-width: ${t.strokeWidth??1};
}
[data-look="neo"].statediagram-cluster rect.outer {
rx: ${t.radius}px;
ry: ${t.radius}px;
filter: ${t.dropShadow?t.dropShadow.replace("url(#drop-shadow)",`url(${t.svgId}-drop-shadow)`):"none"}
}
`,"getStyles"),ze=Ye;export{He as S,We as a,je as b,ze as s};
+1
View File
@@ -0,0 +1 @@
import{_ as i}from"./mermaid.core.js";function t(c,e){c.accDescr&&e.setAccDescription?.(c.accDescr),c.accTitle&&e.setAccTitle?.(c.accTitle),c.title&&e.setDiagramTitle?.(c.title)}i(t,"populateCommonDb");export{t as p};
+1
View File
@@ -0,0 +1 @@
import{_ as a,d as w,l as x}from"./mermaid.core.js";var B=a((e,t,i,r)=>{e.attr("class",i);const{width:o,height:h,x:n,y:c}=u(e,t);w(e,h,o,r);const s=d(n,c,o,h,t);e.attr("viewBox",s),x.debug(`viewBox configured: ${s} with padding: ${t}`)},"setupViewPortForSVG"),u=a((e,t)=>{const i=e.node()?.getBBox()||{width:0,height:0,x:0,y:0};return{width:i.width+t*2,height:i.height+t*2,x:i.x,y:i.y}},"calculateDimensionsWithPadding"),d=a((e,t,i,r,o)=>`${e-o} ${t-o} ${i} ${r}`,"createViewBox");export{B as s};
+88
View File
@@ -0,0 +1,88 @@
import{_ as p,l as C,D as H,y as B,p as q,E as G,d as U,i as j,c as K}from"./mermaid.core.js";var A="",M="",O="",D=[],b=new Map,v=p(e=>j(e,K()),"sanitizeText"),y=p(e=>{switch(e.type){case"terminal":return{...e,value:v(e.value)};case"nonterminal":return{...e,name:v(e.name)};case"sequence":return{...e,elements:e.elements.map(y)};case"choice":return{...e,alternatives:e.alternatives.map(y)};case"optional":return{...e,element:y(e.element)};case"repetition":return{...e,element:y(e.element),separator:e.separator?y(e.separator):void 0};case"special":return{...e,text:v(e.text)}}},"sanitizeAstNode"),J=p(()=>{A="",M="",O="",D.length=0,b.clear(),q(),C.debug("[Railroad] Database cleared")},"clear"),Y=p(e=>{A=v(e),C.debug("[Railroad] Title set:",e)},"setTitle"),P=p(()=>A,"getTitle"),Q=p(e=>{const i={...e,name:v(e.name),definition:y(e.definition),comment:e.comment?v(e.comment):void 0};C.debug("[Railroad] Adding rule:",i.name),b.has(i.name)&&C.warn(`[Railroad] Rule '${i.name}' is already defined. Overwriting.`),D.push(i),b.set(i.name,i)},"addRule"),Z=p(()=>D,"getRules"),V=p(e=>b.get(e),"getRule"),ee=p(e=>{M=v(e).replace(/^\s+/g,""),C.debug("[Railroad] Accessibility title set:",e)},"setAccTitle"),te=p(()=>M,"getAccTitle"),re=p(e=>{O=v(e).replace(/\n\s+/g,`
`),C.debug("[Railroad] Accessibility description set:",e)},"setAccDescription"),ie=p(()=>O,"getAccDescription"),ne=Y,ae=P,oe={clear:J,setTitle:Y,getTitle:P,addRule:Q,getRules:Z,getRule:V,setAccTitle:ee,getAccTitle:te,setAccDescription:re,getAccDescription:ie,setDiagramTitle:ne,getDiagramTitle:ae},f={compactMode:!1,padding:10,verticalSeparation:8,horizontalSeparation:10,arcRadius:10,fontSize:14,fontFamily:"monospace",terminalFill:"#FFFFC0",terminalStroke:"#000000",terminalTextColor:"#000000",nonTerminalFill:"#FFFFFF",nonTerminalStroke:"#000000",nonTerminalTextColor:"#000000",lineColor:"#000000",strokeWidth:2,markerFill:"#000000",commentFill:"#E8E8E8",commentStroke:"#888888",commentTextColor:"#666666",specialFill:"#F0E0FF",specialStroke:"#8800CC",ruleNameColor:"#000066",showMarkers:!0,markerRadius:5},le=/^#(?:[\da-f]{3,4}|[\da-f]{6}|[\da-f]{8})$|^(?:rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch)\([\d\s%+,./-]+\)$|^[a-z]+$/i,se=/^[\w "',.-]+$/,de=new Set(["compactMode","padding","verticalSeparation","horizontalSeparation","arcRadius","fontSize","fontFamily","terminalFill","terminalStroke","terminalTextColor","nonTerminalFill","nonTerminalStroke","nonTerminalTextColor","lineColor","strokeWidth","markerFill","commentFill","commentStroke","commentTextColor","specialFill","specialStroke","ruleNameColor","showMarkers","markerRadius"]),L=p(e=>e?Object.keys(e).every(i=>i==="railroad"||de.has(i)):!1,"isRailroadStyleOptions"),ce=p(e=>e?"railroad"in e&&e.railroad?e.railroad:L(e)?e:{}:{},"extractRailroadOverrides"),me=p(e=>{if(!e||L(e))return{};const{railroad:i,svgId:a,theme:n,look:t,...r}=e;return r},"extractThemeOverrides"),m=p((e,i)=>{if(typeof e!="string")return i;const a=e.trim();return le.test(a)?a:i},"sanitizeColorValue"),I=p((e,i)=>{if(typeof e!="string")return i;const a=e.trim();return se.test(a)?a:i},"sanitizeFontFamilyValue"),F=p((e,i)=>{const a=typeof e=="number"?e:typeof e=="string"?Number.parseFloat(e):Number.NaN;return Number.isFinite(a)&&a>=0?a:i},"sanitizeNumberValue"),he=p(e=>{const i=typeof e=="number"?e:typeof e=="string"?Number.parseFloat(e):Number.NaN;return Number.isFinite(i)&&i>0?i:void 0},"parseThemeFontSize"),pe=p(e=>{const i=I(e.fontFamily,f.fontFamily),a=he(e.fontSize)??f.fontSize;return{...f,fontFamily:i,fontSize:a,terminalFill:m(e.secondBkg??e.secondaryColor,f.terminalFill),terminalStroke:m(e.secondaryBorderColor??e.lineColor,f.terminalStroke),terminalTextColor:m(e.secondaryTextColor??e.textColor,f.terminalTextColor),nonTerminalFill:m(e.mainBkg??e.background,f.nonTerminalFill),nonTerminalStroke:m(e.primaryBorderColor??e.lineColor,f.nonTerminalStroke),nonTerminalTextColor:m(e.primaryTextColor??e.textColor,f.nonTerminalTextColor),lineColor:m(e.lineColor,f.lineColor),markerFill:m(e.lineColor,f.markerFill),commentFill:m(e.labelBackground??e.tertiaryColor,f.commentFill),commentStroke:m(e.tertiaryBorderColor??e.lineColor,f.commentStroke),commentTextColor:m(e.tertiaryTextColor??e.textColor,f.commentTextColor),specialFill:m(e.tertiaryColor??e.secondaryColor,f.specialFill),specialStroke:m(e.tertiaryBorderColor??e.secondaryBorderColor,f.specialStroke),ruleNameColor:m(e.titleColor??e.textColor,f.ruleNameColor)}},"buildThemeDefaults"),E=p(e=>{const i=B(),a={...G(),...i.themeVariables??{},...me(e)},n=pe(a),t={...i.railroad??{},...ce(e)};return{compactMode:t.compactMode??n.compactMode,padding:F(t.padding,n.padding),verticalSeparation:F(t.verticalSeparation,n.verticalSeparation),horizontalSeparation:F(t.horizontalSeparation,n.horizontalSeparation),arcRadius:F(t.arcRadius,n.arcRadius),fontSize:F(t.fontSize,n.fontSize),fontFamily:I(t.fontFamily,n.fontFamily),terminalFill:m(t.terminalFill,n.terminalFill),terminalStroke:m(t.terminalStroke,n.terminalStroke),terminalTextColor:m(t.terminalTextColor,n.terminalTextColor),nonTerminalFill:m(t.nonTerminalFill,n.nonTerminalFill),nonTerminalStroke:m(t.nonTerminalStroke,n.nonTerminalStroke),nonTerminalTextColor:m(t.nonTerminalTextColor,n.nonTerminalTextColor),lineColor:m(t.lineColor,n.lineColor),strokeWidth:F(t.strokeWidth,n.strokeWidth),markerFill:m(t.markerFill,n.markerFill),commentFill:m(t.commentFill,n.commentFill),commentStroke:m(t.commentStroke,n.commentStroke),commentTextColor:m(t.commentTextColor,n.commentTextColor),specialFill:m(t.specialFill,n.specialFill),specialStroke:m(t.specialStroke,n.specialStroke),ruleNameColor:m(t.ruleNameColor,n.ruleNameColor),showMarkers:t.showMarkers??n.showMarkers,markerRadius:F(t.markerRadius,n.markerRadius)}},"buildRailroadStyleOptions"),Te=p(e=>{const{fontFamily:i,fontSize:a,terminalFill:n,terminalStroke:t,terminalTextColor:r,nonTerminalFill:o,nonTerminalStroke:g,nonTerminalTextColor:l,lineColor:s,strokeWidth:h,markerFill:u,commentFill:c,commentStroke:w,commentTextColor:d,specialFill:T,specialStroke:z,ruleNameColor:S}=E(e);return`
.railroad-diagram {
font-family: ${i};
font-size: ${a}px;
}
.railroad-terminal rect {
fill: ${n};
stroke: ${t};
stroke-width: ${h}px;
}
.railroad-terminal text {
fill: ${r};
font-family: ${i};
font-size: ${a}px;
text-anchor: middle;
dominant-baseline: middle;
}
.railroad-nonterminal rect {
fill: ${o};
stroke: ${g};
stroke-width: ${h}px;
}
.railroad-nonterminal text {
fill: ${l};
font-family: ${i};
font-size: ${a}px;
text-anchor: middle;
dominant-baseline: middle;
}
.railroad-line {
stroke: ${s};
stroke-width: ${h}px;
fill: none;
}
.railroad-start circle,
.railroad-end circle {
fill: ${u};
}
.railroad-comment ellipse {
fill: ${c};
stroke: ${w};
stroke-width: ${h}px;
}
.railroad-comment text {
fill: ${d};
font-style: italic;
font-family: ${i};
font-size: ${a}px;
text-anchor: middle;
dominant-baseline: middle;
}
.railroad-special rect {
fill: ${T};
stroke: ${z};
stroke-width: ${h}px;
stroke-dasharray: 5,3;
}
.railroad-special text {
fill: ${l};
font-family: ${i};
font-size: ${a}px;
text-anchor: middle;
dominant-baseline: middle;
}
.railroad-rule-name {
font-weight: bold;
fill: ${S};
font-family: ${i};
font-size: ${a}px;
}
.railroad-group {
/* Grouping container, no specific styles */
}
`},"getStyles"),R,x=(R=class{constructor(){this.d=""}moveTo(i,a){return this.d+=`M ${i} ${a} `,this}lineTo(i,a){return this.d+=`L ${i} ${a} `,this}horizontalTo(i){return this.d+=`H ${i} `,this}verticalTo(i){return this.d+=`V ${i} `,this}arcTo(i,a,n,t,r,o,g){return this.d+=`A ${i} ${a} ${n} ${t?1:0} ${r?1:0} ${o} ${g} `,this}build(){return this.d.trim()}},p(R,"PathBuilder"),R),$,ue=($=class{constructor(i,a=E()){this.textCache=new Map,this.svg=i,this.config=a}measureText(i){if(this.textCache.has(i))return this.textCache.get(i);const a=this.svg.append("text").attr("font-family",this.config.fontFamily).attr("font-size",this.config.fontSize).text(i),n=a.node().getBBox(),t={width:n.width,height:n.height};return a.remove(),this.textCache.set(i,t),t}renderTerminal(i,a){const n=this.measureText(a),t=n.width+this.config.padding*2,r=n.height+this.config.padding*2,o=i.append("g").attr("class","railroad-terminal");return o.append("rect").attr("x",0).attr("y",0).attr("width",t).attr("height",r).attr("rx",10).attr("ry",10),o.append("text").attr("x",t/2).attr("y",r/2).text(a),{element:o.node(),dimensions:{width:t,height:r,up:r/2,down:r/2}}}renderNonTerminal(i,a){const n=this.measureText(a),t=n.width+this.config.padding*2,r=n.height+this.config.padding*2,o=i.append("g").attr("class","railroad-nonterminal");return o.append("rect").attr("x",0).attr("y",0).attr("width",t).attr("height",r),o.append("text").attr("x",t/2).attr("y",r/2).text(a),{element:o.node(),dimensions:{width:t,height:r,up:r/2,down:r/2}}}renderSequence(i,a){const n=a.map(s=>this.renderExpression(i,s));let t=0,r=0,o=0;for(const s of n)t+=s.dimensions.width,r=Math.max(r,s.dimensions.up),o=Math.max(o,s.dimensions.down);t+=(n.length-1)*this.config.horizontalSeparation;const g=i.append("g").attr("class","railroad-sequence");let l=0;for(let s=0;s<n.length;s++){const h=n[s],u=r-h.dimensions.up;if(g.node().appendChild(h.element).setAttribute("transform",`translate(${l}, ${u})`),s<n.length-1){const w=l+h.dimensions.width,d=w+this.config.horizontalSeparation,T=r;g.append("path").attr("class","railroad-line").attr("d",new x().moveTo(w,T).lineTo(d,T).build())}l+=h.dimensions.width+this.config.horizontalSeparation}return{element:g.node(),dimensions:{width:t,height:r+o,up:r,down:o}}}renderChoice(i,a){const n=a.map(c=>this.renderExpression(i,c));let t=0,r=0;for(const c of n)t=Math.max(t,c.dimensions.width),r+=c.dimensions.height;r+=(n.length-1)*this.config.verticalSeparation;const o=this.config.arcRadius,g=o*4,l=t+g,s=i.append("g").attr("class","railroad-choice");let h=0;const u=r/2;for(const c of n){const w=h,d=w+c.dimensions.up,T=o*2+(t-c.dimensions.width)/2;s.node().appendChild(c.element).setAttribute("transform",`translate(${T}, ${w})`);const S=new x,k=d>u;d===u?S.moveTo(0,u).lineTo(T,d):S.moveTo(0,u).arcTo(o,o,0,!1,k,o,u+(k?o:-o)).lineTo(o,d-(k?o:-o)).arcTo(o,o,0,!1,!k,o*2,d).lineTo(T,d),s.append("path").attr("class","railroad-line").attr("d",S.build());const N=new x,_=T+c.dimensions.width,X=l-o*2;d===u?N.moveTo(_,d).lineTo(l,u):N.moveTo(_,d).lineTo(X,d).arcTo(o,o,0,!1,!k,l-o,d+(k?-o:o)).lineTo(l-o,u+(k?o:-o)).arcTo(o,o,0,!1,k,l,u),s.append("path").attr("class","railroad-line").attr("d",N.build()),h+=c.dimensions.height+this.config.verticalSeparation}return{element:s.node(),dimensions:{width:l,height:r,up:u,down:r-u}}}renderOptional(i,a){const n=this.renderExpression(i,a),t=this.config.arcRadius,r=t*2,o=n.dimensions.width+t*4,g=n.dimensions.height+r,l=i.append("g").attr("class","railroad-optional"),s=t*2,h=r;l.node().appendChild(n.element).setAttribute("transform",`translate(${s}, ${h})`);const c=h+n.dimensions.up,w=new x().moveTo(0,c).lineTo(t*2,c);l.append("path").attr("class","railroad-line").attr("d",w.build());const d=new x().moveTo(s+n.dimensions.width,c).lineTo(o,c);l.append("path").attr("class","railroad-line").attr("d",d.build());const T=new x().moveTo(0,c).arcTo(t,t,0,!1,!1,t,c-t).lineTo(t,t).arcTo(t,t,0,!1,!0,t*2,0).lineTo(o-t*2,0).arcTo(t,t,0,!1,!0,o-t,t).lineTo(o-t,c-t).arcTo(t,t,0,!1,!1,o,c);return l.append("path").attr("class","railroad-line").attr("d",T.build()),{element:l.node(),dimensions:{width:o,height:g,up:c,down:g-c}}}renderRepetition(i,a,n){const t=this.renderExpression(i,a),r=this.config.arcRadius,o=r*2,g=t.dimensions.width+r*4,l=n===0,s=t.dimensions.height+o+(l?o:0),h=i.append("g").attr("class","railroad-repetition"),u=r*2,c=l?o:0;h.node().appendChild(t.element).setAttribute("transform",`translate(${u}, ${c})`);const d=c+t.dimensions.up;h.append("path").attr("class","railroad-line").attr("d",new x().moveTo(0,d).lineTo(r*2,d).build()),h.append("path").attr("class","railroad-line").attr("d",new x().moveTo(u+t.dimensions.width,d).lineTo(g,d).build());const T=c+t.dimensions.height+r,z=new x().moveTo(u+t.dimensions.width,d).arcTo(r,r,0,!1,!0,u+t.dimensions.width+r,d+r).lineTo(u+t.dimensions.width+r,T).arcTo(r,r,0,!1,!0,u+t.dimensions.width,T+r).lineTo(r*2,T+r).arcTo(r,r,0,!1,!0,r,T).lineTo(r,d+r).arcTo(r,r,0,!1,!0,r*2,d);if(h.append("path").attr("cl Line truncated
`+e);try{const n=H(i);n.attr("class","railroad-diagram");const r=B().railroad?.useMaxWidth??!0,o=oe.getRules();if(C.debug(`[Railroad] Rendering ${o.length} rules`),o.length===0){C.warn("[Railroad] No rules to render"),W(n,{height:100,width:200},r);return}const l=new ue(n,E()).renderDiagram(o);W(n,l,r),C.debug("[Railroad] Render complete")}catch(n){throw C.error("[Railroad] Render error:",n),n}},"draw"),xe={draw:ge};export{oe as d,Te as g,xe as r};
+206
View File
@@ -0,0 +1,206 @@
import{g as st}from"./chunk-5VM5RSS4.js";import{g as it}from"./chunk-XXDRQBXY.js";import{s as at}from"./chunk-POPQ4Y6H.js";import{_ as f,l as we,c as F,u as nt,v as rt,x as Ve,j as Ae,O as ut,b as lt,a as ct,s as ot,g as ht,n as dt,o as pt,k as I,p as At,q as ft,i as gt,P as U}from"./mermaid.core.js";import{f as mt}from"./chunk-F27PBJKO.js";var Pe=(function(){var s=f(function(O,o,h,p){for(h=h||{},p=O.length;p--;h[O[p]]=o);return h},"o"),i=[1,18],a=[1,19],n=[1,20],r=[1,41],c=[1,26],u=[1,42],d=[1,24],m=[1,25],g=[1,32],N=[1,33],ge=[1,34],b=[1,45],me=[1,35],Ce=[1,36],be=[1,37],ke=[1,38],Ee=[1,27],Te=[1,28],ye=[1,29],De=[1,30],Fe=[1,31],k=[1,44],E=[1,46],T=[1,43],y=[1,47],Be=[1,9],A=[1,8,9],ee=[1,58],te=[1,59],se=[1,60],ie=[1,61],ae=[1,62],_e=[1,63],Se=[1,64],_=[1,8,9,41],Me=[1,77],R=[1,8,9,12,13,22,39,41,44,46,68,69,70,71,72,73,74,79,81],ne=[1,8,9,12,13,18,20,22,39,41,44,46,47,60,68,69,70,71,72,73,74,79,81,86,100,102,103],re=[13,60,86,100,102,103],Y=[13,60,73,74,86,100,102,103],Re=[13,60,68,69,70,71,72,86,100,102,103],ue=[1,103],K=[1,121],W=[1,117],Q=[1,113],j=[1,119],X=[1,114],q=[1,115],H=[1,116],J=[1,118],Z=[1,120],Ge=[22,50,60,61,82,86,87,88,89,90],Ue=[1,128],le=[12,39],Ne=[1,8,9,39,41,44,46],ce=[1,8,9,22],ze=[1,153],Ye=[1,8,9,61],x=[1,8,9,22,50,60,61,82,86,87,88,89,90],Le={trace:f(function(){},"trace"),yy:{},symbols_:{error:2,start:3,mermaidDoc:4,statements:5,graphConfig:6,CLASS_DIAGRAM:7,NEWLINE:8,EOF:9,statement:10,classLabel:11,SQS:12,STR:13,SQE:14,namespaceName:15,alphaNumToken:16,classLiteralName:17,DOT:18,className:19,GENERICTYPE:20,relationStatement:21,LABEL:22,namespaceStatement:23,classStatement:24,memberStatement:25,annotationStatement:26,clickStatement:27,styleStatement:28,cssClassStatement:29,noteStatement:30,classDefStatement:31,direction:32,acc_title:33,acc_title_value:34,acc_descr:35,acc_descr_value:36,acc_descr_multiline_value:37,namespaceIdentifier:38,STRUCT_START:39,classStatements:40,STRUCT_STOP:41,NAMESPACE:42,classIdentifier:43,STYLE_SEPARATOR:44,members:45,ANNOTATION_START:46,ANNOTATION_END:47,CLASS:48,emptyBody:49,SPACE:50,MEMBER:51,SEPARATOR:52,relation:53,NOTE_FOR:54,noteText:55,NOTE:56,CLASSDEF:57,classList:58,stylesOpt:59,ALPHA:60,COMMA:61,direction_tb:62,direction_bt:63,direction_rl:64,direction_lr:65,relationType:66,lineType:67,AGGREGATION:68,EXTENSION:69,COMPOSITION:70,DEPENDENCY:71,LOLLIPOP:72,LINE:73,DOTTED_LINE:74,CALLBACK:75,LINK:76,LINK_TARGET:77,CLICK:78,CALLBACK_NAME:79,CALLBACK_ARGS:80,HREF:81,STYLE:82,CSSCLASS:83,style:84,styleComponent:85,NUM:86,COLON:87,UNIT:88,BRKT:89,PCT:90,commentToken:91,textToken:92,graphCodeTokens:93,textNoTagsToken:94,TAGSTART:95,TAGEND:96,"==":97,"--":98,DEFAULT:99,MINUS:100,keywords:101,UNICODE_TEXT:102,BQUOTE_STR:103,$accept:0,$end:1},terminals_:{2:"error",7:"CLASS_DIAGRAM",8:"NEWLINE",9:"EOF",12:"SQS",13:"STR",14:"SQE",18:"DOT",20:"GENERICTYPE",22:"LABEL",33:"acc_title",34:"acc_title_value",35:"acc_descr",36:"acc_descr_value",37:"acc_descr_multiline_value",39:"STRUCT_START",41:"STRUCT_STOP",42:"NAMESPACE",44:"STYLE_SEPARATOR",46:"ANNOTATION_START",47:"ANNOTATION_END",48:"CLASS",50:"SPACE",51:"MEMBER",52:"SEPARATOR",54:"NOTE_FOR",56:"NOTE",57:"CLASSDEF",60:"ALPHA",61:"COMMA",62:"direction_tb",63:"direction_bt",64:"direction_rl",65:"direction_lr",68:"AGGREGATION",69:"EXTENSION",70:"COMPOSITION",71:"DEPENDENCY",72:"LOLLIPOP",73:"LINE",74:"DOTTED_LINE",75:"CALLBACK",76:"LINK",77:"LINK_TARGET",78:"CLICK",79:"CALLBACK_NAME",80:"CALLBACK_ARGS",81:"HREF",82:"STYLE",83:"CSSCLASS",86:"NUM",87:"COLON",88:"UNIT",89:"BRKT",90:"PCT",93:"graphCodeTokens",95:"TAGSTART",96:"TAGEND",97:"==",98:"--",99:"DEFAULT",100:"MINUS",101:"keywords",102:"UNICODE_TEXT",103:"BQUOTE_STR"},productions_:[0,[3,1],[3,1],[4,1],[6,4],[5,1],[5,2],[5,3],[11,3],[15,1],[15,1],[15,3],[15,2],[19,1],[19,3],[19,1],[19,2],[19,2],[19,2],[10,1],[10,2],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,2],[10,2],[10,1],[23,4],[23,5],[38,2],[38,3],[40,1],[40,2],[40,3],[40,1],[40,2],[40,3],[40,1],[40,2],[40,3],[24,1],[24,3],[24,4],[24,3],[24,6],[24,4],[24,7],[24,6],[43,2],[43,3],[49,0],[49,2],[49,2],[26,4],[45,1],[45,2],[25,1],[25,2],[25,1],[25,1],[21,3],[21,4],[21,4],[21,5],[30,3],[30,2],[31,3],[58,1],[58,3],[32,1],[32,1],[32,1],[32,1],[53,3],[53,2],[53,2],[53,1],[66,1],[66,1],[66,1],[66,1],[66,1],[67,1],[67,1],[27,3],[27,4],[27,3],[27,4],[27,4],[27,5],[27,3],[27,4],[27,4],[27,5],[27,4],[27,5],[27,5],[27,6],[28,3],[29,3],[59,1],[59,3],[84,1],[84,2],[85,1],[85,1],[85,1],[85,1],[85,1],[85,1],[85,1],[85,1],[85,1],[91,1],[91,1],[92,1],[92,1],[92,1],[92,1],[92,1],[92,1],[92,1],[94,1],[94,1],[94,1],[94,1],[16,1],[16,1],[16,1],[16,1],[17,1],[55,1]],performAction:f(function(o,h,p,l,C,e,$){var t=e.length-1;switch(C){case 8:this.$=e[t-1];break;case 9:case 10:case 13:case 15:this.$=e[t];break;case 11:case 14:this.$=e[t-2]+"."+e[t];break;case 12:case 16:this.$=e[t-1]+e[t];break;case 17:case 18:this.$=e[t-1]+"~"+e[t]+"~";break;case 19:l.addRelation(e[t]);break;case 20:e[t-1].titlLine truncated
`+D.showPosition()+`
Expecting `+pe.join(", ")+", got '"+(this.terminals_[B]||B)+"'":Oe="Parse error on line "+(he+1)+": Unexpected "+(B==We?"end of input":"'"+(this.terminals_[B]||B)+"'"),this.parseError(Oe,{text:D.match,token:this.terminals_[B]||B,line:D.yylineno,loc:ve,expected:pe})}if(L[0]instanceof Array&&L.length>1)throw new Error("Parse Error: multiple actions possible at state: "+P+", token: "+B);switch(L[0]){case 1:p.push(B),C.push(D.yytext),e.push(D.yylloc),p.push(L[1]),B=null,Ke=D.yyleng,t=D.yytext,he=D.yylineno,ve=D.yylloc;break;case 2:if(v=this.productions_[L[1]][1],G.$=C[C.length-v],G._$={first_line:e[e.length-(v||1)].first_line,last_line:e[e.length-1].last_line,first_column:e[e.length-(v||1)].first_column,last_column:e[e.length-1].last_column},et&&(G._$.range=[e[e.length-(v||1)].range[0],e[e.length-1].range[1]]),Ie=this.performAction.apply(G,[t,Ke,he,V.yy,L[1],C,e].concat($e)),typeof Ie<"u")return Ie;v&&(p=p.slice(0,-1*v*2),C=C.slice(0,-1*v),e=e.slice(0,-1*v)),p.push(this.productions_[L[1]][0]),C.push(G.$),e.push(G._$),je=$[p[p.length-2]][p[p.length-1]],p.push(je);break;case 3:return!0}}return!0},"parse")},Je=(function(){var O={EOF:1,parseError:f(function(h,p){if(this.yy.parser)this.yy.parser.parseError(h,p);else throw new Error(h)},"parseError"),setInput:f(function(o,h){return this.yy=h||this.yy||{},this._input=o,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:f(function(){var o=this._input[0];this.yytext+=o,this.yyleng++,this.offset++,this.match+=o,this.matched+=o;var h=o.match(/(?:\r\n?|\n).*/g);return h?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),o},"input"),unput:f(function(o){var h=o.length,p=o.split(/(?:\r\n?|\n)/g);this._input=o+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-h),this.offset-=h;var l=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),p.length-1&&(this.yylineno-=p.length-1);var C=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:p?(p.length===l.length?this.yylloc.first_column:0)+l[l.length-p.length].length-p[0].length:this.yylloc.first_column-h},this.options.ranges&&(this.yylloc.range=[C[0],C[0]+this.yyleng-h]),this.yyleng=this.yytext.length,this},"unput"),more:f(function(){return this._more=!0,this},"more"),reject:f(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:f(function(o){this.unput(this.match.slice(o))},"less"),pastInput:f(function(){var o=this.matched.substr(0,this.matched.length-this.match.length);return(o.length>20?"...":"")+o.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:f(function(){var o=this.match;return o.length<20&&(o+=this._input.substr(0,20-o.length)),(o.substr(0,20)+(o.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:f(function(){var o=this.pastInput(),h=new Array(o.length+1).join("-");return o+this.upcomingInput()+`
`+h+"^"},"showPosition"),test_match:f(function(o,h){var p,l,C;if(this.options.backtrack_lexer&&(C={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(C.yylloc.range=this.yylloc.range.slice(0))),l=o[0].match(/(?:\r\n?|\n).*/g),l&&(this.yylineno+=l.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:l?l[l.length-1].length-l[l.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+o[0].length},this.yytext+=o[0],this.match+=o[0],this.matches=o,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(o[0].length),this.matched+=o[0],p=this.performAction.call(this,this.yy,this,h,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),p)return p;if(this._backtrack){for(var e in C)this[e]=C[e];return!1}return!1},"test_match"),next:f(function(){if(this.done)return this.EOF;this._input||(this.done=!0);var o,h,p,l;this._more||(this.yytext="",this.match="");for(var C=this._currentRules(),e=0;e<C.length;e++)if(p=this._input.match(this.rules[C[e]]),p&&(!h||p[0].length>h[0].length)){if(h=p,l=e,this.options.backtrack_lexer){if(o=this.test_match(p,C[e]),o!==!1)return o;if(this._backtrack){h=!1;continue}else return!1}else if(!this.options.flex)break}return h?(o=this.test_match(h,C[l]),o!==!1?o:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text.
`+this.showPosition(),{text:"",token:null,line:this.yylineno})},"next"),lex:f(function(){var h=this.next();return h||this.lex()},"lex"),begin:f(function(h){this.conditionStack.push(h)},"begin"),popState:f(function(){var h=this.conditionStack.length-1;return h>0?this.conditionStack.pop():this.conditionStack[0]},"popState"),_currentRules:f(function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},"_currentRules"),topState:f(function(h){return h=this.conditionStack.length-1-Math.abs(h||0),h>=0?this.conditionStack[h]:"INITIAL"},"topState"),pushState:f(function(h){this.begin(h)},"pushState"),stateStackSize:f(function(){return this.conditionStack.length},"stateStackSize"),options:{},performAction:f(function(h,p,l,C){switch(l){case 0:return 62;case 1:return 63;case 2:return 64;case 3:return 65;case 4:break;case 5:break;case 6:return this.begin("acc_title"),33;case 7:return this.popState(),"acc_title_value";case 8:return this.begin("acc_descr"),35;case 9:return this.popState(),"acc_descr_value";case 10:this.begin("acc_descr_multiline");break;case 11:this.popState();break;case 12:return"acc_descr_multiline_value";case 13:return 8;case 14:break;case 15:return 7;case 16:return 7;case 17:return"EDGE_STATE";case 18:this.begin("callback_name");break;case 19:this.popState();break;case 20:this.popState(),this.begin("callback_args");break;case 21:return 79;case 22:this.popState();break;case 23:return 80;case 24:this.popState();break;case 25:return"STR";case 26:this.begin("string");break;case 27:return 82;case 28:return 57;case 29:return this.begin("namespace"),42;case 30:return this.popState(),8;case 31:break;case 32:return this.begin("namespace-body"),39;case 33:this.popState(),this.less(0);break;case 34:return this.popState(),41;case 35:return"EOF_IN_STRUCT";case 36:return 8;case 37:break;case 38:return"EDGE_STATE";case 39:return this.begin("class"),48;case 40:return this.popState(),8;case 41:break;case 42:return this.popState(),this.popState(),41;case 43:return this.begin("class-body"),39;case 44:return this.popState(),41;case 45:return"EOF_IN_STRUCT";case 46:return"EDGE_STATE";case 47:return"OPEN_IN_STRUCT";case 48:break;case 49:return"MEMBER";case 50:return 83;case 51:return 75;case 52:return 76;case 53:return 78;case 54:return 54;case 55:return 56;case 56:return 46;case 57:return 47;case 58:return 81;case 59:this.popState();break;case 60:return"GENERICTYPE";case 61:this.begin("generic");break;case 62:this.popState();break;case 63:return"BQUOTE_STR";case 64:this.begin("bqstring");break;case 65:return 77;case 66:return 77;case 67:return 77;case 68:return 77;case 69:return 69;case 70:return 69;case 71:return 71;case 72:return 71;case 73:return 70;case 74:return 68;case 75:return 72;case 76:return 73;case 77:return 74;case 78:return 22;case 79:return 44;case 80:return 100;case 81:return 18;case 82:return"PLUS";case 83:return 87;case 84:return 61;case 85:return 89;case 86:return 89;case 87:return 90;case 88:return"EQUALS";case 89:return"EQUALS";case 90:return 60;case 91:return 12;case 92:return 14;case 93:return"PUNCTUATION";case 94:return 86;case 95:return 102;case 96:return 50;case 97:return 50;case 98:return 9}},"anonymous"),rules:[/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:%%(?!\{)*[^\n]*(\r?\n?)+)/,/^(?:%%[^\n]*(\r?\n)*)/,/^(?:accTitle\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*\{\s*)/,/^(?:[\}])/,/^(?:[^\}]*)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:classDiagram-v2\b)/,/^(?:classDiagram\b)/,/^(?:\[\*\])/,/^(?:call[\s]+)/,/^(?:\([\s]*\))/,/^(?:\()/,/^(?:[^(]*)/,/^(?:\))/,/^(?:[^)]*)/,/^(?:["])/,/^(?:[^"]*)/,/^(?:["])/,/^(?:style\b)/,/^(?:classDef\b)/,/^(?:namespace\b)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:[{])/,/^(?:[}])/,/^(?:[}])/,/^(?:$)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:\[\*\])/,/^(?:class\b)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:[}])/,/^(?:[{])/,/^(?:[}])/,/^(?:$)/,/^(?:\[\*\])/,/^(?:[{])/,/^(?:[\n])/,/^(?:[^{}\n]*)/,/^(?:cssClass\b)/,/^(?:callback\b)/,/^(?:link\b)/,/^(?:click\b)/,/^(?:note for\b)/,/^(?:note\b)/,/^(?:<<)/,/^(?:>>)/,/^(?:href\b)/,/^(?:[~])/,/^(?:[^~]*)/,/^(?:~)/,/^(?:[`])/,/^(?:[^`]+)/,/^(?:[`])/,/^(?:_self\b)/,/^(?:_blank\b)/,/^(?:_parent\b)/,/^(?:_top\b)/,/^(?:\s*<\|)/,/^(?:\s*\|>)/,/^(?:\s*>)/,/^(?:\s*<)/,/^(?:\s*\*)/,/^(?:\s*o\b)/,/^(?:\s*\(\))/,/^(?:--)/,/^(?:\.\.)/,/^(?::{1}[^:\n;]+)/,/^(?::{3})/,/^(?:-)/,/^(?:\.)/,/^(?:\+)/,/^(?::)/,/^(?:,)/,/^(?:#)/,/^(?:#)/,/^(?:%)/,/^(?:=)/,/^(?:=)/,/^(?:\w+)/,/^(?:\[)/,/^(?:\])/,/^(?:[!"#$%&'*+,-.`?\\/])/,/^(?:[0-9]+)/,/^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\uLine truncated
fill: ${s.nodeBorder||s.classText};
stroke: none;
font-family: ${s.fontFamily};
font-size: 10px;
.title {
font-weight: bolder;
}
}
.cluster-label text {
fill: ${s.titleColor};
}
.cluster-label span {
color: ${s.titleColor};
}
.cluster-label span p {
background-color: transparent;
}
.cluster rect {
fill: ${s.clusterBkg};
stroke: ${s.clusterBorder};
stroke-width: 1px;
}
.cluster text {
fill: ${s.titleColor};
}
.cluster span {
color: ${s.titleColor};
}
.nodeLabel, .edgeLabel {
color: ${s.classText};
}
.noteLabel .nodeLabel, .noteLabel .edgeLabel {
color: ${s.noteTextColor};
}
.edgeLabel .label rect {
fill: ${s.mainBkg};
}
.label text {
fill: ${s.classText};
}
.labelBkg {
background: ${s.mainBkg};
}
.edgeLabel .label span {
background: ${s.mainBkg};
}
.classTitle {
font-weight: bolder;
}
.node rect,
.node circle,
.node ellipse,
.node polygon,
.node path {
fill: ${s.mainBkg};
stroke: ${s.nodeBorder};
stroke-width: ${s.strokeWidth};
}
.divider {
stroke: ${s.nodeBorder};
stroke-width: 1;
}
g.clickable {
cursor: pointer;
}
g.classGroup rect {
fill: ${s.mainBkg};
stroke: ${s.nodeBorder};
}
g.classGroup line {
stroke: ${s.nodeBorder};
stroke-width: 1;
}
.classLabel .box {
stroke: none;
stroke-width: 0;
fill: ${s.mainBkg};
opacity: 0.5;
}
.classLabel .label {
fill: ${s.nodeBorder};
font-size: 10px;
}
.relation {
stroke: ${s.lineColor};
stroke-width: ${s.strokeWidth};
fill: none;
}
.dashed-line{
stroke-dasharray: 3;
}
.dotted-line{
stroke-dasharray: 1 2;
}
[id$="-compositionStart"], .composition {
fill: ${s.lineColor} !important;
stroke: ${s.lineColor} !important;
stroke-width: 1;
}
[id$="-compositionEnd"], .composition {
fill: ${s.lineColor} !important;
stroke: ${s.lineColor} !important;
stroke-width: 1;
}
[id$="-dependencyStart"], .dependency {
fill: ${s.lineColor} !important;
stroke: ${s.lineColor} !important;
stroke-width: 1;
}
[id$="-dependencyEnd"], .dependency {
fill: ${s.lineColor} !important;
stroke: ${s.lineColor} !important;
stroke-width: 1;
}
[id$="-extensionStart"], .extension {
fill: transparent !important;
stroke: ${s.lineColor} !important;
stroke-width: 1;
}
[id$="-extensionEnd"], .extension {
fill: transparent !important;
stroke: ${s.lineColor} !important;
stroke-width: 1;
}
[id$="-aggregationStart"], .aggregation {
fill: transparent !important;
stroke: ${s.lineColor} !important;
stroke-width: 1;
}
[id$="-aggregationEnd"], .aggregation {
fill: transparent !important;
stroke: ${s.lineColor} !important;
stroke-width: 1;
}
[id$="-lollipopStart"], .lollipop {
fill: ${s.mainBkg} !important;
stroke: ${s.lineColor} !important;
stroke-width: 1;
}
[id$="-lollipopEnd"], .lollipop {
fill: ${s.mainBkg} !important;
stroke: ${s.lineColor} !important;
stroke-width: 1;
}
.edgeTerminals {
font-size: 11px;
line-height: initial;
}
.classTitleText {
text-anchor: middle;
font-size: 18px;
fill: ${s.textColor};
}
.edgeLabel[data-look="neo"] {
background-color: ${s.edgeLabelBackground};
p {
background-color: ${s.edgeLabelBackground};
}
rect {
opacity: 0.5;
background-color: ${s.edgeLabelBackground};
fill: ${s.edgeLabelBackground};
}
text-align: center;
}
${st()}
`,"getStyles"),Nt=Ct,bt=f((s,i="TB")=>{if(!s.doc)return i;let a=i;for(const n of s.doc)n.stmt==="dir"&&(a=n.value);return a},"getDir"),kt=f(function(s,i){return i.db.getClasses()},"getClasses"),Et=f(async function(s,i,a,n){we.info("REF0:"),we.info("Drawing class diagram (v3)",i);const{securityLevel:r,state:c,layout:u}=F();n.db.setDiagramId(i);const d=n.db.getData(),m=it(i,r);d.type=n.type,d.layoutAlgorithm=nt(u),d.nodeSpacing=c?.nodeSpacing||50,d.rankSpacing=c?.rankSpacing||50,d.markers=["aggregation","extension","composition","dependency","lollipop"],d.diagramId=i,await rt(d,m);const g=8;Ve.insertTitle(m,"classDiagramTitleText",c?.titleTopMargin??25,n.db.getDiagramTitle()),at(m,g,"classDiagram",c?.useMaxWidth??!0)},"draw"),Lt={getClasses:kt,draw:Et,getDir:bt};export{St as C,_t as a,Lt as c,Nt as s};
+1
View File
@@ -0,0 +1 @@
import{_ as a,j as o}from"./mermaid.core.js";var g=a((t,e)=>{let n;return e==="sandbox"&&(n=o("#i"+t)),(e==="sandbox"?o(n.nodes()[0].contentDocument.body):o("body")).select(`[id="${t}"]`)},"getDiagramElement");export{g};
+1
View File
@@ -0,0 +1 @@
import{s as a,c as s,a as e,C as t}from"./chunk-TICWLB2K.js";import{_ as i}from"./mermaid.core.js";import"./chunk-5VM5RSS4.js";import"./chunk-XXDRQBXY.js";import"./chunk-POPQ4Y6H.js";import"./chunk-F27PBJKO.js";import"./index.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
+1
View File
@@ -0,0 +1 @@
import{s as a,c as s,a as e,C as t}from"./chunk-TICWLB2K.js";import{_ as i}from"./mermaid.core.js";import"./chunk-5VM5RSS4.js";import"./chunk-XXDRQBXY.js";import"./chunk-POPQ4Y6H.js";import"./chunk-F27PBJKO.js";import"./index.js";var n={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{n as diagram};
@@ -1 +1 @@
var b;(function(s){s.assertEqual=n=>{};function e(n){}s.assertIs=e;function t(n){throw new Error}s.assertNever=t,s.arrayToEnum=n=>{const i={};for(const a of n)i[a]=a;return i},s.getValidEnumValues=n=>{const i=s.objectKeys(n).filter(o=>typeof n[n[o]]!="number"),a={};for(const o of i)a[o]=n[o];return s.objectValues(a)},s.objectValues=n=>s.objectKeys(n).map(function(i){return n[i]}),s.objectKeys=typeof Object.keys=="function"?n=>Object.keys(n):n=>{const i=[];for(const a in n)Object.prototype.hasOwnProperty.call(n,a)&&i.push(a);return i},s.find=(n,i)=>{for(const a of n)if(i(a))return a},s.isInteger=typeof Number.isInteger=="function"?n=>Number.isInteger(n):n=>typeof n=="number"&&Number.isFinite(n)&&Math.floor(n)===n;function r(n,i=" | "){return n.map(a=>typeof a=="string"?`'${a}'`:a).join(i)}s.joinValues=r,s.jsonStringifyReplacer=(n,i)=>typeof i=="bigint"?i.toString():i})(b||(b={}));var Ie;(function(s){s.mergeShapes=(e,t)=>({...e,...t})})(Ie||(Ie={}));const f=b.arrayToEnum(["string","nan","number","integer","float","boolean","date","bigint","symbol","function","undefined","null","array","object","unknown","promise","void","never","map","set"]),I=s=>{switch(typeof s){case"undefined":return f.undefined;case"string":return f.string;case"number":return Number.isNaN(s)?f.nan:f.number;case"boolean":return f.boolean;case"function":return f.function;case"bigint":return f.bigint;case"symbol":return f.symbol;case"object":return Array.isArray(s)?f.array:s===null?f.null:s.then&&typeof s.then=="function"&&s.catch&&typeof s.catch=="function"?f.promise:typeof Map<"u"&&s instanceof Map?f.map:typeof Set<"u"&&s instanceof Set?f.set:typeof Date<"u"&&s instanceof Date?f.date:f.object;default:return f.unknown}},c=b.arrayToEnum(["invalid_type","invalid_literal","custom","invalid_union","invalid_union_discriminator","invalid_enum_value","unrecognized_keys","invalid_arguments","invalid_return_type","invalid_date","invalid_string","too_small","too_big","invalid_intersection_types","not_multiple_of","not_finite"]);class T extends Error{get errors(){return this.issues}constructor(e){super(),this.issues=[],this.addIssue=r=>{this.issues=[...this.issues,r]},this.addIssues=(r=[])=>{this.issues=[...this.issues,...r]};const t=new.target.prototype;Object.setPrototypeOf?Object.setPrototypeOf(this,t):this.__proto__=t,this.name="ZodError",this.issues=e}format(e){const t=e||function(i){return i.message},r={_errors:[]},n=i=>{for(const a of i.issues)if(a.code==="invalid_union")a.unionErrors.map(n);else if(a.code==="invalid_return_type")n(a.returnTypeError);else if(a.code==="invalid_arguments")n(a.argumentsError);else if(a.path.length===0)r._errors.push(t(a));else{let o=r,l=0;for(;l<a.path.length;){const d=a.path[l];l===a.path.length-1?(o[d]=o[d]||{_errors:[]},o[d]._errors.push(t(a))):o[d]=o[d]||{_errors:[]},o=o[d],l++}}};return n(this),r}static assert(e){if(!(e instanceof T))throw new Error(`Not a ZodError: ${e}`)}toString(){return this.message}get message(){return JSON.stringify(this.issues,b.jsonStringifyReplacer,2)}get isEmpty(){return this.issues.length===0}flatten(e=t=>t.message){const t={},r=[];for(const n of this.issues)if(n.path.length>0){const i=n.path[0];t[i]=t[i]||[],t[i].push(e(n))}else r.push(e(n));return{formErrors:r,fieldErrors:t}}get formErrors(){return this.flatten()}}T.create=s=>new T(s);const _e=(s,e)=>{let t;switch(s.code){case c.invalid_type:s.received===f.undefined?t="Required":t=`Expected ${s.expected}, received ${s.received}`;break;case c.invalid_literal:t=`Invalid literal value, expected ${JSON.stringify(s.expected,b.jsonStringifyReplacer)}`;break;case c.unrecognized_keys:t=`Unrecognized key(s) in object: ${b.joinValues(s.keys,", ")}`;break;case c.invalid_union:t="Invalid input";break;case c.invalid_union_discriminator:t=`Invalid discriminator value. Expected ${b.joinValues(s.options)}`;break;case c.invalid_enum_value:t=`Invalid enum value. Expected ${b.joinValues(s.options)}, received '${s.received}'`;break;case c.invalid_arguments:t="Invalid function arguments";break;case c.invalid_return_type:t="Invalid function return type";break;case c.invalid_date:t="Invalid date";break;case c.invalid_string:typeof s.validation=="object"?"includes"in s.validation?(t=`Invalid input: must include "${s.validation.includes}"`,typeof s.validation.position=="number"&&(t=`${t} at one or more positions greater than or equal to ${s.validation.position}`)):"startsWith"in s.validation?t=`Invalid input: must start with "${s.validation.startsWith}"`:"endsWith"in s.validation?t=`Invalid input: must end with "${s.validation.endsWith}"`:b.assertNever(s.validation):s.validation!=="regex"?t=`Invalid ${s.validation}`:t="Invalid";break;case c.too_small:s.type==="array"?t=`Array must contain ${s.exact?"exactly":s.inclusive?"at least":"more than"} ${s.minimum} element(s)`:s.type==="string"?t=`String must contain ${s.exact?"exactly":s.inclusive?"at least":"over"} ${s.minimum} character(s)`:s.type==="number"?t=`Number must be ${s.exact?"exactly equal to ":s.iLine truncated
var b;(function(s){s.assertEqual=n=>{};function e(n){}s.assertIs=e;function t(n){throw new Error}s.assertNever=t,s.arrayToEnum=n=>{const i={};for(const a of n)i[a]=a;return i},s.getValidEnumValues=n=>{const i=s.objectKeys(n).filter(o=>typeof n[n[o]]!="number"),a={};for(const o of i)a[o]=n[o];return s.objectValues(a)},s.objectValues=n=>s.objectKeys(n).map(function(i){return n[i]}),s.objectKeys=typeof Object.keys=="function"?n=>Object.keys(n):n=>{const i=[];for(const a in n)Object.prototype.hasOwnProperty.call(n,a)&&i.push(a);return i},s.find=(n,i)=>{for(const a of n)if(i(a))return a},s.isInteger=typeof Number.isInteger=="function"?n=>Number.isInteger(n):n=>typeof n=="number"&&Number.isFinite(n)&&Math.floor(n)===n;function r(n,i=" | "){return n.map(a=>typeof a=="string"?`'${a}'`:a).join(i)}s.joinValues=r,s.jsonStringifyReplacer=(n,i)=>typeof i=="bigint"?i.toString():i})(b||(b={}));var Ie;(function(s){s.mergeShapes=(e,t)=>({...e,...t})})(Ie||(Ie={}));const f=b.arrayToEnum(["string","nan","number","integer","float","boolean","date","bigint","symbol","function","undefined","null","array","object","unknown","promise","void","never","map","set"]),I=s=>{switch(typeof s){case"undefined":return f.undefined;case"string":return f.string;case"number":return Number.isNaN(s)?f.nan:f.number;case"boolean":return f.boolean;case"function":return f.function;case"bigint":return f.bigint;case"symbol":return f.symbol;case"object":return Array.isArray(s)?f.array:s===null?f.null:s.then&&typeof s.then=="function"&&s.catch&&typeof s.catch=="function"?f.promise:typeof Map<"u"&&s instanceof Map?f.map:typeof Set<"u"&&s instanceof Set?f.set:typeof Date<"u"&&s instanceof Date?f.date:f.object;default:return f.unknown}},c=b.arrayToEnum(["invalid_type","invalid_literal","custom","invalid_union","invalid_union_discriminator","invalid_enum_value","unrecognized_keys","invalid_arguments","invalid_return_type","invalid_date","invalid_string","too_small","too_big","invalid_intersection_types","not_multiple_of","not_finite"]);class T extends Error{get errors(){return this.issues}constructor(e){super(),this.issues=[],this.addIssue=r=>{this.issues=[...this.issues,r]},this.addIssues=(r=[])=>{this.issues=[...this.issues,...r]};const t=new.target.prototype;Object.setPrototypeOf?Object.setPrototypeOf(this,t):this.__proto__=t,this.name="ZodError",this.issues=e}format(e){const t=e||function(i){return i.message},r={_errors:[]},n=i=>{for(const a of i.issues)if(a.code==="invalid_union")a.unionErrors.map(n);else if(a.code==="invalid_return_type")n(a.returnTypeError);else if(a.code==="invalid_arguments")n(a.argumentsError);else if(a.path.length===0)r._errors.push(t(a));else{let o=r,l=0;for(;l<a.path.length;){const d=a.path[l];l===a.path.length-1?(o[d]=o[d]||{_errors:[]},o[d]._errors.push(t(a))):o[d]=o[d]||{_errors:[]},o=o[d],l++}}};return n(this),r}static assert(e){if(!(e instanceof T))throw new Error(`Not a ZodError: ${e}`)}toString(){return this.message}get message(){return JSON.stringify(this.issues,b.jsonStringifyReplacer,2)}get isEmpty(){return this.issues.length===0}flatten(e=t=>t.message){const t={},r=[];for(const n of this.issues)if(n.path.length>0){const i=n.path[0];t[i]=t[i]||[],t[i].push(e(n))}else r.push(e(n));return{formErrors:r,fieldErrors:t}}get formErrors(){return this.flatten()}}T.create=s=>new T(s);const _e=(s,e)=>{let t;switch(s.code){case c.invalid_type:s.received===f.undefined?t="Required":t=`Expected ${s.expected}, received ${s.received}`;break;case c.invalid_literal:t=`Invalid literal value, expected ${JSON.stringify(s.expected,b.jsonStringifyReplacer)}`;break;case c.unrecognized_keys:t=`Unrecognized key(s) in object: ${b.joinValues(s.keys,", ")}`;break;case c.invalid_union:t="Invalid input";break;case c.invalid_union_discriminator:t=`Invalid discriminator value. Expected ${b.joinValues(s.options)}`;break;case c.invalid_enum_value:t=`Invalid enum value. Expected ${b.joinValues(s.options)}, received '${s.received}'`;break;case c.invalid_arguments:t="Invalid function arguments";break;case c.invalid_return_type:t="Invalid function return type";break;case c.invalid_date:t="Invalid date";break;case c.invalid_string:typeof s.validation=="object"?"includes"in s.validation?(t=`Invalid input: must include "${s.validation.includes}"`,typeof s.validation.position=="number"&&(t=`${t} at one or more positions greater than or equal to ${s.validation.position}`)):"startsWith"in s.validation?t=`Invalid input: must start with "${s.validation.startsWith}"`:"endsWith"in s.validation?t=`Invalid input: must end with "${s.validation.endsWith}"`:b.assertNever(s.validation):s.validation!=="regex"?t=`Invalid ${s.validation}`:t="Invalid";break;case c.too_small:s.type==="array"?t=`Array must contain ${s.exact?"exactly":s.inclusive?"at least":"more than"} ${s.minimum} element(s)`:s.type==="string"?t=`String must contain ${s.exact?"exactly":s.inclusive?"at least":"over"} ${s.minimum} character(s)`:s.type==="number"?t=`Number must be ${s.exact?"exactly equal to ":s.iLine truncated
+1
View File
@@ -0,0 +1 @@
import{_ as V,l as $,j as lt}from"./mermaid.core.js";import{c as tt}from"./cytoscape.esm.js";import{g as gt}from"./index.js";var k={exports:{}},Z={exports:{}},Q={exports:{}},ut=Q.exports,q;function ft(){return q||(q=1,(function(G,b){(function(I,L){G.exports=L()})(ut,function(){return(function(N){var I={};function L(o){if(I[o])return I[o].exports;var e=I[o]={i:o,l:!1,exports:{}};return N[o].call(e.exports,e,e.exports,L),e.l=!0,e.exports}return L.m=N,L.c=I,L.i=function(o){return o},L.d=function(o,e,t){L.o(o,e)||Object.defineProperty(o,e,{configurable:!1,enumerable:!0,get:t})},L.n=function(o){var e=o&&o.__esModule?function(){return o.default}:function(){return o};return L.d(e,"a",e),e},L.o=function(o,e){return Object.prototype.hasOwnProperty.call(o,e)},L.p="",L(L.s=26)})([(function(N,I,L){function o(){}o.QUALITY=1,o.DEFAULT_CREATE_BENDS_AS_NEEDED=!1,o.DEFAULT_INCREMENTAL=!1,o.DEFAULT_ANIMATION_ON_LAYOUT=!0,o.DEFAULT_ANIMATION_DURING_LAYOUT=!1,o.DEFAULT_ANIMATION_PERIOD=50,o.DEFAULT_UNIFORM_LEAF_NODE_SIZES=!1,o.DEFAULT_GRAPH_MARGIN=15,o.NODE_DIMENSIONS_INCLUDE_LABELS=!1,o.SIMPLE_NODE_SIZE=40,o.SIMPLE_NODE_HALF_SIZE=o.SIMPLE_NODE_SIZE/2,o.EMPTY_COMPOUND_NODE_SIZE=40,o.MIN_EDGE_LENGTH=1,o.WORLD_BOUNDARY=1e6,o.INITIAL_WORLD_BOUNDARY=o.WORLD_BOUNDARY/1e3,o.WORLD_CENTER_X=1200,o.WORLD_CENTER_Y=900,N.exports=o}),(function(N,I,L){var o=L(2),e=L(8),t=L(9);function i(g,n,d){o.call(this,d),this.isOverlapingSourceAndTarget=!1,this.vGraphObject=d,this.bendpoints=[],this.source=g,this.target=n}i.prototype=Object.create(o.prototype);for(var l in o)i[l]=o[l];i.prototype.getSource=function(){return this.source},i.prototype.getTarget=function(){return this.target},i.prototype.isInterGraph=function(){return this.isInterGraph},i.prototype.getLength=function(){return this.length},i.prototype.isOverlapingSourceAndTarget=function(){return this.isOverlapingSourceAndTarget},i.prototype.getBendpoints=function(){return this.bendpoints},i.prototype.getLca=function(){return this.lca},i.prototype.getSourceInLca=function(){return this.sourceInLca},i.prototype.getTargetInLca=function(){return this.targetInLca},i.prototype.getOtherEnd=function(g){if(this.source===g)return this.target;if(this.target===g)return this.source;throw"Node is not incident with this edge"},i.prototype.getOtherEndInGraph=function(g,n){for(var d=this.getOtherEnd(g),r=n.getGraphManager().getRoot();;){if(d.getOwner()==n)return d;if(d.getOwner()==r)break;d=d.getOwner().getParent()}return null},i.prototype.updateLength=function(){var g=new Array(4);this.isOverlapingSourceAndTarget=e.getIntersection(this.target.getRect(),this.source.getRect(),g),this.isOverlapingSourceAndTarget||(this.lengthX=g[0]-g[2],this.lengthY=g[1]-g[3],Math.abs(this.lengthX)<1&&(this.lengthX=t.sign(this.lengthX)),Math.abs(this.lengthY)<1&&(this.lengthY=t.sign(this.lengthY)),this.length=Math.sqrt(this.lengthX*this.lengthX+this.lengthY*this.lengthY))},i.prototype.updateLengthSimple=function(){this.lengthX=this.target.getCenterX()-this.source.getCenterX(),this.lengthY=this.target.getCenterY()-this.source.getCenterY(),Math.abs(this.lengthX)<1&&(this.lengthX=t.sign(this.lengthX)),Math.abs(this.lengthY)<1&&(this.lengthY=t.sign(this.lengthY)),this.length=Math.sqrt(this.lengthX*this.lengthX+this.lengthY*this.lengthY)},N.exports=i}),(function(N,I,L){function o(e){this.vGraphObject=e}N.exports=o}),(function(N,I,L){var o=L(2),e=L(10),t=L(13),i=L(0),l=L(16),g=L(4);function n(r,h,a,p){a==null&&p==null&&(p=h),o.call(this,p),r.graphManager!=null&&(r=r.graphManager),this.estimatedSize=e.MIN_VALUE,this.inclusionTreeDepth=e.MAX_VALUE,this.vGraphObject=p,this.edges=[],this.graphManager=r,a!=null&&h!=null?this.rect=new t(h.x,h.y,a.width,a.height):this.rect=new t}n.prototype=Object.create(o.prototype);for(var d in o)n[d]=o[d];n.prototype.getEdges=function(){return this.edges},n.prototype.getChild=function(){return this.child},n.prototype.getOwner=function(){return this.owner},n.prototype.getWidth=function(){return this.rect.width},n.prototype.setWidth=function(r){this.rect.width=r},n.prototype.getHeight=function(){return this.rect.height},n.prototype.setHeight=function(r){this.rect.height=r},n.prototype.getCenterX=function(){return this.rect.x+this.rect.width/2},n.prototype.getCenterY=function(){return this.rect.y+this.rect.height/2},n.prototype.getCenter=function(){return new g(this.rect.x+this.rect.width/2,this.rect.y+this.rect.height/2)},n.prototype.getLocation=function(){return new g(this.rect.x,this.rect.y)},n.prototype.getRect=function(){return this.rect},n.prototype.getDiagonal=function(){return Math.sqrt(this.rect.width*this.rect.width+this.rect.height*this.rect.height)},n.prototype.getHalfTheDiagonal=function(){return Math.sqrt(this.rect.height*this.rect.height+this.rect.width*this.rect.width)/2},n.prototype.setRect=function(r,h){this.rect.x=r.x,this.rect.y=r.y,this.rect.width=h.width,this.rect.height=h.height},n.prototype.setCenter=function(r,h){this.rect.x=r-this.rect.width/2,this.rect.y=h-this.rect.height/2},nLine truncated
+166
View File
@@ -0,0 +1,166 @@
import{_ as ut}from"./index.js";var fk=Object.create,Lu=Object.defineProperty,dk=Object.getOwnPropertyDescriptor,vh=Object.getOwnPropertyNames,pk=Object.getPrototypeOf,mk=Object.prototype.hasOwnProperty,s=(t,e)=>Lu(t,"name",{value:e,configurable:!0}),hk=(t,e)=>function(){return t&&(e=(0,t[vh(t)[0]])(t=0)),e},X=(t,e)=>function(){return e||(0,t[vh(t)[0]])((e={exports:{}}).exports,e),e.exports},en=(t,e)=>{for(var r in e)Lu(t,r,{get:e[r],enumerable:!0})},Th=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of vh(e))!mk.call(t,a)&&a!==r&&Lu(t,a,{get:()=>e[a],enumerable:!(n=dk(e,a))||n.enumerable});return t},kf=(t,e,r)=>(Th(t,e,"default"),r),$h=(t,e,r)=>(r=t!=null?fk(pk(t)):{},Th(Lu(r,"default",{value:t,enumerable:!0}),t)),Rh=t=>Th(Lu({},"__esModule",{value:!0}),t),Of={};en(Of,{AnnotatedTextEdit:()=>Ar,ChangeAnnotation:()=>pn,ChangeAnnotationIdentifier:()=>et,CodeAction:()=>Zp,CodeActionContext:()=>Jp,CodeActionKind:()=>Xp,CodeActionTriggerKind:()=>Yl,CodeDescription:()=>wp,CodeLens:()=>Qp,Color:()=>Ac,ColorInformation:()=>Ap,ColorPresentation:()=>Ep,Command:()=>dn,CompletionItem:()=>Gp,CompletionItemKind:()=>kp,CompletionItemLabelDetails:()=>Mp,CompletionItemTag:()=>Lp,CompletionList:()=>Fp,CreateFile:()=>ba,DeleteFile:()=>Sa,Diagnostic:()=>Wl,DiagnosticRelatedInformation:()=>Ec,DiagnosticSeverity:()=>_p,DiagnosticTag:()=>Sp,DocumentHighlight:()=>Kp,DocumentHighlightKind:()=>Up,DocumentLink:()=>tm,DocumentSymbol:()=>Yp,DocumentUri:()=>Tp,EOL:()=>x$,FoldingRange:()=>bp,FoldingRangeKind:()=>Cp,FormattingOptions:()=>em,Hover:()=>zp,InlayHint:()=>cm,InlayHintKind:()=>_c,InlayHintLabelPart:()=>Sc,InlineCompletionContext:()=>ym,InlineCompletionItem:()=>dm,InlineCompletionList:()=>pm,InlineCompletionTriggerKind:()=>mm,InlineValueContext:()=>um,InlineValueEvaluatableExpression:()=>lm,InlineValueText:()=>sm,InlineValueVariableLookup:()=>om,InsertReplaceEdit:()=>Dp,InsertTextFormat:()=>Op,InsertTextMode:()=>xp,Location:()=>Kl,LocationLink:()=>Rp,MarkedString:()=>Hl,MarkupContent:()=>wa,MarkupKind:()=>bc,OptionalVersionedTextDocumentIdentifier:()=>ql,ParameterInformation:()=>jp,Position:()=>oe,Range:()=>te,RenameFile:()=>_a,SelectedCompletionInfo:()=>hm,SelectionRange:()=>rm,SemanticTokenModifiers:()=>am,SemanticTokenTypes:()=>nm,SemanticTokens:()=>im,SignatureInformation:()=>Bp,StringValue:()=>fm,SymbolInformation:()=>qp,SymbolKind:()=>Wp,SymbolTag:()=>Vp,TextDocument:()=>vm,TextDocumentEdit:()=>Vl,TextDocumentIdentifier:()=>Ip,TextDocumentItem:()=>Pp,TextEdit:()=>ar,URI:()=>Rc,VersionedTextDocumentIdentifier:()=>Np,WorkspaceChange:()=>D$,WorkspaceEdit:()=>Cc,WorkspaceFolder:()=>gm,WorkspaceSymbol:()=>Hp,integer:()=>$p,uinteger:()=>Ul});var Tp,Rc,$p,Ul,oe,te,Kl,Rp,Ac,Ap,Ep,Cp,bp,Ec,_p,Sp,wp,Wl,dn,ar,pn,et,Ar,Vl,ba,_a,Sa,Cc,Pl,Bd,D$,Ip,Np,ql,Pp,bc,wa,kp,Op,Lp,Dp,xp,Mp,Gp,Fp,Hl,zp,jp,Bp,Up,Kp,Wp,Vp,qp,Hp,Yp,Xp,Yl,Jp,Zp,Qp,em,tm,rm,nm,am,im,sm,om,lm,um,_c,Sc,cm,fm,dm,pm,mm,hm,ym,gm,x$,vm,av,E,Du=hk({"../../node_modules/.pnpm/[email protected]/node_modules/vscode-languageserver-types/lib/esm/main.js"(){var t,e,r,n;(function(a){function i(o){return typeof o=="string"}s(i,"is"),a.is=i})(Tp||(Tp={})),(function(a){function i(o){return typeof o=="string"}s(i,"is"),a.is=i})(Rc||(Rc={})),(function(a){a.MIN_VALUE=-2147483648,a.MAX_VALUE=2147483647;function i(o){return typeof o=="number"&&a.MIN_VALUE<=o&&o<=a.MAX_VALUE}s(i,"is"),a.is=i})($p||($p={})),(function(a){a.MIN_VALUE=0,a.MAX_VALUE=2147483647;function i(o){return typeof o=="number"&&a.MIN_VALUE<=o&&o<=a.MAX_VALUE}s(i,"is"),a.is=i})(Ul||(Ul={})),(function(a){function i(u,l){return u===Number.MAX_VALUE&&(u=Ul.MAX_VALUE),l===Number.MAX_VALUE&&(l=Ul.MAX_VALUE),{line:u,character:l}}s(i,"create"),a.create=i;function o(u){let l=u;return E.objectLiteral(l)&&E.uinteger(l.line)&&E.uinteger(l.character)}s(o,"is"),a.is=o})(oe||(oe={})),(function(a){function i(u,l,c,f){if(E.uinteger(u)&&E.uinteger(l)&&E.uinteger(c)&&E.uinteger(f))return{start:oe.create(u,l),end:oe.create(c,f)};if(oe.is(u)&&oe.is(l))return{start:u,end:l};throw new Error(`Range#create called with invalid arguments[${u}, ${l}, ${c}, ${f}]`)}s(i,"create"),a.create=i;function o(u){let l=u;return E.objectLiteral(l)&&oe.is(l.start)&&oe.is(l.end)}s(o,"is"),a.is=o})(te||(te={})),(function(a){function i(u,l){return{uri:u,range:l}}s(i,"create"),a.create=i;function o(u){let l=u;return E.objectLiteral(l)&&te.is(l.range)&&(E.string(l.uri)||E.undefined(l.uri))}s(o,"is"),a.is=o})(Kl||(Kl={})),(function(a){function i(u,l,c,f){return{targetUri:u,targetRange:l,targetSelectionRange:c,originSelectionRange:f}}s(i,"create"),a.create=i;function o(u){let l=u;return E.objectLiteral(l)&&te.is(l.targetRange)&&E.string(l.targetUri)&&te.is(l.targetSelectionRange)&&(te.is(l.originSelectionRange)||E.undefined(l.originSelectionRange))}s(o,"is"),a.is=o})(Rp||(Rp={})),(function(a){function i(u,l,c,f){return{red:u,green:l,blue:c,alpha:f}}s(i,"create"),a.create=i;function o(u){const l=u;return E.objectLiteral(l)&&E.numberRaLine truncated
`,`\r
`,"\r"],(function(a){function i(c,f,d,p){return new av(c,f,d,p)}s(i,"create"),a.create=i;function o(c){let f=c;return!!(E.defined(f)&&E.string(f.uri)&&(E.undefined(f.languageId)||E.string(f.languageId))&&E.uinteger(f.lineCount)&&E.func(f.getText)&&E.func(f.positionAt)&&E.func(f.offsetAt))}s(o,"is"),a.is=o;function u(c,f){let d=c.getText(),p=l(f,(h,T)=>{let C=h.range.start.line-T.range.start.line;return C===0?h.range.start.character-T.range.start.character:C}),y=d.length;for(let h=p.length-1;h>=0;h--){let T=p[h],C=c.offsetAt(T.range.start),v=c.offsetAt(T.range.end);if(v<=y)d=d.substring(0,C)+T.newText+d.substring(v,d.length);else throw new Error("Overlapping edit");y=C}return d}s(u,"applyEdits"),a.applyEdits=u;function l(c,f){if(c.length<=1)return c;const d=c.length/2|0,p=c.slice(0,d),y=c.slice(d);l(p,f),l(y,f);let h=0,T=0,C=0;for(;h<p.length&&T<y.length;)f(p[h],y[T])<=0?c[C++]=p[h++]:c[C++]=y[T++];for(;h<p.length;)c[C++]=p[h++];for(;T<y.length;)c[C++]=y[T++];return c}s(l,"mergeSort")})(vm||(vm={})),av=(n=class{constructor(i,o,u,l){this._uri=i,this._languageId=o,this._version=u,this._content=l,this._lineOffsets=void 0}get uri(){return this._uri}get languageId(){return this._languageId}get version(){return this._version}getText(i){if(i){let o=this.offsetAt(i.start),u=this.offsetAt(i.end);return this._content.substring(o,u)}return this._content}update(i,o){this._content=i.text,this._version=o,this._lineOffsets=void 0}getLineOffsets(){if(this._lineOffsets===void 0){let i=[],o=this._content,u=!0;for(let l=0;l<o.length;l++){u&&(i.push(l),u=!1);let c=o.charAt(l);u=c==="\r"||c===`
`,c==="\r"&&l+1<o.length&&o.charAt(l+1)===`
`&&l++}u&&o.length>0&&i.push(o.length),this._lineOffsets=i}return this._lineOffsets}positionAt(i){i=Math.max(Math.min(i,this._content.length),0);let o=this.getLineOffsets(),u=0,l=o.length;if(l===0)return oe.create(0,i);for(;u<l;){let f=Math.floor((u+l)/2);o[f]>i?l=f:u=f+1}let c=u-1;return oe.create(c,i-o[c])}offsetAt(i){let o=this.getLineOffsets();if(i.line>=o.length)return this._content.length;if(i.line<0)return 0;let u=o[i.line],l=i.line+1<o.length?o[i.line+1]:this._content.length;return Math.max(Math.min(u+i.character,l),u)}get lineCount(){return this.getLineOffsets().length}},s(n,"FullTextDocument"),n),(function(a){const i=Object.prototype.toString;function o(v){return typeof v<"u"}s(o,"defined"),a.defined=o;function u(v){return typeof v>"u"}s(u,"undefined"),a.undefined=u;function l(v){return v===!0||v===!1}s(l,"boolean"),a.boolean=l;function c(v){return i.call(v)==="[object String]"}s(c,"string"),a.string=c;function f(v){return i.call(v)==="[object Number]"}s(f,"number"),a.number=f;function d(v,w,b){return i.call(v)==="[object Number]"&&w<=v&&v<=b}s(d,"numberRange"),a.numberRange=d;function p(v){return i.call(v)==="[object Number]"&&-2147483648<=v&&v<=2147483647}s(p,"integer"),a.integer=p;function y(v){return i.call(v)==="[object Number]"&&0<=v&&v<=2147483647}s(y,"uinteger"),a.uinteger=y;function h(v){return i.call(v)==="[object Function]"}s(h,"func"),a.func=h;function T(v){return v!==null&&typeof v=="object"}s(T,"objectLiteral"),a.objectLiteral=T;function C(v,w){return Array.isArray(v)&&v.every(w)}s(C,"typedArray"),a.typedArray=C})(E||(E={}))}}),Wn=X({"../../node_modules/.pnpm/[email protected]/node_modules/vscode-jsonrpc/lib/common/ral.js"(t){Object.defineProperty(t,"__esModule",{value:!0});var e;function r(){if(e===void 0)throw new Error("No runtime abstraction layer installed");return e}s(r,"RAL"),(function(n){function a(i){if(i===void 0)throw new Error("No runtime abstraction layer provided");e=i}s(a,"install"),n.install=a})(r||(r={})),t.default=r}}),xu=X({"../../node_modules/.pnpm/[email protected]/node_modules/vscode-jsonrpc/lib/common/is.js"(t){Object.defineProperty(t,"__esModule",{value:!0}),t.stringArray=t.array=t.func=t.error=t.number=t.string=t.boolean=void 0;function e(l){return l===!0||l===!1}s(e,"boolean"),t.boolean=e;function r(l){return typeof l=="string"||l instanceof String}s(r,"string"),t.string=r;function n(l){return typeof l=="number"||l instanceof Number}s(n,"number"),t.number=n;function a(l){return l instanceof Error}s(a,"error"),t.error=a;function i(l){return typeof l=="function"}s(i,"func"),t.func=i;function o(l){return Array.isArray(l)}s(o,"array"),t.array=o;function u(l){return o(l)&&l.every(c=>r(c))}s(u,"stringArray"),t.stringArray=u}}),nl=X({"../../node_modules/.pnpm/[email protected]/node_modules/vscode-jsonrpc/lib/common/events.js"(t){var i,o;Object.defineProperty(t,"__esModule",{value:!0}),t.Emitter=t.Event=void 0;var e=Wn(),r;(function(u){const l={dispose(){}};u.None=function(){return l}})(r||(t.Event=r={}));var n=(i=class{add(l,c=null,f){this._callbacks||(this._callbacks=[],this._contexts=[]),this._callbacks.push(l),this._contexts.push(c),Array.isArray(f)&&f.push({dispose:s(()=>this.remove(l,c),"dispose")})}remove(l,c=null){if(!this._callbacks)return;let f=!1;for(let d=0,p=this._callbacks.length;d<p;d++)if(this._callbacks[d]===l)if(this._contexts[d]===c){this._callbacks.splice(d,1),this._contexts.splice(d,1);return}else f=!0;if(f)throw new Error("When adding a listener with a context, you should remove it with the same context")}invoke(...l){if(!this._callbacks)return[];const c=[],f=this._callbacks.slice(0),d=this._contexts.slice(0);for(let p=0,y=f.length;p<y;p++)try{c.push(f[p].apply(d[p],l))}catch(h){(0,e.default)().console.error(h)}return c}isEmpty(){return!this._callbacks||this._callbacks.length===0}dispose(){this._callbacks=void 0,this._contexts=void 0}},s(i,"CallbackList"),i),a=(o=class{constructor(l){this._options=l}get event(){return this._event||(this._event=(l,c,f)=>{this._callbacks||(this._callbacks=new n),this._options&&this._options.onFirstListenerAdd&&this._callbacks.isEmpty()&&this._options.onFirstListenerAdd(this),this._callbacks.add(l,c);const d={dispose:s(()=>{this._callbacks&&(this._callbacks.remove(l,c),d.dispose=o._noop,this._options&&this._options.onLastListenerRemove&&this._callbacks.isEmpty()&&this._options.onLastListenerRemove(this))},"dispose")};return Array.isArray(f)&&f.push(d),d}),this._event}fire(l){this._callbacks&&this._callbacks.invoke.call(this._callbacks,l)}dispose(){this._callbacks&&(this._callbacks.dispose(),this._callbacks=void 0)}},s(o,"Emitter"),o);t.Emitter=a,a._noop=function(){}}}),Lf=X({"../../node_modules/.pnpm/[email protected]/node_modules/vscode-jsonrpc/lib/common/cancellation.js"(t){var l,c;Object.defineProperty(t,"__esModule",{value:!0}),t.CancellationTokenSource=t.CancellationToken=void 0;var e=Wn(),r=xu(),n=nl(),a;(function(f){f.None=Object.freeze({isCancellationRequested:!1,onCancellationRequested:n.Even Line truncated
${JSON.stringify(Object.fromEntries(h))}`));return}const C=parseInt(T);if(isNaN(C)){this.fireError(new Error(`Content-Length value must be a number. Got ${T}`));return}this.nextMessageLength=C}const y=this.buffer.tryReadBody(this.nextMessageLength);if(y===void 0){this.setPartialMessageTimer();return}this.clearPartialMessageTimer(),this.nextMessageLength=-1,this.readSemaphore.lock(async()=>{const h=this.options.contentDecoder!==void 0?await this.options.contentDecoder.decode(y):y,T=await this.options.contentTypeDecoder.decode(h,this.options);this.callback(T)}).catch(h=>{this.fireError(h)})}}catch(y){this.fireError(y)}}clearPartialMessageTimer(){this.partialMessageTimer&&(this.partialMessageTimer.dispose(),this.partialMessageTimer=void 0)}setPartialMessageTimer(){this.clearPartialMessageTimer(),!(this._partialMessageTimeout<=0)&&(this.partialMessageTimer=(0,e.default)().timer.setTimeout((p,y)=>{this.partialMessageTimer=void 0,p===this.messageToken&&(this.firePartialMessage({messageToken:p,waitingTime:y}),this.setPartialMessageTimer())},this._partialMessageTimeout,this.messageToken,this._partialMessageTimeout))}},s(f,"ReadableStreamMessageReader"),f);t.ReadableStreamMessageReader=l}}),Tk=X({"../../node_modules/.pnpm/[email protected]/node_modules/vscode-jsonrpc/lib/common/messageWriter.js"(t){var d,p;Object.defineProperty(t,"__esModule",{value:!0}),t.WriteableStreamMessageWriter=t.AbstractMessageWriter=t.MessageWriter=void 0;var e=Wn(),r=xu(),n=F$(),a=nl(),i="Content-Length: ",o=`\r
`,u;(function(y){function h(T){let C=T;return C&&r.func(C.dispose)&&r.func(C.onClose)&&r.func(C.onError)&&r.func(C.write)}s(h,"is"),y.is=h})(u||(t.MessageWriter=u={}));var l=(d=class{constructor(){this.errorEmitter=new a.Emitter,this.closeEmitter=new a.Emitter}dispose(){this.errorEmitter.dispose(),this.closeEmitter.dispose()}get onError(){return this.errorEmitter.event}fireError(h,T,C){this.errorEmitter.fire([this.asError(h),T,C])}get onClose(){return this.closeEmitter.event}fireClose(){this.closeEmitter.fire(void 0)}asError(h){return h instanceof Error?h:new Error(`Writer received error. Reason: ${r.string(h.message)?h.message:"unknown"}`)}},s(d,"AbstractMessageWriter"),d);t.AbstractMessageWriter=l;var c;(function(y){function h(T){return T===void 0||typeof T=="string"?{charset:T??"utf-8",contentTypeEncoder:(0,e.default)().applicationJson.encoder}:{charset:T.charset??"utf-8",contentEncoder:T.contentEncoder,contentTypeEncoder:T.contentTypeEncoder??(0,e.default)().applicationJson.encoder}}s(h,"fromOptions"),y.fromOptions=h})(c||(c={}));var f=(p=class extends l{constructor(h,T){super(),this.writable=h,this.options=c.fromOptions(T),this.errorCount=0,this.writeSemaphore=new n.Semaphore(1),this.writable.onError(C=>this.fireError(C)),this.writable.onClose(()=>this.fireClose())}async write(h){return this.writeSemaphore.lock(async()=>this.options.contentTypeEncoder.encode(h,this.options).then(C=>this.options.contentEncoder!==void 0?this.options.contentEncoder.encode(C):C).then(C=>{const v=[];return v.push(i,C.byteLength.toString(),o),v.push(o),this.doWrite(h,v,C)},C=>{throw this.fireError(C),C}))}async doWrite(h,T,C){try{return await this.writable.write(T.join(""),"ascii"),this.writable.write(C)}catch(v){return this.handleError(v,h),Promise.reject(v)}}handleError(h,T){this.errorCount++,this.fireError(h,T,this.errorCount)}end(){this.writable.end()}},s(p,"WriteableStreamMessageWriter"),p);t.WriteableStreamMessageWriter=f}}),$k=X({"../../node_modules/.pnpm/[email protected]/node_modules/vscode-jsonrpc/lib/common/messageBuffer.js"(t){var i;Object.defineProperty(t,"__esModule",{value:!0}),t.AbstractMessageBuffer=void 0;var e=13,r=10,n=`\r
`,a=(i=class{constructor(u="utf-8"){this._encoding=u,this._chunks=[],this._totalLength=0}get encoding(){return this._encoding}append(u){const l=typeof u=="string"?this.fromString(u,this._encoding):u;this._chunks.push(l),this._totalLength+=l.byteLength}tryReadHeaders(u=!1){if(this._chunks.length===0)return;let l=0,c=0,f=0,d=0;e:for(;c<this._chunks.length;){const T=this._chunks[c];for(f=0;f<T.length;){switch(T[f]){case e:switch(l){case 0:l=1;break;case 2:l=3;break;default:l=0}break;case r:switch(l){case 1:l=2;break;case 3:l=4,f++;break e;default:l=0}break;default:l=0}f++}d+=T.byteLength,c++}if(l!==4)return;const p=this._read(d+f),y=new Map,h=this.toString(p,"ascii").split(n);if(h.length<2)return y;for(let T=0;T<h.length-2;T++){const C=h[T],v=C.indexOf(":");if(v===-1)throw new Error(`Message header must separate key and value using ':'
${C}`);const w=C.substr(0,v),b=C.substr(v+1).trim();y.set(u?w.toLowerCase():w,b)}return y}tryReadBody(u){if(!(this._totalLength<u))return this._read(u)}get numberOfBytes(){return this._totalLength}_read(u){if(u===0)return this.emptyBuffer();if(u>this._totalLength)throw new Error("Cannot read so many bytes!");if(this._chunks[0].byteLength===u){const d=this._chunks[0];return this._chunks.shift(),this._totalLength-=u,this.asNative(d)}if(this._chunks[0].byteLength>u){const d=this._chunks[0],p=this.asNative(d,u);return this._chunks[0]=d.slice(u),this._totalLength-=u,p}const l=this.allocNative(u);let c=0,f=0;for(;u>0;){const d=this._chunks[f];if(d.byteLength>u){const p=d.slice(0,u);l.set(p,c),c+=u,this._chunks[f]=d.slice(u),this._totalLength-=u,u-=u}else l.set(d,c),c+=d.byteLength,this._chunks.shift(),this._totalLength-=d.byteLength,u-=d.byteLength}return l}},s(i,"AbstractMessageBuffer"),i);t.AbstractMessageBuffer=a}}),Rk=X({"../../node_modules/.pnpm/[email protected]/node_modules/vscode-jsonrpc/lib/common/connection.js"(t){var k,_;Object.defineProperty(t,"__esModule",{value:!0}),t.createMessageConnection=t.ConnectionOptions=t.MessageStrategy=t.CancellationStrategy=t.CancellationSenderStrategy=t.CancellationReceiverStrategy=t.RequestCancellationReceiverStrategy=t.IdCancellationReceiverStrategy=t.ConnectionStrategy=t.ConnectionError=t.ConnectionErrors=t.LogTraceNotification=t.SetTraceNotification=t.TraceFormat=t.TraceValues=t.Trace=t.NullLogger=t.ProgressType=t.ProgressToken=void 0;var e=Wn(),r=xu(),n=M$(),a=G$(),i=nl(),o=Lf(),u;(function($){$.type=new n.NotificationType("$/cancelRequest")})(u||(u={}));var l;(function($){function I(R){return typeof R=="string"||typeof R=="number"}s(I,"is"),$.is=I})(l||(t.ProgressToken=l={}));var c;(function($){$.type=new n.NotificationType("$/progress")})(c||(c={}));var f=(k=class{constructor(){}},s(k,"ProgressType"),k);t.ProgressType=f;var d;(function($){function I(R){return r.func(R)}s(I,"is"),$.is=I})(d||(d={})),t.NullLogger=Object.freeze({error:s(()=>{},"error"),warn:s(()=>{},"warn"),info:s(()=>{},"info"),log:s(()=>{},"log")});var p;(function($){$[$.Off=0]="Off",$[$.Messages=1]="Messages",$[$.Compact=2]="Compact",$[$.Verbose=3]="Verbose"})(p||(t.Trace=p={}));var y;(function($){$.Off="off",$.Messages="messages",$.Compact="compact",$.Verbose="verbose"})(y||(t.TraceValues=y={})),(function($){function I(A){if(!r.string(A))return $.Off;switch(A=A.toLowerCase(),A){case"off":return $.Off;case"messages":return $.Messages;case"compact":return $.Compact;case"verbose":return $.Verbose;default:return $.Off}}s(I,"fromString"),$.fromString=I;function R(A){switch(A){case $.Off:return"off";case $.Messages:return"messages";case $.Compact:return"compact";case $.Verbose:return"verbose";default:return"off"}}s(R,"toString"),$.toString=R})(p||(t.Trace=p={}));var h;(function($){$.Text="text",$.JSON="json"})(h||(t.TraceFormat=h={})),(function($){function I(R){return r.string(R)?(R=R.toLowerCase(),R==="json"?$.JSON:$.Text):$.Text}s(I,"fromString"),$.fromString=I})(h||(t.TraceFormat=h={}));var T;(function($){$.type=new n.NotificationType("$/setTrace")})(T||(t.SetTraceNotification=T={}));var C;(function($){$.type=new n.NotificationType("$/logTrace")})(C||(t.LogTraceNotification=C={}));var v;(function($){$[$.Closed=1]="Closed",$[$.Disposed=2]="Disposed",$[$.AlreadyListening=3]="AlreadyListening"})(v||(t.ConnectionErrors=v={}));var w=(_=class extends Error{constructor(I,R){super(R),this.code=I,Object.setPrototypeOf(this,_.prototype)}},s(_,"ConnectionError"),_);t.ConnectionError=w;var b;(function($){function I(R){const A=R;return A&&r.func(A.cancelUndispatched)}s(I,"is"),$.is=I})(b||(t.ConnectionStrategy=b={}));var N;(function($){function I(R){const A=R;return A&&(A.kind===void 0||A.kind==="id")&&r.func(A.createCancellationTokenSource)&&(A.dispose===void 0||r.func(A.dispose))}s(I,"is"),$.is=I})(N||(t.IdCancellationReceiverStrategy=N={}));var B;(function($){function I(R){const A=R;return A&&A.kind==="request"&&r.func(A.createCancellationTokenSource)&&(A.dispose===void 0||r.func(A.dispose))}s(I,"is"),$.is=I})(B||(t.RequestCancellationReceiverStrategy=B={}));var ne;(function($){$.Message=Object.freeze({createCancellationTokenSource(R){return new o.CancellationTokenSource}});function I(R){return N.is(R)||B.is(R)}s(I,"is"),$.is=I})(ne||(t.CancellationReceiverStrategy=ne={}));var J;(function($){$.Message=Object.freeze({sendCancellation(R,A){return R.sendNotification(u.type,{id:A})},cleanup(R){}});function I(R){const A=R;return A&&r.func(A.sendCancellation)&&r.func(A.cleanup)}s(I,"is"),$.is=I})(J||(t.CancellationSenderStrategy=J={}));var he;(function($){$.Message=Object.freeze({receiver:ne.Message,sender:J.Message});function I(R){const A=R;return A&&ne.is(A.receiver)&&J.is(A.sender)}s(I,"is"),$.is=I})(he||(t.CancellationStrategy=he={}));var Ae;(function($){function I(R){const A=R;return A&&r.func(A.handleMessage)}s(I,"is"),$.is=I})(Ae||(t.MessageStrategy=Ae={}));var ye;(function($){function I(R){const A=R;ret Line truncated
${JSON.stringify(g.error,void 0,4)}`):S.error("Received response message without id. No further error information provided.");else{const P=g.id,D=Ee.get(P);if(wl(g,D),D!==void 0){Ee.delete(P);try{if(g.error){const F=g.error;D.reject(new n.ResponseError(F.code,F.message,F.data))}else if(g.result!==void 0)D.resolve(g.result);else throw new Error("Should never happen.")}catch(F){F.message?S.error(`Response handler '${D.method}' failed with message: ${F.message}`):S.error(`Response handler '${D.method}' failed unexpectedly.`)}}}}s(Al,"handleResponse");function El(g){if(er())return;let P,D;if(g.method===u.type.method){const F=g.params.id;Ve.delete(F),sn(g);return}else{const F=Z.get(g.method);F&&(D=F.handler,P=F.type)}if(D||q)try{if(sn(g),D)if(g.params===void 0)P!==void 0&&P.numberOfParams!==0&&P.parameterStructures!==n.ParameterStructures.byName&&S.error(`Notification ${g.method} defines ${P.numberOfParams} params but received none.`),D();else if(Array.isArray(g.params)){const F=g.params;g.method===c.type.method&&F.length===2&&l.is(F[0])?D({token:F[0],value:F[1]}):(P!==void 0&&(P.parameterStructures===n.ParameterStructures.byName&&S.error(`Notification ${g.method} defines parameters by name but received parameters by position`),P.numberOfParams!==g.params.length&&S.error(`Notification ${g.method} defines ${P.numberOfParams} params but received ${F.length} arguments`)),D(...F))}else P!==void 0&&P.parameterStructures===n.ParameterStructures.byPosition&&S.error(`Notification ${g.method} defines parameters by position but received parameters by name`),D(g.params);else q&&q(g.method,g.params)}catch(F){F.message?S.error(`Notification handler '${g.method}' failed with message: ${F.message}`):S.error(`Notification handler '${g.method}' failed unexpectedly.`)}else je.fire(g)}s(El,"handleNotification");function Cl(g){if(!g){S.error("Received empty message.");return}S.error(`Received message which is neither a response nor a notification message:
${JSON.stringify(g,null,4)}`);const P=g;if(r.string(P.id)||r.number(P.id)){const D=P.id,F=Ee.get(D);F&&F.reject(new Error("The received response has neither a result nor an error property."))}}s(Cl,"handleInvalidMessage");function xt(g){if(g!=null)switch(ee){case p.Verbose:return JSON.stringify(g,null,4);case p.Compact:return JSON.stringify(g);default:return}}s(xt,"stringifyTrace");function bl(g){if(!(ee===p.Off||!ce))if(Qe===h.Text){let P;(ee===p.Verbose||ee===p.Compact)&&g.params&&(P=`Params: ${xt(g.params)}
`),ce.log(`Sending request '${g.method} - (${g.id})'.`,P)}else tr("send-request",g)}s(bl,"traceSendingRequest");function _l(g){if(!(ee===p.Off||!ce))if(Qe===h.Text){let P;(ee===p.Verbose||ee===p.Compact)&&(g.params?P=`Params: ${xt(g.params)}
`:P=`No parameters provided.
`),ce.log(`Sending notification '${g.method}'.`,P)}else tr("send-notification",g)}s(_l,"traceSendingNotification");function jr(g,P,D){if(!(ee===p.Off||!ce))if(Qe===h.Text){let F;(ee===p.Verbose||ee===p.Compact)&&(g.error&&g.error.data?F=`Error data: ${xt(g.error.data)}
`:g.result?F=`Result: ${xt(g.result)}
`:g.error===void 0&&(F=`No result returned.
`)),ce.log(`Sending response '${P} - (${g.id})'. Processing request took ${Date.now()-D}ms`,F)}else tr("send-response",g)}s(jr,"traceSendingResponse");function Sl(g){if(!(ee===p.Off||!ce))if(Qe===h.Text){let P;(ee===p.Verbose||ee===p.Compact)&&g.params&&(P=`Params: ${xt(g.params)}
`),ce.log(`Received request '${g.method} - (${g.id})'.`,P)}else tr("receive-request",g)}s(Sl,"traceReceivedRequest");function sn(g){if(!(ee===p.Off||!ce||g.method===C.type.method))if(Qe===h.Text){let P;(ee===p.Verbose||ee===p.Compact)&&(g.params?P=`Params: ${xt(g.params)}
`:P=`No parameters provided.
`),ce.log(`Received notification '${g.method}'.`,P)}else tr("receive-notification",g)}s(sn,"traceReceivedNotification");function wl(g,P){if(!(ee===p.Off||!ce))if(Qe===h.Text){let D;if((ee===p.Verbose||ee===p.Compact)&&(g.error&&g.error.data?D=`Error data: ${xt(g.error.data)}
`:g.result?D=`Result: ${xt(g.result)}
`:g.error===void 0&&(D=`No result returned.
`)),P){const F=g.error?` Request failed: ${g.error.message} (${g.error.code}).`:"";ce.log(`Received response '${P.method} - (${g.id})' in ${Date.now()-P.timerStart}ms.${F}`,D)}else ce.log(`Received response ${g.id} without active response promise.`,D)}else tr("receive-response",g)}s(wl,"traceReceivedResponse");function tr(g,P){if(!ce||ee===p.Off)return;const D={isLSPMessage:!0,type:g,message:P,timestamp:Date.now()};ce.log(D)}s(tr,"logLSPMessage");function Tr(){if(ma())throw new w(v.Closed,"Connection is closed.");if(er())throw new w(v.Disposed,"Connection is disposed.")}s(Tr,"throwIfClosedOrDisposed");function Il(){if(pa())throw new w(v.AlreadyListening,"Connection is already listening")}s(Il,"throwIfListening");function Nl(){if(!pa())throw new Error("Call listen() first.")}s(Nl,"throwIfNotListening");function m(g){return g===void 0?null:g}s(m,"undefinedToNull");function le(g){if(g!==null)return g}s(le,"nullToUndefined");function we(g){return g!=null&&!Array.isArray(g)&&typeof g=="object"}s(we,"isNamedParam");function H(g,P){switch(g){case n.ParameterStructures.auto:return we(P)?le(P):[m(P)];case n.ParameterStructures.byName:if(!we(P))throw new Error("Received parameters by name but param is not an object literal.");return le(P);case n.ParameterStructures.byPosition:return[m(P)];default:throw new Error(`Unknown parameter structure ${g.toString()}`)}}s(H,"computeSingleParam");function Ie(g,P){let D;const F=g.numberOfParams;switch(F){case 0:D=void 0;break;case 1:D=H(g.parameterStructures,P[0]);break;default:D=[];for(let Ce=0;Ce<P.length&&Ce<F;Ce++)D.push(m(P[Ce]));if(P.length<F)for(let Ce=P.length;Ce<F;Ce++)D.push(null);break}return D}s(Ie,"computeMessageParams");const va={sendNotification:s((g,...P)=>{Tr();let D,F;if(r.string(g)){D=g;const me=P[0];let De=0,Ge=n.ParameterStructures.auto;n.ParameterStructures.is(me)&&(De=1,Ge=me);let ie=P.length;const Ne=ie-De;switch(Ne){case 0:F=void 0;break;case 1:F=H(Ge,P[De]);break;default:if(Ge===n.ParameterStructures.byName)throw new Error(`Received ${Ne} parameters for 'by Name' notification parameter structure.`);F=P.slice(De,ie).map(fe=>m(fe));break}}else{const me=P;D=g.method,F=Ie(g,me)}const Ce={jsonrpc:z,method:D,params:F};return _l(Ce),I.write(Ce).catch(me=>{throw S.error("Sending notification failed."),me})},"sendNotification"),onNotification:s((g,P)=>{Tr();let D;return r.func(g)?q=g:P&&(r.string(g)?(D=g,Z.set(g,{type:void 0,handler:P})):(D=g.method,Z.set(g.method,{type:g,handler:P}))),{dispose:s(()=>{D!==void 0?Z.delete(D):q=void 0},"dispose")}},"onNotification"),onProgress:s((g,P,D)=>{if(ae.has(P))throw new Error(`Progress handler for token ${P} already registered`);return ae.set(P,D),{dispose:s(()=>{ae.delete(P)},"dispose")}},"onProgress"),sendProgress:s((g,P,D)=>va.sendNotification(c.type,{token:P,value:D}),"sendProgress"),onUnhandledProgress:Qt.event,sendRequest:s((g,...P)=>{Tr(),Nl();let D,F,Ce;if(r.string(g)){D=g;const ie=P[0],Ne=P[P.length-1];let fe=0,Ue=n.ParameterStructures.auto;n.ParameterStructures.is(ie)&&(fe=1,Ue=ie);let lt=P.length;o.CancellationToken.is(Ne)&&(lt=lt-1,Ce=Ne);const rr=lt-fe;switch(rr){case 0:F=void 0;break;case 1:F=H(Ue,P[fe]);break;default:if(Ue===n.ParameterStructures.byName)throw new Error(`Received ${rr} parameters for 'by Name' request parameter structure.`);F=P.slice(fe,lt).map(ck=>m(ck));break}}else{const ie=P;D=g.method,F=Ie(g,ie);const Ne=g.numberOfParams;Ce=o.CancellationToken.is(ie[Ne])?ie[Ne]:void 0}const me=L++;let De;Ce&&(De=Ce.onCancellationRequested(()=>{const ie=ve.sender.sendCancellation(va,me);return ie===void 0?(S.log(`Received no promise from cancellation strategy when cancelling id ${me}`),Promise.resolve()):ie.catch(()=>{S.log(`Sending cancellation messages for id ${me} failed`)})}));const Ge={jsonrpc:z,id:me,method:D,params:F};return bl(Ge),typeof ve.sender.enableCancellation=="function"&&ve.sender.enableCancellation(Ge),new Promise(async(ie,Ne)=>{const fe=s(rr=>{ie(rr),ve.sender.cleanup(me),De?.dispose()},"resolveWithCleanup"),Ue=s(rr=>{Ne(rr),ve.sender.cleanup(me),De?.dispose()},"rejectWithCleanup"),lt={method:D,timerStart:Date.now(),resolve:fe,reject:Ue};try{await I.write(Ge),Ee.set(me,lt)}catch(rr){throw S.error("Sending request failed."),lt.reject(new n.ResponseError(n.ErrorCodes.MessageWriteError,rr.message?rr.message:"Unknown reason")),rr}})},"sendRequest"),onRequest:s((g,P)=>{Tr();let D=null;return d.is(g)?(D=void 0,M=g):r.string(g)?(D=null,P!==void 0&&(D=g,Y.set(g,{handler:P,type:void 0}))):P!==void 0&&(D=g.method,Y.set(g.method,{type:g,handler:P})),{dispose:s(()=>{D!==null&&(D!==void 0?Y.delete(D):M=void 0)},"dispose")}},"onRequest"),hasPendingResponse:s(()=>Ee.size>0,"hasPendingResponse"),trace:s(async(g,P,D)=>{let F=!1,Ce=h.Text;D!==void 0&&(r.boolean(D)?F=D:(F=D.sendNotification||!1,Ce=D.traceFormat||h.Text)),ee=g,Qe=Ce,ee===p.Off?ce=void 0:ce=P,F&&!ma()&&!er()&&await va.sendNotification(T.type,{value:p.toString(g)})},"trace"),onError:ge.event,onClose:G.event,onUnhandledNotification:je.event,onD Line truncated
`),W("\r"),W(" "),W("\v"),W(" "),W(" "),W(" "),W(" "),W(" "),W(" "),W(" "),W(" "),W(" "),W(" "),W(" "),W(" "),W(" "),W(" "),W("\u2028"),W("\u2029"),W(" "),W(" "),W(" "),W("\uFEFF")],Yk=/[0-9a-fA-F]/,nc=/[0-9]/,Xk=/[1-9]/,ri,mR=(ri=class{constructor(){this.idx=0,this.input="",this.groupIdx=0}saveState(){return{idx:this.idx,input:this.input,groupIdx:this.groupIdx}}restoreState(e){this.idx=e.idx,this.input=e.input,this.groupIdx=e.groupIdx}pattern(e){this.idx=0,this.input=e,this.groupIdx=0,this.consumeChar("/");const r=this.disjunction();this.consumeChar("/");const n={type:"Flags",loc:{begin:this.idx,end:e.length},global:!1,ignoreCase:!1,multiLine:!1,unicode:!1,sticky:!1};for(;this.isRegExpFlag();)switch(this.popChar()){case"g":Ia(n,"global");break;case"i":Ia(n,"ignoreCase");break;case"m":Ia(n,"multiLine");break;case"u":Ia(n,"unicode");break;case"y":Ia(n,"sticky");break}if(this.idx!==this.input.length)throw Error("Redundant input: "+this.input.substring(this.idx));return{type:"Pattern",flags:n,value:r,loc:this.loc(0)}}disjunction(){const e=[],r=this.idx;for(e.push(this.alternative());this.peekChar()==="|";)this.consumeChar("|"),e.push(this.alternative());return{type:"Disjunction",value:e,loc:this.loc(r)}}alternative(){const e=[],r=this.idx;for(;this.isTerm();)e.push(this.term());return{type:"Alternative",value:e,loc:this.loc(r)}}term(){return this.isAssertion()?this.assertion():this.atom()}assertion(){const e=this.idx;switch(this.popChar()){case"^":return{type:"StartAnchor",loc:this.loc(e)};case"$":return{type:"EndAnchor",loc:this.loc(e)};case"\\":switch(this.popChar()){case"b":return{type:"WordBoundary",loc:this.loc(e)};case"B":return{type:"NonWordBoundary",loc:this.loc(e)}}throw Error("Invalid Assertion Escape");case"(":this.consumeChar("?");let r;switch(this.popChar()){case"=":r="Lookahead";break;case"!":r="NegativeLookahead";break;case"<":{switch(this.popChar()){case"=":r="Lookbehind";break;case"!":r="NegativeLookbehind"}break}}mn(r);const n=this.disjunction();return this.consumeChar(")"),{type:r,value:n,loc:this.loc(e)}}return pR()}quantifier(e=!1){let r;const n=this.idx;switch(this.popChar()){case"*":r={atLeast:0,atMost:1/0};break;case"+":r={atLeast:1,atMost:1/0};break;case"?":r={atLeast:0,atMost:1};break;case"{":const a=this.integerIncludingZero();switch(this.popChar()){case"}":r={atLeast:a,atMost:a};break;case",":let i;this.isDigit()?(i=this.integerIncludingZero(),r={atLeast:a,atMost:i}):r={atLeast:a,atMost:1/0},this.consumeChar("}");break}if(e===!0&&r===void 0)return;mn(r);break}if(!(e===!0&&r===void 0)&&mn(r))return this.peekChar(0)==="?"?(this.consumeChar("?"),r.greedy=!1):r.greedy=!0,r.type="Quantifier",r.loc=this.loc(n),r}atom(){let e;const r=this.idx;switch(this.peekChar()){case".":e=this.dotAll();break;case"\\":e=this.atomEscape();break;case"[":e=this.characterClass();break;case"(":e=this.group();break}if(e===void 0&&this.isPatternCharacter()&&(e=this.patternCharacter()),mn(e))return e.loc=this.loc(r),this.isQuantifier()&&(e.quantifier=this.quantifier()),e}dotAll(){return this.consumeChar("."),{type:"Set",complement:!0,value:[W(`
`),W("\r"),W("\u2028"),W("\u2029")]}}atomEscape(){switch(this.consumeChar("\\"),this.peekChar()){case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":return this.decimalEscapeAtom();case"d":case"D":case"s":case"S":case"w":case"W":return this.characterClassEscape();case"f":case"n":case"r":case"t":case"v":return this.controlEscapeAtom();case"c":return this.controlLetterEscapeAtom();case"0":return this.nulCharacterAtom();case"x":return this.hexEscapeSequenceAtom();case"u":return this.regExpUnicodeEscapeSequenceAtom();default:return this.identityEscapeAtom()}}decimalEscapeAtom(){return{type:"GroupBackReference",value:this.positiveInteger()}}characterClassEscape(){let e,r=!1;switch(this.popChar()){case"d":e=lf;break;case"D":e=lf,r=!0;break;case"s":e=sv;break;case"S":e=sv,r=!0;break;case"w":e=uf;break;case"W":e=uf,r=!0;break}if(mn(e))return{type:"Set",value:e,complement:r}}controlEscapeAtom(){let e;switch(this.popChar()){case"f":e=W("\f");break;case"n":e=W(`
`);break;case"r":e=W("\r");break;case"t":e=W(" ");break;case"v":e=W("\v");break}if(mn(e))return{type:"Character",value:e}}controlLetterEscapeAtom(){this.consumeChar("c");const e=this.popChar();if(/[a-zA-Z]/.test(e)===!1)throw Error("Invalid ");return{type:"Character",value:e.toUpperCase().charCodeAt(0)-64}}nulCharacterAtom(){return this.consumeChar("0"),{type:"Character",value:W("\0")}}hexEscapeSequenceAtom(){return this.consumeChar("x"),this.parseHexDigits(2)}regExpUnicodeEscapeSequenceAtom(){return this.consumeChar("u"),this.parseHexDigits(4)}identityEscapeAtom(){const e=this.popChar();return{type:"Character",value:W(e)}}classPatternCharacterAtom(){switch(this.peekChar()){case`
`:case"\r":case"\u2028":case"\u2029":case"\\":case"]":throw Error("TBD");default:const e=this.popChar();return{type:"Character",value:W(e)}}}characterClass(){const e=[];let r=!1;for(this.consumeChar("["),this.peekChar(0)==="^"&&(this.consumeChar("^"),r=!0);this.isClassAtom();){const n=this.classAtom();if(n.type,Rm(n)&&this.isRangeDash()){this.consumeChar("-");const a=this.classAtom();if(a.type,Rm(a)){if(a.value<n.value)throw Error("Range out of order in character class");e.push({from:n.value,to:a.value})}else wc(n.value,e),e.push(W("-")),wc(a.value,e)}else wc(n.value,e)}return this.consumeChar("]"),{type:"Set",complement:r,value:e}}classAtom(){switch(this.peekChar()){case"]":case`
`:case"\r":case"\u2028":case"\u2029":throw Error("TBD");case"\\":return this.classEscape();default:return this.classPatternCharacterAtom()}}classEscape(){switch(this.consumeChar("\\"),this.peekChar()){case"b":return this.consumeChar("b"),{type:"Character",value:W("\b")};case"d":case"D":case"s":case"S":case"w":case"W":return this.characterClassEscape();case"f":case"n":case"r":case"t":case"v":return this.controlEscapeAtom();case"c":return this.controlLetterEscapeAtom();case"0":return this.nulCharacterAtom();case"x":return this.hexEscapeSequenceAtom();case"u":return this.regExpUnicodeEscapeSequenceAtom();default:return this.identityEscapeAtom()}}group(){let e=!0;this.consumeChar("("),this.peekChar(0)==="?"?(this.consumeChar("?"),this.consumeChar(":"),e=!1):this.groupIdx++;const r=this.disjunction();this.consumeChar(")");const n={type:"Group",capturing:e,value:r};return e&&(n.idx=this.groupIdx),n}positiveInteger(){let e=this.popChar();if(Xk.test(e)===!1)throw Error("Expecting a positive integer");for(;nc.test(this.peekChar(0));)e+=this.popChar();return parseInt(e,10)}integerIncludingZero(){let e=this.popChar();if(nc.test(e)===!1)throw Error("Expecting an integer");for(;nc.test(this.peekChar(0));)e+=this.popChar();return parseInt(e,10)}patternCharacter(){const e=this.popChar();switch(e){case`
`:case"\r":case"\u2028":case"\u2029":case"^":case"$":case"\\":case".":case"*":case"+":case"?":case"(":case")":case"[":case"|":throw Error("TBD");default:return{type:"Character",value:W(e)}}}isRegExpFlag(){switch(this.peekChar(0)){case"g":case"i":case"m":case"u":case"y":return!0;default:return!1}}isRangeDash(){return this.peekChar()==="-"&&this.isClassAtom(1)}isDigit(){return nc.test(this.peekChar(0))}isClassAtom(e=0){switch(this.peekChar(e)){case"]":case`
`:case"\r":case"\u2028":case"\u2029":return!1;default:return!0}}isTerm(){return this.isAtom()||this.isAssertion()}isAtom(){if(this.isPatternCharacter())return!0;switch(this.peekChar(0)){case".":case"\\":case"[":case"(":return!0;default:return!1}}isAssertion(){switch(this.peekChar(0)){case"^":case"$":return!0;case"\\":switch(this.peekChar(1)){case"b":case"B":return!0;default:return!1}case"(":return this.peekChar(1)==="?"&&(this.peekChar(2)==="="||this.peekChar(2)==="!"||this.peekChar(2)==="<"&&(this.peekChar(3)==="="||this.peekChar(3)==="!"));default:return!1}}isQuantifier(){const e=this.saveState();try{return this.quantifier(!0)!==void 0}catch{return!1}finally{this.restoreState(e)}}isPatternCharacter(){switch(this.peekChar()){case"^":case"$":case"\\":case".":case"*":case"+":case"?":case"(":case")":case"[":case"|":case"/":case`
`:case"\r":case"\u2028":case"\u2029":return!1;default:return!0}}parseHexDigits(e){let r="";for(let a=0;a<e;a++){const i=this.popChar();if(Yk.test(i)===!1)throw Error("Expecting a HexDecimal digits");r+=i}return{type:"Character",value:parseInt(r,16)}}peekChar(e=0){return this.input[this.idx+e]}popChar(){const e=this.peekChar(0);return this.consumeChar(void 0),e}consumeChar(e){if(e!==void 0&&this.input[this.idx]!==e)throw Error("Expected: '"+e+"' but found: '"+this.input[this.idx]+"' at offset: "+this.idx);if(this.idx>=this.input.length)throw Error("Unexpected end of input");this.idx++}loc(e){return{begin:e,end:this.idx}}},s(ri,"RegExpParser"),ri),ni,Kf=(ni=class{visitChildren(e){for(const r in e){const n=e[r];e.hasOwnProperty(r)&&(n.type!==void 0?this.visit(n):Array.isArray(n)&&n.forEach(a=>{this.visit(a)},this))}}visit(e){switch(e.type){case"Pattern":this.visitPattern(e);break;case"Flags":this.visitFlags(e);break;case"Disjunction":this.visitDisjunction(e);break;case"Alternative":this.visitAlternative(e);break;case"StartAnchor":this.visitStartAnchor(e);break;case"EndAnchor":this.visitEndAnchor(e);break;case"WordBoundary":this.visitWordBoundary(e);break;case"NonWordBoundary":this.visitNonWordBoundary(e);break;case"Lookahead":this.visitLookahead(e);break;case"NegativeLookahead":this.visitNegativeLookahead(e);break;case"Lookbehind":this.visitLookbehind(e);break;case"NegativeLookbehind":this.visitNegativeLookbehind(e);break;case"Character":this.visitCharacter(e);break;case"Set":this.visitSet(e);break;case"Group":this.visitGroup(e);break;case"GroupBackReference":this.visitGroupBackReference(e);break;case"Quantifier":this.visitQuantifier(e);break}this.visitChildren(e)}visitPattern(e){}visitFlags(e){}visitDisjunction(e){}visitAlternative(e){}visitStartAnchor(e){}visitEndAnchor(e){}visitWordBoundary(e){}visitNonWordBoundary(e){}visitLookahead(e){}visitNegativeLookahead(e){}visitLookbehind(e){}visitNegativeLookbehind(e){}visitCharacter(e){}visitSet(e){}visitGroup(e){}visitGroupBackReference(e){}visitQuantifier(e){}},s(ni,"BaseRegExpVisitor"),ni),hR=/\r?\n/gm,yR=new mR,ai,Jk=(ai=class extends Kf{constructor(){super(...arguments),this.isStarting=!0,this.endRegexpStack=[],this.multiline=!1}get endRegex(){return this.endRegexpStack.join("")}reset(e){this.multiline=!1,this.regex=e,this.startRegexp="",this.isStarting=!0,this.endRegexpStack=[]}visitGroup(e){e.quantifier&&(this.isStarting=!1,this.endRegexpStack=[])}visitCharacter(e){const r=String.fromCharCode(e.value);if(!this.multiline&&r===`
`&&(this.multiline=!0),e.quantifier)this.isStarting=!1,this.endRegexpStack=[];else{const n=il(r);this.endRegexpStack.push(n),this.isStarting&&(this.startRegexp+=n)}}visitSet(e){if(!this.multiline){const r=this.regex.substring(e.loc.begin,e.loc.end),n=new RegExp(r);this.multiline=!!`
`.match(n)}if(e.quantifier)this.isStarting=!1,this.endRegexpStack=[];else{const r=this.regex.substring(e.loc.begin,e.loc.end);this.endRegexpStack.push(r),this.isStarting&&(this.startRegexp+=r)}}visitChildren(e){e.type==="Group"&&e.quantifier||super.visitChildren(e)}},s(ai,"TerminalRegExpVisitor"),ai),On=new Jk;function gR(t){try{typeof t!="string"&&(t=t.source),t=`/${t}/`;const e=yR.pattern(t),r=[];for(const n of e.value.value)On.reset(t),On.visit(n),r.push({start:On.startRegexp,end:On.endRegex});return r}catch{return[]}}s(gR,"getTerminalParts");function iy(t){try{return typeof t=="string"&&(t=new RegExp(t)),t=t.toString(),On.reset(t),On.visit(yR.pattern(t)),On.multiline}catch{return!1}}s(iy,"isMultilineComment");var vR=`\f
\r \v              \u2028\u2029   \uFEFF`.split("");function Wf(t){const e=typeof t=="string"?new RegExp(t):t;return vR.some(r=>e.test(r))}s(Wf,"isWhitespace");function il(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}s(il,"escapeRegExp");function sy(t,e){const r=oy(t),n=e.match(r);return!!n&&n[0].length>0}s(sy,"partialMatches");function oy(t){typeof t=="string"&&(t=new RegExp(t));const e=t,r=t.source;let n=0;function a(){let i="",o;function u(c){i+=r.substr(n,c),n+=c}s(u,"appendRaw");function l(c){i+="(?:"+r.substr(n,c)+"|$)",n+=c}for(s(l,"appendOptional");n<r.length;)switch(r[n]){case"\\":switch(r[n+1]){case"c":l(3);break;case"x":l(4);break;case"u":e.unicode?r[n+2]==="{"?l(r.indexOf("}",n)-n+1):l(6):l(2);break;case"p":case"P":e.unicode?l(r.indexOf("}",n)-n+1):l(2);break;case"k":l(r.indexOf(">",n)-n+1);break;default:l(2);break}break;case"[":o=/\[(?:\\.|.)*?\]/g,o.lastIndex=n,o=o.exec(r)||[],l(o[0].length);break;case"|":case"^":case"$":case"*":case"+":case"?":u(1);break;case"{":o=/\{\d+,?\d*\}/g,o.lastIndex=n,o=o.exec(r),o?u(o[0].length):l(1);break;case"(":if(r[n+1]==="?")switch(r[n+2]){case":":i+="(?:",n+=3,i+=a()+"|$)";break;case"=":i+="(?=",n+=3,i+=a()+")";break;case"!":o=n,n+=3,a(),i+=r.substr(o,n-o);break;case"<":switch(r[n+3]){case"=":case"!":o=n,n+=4,a(),i+=r.substr(o,n-o);break;default:u(r.indexOf(">",n)-n+1),i+=a()+"|$)";break}break}else u(1),i+=a()+"|$)";break;case")":return++n,i;default:l(1);break}return i}return s(a,"process"),new RegExp(a(),t.flags)}s(oy,"partialRegExp");function ly(t){return t.rules.find(e=>mt(e)&&e.entry)}s(ly,"getEntryRule");function uy(t){return t.rules.filter(e=>jt(e)&&e.hidden)}s(uy,"getHiddenRules");function Vf(t,e){const r=new Set,n=ly(t);if(!n)return new Set(t.rules);const a=[n].concat(uy(t));for(const o of a)cy(o,r,e);const i=new Set;for(const o of t.rules)(r.has(o.name)||jt(o)&&o.hidden)&&i.add(o);return i}s(Vf,"getAllReachableRules");function cy(t,e,r){e.add(t.name),Mr(t).forEach(n=>{if(Nr(n)||r&&Ff(n)){const a=n.rule.ref;a&&!e.has(a.name)&&cy(a,e,r)}})}s(cy,"ruleDfs");function TR(t){const e=new Set;return Mr(t).forEach(r=>{Yn(r)&&(mt(r.type.ref)&&e.add(r.type.ref),Gu(r.type.ref)&&mt(r.type.ref.$container)&&e.add(r.type.ref.$container))}),e}s(TR,"getAllRulesUsedForCrossReferences");function fy(t){if(t.terminal)return t.terminal;if(t.type.ref)return Xf(t.type.ref)?.terminal}s(fy,"getCrossReferenceTerminal");function dy(t){return t.hidden&&!Wf(ju(t))}s(dy,"isCommentTerminal");function py(t,e){return!t||!e?[]:Hf(t,e,t.astNode,!0)}s(py,"findNodesForProperty");function qf(t,e,r){if(!t||!e)return;const n=Hf(t,e,t.astNode,!0);if(n.length!==0)return r!==void 0?r=Math.max(0,Math.min(r,n.length-1)):r=0,n[r]}s(qf,"findNodeForProperty");function Hf(t,e,r,n){if(!n){const a=qn(t.grammarSource,wr);if(a&&a.feature===e)return[t]}return Sr(t)&&t.astNode===r?t.content.flatMap(a=>Hf(a,e,r,!1)):[]}s(Hf,"findNodesForPropertyInternal");function $R(t,e){return t?Yf(t,e,t?.astNode):[]}s($R,"findNodesForKeyword");function my(t,e,r){if(!t)return;const n=Yf(t,e,t?.astNode);if(n.length!==0)return r!==void 0?r=Math.max(0,Math.min(r,n.length-1)):r=0,n[r]}s(my,"findNodeForKeyword");function Yf(t,e,r){if(t.astNode!==r)return[];if(Ir(t.grammarSource)&&t.grammarSource.value===e)return[t];const n=Jo(t).iterator();let a;const i=[];do if(a=n.next(),!a.done){const o=a.value;o.astNode===r?Ir(o.grammarSource)&&o.grammarSource.value===e&&i.push(o):n.prune()}while(!a.done);return i}s(Yf,"findNodesForKeywordInternal");function hy(t){const e=t.astNode;for(;e===t.container?.astNode;){const r=qn(t.grammarSource,wr);if(r)return r;t=t.container}}s(hy,"findAssignment");function Xf(t){let e=t;return Gu(e)&&(Yr(e.$container)?e=e.$container.$container:Hn(e.$container)?e=e.$container:tn(e.$container)),yy(t,e,new Map)}s(Xf,"findNameAssignment");function yy(t,e,r){function n(a,i){let o;return qn(a,wr)||(o=yy(i,i,r)),r.set(t,o),o}if(s(n,"go"),r.has(t))return r.get(t);r.set(t,void 0);for(const a of Mr(e)){if(wr(a)&&a.feature.toLowerCase()==="name")return r.set(t,a),a;if(Nr(a)&&mt(a.rule.ref))return n(a,a.rule.ref);if(Gf(a)&&a.typeRef?.ref)return n(a,a.typeRef.ref)}}s(yy,"findNameAssignmentInternal");function gy(t){const e=t.$container;if(Xn(e)){const r=e.elements,n=r.indexOf(t);for(let a=n-1;a>=0;a--){const i=r[a];if(Yr(i))return i;{const o=Mr(r[a]).find(Yr);if(o)return o}}}if(xf(e))return gy(e)}s(gy,"getActionAtElement");function RR(t,e){return t==="?"||t==="*"||Xn(e)&&!!e.guardCondition}s(RR,"isOptionalCardinality");function AR(t){return t==="*"||t==="+"}s(AR,"isArrayCardinality");function ER(t){return t==="+="}s(ER,"isArrayOperator");function Fu(t){return vy(t,new Set)}s(Fu,"isDataTypeRule");function vy(t,e){if(e.has(t))return!0;e.add(t);for(const r of Mr(t))if(Nr(r)){if(!r.rule.ref||mt(r.rule.ref)&&!vy(r.rule.ref,e)||Xo(r.rule.ref))return!1}else{if(wr(r))return!1;if(Yr(r))return!1}return!!t.definition}s(vy,"isDataTypeRuleInternal");function CR(t){return cf(t.type,new Set)}s(CR,"isDat Line truncated
`;function Fb(t,e=!1){try{const r=Ju(t);return hf(r.value,{},r.flags.ignoreCase)}catch(r){if(r.message===Gb)e&&Uy(`${mf} Unable to optimize: < ${t.toString()} >
Complement Sets cannot be automatically optimized.
This will disable the lexer's first char optimizations.
See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#COMPLEMENT for details.`);else{let n="";e&&(n=`
This will disable the lexer's first char optimizations.
See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#REGEXP_PARSING for details.`),pf(`${mf}
Failed parsing: < ${t.toString()} >
Using the @chevrotain/regexp-to-ast library
Please open an issue at: https://github.com/chevrotain/chevrotain/issues`+n)}}return[]}s(Fb,"getOptimizedStartCodesIndices");function hf(t,e,r){switch(t.type){case"Disjunction":for(let a=0;a<t.value.length;a++)hf(t.value[a],e,r);break;case"Alternative":const n=t.value;for(let a=0;a<n.length;a++){const i=n[a];switch(i.type){case"EndAnchor":case"GroupBackReference":case"Lookahead":case"NegativeLookahead":case"Lookbehind":case"NegativeLookbehind":case"StartAnchor":case"WordBoundary":case"NonWordBoundary":continue}const o=i;switch(o.type){case"Character":Xl(o.value,e,r);break;case"Set":if(o.complement===!0)throw Error(Gb);V(o.value,l=>{if(typeof l=="number")Xl(l,e,r);else{const c=l;if(r===!0)for(let f=c.from;f<=c.to;f++)Xl(f,e,r);else{for(let f=c.from;f<=c.to&&f<Zl;f++)Xl(f,e,r);if(c.to>=Zl){const f=c.from>=Zl?c.from:Zl,d=c.to,p=Or(f),y=Or(d);for(let h=p;h<=y;h++)e[h]=h}}}});break;case"Group":hf(o.value,e,r);break;default:throw Error("Non Exhaustive Match")}const u=o.quantifier!==void 0&&o.quantifier.atLeast===0;if(o.type==="Group"&&yf(o)===!1||o.type!=="Group"&&u===!1)break}break;default:throw Error("non exhaustive match!")}return Ke(e)}s(hf,"firstCharOptimizedIndices");function Xl(t,e,r){const n=Or(t);e[n]=n,r===!0&&zb(t,e)}s(Xl,"addOptimizedIdxToResult");function zb(t,e){const r=String.fromCharCode(t),n=r.toUpperCase();if(n!==r){const a=Or(n.charCodeAt(0));e[a]=a}else{const a=r.toLowerCase();if(a!==r){const i=Or(a.charCodeAt(0));e[i]=i}}}s(zb,"handleIgnoreCase");function Sm(t,e){return el(t.value,r=>{if(typeof r=="number")return vt(e,r);{const n=r;return el(e,a=>n.from<=a&&a<=n.to)!==void 0}})}s(Sm,"findCode");function yf(t){const e=t.quantifier;return e&&e.atLeast===0?!0:t.value?se(t.value)?Yt(t.value,yf):yf(t.value):!1}s(yf,"isWholeOptional");var Ti,v1=(Ti=class extends Kf{constructor(e){super(),this.targetCharCodes=e,this.found=!1}visitChildren(e){if(this.found!==!0){switch(e.type){case"Lookahead":this.visitLookahead(e);return;case"NegativeLookahead":this.visitNegativeLookahead(e);return;case"Lookbehind":this.visitLookbehind(e);return;case"NegativeLookbehind":this.visitNegativeLookbehind(e);return}super.visitChildren(e)}}visitCharacter(e){vt(this.targetCharCodes,e.value)&&(this.found=!0)}visitSet(e){e.complement?Sm(e,this.targetCharCodes)===void 0&&(this.found=!0):Sm(e,this.targetCharCodes)!==void 0&&(this.found=!0)}},s(Ti,"CharCodeFinder"),Ti);function dd(t,e){if(e instanceof RegExp){const r=Ju(e),n=new v1(t);return n.visit(r),n.found}else return el(e,r=>vt(t,r.charCodeAt(0)))!==void 0}s(dd,"canMatchCharCode");var Un="PATTERN",Jl="defaultMode",ic="modes";function jb(t,e){e=jy(e,{debug:!1,safeMode:!1,positionTracking:"full",lineTerminatorCharacters:["\r",`
`],tracer:s((w,b)=>b(),"tracer")});const r=e.tracer;r("initCharCodeToOptimizedIndexMap",()=>{l_()});let n;r("Reject Lexer.NA",()=>{n=cd(t,w=>w[Un]===pt.NA)});let a=!1,i;r("Transform Patterns",()=>{a=!1,i=j(n,w=>{const b=w[Un];if(Pr(b)){const N=b.source;return N.length===1&&N!=="^"&&N!=="$"&&N!=="."&&!b.ignoreCase?N:N.length===2&&N[0]==="\\"&&!vt(["d","D","s","S","t","r","n","t","0","c","b","B","f","v","w","W"],N[1])?N[1]:wm(b)}else{if(Gr(b))return a=!0,{exec:b};if(typeof b=="object")return a=!0,b;if(typeof b=="string"){if(b.length===1)return b;{const N=b.replace(/[\\^$.*+?()[\]{}|]/g,"\\$&"),B=new RegExp(N);return wm(B)}}else throw Error("non exhaustive match")}})});let o,u,l,c,f;r("misc mapping",()=>{o=j(n,w=>w.tokenTypeIdx),u=j(n,w=>{const b=w.GROUP;if(b!==pt.SKIPPED){if(Ct(b))return b;if(kr(b))return!1;throw Error("non exhaustive match")}}),l=j(n,w=>{const b=w.LONGER_ALT;if(b)return se(b)?j(b,B=>Fv(n,B)):[Fv(n,b)]}),c=j(n,w=>w.PUSH_MODE),f=j(n,w=>K(w,"POP_MODE"))});let d;r("Line Terminator Handling",()=>{const w=Hy(e.lineTerminatorCharacters);d=j(n,b=>!1),e.positionTracking!=="onlyOffset"&&(d=j(n,b=>K(b,"LINE_BREAKS")?!!b.LINE_BREAKS:qy(b,w)===!1&&dd(w,b.PATTERN)))});let p,y,h,T;r("Misc Mapping #2",()=>{p=j(n,Vy),y=j(i,s_),h=kt(n,(w,b)=>{const N=b.GROUP;return Ct(N)&&N!==pt.SKIPPED&&(w[N]=[]),w},{}),T=j(i,(w,b)=>({pattern:i[b],longerAlt:l[b],canLineTerminator:d[b],isCustom:p[b],short:y[b],group:u[b],push:c[b],pop:f[b],tokenTypeIdx:o[b],tokenType:n[b]}))});let C=!0,v=[];return e.safeMode||r("First Char Optimization",()=>{v=kt(n,(w,b,N)=>{if(typeof b.PATTERN=="string"){const B=b.PATTERN.charCodeAt(0),ne=Or(B);Pc(w,ne,T[N])}else if(se(b.START_CHARS_HINT)){let B;V(b.START_CHARS_HINT,ne=>{const J=typeof ne=="string"?ne.charCodeAt(0):ne,he=Or(J);B!==he&&(B=he,Pc(w,he,T[N]))})}else if(Pr(b.PATTERN))if(b.PATTERN.unicode)C=!1,e.ensureOptimizations&&pf(`${mf} Unable to analyze < ${b.PATTERN.toString()} > pattern.
The regexp unicode flag is not currently supported by the regexp-to-ast library.
This will disable the lexer's first char optimizations.
For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#UNICODE_OPTIMIZE`);else{const B=Fb(b.PATTERN,e.ensureOptimizations);Re(B)&&(C=!1),V(B,ne=>{Pc(w,ne,T[N])})}else e.ensureOptimizations&&pf(`${mf} TokenType: <${b.name}> is using a custom token pattern without providing <start_chars_hint> parameter.
This will disable the lexer's first char optimizations.
For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#CUSTOM_OPTIMIZE`),C=!1;return w},[])}),{emptyGroups:h,patternIdxToConfig:T,charCodeToPatternIdxToConfig:v,hasCustom:a,canBeOptimized:C}}s(jb,"analyzeTokenTypes");function Bb(t,e){let r=[];const n=Kb(t);r=r.concat(n.errors);const a=Wb(n.valid),i=a.valid;return r=r.concat(a.errors),r=r.concat(Ub(i)),r=r.concat(Jb(i)),r=r.concat(Zb(i,e)),r=r.concat(Qb(i)),r}s(Bb,"validatePatterns");function Ub(t){let e=[];const r=Bt(t,n=>Pr(n[Un]));return e=e.concat(Vb(r)),e=e.concat(Hb(r)),e=e.concat(Yb(r)),e=e.concat(Xb(r)),e=e.concat(qb(r)),e}s(Ub,"validateRegExpPattern");function Kb(t){const e=Bt(t,a=>!K(a,Un)),r=j(e,a=>({message:"Token Type: ->"+a.name+"<- missing static 'PATTERN' property",type:Me.MISSING_PATTERN,tokenTypes:[a]})),n=ud(t,e);return{errors:r,valid:n}}s(Kb,"findMissingPatterns");function Wb(t){const e=Bt(t,a=>{const i=a[Un];return!Pr(i)&&!Gr(i)&&!K(i,"exec")&&!Ct(i)}),r=j(e,a=>({message:"Token Type: ->"+a.name+"<- static 'PATTERN' can only be a RegExp, a Function matching the {CustomPatternMatcherFunc} type or an Object matching the {ICustomPattern} interface.",type:Me.INVALID_PATTERN,tokenTypes:[a]})),n=ud(t,e);return{errors:r,valid:n}}s(Wb,"findInvalidPatterns");var T1=/[^\\][$]/;function Vb(t){const a=class a extends Kf{constructor(){super(...arguments),this.found=!1}visitEndAnchor(o){this.found=!0}};s(a,"EndAnchorFinder");let e=a;const r=Bt(t,i=>{const o=i.PATTERN;try{const u=Ju(o),l=new e;return l.visit(u),l.found}catch{return T1.test(o.source)}});return j(r,i=>({message:`Unexpected RegExp Anchor Error:
Token Type: ->`+i.name+`<- static 'PATTERN' cannot contain end of input anchor '$'
See chevrotain.io/docs/guide/resolving_lexer_errors.html#ANCHORS for details.`,type:Me.EOI_ANCHOR_FOUND,tokenTypes:[i]}))}s(Vb,"findEndOfInputAnchor");function qb(t){const e=Bt(t,n=>n.PATTERN.test(""));return j(e,n=>({message:"Token Type: ->"+n.name+"<- static 'PATTERN' must not match an empty string",type:Me.EMPTY_MATCH_PATTERN,tokenTypes:[n]}))}s(qb,"findEmptyMatchRegExps");var $1=/[^\\[][\^]|^\^/;function Hb(t){const a=class a extends Kf{constructor(){super(...arguments),this.found=!1}visitStartAnchor(o){this.found=!0}};s(a,"StartAnchorFinder");let e=a;const r=Bt(t,i=>{const o=i.PATTERN;try{const u=Ju(o),l=new e;return l.visit(u),l.found}catch{return $1.test(o.source)}});return j(r,i=>({message:`Unexpected RegExp Anchor Error:
Token Type: ->`+i.name+`<- static 'PATTERN' cannot contain start of input anchor '^'
See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#ANCHORS for details.`,type:Me.SOI_ANCHOR_FOUND,tokenTypes:[i]}))}s(Hb,"findStartOfInputAnchor");function Yb(t){const e=Bt(t,n=>{const a=n[Un];return a instanceof RegExp&&(a.multiline||a.global)});return j(e,n=>({message:"Token Type: ->"+n.name+"<- static 'PATTERN' may NOT contain global('g') or multiline('m')",type:Me.UNSUPPORTED_FLAGS_FOUND,tokenTypes:[n]}))}s(Yb,"findUnsupportedFlags");function Xb(t){const e=[];let r=j(t,i=>kt(t,(o,u)=>(i.PATTERN.source===u.PATTERN.source&&!vt(e,u)&&u.PATTERN!==pt.NA&&(e.push(u),o.push(u)),o),[]));r=Xu(r);const n=Bt(r,i=>i.length>1);return j(n,i=>{const o=j(i,l=>l.name);return{message:`The same RegExp pattern ->${Jt(i).PATTERN}<-has been used in all of the following Token Types: ${o.join(", ")} <-`,type:Me.DUPLICATE_PATTERNS_FOUND,tokenTypes:i}})}s(Xb,"findDuplicatePatterns");function Jb(t){const e=Bt(t,n=>{if(!K(n,"GROUP"))return!1;const a=n.GROUP;return a!==pt.SKIPPED&&a!==pt.NA&&!Ct(a)});return j(e,n=>({message:"Token Type: ->"+n.name+"<- static 'GROUP' can only be Lexer.SKIPPED/Lexer.NA/A String",type:Me.INVALID_GROUP_TYPE_FOUND,tokenTypes:[n]}))}s(Jb,"findInvalidGroupType");function Zb(t,e){const r=Bt(t,a=>a.PUSH_MODE!==void 0&&!vt(e,a.PUSH_MODE));return j(r,a=>({message:`Token Type: ->${a.name}<- static 'PUSH_MODE' value cannot refer to a Lexer Mode ->${a.PUSH_MODE}<-which does not exist`,type:Me.PUSH_MODE_DOES_NOT_EXIST,tokenTypes:[a]}))}s(Zb,"findModesThatDoNotExist");function Qb(t){const e=[],r=kt(t,(n,a,i)=>{const o=a.PATTERN;return o===pt.NA||(Ct(o)?n.push({str:o,idx:i,tokenType:a}):Pr(o)&&t_(o)&&n.push({str:o.source,idx:i,tokenType:a})),n},[]);return V(t,(n,a)=>{V(r,({str:i,idx:o,tokenType:u})=>{if(a<o&&e_(i,n.PATTERN)){const l=`Token: ->${u.name}<- can never be matched.
Because it appears AFTER the Token Type ->${n.name}<-in the lexer's definition.
See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#UNREACHABLE`;e.push({message:l,type:Me.UNREACHABLE_PATTERN,tokenTypes:[n,u]})}})}),e}s(Qb,"findUnreachablePatterns");function e_(t,e){if(Pr(e)){if(r_(e))return!1;const r=e.exec(t);return r!==null&&r.index===0}else{if(Gr(e))return e(t,0,[],{});if(K(e,"exec"))return e.exec(t,0,[],{});if(typeof e=="string")return e===t;throw Error("non exhaustive match")}}s(e_,"tryToMatchStrToPattern");function t_(t){return el([".","\\","[","]","|","^","$","(",")","?","*","+","{"],r=>t.source.indexOf(r)!==-1)===void 0}s(t_,"noMetaChar");function r_(t){return/(\(\?=)|(\(\?!)|(\(\?<=)|(\(\?<!)/.test(t.source)}s(r_,"usesLookAheadOrBehind");function wm(t){const e=t.ignoreCase?"iy":"y";return new RegExp(`${t.source}`,e)}s(wm,"addStickyFlag");function n_(t,e,r){const n=[];return K(t,Jl)||n.push({message:"A MultiMode Lexer cannot be initialized without a <"+Jl+`> property in its definition
`,type:Me.MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE}),K(t,ic)||n.push({message:"A MultiMode Lexer cannot be initialized without a <"+ic+`> property in its definition
`,type:Me.MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY}),K(t,ic)&&K(t,Jl)&&!K(t.modes,t.defaultMode)&&n.push({message:`A MultiMode Lexer cannot be initialized with a ${Jl}: <${t.defaultMode}>which does not exist
`,type:Me.MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST}),K(t,ic)&&V(t.modes,(a,i)=>{V(a,(o,u)=>{if(kr(o))n.push({message:`A Lexer cannot be initialized using an undefined Token Type. Mode:<${i}> at index: <${u}>
`,type:Me.LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED});else if(K(o,"LONGER_ALT")){const l=se(o.LONGER_ALT)?o.LONGER_ALT:[o.LONGER_ALT];V(l,c=>{!kr(c)&&!vt(a,c)&&n.push({message:`A MultiMode Lexer cannot be initialized with a longer_alt <${c.name}> on token <${o.name}> outside of mode <${i}>
`,type:Me.MULTI_MODE_LEXER_LONGER_ALT_NOT_IN_CURRENT_MODE})})}})}),n}s(n_,"performRuntimeChecks");function a_(t,e,r){const n=[];let a=!1;const i=Xu(Ht(Ke(t.modes))),o=cd(i,l=>l[Un]===pt.NA),u=Hy(r);return e&&V(o,l=>{const c=qy(l,u);if(c!==!1){const d={message:o_(l,c),type:c.issue,tokenType:l};n.push(d)}else K(l,"LINE_BREAKS")?l.LINE_BREAKS===!0&&(a=!0):dd(u,l.PATTERN)&&(a=!0)}),e&&!a&&n.push({message:`Warning: No LINE_BREAKS Found.
This Lexer has been defined to track line and column information,
But none of the Token Types can be identified as matching a line terminator.
See https://chevrotain.io/docs/guide/resolving_lexer_errors.html#LINE_BREAKS
for details.`,type:Me.NO_LINE_BREAKS_FLAGS}),n}s(a_,"performWarningRuntimeChecks");function i_(t){const e={},r=Nt(t);return V(r,n=>{const a=t[n];if(se(a))e[n]=[];else throw Error("non exhaustive match")}),e}s(i_,"cloneEmptyGroups");function Vy(t){const e=t.PATTERN;if(Pr(e))return!1;if(Gr(e))return!0;if(K(e,"exec"))return!0;if(Ct(e))return!1;throw Error("non exhaustive match")}s(Vy,"isCustomPattern");function s_(t){return Ct(t)&&t.length===1?t.charCodeAt(0):!1}s(s_,"isShortPattern");var R1={test:s(function(t){const e=t.length;for(let r=this.lastIndex;r<e;r++){const n=t.charCodeAt(r);if(n===10)return this.lastIndex=r+1,!0;if(n===13)return t.charCodeAt(r+1)===10?this.lastIndex=r+2:this.lastIndex=r+1,!0}return!1},"test"),lastIndex:0};function qy(t,e){if(K(t,"LINE_BREAKS"))return!1;if(Pr(t.PATTERN)){try{dd(e,t.PATTERN)}catch(r){return{issue:Me.IDENTIFY_TERMINATOR,errMsg:r.message}}return!1}else{if(Ct(t.PATTERN))return!1;if(Vy(t))return{issue:Me.CUSTOM_LINE_BREAK};throw Error("non exhaustive match")}}s(qy,"checkLineBreaksIssues");function o_(t,e){if(e.issue===Me.IDENTIFY_TERMINATOR)return`Warning: unable to identify line terminator usage in pattern.
The problem is in the <${t.name}> Token Type
Root cause: ${e.errMsg}.
For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#IDENTIFY_TERMINATOR`;if(e.issue===Me.CUSTOM_LINE_BREAK)return`Warning: A Custom Token Pattern should specify the <line_breaks> option.
The problem is in the <${t.name}> Token Type
For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#CUSTOM_LINE_BREAK`;throw Error("non exhaustive match")}s(o_,"buildLineBreakIssueMessage");function Hy(t){return j(t,r=>Ct(r)?r.charCodeAt(0):r)}s(Hy,"getCharCodes");function Pc(t,e,r){t[e]===void 0?t[e]=[r]:t[e].push(r)}s(Pc,"addToMapOfArrays");var Zl=256,kc=[];function Or(t){return t<Zl?t:kc[t]}s(Or,"charCodeToOptimizedIndex");function l_(){if(Re(kc)){kc=new Array(65536);for(let t=0;t<65536;t++)kc[t]=t>255?255+~~(t/255):t}}s(l_,"initCharCodeToOptimizedIndexMap");function ul(t,e){const r=t.tokenTypeIdx;return r===e.tokenTypeIdx?!0:e.isParent===!0&&e.categoryMatchesMap[r]===!0}s(ul,"tokenStructuredMatcher");function _u(t,e){return t.tokenTypeIdx===e.tokenTypeIdx}s(_u,"tokenStructuredMatcherNoCategories");var jv=1,u_={};function cl(t){const e=c_(t);f_(e),p_(e),d_(e),V(e,r=>{r.isParent=r.categoryMatches.length>0})}s(cl,"augmentTokenTypes");function c_(t){let e=it(t),r=t,n=!0;for(;n;){r=Xu(Ht(j(r,i=>i.CATEGORIES)));const a=ud(r,e);e=e.concat(a),Re(a)?n=!1:r=a}return e}s(c_,"expandCategories");function f_(t){V(t,e=>{Xy(e)||(u_[jv]=e,e.tokenTypeIdx=jv++),Im(e)&&!se(e.CATEGORIES)&&(e.CATEGORIES=[e.CATEGORIES]),Im(e)||(e.CATEGORIES=[]),m_(e)||(e.categoryMatches=[]),h_(e)||(e.categoryMatchesMap={})})}s(f_,"assignTokenDefaultProps");function d_(t){V(t,e=>{e.categoryMatches=[],V(e.categoryMatchesMap,(r,n)=>{e.categoryMatches.push(u_[n].tokenTypeIdx)})})}s(d_,"assignCategoriesTokensProp");function p_(t){V(t,e=>{Yy([],e)})}s(p_,"assignCategoriesMapProp");function Yy(t,e){V(t,r=>{e.categoryMatchesMap[r.tokenTypeIdx]=!0}),V(e.CATEGORIES,r=>{const n=t.concat(e);vt(n,r)||Yy(n,r)})}s(Yy,"singleAssignCategoriesToksMap");function Xy(t){return K(t,"tokenTypeIdx")}s(Xy,"hasShortKeyProperty");function Im(t){return K(t,"CATEGORIES")}s(Im,"hasCategoriesProperty");function m_(t){return K(t,"categoryMatches")}s(m_,"hasExtendingTokensTypesProperty");function h_(t){return K(t,"categoryMatchesMap")}s(h_,"hasExtendingTokensTypesMapProperty");function y_(t){return K(t,"tokenTypeIdx")}s(y_,"isTokenType");var Nm={buildUnableToPopLexerModeMessage(t){return`Unable to pop Lexer Mode after encountering Token ->${t.image}<- The Mode Stack is empty`},buildUnexpectedCharactersMessage(t,e,r,n,a,i){return`unexpected character: ->${t.charAt(e)}<- at offset: ${e}, skipped ${r} characters.`}},Me;(function(t){t[t.MISSING_PATTERN=0]="MISSING_PATTERN",t[t.INVALID_PATTERN=1]="INVALID_PATTERN",t[t.EOI_ANCHOR_FOUND=2]="EOI_ANCHOR_FOUND",t[t.UNSUPPORTED_FLAGS_FOUND=3]="UNSUPPORTED_FLAGS_FOUND",t[t.DUPLICATE_PATTERNS_FOUND=4]="DUPLICATE_PATTERNS_FOUND",t[t.INVALID_GROUP_TYPE_FOUND=5]="INVALID_GROUP_TYPE_FOUND",t[t.PUSH_MODE_DOES_NOT_EXIST=6]="PUSH_MODE_DOES_NOT_EXIST",t[t.MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE=7]="MULTI_MODE_LEXER_WITHOUT_DEFAULT_MODE",t[t.MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY=8]="MULTI_MODE_LEXER_WITHOUT_MODES_PROPERTY",t[t.MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST=9]="MULTI_MODE_LEXER_DEFAULT_MODE_VALUE_DOES_NOT_EXIST",t[t.LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED=10]="LEXER_DEFINITION_CANNOT_CONTAIN_UNDEFINED",t[t.SOI_ANCHOR_FOUND=11]="SOI_ANCHOR_FOUND",t[t.EMPTY_MATCH_PATTERN=12]="EMPTY_MATCH_PATTERN",t[t.NO_LINE_BREAKS_FLAGS=13]="NO_LINE_BREAKS_FLAGS",t[t.UNREACHABLE_PATTERN=14]="UNREACHABLE_PATTERN",t[t.IDENTIFY_TERMINATOR=15]="IDENTIFY_TERMINATOR",t[t.CUSTOM_LINE_BREAK=16]="CUSTOM_LINE_BREAK",t[t.MULTI_MODE_LEXER_LONGER_ALT_NOT_IN_CURRENT_MODE=17]="MULTI_MODE_LEXER_LONGER_ALT_NOT_IN_CURRENT_MODE"})(Me||(Me={}));var Ql={deferDefinitionErrorsHandling:!1,positionTracking:"full",lineTerminatorsPattern:/\n|\r\n?/g,lineTerminatorCharacters:[`
`,"\r"],ensureOptimizations:!1,safeMode:!1,errorMessageProvider:Nm,traceInitPerf:!1,skipValidations:!1,recoveryEnabled:!0};Object.freeze(Ql);var $i,pt=($i=class{constructor(e,r=Ql){if(this.lexerDefinition=e,this.lexerDefinitionErrors=[],this.lexerDefinitionWarning=[],this.patternIdxToConfig={},this.charCodeToPatternIdxToConfig={},this.modes=[],this.emptyGroups={},this.trackStartLines=!0,this.trackEndLines=!0,this.hasCustom=!1,this.canModeBeOptimized={},this.TRACE_INIT=(a,i)=>{if(this.traceInitPerf===!0){this.traceInitIndent++;const o=new Array(this.traceInitIndent+1).join(" ");this.traceInitIndent<this.traceInitMaxIdent&&console.log(`${o}--> <${a}>`);const{time:u,value:l}=Ky(i),c=u>10?console.warn:console.log;return this.traceInitIndent<this.traceInitMaxIdent&&c(`${o}<-- <${a}> time: ${u}ms`),this.traceInitIndent--,l}else return i()},typeof r=="boolean")throw Error(`The second argument to the Lexer constructor is now an ILexerConfig Object.
a boolean 2nd argument is no longer supported`);this.config=Pt({},Ql,r);const n=this.config.traceInitPerf;n===!0?(this.traceInitMaxIdent=1/0,this.traceInitPerf=!0):typeof n=="number"&&(this.traceInitMaxIdent=n,this.traceInitPerf=!0),this.traceInitIndent=-1,this.TRACE_INIT("Lexer Constructor",()=>{let a,i=!0;this.TRACE_INIT("Lexer Config handling",()=>{if(this.config.lineTerminatorsPattern===Ql.lineTerminatorsPattern)this.config.lineTerminatorsPattern=R1;else if(this.config.lineTerminatorCharacters===Ql.lineTerminatorCharacters)throw Error(`Error: Missing <lineTerminatorCharacters> property on the Lexer config.
For details See: https://chevrotain.io/docs/guide/resolving_lexer_errors.html#MISSING_LINE_TERM_CHARS`);if(r.safeMode&&r.ensureOptimizations)throw Error('"safeMode" and "ensureOptimizations" flags are mutually exclusive.');this.trackStartLines=/full|onlyStart/i.test(this.config.positionTracking),this.trackEndLines=/full/i.test(this.config.positionTracking),se(e)?a={modes:{defaultMode:it(e)},defaultMode:Jl}:(i=!1,a=it(e))}),this.config.skipValidations===!1&&(this.TRACE_INIT("performRuntimeChecks",()=>{this.lexerDefinitionErrors=this.lexerDefinitionErrors.concat(n_(a,this.trackStartLines,this.config.lineTerminatorCharacters))}),this.TRACE_INIT("performWarningRuntimeChecks",()=>{this.lexerDefinitionWarning=this.lexerDefinitionWarning.concat(a_(a,this.trackStartLines,this.config.lineTerminatorCharacters))})),a.modes=a.modes?a.modes:{},V(a.modes,(u,l)=>{a.modes[l]=cd(u,c=>kr(c))});const o=Nt(a.modes);if(V(a.modes,(u,l)=>{this.TRACE_INIT(`Mode: <${l}> processing`,()=>{if(this.modes.push(l),this.config.skipValidations===!1&&this.TRACE_INIT("validatePatterns",()=>{this.lexerDefinitionErrors=this.lexerDefinitionErrors.concat(Bb(u,o))}),Re(this.lexerDefinitionErrors)){cl(u);let c;this.TRACE_INIT("analyzeTokenTypes",()=>{c=jb(u,{lineTerminatorCharacters:this.config.lineTerminatorCharacters,positionTracking:r.positionTracking,ensureOptimizations:r.ensureOptimizations,safeMode:r.safeMode,tracer:this.TRACE_INIT})}),this.patternIdxToConfig[l]=c.patternIdxToConfig,this.charCodeToPatternIdxToConfig[l]=c.charCodeToPatternIdxToConfig,this.emptyGroups=Pt({},this.emptyGroups,c.emptyGroups),this.hasCustom=c.hasCustom||this.hasCustom,this.canModeBeOptimized[l]=c.canBeOptimized}})}),this.defaultMode=a.defaultMode,!Re(this.lexerDefinitionErrors)&&!this.config.deferDefinitionErrorsHandling){const l=j(this.lexerDefinitionErrors,c=>c.message).join(`-----------------------
`);throw new Error(`Errors detected in definition of Lexer:
`+l)}V(this.lexerDefinitionWarning,u=>{Uy(u.message)}),this.TRACE_INIT("Choosing sub-methods implementations",()=>{if(i&&(this.handleModes=He),this.trackStartLines===!1&&(this.computeNewColumn=Ku),this.trackEndLines===!1&&(this.updateTokenEndLineColumnLocation=He),/full/i.test(this.config.positionTracking))this.createTokenInstance=this.createFullToken;else if(/onlyStart/i.test(this.config.positionTracking))this.createTokenInstance=this.createStartOnlyToken;else if(/onlyOffset/i.test(this.config.positionTracking))this.createTokenInstance=this.createOffsetOnlyToken;else throw Error(`Invalid <positionTracking> config option: "${this.config.positionTracking}"`);this.hasCustom?(this.addToken=this.addTokenUsingPush,this.handlePayload=this.handlePayloadWithCustom):(this.addToken=this.addTokenUsingMemberAccess,this.handlePayload=this.handlePayloadNoCustom)}),this.TRACE_INIT("Failed Optimization Warnings",()=>{const u=kt(this.canModeBeOptimized,(l,c,f)=>(c===!1&&l.push(f),l),[]);if(r.ensureOptimizations&&!Re(u))throw Error(`Lexer Modes: < ${u.join(", ")} > cannot be optimized.
Disable the "ensureOptimizations" lexer config flag to silently ignore this and run the lexer in an un-optimized mode.
Or inspect the console log for details on how to resolve these issues.`)}),this.TRACE_INIT("clearRegExpParserCache",()=>{Mb()}),this.TRACE_INIT("toFastProperties",()=>{Wy(this)})})}tokenize(e,r=this.defaultMode){if(!Re(this.lexerDefinitionErrors)){const a=j(this.lexerDefinitionErrors,i=>i.message).join(`-----------------------
`);throw new Error(`Unable to Tokenize because Errors detected in definition of Lexer:
`+a)}return this.tokenizeInternal(e,r)}tokenizeInternal(e,r){let n,a,i,o,u,l,c,f,d,p,y,h,T,C,v;const w=e,b=w.length;let N=0,B=0;const ne=this.hasCustom?0:Math.floor(e.length/10),J=new Array(ne),he=[];let Ae=this.trackStartLines?1:void 0,ye=this.trackStartLines?1:void 0;const ue=i_(this.emptyGroups),ot=this.trackStartLines,k=this.config.lineTerminatorsPattern;let _=0,$=[],I=[];const R=[],A=[];Object.freeze(A);let S=!1;const L=s(M=>{if(R.length===1&&M.tokenType.PUSH_MODE===void 0){const Y=this.config.errorMessageProvider.buildUnableToPopLexerModeMessage(M);he.push({offset:M.startOffset,line:M.startLine,column:M.startColumn,length:M.image.length,message:Y})}else{R.pop();const Y=Bn(R);$=this.patternIdxToConfig[Y],I=this.charCodeToPatternIdxToConfig[Y],_=$.length;const q=this.canModeBeOptimized[Y]&&this.config.safeMode===!1;I&&q?S=!0:S=!1}},"pop_mode");function x(M){R.push(M),I=this.charCodeToPatternIdxToConfig[M],$=this.patternIdxToConfig[M],_=$.length,_=$.length;const Y=this.canModeBeOptimized[M]&&this.config.safeMode===!1;I&&Y?S=!0:S=!1}s(x,"push_mode"),x.call(this,r);let O;const z=this.config.recoveryEnabled;for(;N<b;){l=null,d=-1;const M=w.charCodeAt(N);let Y;if(S){const Z=Or(M),ae=I[Z];Y=ae!==void 0?ae:A}else Y=$;const q=Y.length;for(n=0;n<q;n++){O=Y[n];const Z=O.pattern;c=null;const ae=O.short;if(ae!==!1?M===ae&&(d=1,l=Z):O.isCustom===!0?(v=Z.exec(w,N,J,ue),v!==null?(l=v[0],d=l.length,v.payload!==void 0&&(c=v.payload)):l=null):(Z.lastIndex=N,d=this.matchLength(Z,e,N)),d!==-1){if(u=O.longerAlt,u!==void 0){l=e.substring(N,N+d);const Oe=u.length;for(i=0;i<Oe;i++){const pe=$[u[i]],Ee=pe.pattern;if(f=null,pe.isCustom===!0?(v=Ee.exec(w,N,J,ue),v!==null?(o=v[0],v.payload!==void 0&&(f=v.payload)):o=null):(Ee.lastIndex=N,o=this.match(Ee,e,N)),o&&o.length>l.length){l=o,d=o.length,c=f,O=pe;break}}}break}}if(d!==-1){if(p=O.group,p!==void 0&&(l=l!==null?l:e.substring(N,N+d),y=O.tokenTypeIdx,h=this.createTokenInstance(l,N,y,O.tokenType,Ae,ye,d),this.handlePayload(h,c),p===!1?B=this.addToken(J,B,h):ue[p].push(h)),ot===!0&&O.canLineTerminator===!0){let Z=0,ae,Oe;k.lastIndex=0;do l=l!==null?l:e.substring(N,N+d),ae=k.test(l),ae===!0&&(Oe=k.lastIndex-1,Z++);while(ae===!0);Z!==0?(Ae=Ae+Z,ye=d-Oe,this.updateTokenEndLineColumnLocation(h,p,Oe,Z,Ae,ye,d)):ye=this.computeNewColumn(ye,d)}else ye=this.computeNewColumn(ye,d);N=N+d,this.handleModes(O,L,x,h)}else{const Z=N,ae=Ae,Oe=ye;let pe=z===!1;for(;pe===!1&&N<b;)for(N++,a=0;a<_;a++){const Ee=$[a],Ve=Ee.pattern,Le=Ee.short;if(Le!==!1?w.charCodeAt(N)===Le&&(pe=!0):Ee.isCustom===!0?pe=Ve.exec(w,N,J,ue)!==null:(Ve.lastIndex=N,pe=Ve.exec(e)!==null),pe===!0)break}if(T=N-Z,ye=this.computeNewColumn(ye,T),C=this.config.errorMessageProvider.buildUnexpectedCharactersMessage(w,Z,T,ae,Oe,Bn(R)),he.push({offset:Z,line:ae,column:Oe,length:T,message:C}),z===!1)break}}return this.hasCustom||(J.length=B),{tokens:J,groups:ue,errors:he}}handleModes(e,r,n,a){if(e.pop===!0){const i=e.push;r(a),i!==void 0&&n.call(this,i)}else e.push!==void 0&&n.call(this,e.push)}updateTokenEndLineColumnLocation(e,r,n,a,i,o,u){let l,c;r!==void 0&&(l=n===u-1,c=l?-1:0,a===1&&l===!0||(e.endLine=i+c,e.endColumn=o-1+-c))}computeNewColumn(e,r){return e+r}createOffsetOnlyToken(e,r,n,a){return{image:e,startOffset:r,tokenTypeIdx:n,tokenType:a}}createStartOnlyToken(e,r,n,a,i,o){return{image:e,startOffset:r,startLine:i,startColumn:o,tokenTypeIdx:n,tokenType:a}}createFullToken(e,r,n,a,i,o,u){return{image:e,startOffset:r,endOffset:r+u-1,startLine:i,endLine:i,startColumn:o,endColumn:o+u-1,tokenTypeIdx:n,tokenType:a}}addTokenUsingPush(e,r,n){return e.push(n),r}addTokenUsingMemberAccess(e,r,n){return e[r]=n,r++,r}handlePayloadNoCustom(e,r){}handlePayloadWithCustom(e,r){r!==null&&(e.payload=r)}match(e,r,n){return e.test(r)===!0?r.substring(n,e.lastIndex):null}matchLength(e,r,n){return e.test(r)===!0?e.lastIndex-n:-1}},s($i,"Lexer"),$i);pt.SKIPPED="This marks a skipped Token pattern, this means each token identified by it will be consumed and then thrown into oblivion, this can be used to for example to completely ignore whitespace.";pt.NA=/NOT_APPLICABLE/;function Mn(t){return Jy(t)?t.LABEL:t.name}s(Mn,"tokenLabel");function Jy(t){return Ct(t.LABEL)&&t.LABEL!==""}s(Jy,"hasTokenLabel");var A1="parent",Bv="categories",Uv="label",Kv="group",Wv="push_mode",Vv="pop_mode",qv="longer_alt",Hv="line_breaks",Yv="start_chars_hint";function Xa(t){return g_(t)}s(Xa,"createToken");function g_(t){const e=t.pattern,r={};if(r.name=t.name,kr(e)||(r.PATTERN=e),K(t,A1))throw`The parent property is no longer supported.
See: https://github.com/chevrotain/chevrotain/issues/564#issuecomment-349062346 for details.`;return K(t,Bv)&&(r.CATEGORIES=t[Bv]),cl([r]),K(t,Uv)&&(r.LABEL=t[Uv]),K(t,Kv)&&(r.GROUP=t[Kv]),K(t,Vv)&&(r.POP_MODE=t[Vv]),K(t,Wv)&&(r.PUSH_MODE=t[Wv]),K(t,qv)&&(r.LONGER_ALT=t[qv]),K(t,Hv)&&(r.LINE_BREAKS=t[Hv]),K(t,Yv)&&(r.START_CHARS_HINT=t[Yv]),r}s(g_,"createTokenInternal");var Jr=Xa({name:"EOF",pattern:pt.NA});cl([Jr]);function Zu(t,e,r,n,a,i,o,u){return{image:e,startOffset:r,endOffset:n,startLine:a,endLine:i,startColumn:o,endColumn:u,tokenTypeIdx:t.tokenTypeIdx,tokenType:t}}s(Zu,"createTokenInstance");function Zy(t,e){return ul(t,e)}s(Zy,"tokenMatcher");var qa={buildMismatchTokenMessage({expected:t,actual:e,previous:r,ruleName:n}){return`Expecting ${Jy(t)?`--> ${Mn(t)} <--`:`token of type --> ${t.name} <--`} but found --> '${e.image}' <--`},buildNotAllInputParsedMessage({firstRedundant:t,ruleName:e}){return"Redundant input, expecting EOF but found: "+t.image},buildNoViableAltMessage({expectedPathsPerAlt:t,actual:e,previous:r,customUserDescription:n,ruleName:a}){const i="Expecting: ",u=`
but found: '`+Jt(e).image+"'";if(n)return i+n+u;{const l=kt(t,(p,y)=>p.concat(y),[]),c=j(l,p=>`[${j(p,y=>Mn(y)).join(", ")}]`),d=`one of these possible Token sequences:
${j(c,(p,y)=>` ${y+1}. ${p}`).join(`
`)}`;return i+d+u}},buildEarlyExitMessage({expectedIterationPaths:t,actual:e,customUserDescription:r,ruleName:n}){const a="Expecting: ",o=`
but found: '`+Jt(e).image+"'";if(r)return a+r+o;{const l=`expecting at least one iteration which starts with one of these possible Token sequences::
<${j(t,c=>`[${j(c,f=>Mn(f)).join(",")}]`).join(" ,")}>`;return a+l+o}}};Object.freeze(qa);var E1={buildRuleNotFoundError(t,e){return"Invalid grammar, reference to a rule which is not defined: ->"+e.nonTerminalName+`<-
inside top level rule: ->`+t.name+"<-"}},Ln={buildDuplicateFoundError(t,e){function r(f){return f instanceof Se?f.terminalType.name:f instanceof ht?f.nonTerminalName:""}s(r,"getExtraProductionArgument");const n=t.name,a=Jt(e),i=a.idx,o=Kt(a),u=r(a),l=i>0;let c=`->${o}${l?i:""}<- ${u?`with argument: ->${u}<-`:""}
appears more than once (${e.length} times) in the top level rule: ->${n}<-.
For further details see: https://chevrotain.io/docs/FAQ.html#NUMERICAL_SUFFIXES
`;return c=c.replace(/[ \t]+/g," "),c=c.replace(/\s\s+/g,`
`),c},buildNamespaceConflictError(t){return`Namespace conflict found in grammar.
The grammar has both a Terminal(Token) and a Non-Terminal(Rule) named: <${t.name}>.
To resolve this make sure each Terminal and Non-Terminal names are unique
This is easy to accomplish by using the convention that Terminal names start with an uppercase letter
and Non-Terminal names start with a lower case letter.`},buildAlternationPrefixAmbiguityError(t){const e=j(t.prefixPath,a=>Mn(a)).join(", "),r=t.alternation.idx===0?"":t.alternation.idx;return`Ambiguous alternatives: <${t.ambiguityIndices.join(" ,")}> due to common lookahead prefix
in <OR${r}> inside <${t.topLevelRule.name}> Rule,
<${e}> may appears as a prefix path in all these alternatives.
See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#COMMON_PREFIX
For Further details.`},buildAlternationAmbiguityError(t){const e=t.alternation.idx===0?"":t.alternation.idx,r=t.prefixPath.length===0;let n=`Ambiguous Alternatives Detected: <${t.ambiguityIndices.join(" ,")}> in <OR${e}> inside <${t.topLevelRule.name}> Rule,
`;if(r)n+=`These alternatives are all empty (match no tokens), making them indistinguishable.
Only the last alternative may be empty.
`;else{const a=j(t.prefixPath,i=>Mn(i)).join(", ");n+=`<${a}> may appears as a prefix path in all these alternatives.
`}return n+=`See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#AMBIGUOUS_ALTERNATIVES
For Further details.`,n},buildEmptyRepetitionError(t){let e=Kt(t.repetition);return t.repetition.idx!==0&&(e+=t.repetition.idx),`The repetition <${e}> within Rule <${t.topLevelRule.name}> can never consume any tokens.
This could lead to an infinite loop.`},buildTokenNameError(t){return"deprecated"},buildEmptyAlternationError(t){return`Ambiguous empty alternative: <${t.emptyChoiceIdx+1}> in <OR${t.alternation.idx}> inside <${t.topLevelRule.name}> Rule.
Only the last alternative may be an empty alternative.`},buildTooManyAlternativesError(t){return`An Alternation cannot have more than 256 alternatives:
<OR${t.alternation.idx}> inside <${t.topLevelRule.name}> Rule.
has ${t.alternation.definition.length+1} alternatives.`},buildLeftRecursionError(t){const e=t.topLevelRule.name,r=j(t.leftRecursionPath,i=>i.name),n=`${e} --> ${r.concat([e]).join(" --> ")}`;return`Left Recursion found in grammar.
rule: <${e}> can be invoked from itself (directly or indirectly)
without consuming any Tokens. The grammar path that causes this is:
${n}
To fix this refactor your grammar to remove the left recursion.
see: https://en.wikipedia.org/wiki/LL_parser#Left_factoring.`},buildInvalidRuleNameError(t){return"deprecated"},buildDuplicateRuleNameError(t){let e;return t.topLevelRule instanceof sl?e=t.topLevelRule.name:e=t.topLevelRule,`Duplicate definition, rule: ->${e}<- is already defined in the grammar: ->${t.grammarName}<-`}};function v_(t,e){const r=new C1(t,e);return r.resolveRefs(),r.errors}s(v_,"resolveGrammar");var Ri,C1=(Ri=class extends ol{constructor(e,r){super(),this.nameToTopRule=e,this.errMsgProvider=r,this.errors=[]}resolveRefs(){V(Ke(this.nameToTopRule),e=>{this.currTopLevel=e,e.accept(this)})}visitNonTerminal(e){const r=this.nameToTopRule[e.nonTerminalName];if(r)e.referencedRule=r;else{const n=this.errMsgProvider.buildRuleNotFoundError(this.currTopLevel,e);this.errors.push({message:n,type:yt.UNRESOLVED_SUBRULE_REF,ruleName:this.currTopLevel.name,unresolvedRefName:e.nonTerminalName})}}},s(Ri,"GastRefResolverVisitor"),Ri),Ai,b1=(Ai=class extends fd{constructor(e,r){super(),this.topProd=e,this.path=r,this.possibleTokTypes=[],this.nextProductionName="",this.nextProductionOccurrence=0,this.found=!1,this.isAtEndOfPath=!1}startWalking(){if(this.found=!1,this.path.ruleStack[0]!==this.topProd.name)throw Error("The path does not start with the walker's top Rule!");return this.ruleStack=it(this.path.ruleStack).reverse(),this.occurrenceStack=it(this.path.occurrenceStack).reverse(),this.ruleStack.pop(),this.occurrenceStack.pop(),this.updateExpectedNext(),this.walk(this.topProd),this.possibleTokTypes}walk(e,r=[]){this.found||super.walk(e,r)}walkProdRef(e,r,n){if(e.referencedRule.name===this.nextProductionName&&e.idx===this.nextProductionOccurrence){const a=r.concat(n);this.updateExpectedNext(),this.walk(e.referencedRule,a)}}updateExpectedNext(){Re(this.ruleStack)?(this.nextProductionName="",this.nextProductionOccurrence=0,this.isAtEndOfPath=!0):(this.nextProductionName=this.ruleStack.pop(),this.nextProductionOccurrence=this.occurrenceStack.pop())}},s(Ai,"AbstractNextPossibleTokensWalker"),Ai),Ei,_1=(Ei=class extends b1{constructor(e,r){super(e,r),this.path=r,this.nextTerminalName="",this.nextTerminalOccurrence=0,this.nextTerminalName=this.path.lastTok.name,this.nextTerminalOccurrence=this.path.lastTokOccurrence}walkTerminal(e,r,n){if(this.isAtEndOfPath&&e.terminalType.name===this.nextTerminalName&&e.idx===this.nextTerminalOccurrence&&!this.found){const a=r.concat(n),i=new bt({definition:a});this.possibleTokTypes=ll(i),this.found=!0}}},s(Ei,"NextAfterTokenWalker"),Ei),Ci,pd=(Ci=class extends fd{constructor(e,r){super(),this.topRule=e,this.occurrence=r,this.result={token:void 0,occurrence:void 0,isEndOfRule:void 0}}startWalking(){return this.walk(this.topRule),this.result}},s(Ci,"AbstractNextTerminalAfterProductionWalker"),Ci),bi,S1=(bi=class extends pd{walkMany(e,r,n){if(e.idx===this.occurrence){const a=Jt(r.concat(n));this.result.isEndOfRule=a===void 0,a instanceof Se&&(this.result.token=a.terminalType,this.result.occurrence=a.idx)}else super.walkMany(e,r,n)}},s(bi,"NextTerminalAfterManyWalker"),bi),_i,Xv=(_i=class extends pd{walkManySep(e,r,n){if(e.idx===this.occurrence){const a=Jt(r.concat(n));this.result.isEndOfRule=a===void 0,a instanceof Se&&(this.result.token=a.terminalType,this.result.occurrence=a.idx)}else super.walkManySep(e,r,n)}},s(_i,"NextTerminalAfterManySepWalker"),_i),Si,w1=(Si=class extends pd{walkAtLeastOne(e,r,n){if(e.idx===this.occurrence){const a=Jt(r.concat(n));this.result.isEndOfRule=a===void 0,a instanceof Se&&(this.result.token=a.terminalType,this.result.occurrence=a.idx)}else super.walkAtLeastOne(e,r,n)}},s(Si,"NextTerminalAfterAtLeastOneWalker"),Si),wi,Jv=(wi=class extends pd{walkAtLeastOneSep(e,r,n){if(e.idx===this.occurrence){const a=Jt(r.concat(n));this.result.isEndOfRule=a===void 0,a instanceof Se&&(this.result.token=a.terminalType,this.result.occurrence=a.idx)}else super.walkAtLeastOneSep(e,r,n)}},s(wi,"NextTerminalAfterAtLeastOneSepWalker"),wi);function gf(t,e,r=[]){r=it(r);let n=[],a=0;function i(u){return u.concat(nt(t,a+1))}s(i,"remainingPathWith");function o(u){const l=gf(i(u),e,r);return n.concat(l)}for(s(o,"getAlternativesForProd");r.length<e&&a<t.length;){const u=t[a];if(u instanceof bt)return o(u.definition);if(u instanceof ht)return o(u.definition);if(u instanceof at)n=o(u.definition);else if(u instanceof Ot){const l=u.definition.concat([new xe({definition:u.definition})]);return o(l)}else if(u instanceof Lt){const l=[new bt({definition:u.definition}),new xe({definition:[new Se({terminalType:u.separator})].concat(u.definition)})];return o(l)}else if(u instanceof _t){const l=u.definition.concat([new xe({definition:[new Se({terminalType:u.separator})].concat(u.definition)})]);n=o(l)}else if(u instanceof xe){const l=u.definition.concat([new xe({definition:u.definition})]);n=o(l)}else{if(u instanceof St)return V(u.definition,l=>{Re(l.definition)===!1&&(n=o(l.definition))}),n;if(u instanceof Se)r.push(u.terminalType);else throw Error("non exhaustive match")}a++}return n.push({p Line truncated
${i.join(`
`).replace(/\n/g,`
`)}`)}},"validateVisitor")};return r.prototype=n,r.prototype.constructor=r,r._RULE_NAMES=e,r}s(rS,"createBaseSemanticVisitorConstructor");function nS(t,e,r){const n=s(function(){},"derivedConstructor");sg(n,t+"BaseSemanticsWithDefaults");const a=Object.create(r.prototype);return V(e,i=>{a[i]=tS}),n.prototype=a,n.prototype.constructor=n,n}s(nS,"createBaseVisitorConstructorWithDefaults");var Gm;(function(t){t[t.REDUNDANT_METHOD=0]="REDUNDANT_METHOD",t[t.MISSING_METHOD=1]="MISSING_METHOD"})(Gm||(Gm={}));function aS(t,e){return iS(t,e)}s(aS,"validateVisitor");function iS(t,e){const r=Bt(e,a=>Gr(t[a])===!1),n=j(r,a=>({msg:`Missing visitor method: <${a}> on ${t.constructor.name} CST Visitor.`,type:Gm.MISSING_METHOD,methodName:a}));return Xu(n)}s(iS,"validateMissingCstMethods");var Ki,j1=(Ki=class{initTreeBuilder(e){if(this.CST_STACK=[],this.outputCst=e.outputCst,this.nodeLocationTracking=K(e,"nodeLocationTracking")?e.nodeLocationTracking:Lr.nodeLocationTracking,!this.outputCst)this.cstInvocationStateUpdate=He,this.cstFinallyStateUpdate=He,this.cstPostTerminal=He,this.cstPostNonTerminal=He,this.cstPostRule=He;else if(/full/i.test(this.nodeLocationTracking))this.recoveryEnabled?(this.setNodeLocationFromToken=Mm,this.setNodeLocationFromNode=Mm,this.cstPostRule=He,this.setInitialNodeLocation=this.setInitialNodeLocationFullRecovery):(this.setNodeLocationFromToken=He,this.setNodeLocationFromNode=He,this.cstPostRule=this.cstPostRuleFull,this.setInitialNodeLocation=this.setInitialNodeLocationFullRegular);else if(/onlyOffset/i.test(this.nodeLocationTracking))this.recoveryEnabled?(this.setNodeLocationFromToken=xm,this.setNodeLocationFromNode=xm,this.cstPostRule=He,this.setInitialNodeLocation=this.setInitialNodeLocationOnlyOffsetRecovery):(this.setNodeLocationFromToken=He,this.setNodeLocationFromNode=He,this.cstPostRule=this.cstPostRuleOnlyOffset,this.setInitialNodeLocation=this.setInitialNodeLocationOnlyOffsetRegular);else if(/none/i.test(this.nodeLocationTracking))this.setNodeLocationFromToken=He,this.setNodeLocationFromNode=He,this.cstPostRule=He,this.setInitialNodeLocation=He;else throw Error(`Invalid <nodeLocationTracking> config option: "${e.nodeLocationTracking}"`)}setInitialNodeLocationOnlyOffsetRecovery(e){e.location={startOffset:NaN,endOffset:NaN}}setInitialNodeLocationOnlyOffsetRegular(e){e.location={startOffset:this.LA(1).startOffset,endOffset:NaN}}setInitialNodeLocationFullRecovery(e){e.location={startOffset:NaN,startLine:NaN,startColumn:NaN,endOffset:NaN,endLine:NaN,endColumn:NaN}}setInitialNodeLocationFullRegular(e){const r=this.LA(1);e.location={startOffset:r.startOffset,startLine:r.startLine,startColumn:r.startColumn,endOffset:NaN,endLine:NaN,endColumn:NaN}}cstInvocationStateUpdate(e){const r={name:e,children:Object.create(null)};this.setInitialNodeLocation(r),this.CST_STACK.push(r)}cstFinallyStateUpdate(){this.CST_STACK.pop()}cstPostRuleFull(e){const r=this.LA(0),n=e.location;n.startOffset<=r.startOffset?(n.endOffset=r.endOffset,n.endLine=r.endLine,n.endColumn=r.endColumn):(n.startOffset=NaN,n.startLine=NaN,n.startColumn=NaN)}cstPostRuleOnlyOffset(e){const r=this.LA(0),n=e.location;n.startOffset<=r.startOffset?n.endOffset=r.endOffset:n.startOffset=NaN}cstPostTerminal(e,r){const n=this.CST_STACK[this.CST_STACK.length-1];Q_(n,r,e),this.setNodeLocationFromToken(n.location,r)}cstPostNonTerminal(e,r){const n=this.CST_STACK[this.CST_STACK.length-1];eS(n,r,e),this.setNodeLocationFromNode(n.location,e.location)}getBaseCstVisitorConstructor(){if(kr(this.baseCstVisitorConstructor)){const e=rS(this.className,Nt(this.gastProductionsCache));return this.baseCstVisitorConstructor=e,e}return this.baseCstVisitorConstructor}getBaseCstVisitorConstructorWithDefaults(){if(kr(this.baseCstVisitorWithDefaultsConstructor)){const e=nS(this.className,Nt(this.gastProductionsCache),this.getBaseCstVisitorConstructor());return this.baseCstVisitorWithDefaultsConstructor=e,e}return this.baseCstVisitorWithDefaultsConstructor}getLastExplicitRuleShortName(){const e=this.RULE_STACK;return e[e.length-1]}getPreviousExplicitRuleShortName(){const e=this.RULE_STACK;return e[e.length-2]}getLastExplicitRuleOccurrenceIndex(){const e=this.RULE_OCCURRENCE_STACK;return e[e.length-1]}},s(Ki,"TreeBuilder"),Ki),Wi,B1=(Wi=class{initLexerAdapter(){this.tokVector=[],this.tokVectorLength=0,this.currIdx=-1}set input(e){if(this.selfAnalysisDone!==!0)throw Error("Missing <performSelfAnalysis> invocation at the end of the Parser's constructor.");this.reset(),this.tokVector=e,this.tokVectorLength=e.length}get input(){return this.tokVector}SKIP_TOKEN(){return this.currIdx<=this.tokVector.length-2?(this.consumeToken(),this.LA(1)):Tf}LA(e){const r=this.currIdx+e;return r<0||this.tokVectorLength<=r?Tf:this.tokVector[r]}consumeToken(){this.currIdx++}exportLexerState(){return this.currIdx}importLexerState(e){this.currIdx=e}resetLexerState(){this.currIdx=-1}moveToTerminatedState(){this.currIdx=this.tokVector.length-1}getLexerPosition(){return this.exportLexerState()}},sLine truncated
See: https://chevrotain.io/docs/changes/BREAKING_CHANGES.html#_6-0-0
For Further details.`);if(se(e)){if(Re(e))throw Error(`A Token Vocabulary cannot be empty.
Note that the first argument for the parser constructor
is no longer a Token vector (since v4.0).`);if(typeof e[0].startOffset=="number")throw Error(`The Parser constructor no longer accepts a token vector as the first argument.
See: https://chevrotain.io/docs/changes/BREAKING_CHANGES.html#_4-0-0
For Further details.`)}if(se(e))this.tokensMap=kt(e,(i,o)=>(i[o.name]=o,i),{});else if(K(e,"modes")&&Yt(Ht(Ke(e.modes)),y_)){const i=Ht(Ke(e.modes)),o=By(i);this.tokensMap=kt(o,(u,l)=>(u[l.name]=l,u),{})}else if(zt(e))this.tokensMap=it(e);else throw new Error("<tokensDictionary> argument must be An Array of Token constructors, A dictionary of Token constructors or an IMultiModeLexerDefinition");this.tokensMap.EOF=Jr;const n=K(e,"modes")?Ht(Ke(e.modes)):Ke(e),a=Yt(n,i=>Re(i.categoryMatches));this.tokenMatcher=a?_u:ul,cl(Ke(this.tokensMap))}defineRule(e,r,n){if(this.selfAnalysisDone)throw Error(`Grammar rule <${e}> may not be defined after the 'performSelfAnalysis' method has been called'
Make sure that all grammar rule definitions are done before 'performSelfAnalysis' is called.`);const a=K(n,"resyncEnabled")?n.resyncEnabled:$f.resyncEnabled,i=K(n,"recoveryValueFunc")?n.recoveryValueFunc:$f.recoveryValueFunc,o=this.ruleShortNameIdx<<M1+nn;this.ruleShortNameIdx++,this.shortRuleNameToFull[o]=e,this.fullRuleNameToShort[e]=o;let u;return this.outputCst===!0?u=s(function(...f){try{this.ruleInvocationStateUpdate(o,e,this.subruleIdx),r.apply(this,f);const d=this.CST_STACK[this.CST_STACK.length-1];return this.cstPostRule(d),d}catch(d){return this.invokeRuleCatch(d,a,i)}finally{this.ruleFinallyStateUpdate()}},"invokeRuleWithTry"):u=s(function(...f){try{return this.ruleInvocationStateUpdate(o,e,this.subruleIdx),r.apply(this,f)}catch(d){return this.invokeRuleCatch(d,a,i)}finally{this.ruleFinallyStateUpdate()}},"invokeRuleWithTryCst"),Object.assign(u,{ruleName:e,originalGrammarAction:r})}invokeRuleCatch(e,r,n){const a=this.RULE_STACK.length===1,i=r&&!this.isBackTracking()&&this.recoveryEnabled;if(Su(e)){const o=e;if(i){const u=this.findReSyncTokenType();if(this.isInCurrentRuleReSyncSet(u))if(o.resyncedTokens=this.reSyncTo(u),this.outputCst){const l=this.CST_STACK[this.CST_STACK.length-1];return l.recoveredNode=!0,l}else return n(e);else{if(this.outputCst){const l=this.CST_STACK[this.CST_STACK.length-1];l.recoveredNode=!0,o.partialCstResult=l}throw o}}else{if(a)return this.moveToTerminatedState(),n(e);throw o}}else throw e}optionInternal(e,r){const n=this.getKeyForAutomaticLookahead(J_,r);return this.optionInternalLogic(e,r,n)}optionInternalLogic(e,r,n){let a=this.getLaFuncFromCache(n),i;if(typeof e!="function"){i=e.DEF;const o=e.GATE;if(o!==void 0){const u=a;a=s(()=>o.call(this)&&u.call(this),"lookAheadFunc")}}else i=e;if(a.call(this)===!0)return i.call(this)}atLeastOneInternal(e,r){const n=this.getKeyForAutomaticLookahead(Lm,e);return this.atLeastOneInternalLogic(e,r,n)}atLeastOneInternalLogic(e,r,n){let a=this.getLaFuncFromCache(n),i;if(typeof r!="function"){i=r.DEF;const o=r.GATE;if(o!==void 0){const u=a;a=s(()=>o.call(this)&&u.call(this),"lookAheadFunc")}}else i=r;if(a.call(this)===!0){let o=this.doSingleRepetition(i);for(;a.call(this)===!0&&o===!0;)o=this.doSingleRepetition(i)}else throw this.raiseEarlyExitException(e,Pe.REPETITION_MANDATORY,r.ERR_MSG);this.attemptInRepetitionRecovery(this.atLeastOneInternal,[e,r],a,Lm,e,w1)}atLeastOneSepFirstInternal(e,r){const n=this.getKeyForAutomaticLookahead(Lc,e);this.atLeastOneSepFirstInternalLogic(e,r,n)}atLeastOneSepFirstInternalLogic(e,r,n){const a=r.DEF,i=r.SEP;if(this.getLaFuncFromCache(n).call(this)===!0){a.call(this);const u=s(()=>this.tokenMatcher(this.LA(1),i),"separatorLookAheadFunc");for(;this.tokenMatcher(this.LA(1),i)===!0;)this.CONSUME(i),a.call(this);this.attemptInRepetitionRecovery(this.repetitionSepSecondInternal,[e,i,u,a,Jv],u,Lc,e,Jv)}else throw this.raiseEarlyExitException(e,Pe.REPETITION_MANDATORY_WITH_SEPARATOR,r.ERR_MSG)}manyInternal(e,r){const n=this.getKeyForAutomaticLookahead(Om,e);return this.manyInternalLogic(e,r,n)}manyInternalLogic(e,r,n){let a=this.getLaFuncFromCache(n),i;if(typeof r!="function"){i=r.DEF;const u=r.GATE;if(u!==void 0){const l=a;a=s(()=>u.call(this)&&l.call(this),"lookaheadFunction")}}else i=r;let o=!0;for(;a.call(this)===!0&&o===!0;)o=this.doSingleRepetition(i);this.attemptInRepetitionRecovery(this.manyInternal,[e,r],a,Om,e,S1,o)}manySepFirstInternal(e,r){const n=this.getKeyForAutomaticLookahead(Dm,e);this.manySepFirstInternalLogic(e,r,n)}manySepFirstInternalLogic(e,r,n){const a=r.DEF,i=r.SEP;if(this.getLaFuncFromCache(n).call(this)===!0){a.call(this);const u=s(()=>this.tokenMatcher(this.LA(1),i),"separatorLookAheadFunc");for(;this.tokenMatcher(this.LA(1),i)===!0;)this.CONSUME(i),a.call(this);this.attemptInRepetitionRecovery(this.repetitionSepSecondInternal,[e,i,u,a,Xv],u,Dm,e,Xv)}}repetitionSepSecondInternal(e,r,n,a,i){for(;n();)this.CONSUME(r),a.call(this);this.attemptInRepetitionRecovery(this.repetitionSepSecondInternal,[e,r,n,a,i],n,Lc,e,i)}doSingleRepetition(e){const r=this.getLexerPosition();return e.call(this),this.getLexerPosition()>r}orInternal(e,r){const n=this.getKeyForAutomaticLookahead(X_,r),a=se(e)?e:e.DEF,o=this.getLaFuncFromCache(n).call(this,a);if(o!==void 0)return a[o].ALT.call(this);this.raiseNoAltException(r,e.ERR_MSG)}ruleFinallyStateUpdate(){if(this.RULE_STACK.pop(),this.RULE_OCCURRENCE_STACK.pop(),this.cstFinallyStateUpdate(),this.RULE_STACK.length===0&&this.isAtEndOfInput()===!1){const e=this.LA(1),r=this.errorMessageProvider.buildNotAllInputParsedMessage({firstRedundant:e,ruleName:this.getCurrRuleFullName()});this.SAVE_ERROR(new O1(r,e))}}subruleInternal(e,r,n){let a;try{const i=n!==void 0?n.ARGS:void 0;return this.subruleIdx=r,a=e.apply(this,i),this.cstPostNonTerminal(a,n!==void 0&&n.LABEL!==void 0?n.LABEL:e.ruleName),a}catch(i){throw this.subruleInternalError(i,n,e.ruleName)}}subruleInternalError(e,r,n){throw Su(e)&&e.partialCstResult!==void 0&&(this.cstPostNonTerminal(e.partialCstRe Line truncated
See: https://chevrotain.io/docs/guide/internals.html#grammar-recording for details`,-1,-1,-1,-1,-1,-1);Object.freeze(oS);var q1={name:`This CSTNode indicates the Parser is in Recording Phase
See: https://chevrotain.io/docs/guide/internals.html#grammar-recording for details`,children:{}},Xi,H1=(Xi=class{initGastRecorder(e){this.recordingProdStack=[],this.RECORDING_PHASE=!1}enableRecording(){this.RECORDING_PHASE=!0,this.TRACE_INIT("Enable Recording",()=>{for(let e=0;e<10;e++){const r=e>0?e:"";this[`CONSUME${r}`]=function(n,a){return this.consumeInternalRecord(n,e,a)},this[`SUBRULE${r}`]=function(n,a){return this.subruleInternalRecord(n,e,a)},this[`OPTION${r}`]=function(n){return this.optionInternalRecord(n,e)},this[`OR${r}`]=function(n){return this.orInternalRecord(n,e)},this[`MANY${r}`]=function(n){this.manyInternalRecord(e,n)},this[`MANY_SEP${r}`]=function(n){this.manySepFirstInternalRecord(e,n)},this[`AT_LEAST_ONE${r}`]=function(n){this.atLeastOneInternalRecord(e,n)},this[`AT_LEAST_ONE_SEP${r}`]=function(n){this.atLeastOneSepFirstInternalRecord(e,n)}}this.consume=function(e,r,n){return this.consumeInternalRecord(r,e,n)},this.subrule=function(e,r,n){return this.subruleInternalRecord(r,e,n)},this.option=function(e,r){return this.optionInternalRecord(r,e)},this.or=function(e,r){return this.orInternalRecord(r,e)},this.many=function(e,r){this.manyInternalRecord(e,r)},this.atLeastOne=function(e,r){this.atLeastOneInternalRecord(e,r)},this.ACTION=this.ACTION_RECORD,this.BACKTRACK=this.BACKTRACK_RECORD,this.LA=this.LA_RECORD})}disableRecording(){this.RECORDING_PHASE=!1,this.TRACE_INIT("Deleting Recording methods",()=>{const e=this;for(let r=0;r<10;r++){const n=r>0?r:"";delete e[`CONSUME${n}`],delete e[`SUBRULE${n}`],delete e[`OPTION${n}`],delete e[`OR${n}`],delete e[`MANY${n}`],delete e[`MANY_SEP${n}`],delete e[`AT_LEAST_ONE${n}`],delete e[`AT_LEAST_ONE_SEP${n}`]}delete e.consume,delete e.subrule,delete e.option,delete e.or,delete e.many,delete e.atLeastOne,delete e.ACTION,delete e.BACKTRACK,delete e.LA})}ACTION_RECORD(e){}BACKTRACK_RECORD(e,r){return()=>!0}LA_RECORD(e){return Tf}topLevelRuleRecord(e,r){try{const n=new sl({definition:[],name:e});return n.name=e,this.recordingProdStack.push(n),r.call(this),this.recordingProdStack.pop(),n}catch(n){if(n.KNOWN_RECORDER_ERROR!==!0)try{n.message=n.message+`
This error was thrown during the "grammar recording phase" For more info see:
https://chevrotain.io/docs/guide/internals.html#grammar-recording`}catch{throw n}throw n}}optionInternalRecord(e,r){return Na.call(this,at,e,r)}atLeastOneInternalRecord(e,r){Na.call(this,Ot,r,e)}atLeastOneSepFirstInternalRecord(e,r){Na.call(this,Lt,r,e,Zv)}manyInternalRecord(e,r){Na.call(this,xe,r,e)}manySepFirstInternalRecord(e,r){Na.call(this,_t,r,e,Zv)}orInternalRecord(e,r){return lS.call(this,e,r)}subruleInternalRecord(e,r,n){if(wu(r),!e||K(e,"ruleName")===!1){const u=new Error(`<SUBRULE${Fm(r)}> argument is invalid expecting a Parser method reference but got: <${JSON.stringify(e)}>
inside top level rule: <${this.recordingProdStack[0].name}>`);throw u.KNOWN_RECORDER_ERROR=!0,u}const a=Bn(this.recordingProdStack),i=e.ruleName,o=new ht({idx:r,nonTerminalName:i,label:n?.LABEL,referencedRule:void 0});return a.definition.push(o),this.outputCst?q1:yd}consumeInternalRecord(e,r,n){if(wu(r),!Xy(e)){const o=new Error(`<CONSUME${Fm(r)}> argument is invalid expecting a TokenType reference but got: <${JSON.stringify(e)}>
inside top level rule: <${this.recordingProdStack[0].name}>`);throw o.KNOWN_RECORDER_ERROR=!0,o}const a=Bn(this.recordingProdStack),i=new Se({idx:r,terminalType:e,label:n?.LABEL});return a.definition.push(i),oS}},s(Xi,"GastRecorder"),Xi);function Na(t,e,r,n=!1){wu(r);const a=Bn(this.recordingProdStack),i=Gr(e)?e:e.DEF,o=new t({definition:[],idx:r});return n&&(o.separator=e.SEP),K(e,"MAX_LOOKAHEAD")&&(o.maxLookahead=e.MAX_LOOKAHEAD),this.recordingProdStack.push(o),i.call(this),a.definition.push(o),this.recordingProdStack.pop(),yd}s(Na,"recordProd");function lS(t,e){wu(e);const r=Bn(this.recordingProdStack),n=se(t)===!1,a=n===!1?t:t.DEF,i=new St({definition:[],idx:e,ignoreAmbiguities:n&&t.IGNORE_AMBIGUITIES===!0});K(t,"MAX_LOOKAHEAD")&&(i.maxLookahead=t.MAX_LOOKAHEAD);const o=Eb(a,u=>Gr(u.GATE));return i.hasPredicates=o,r.definition.push(i),V(a,u=>{const l=new bt({definition:[]});i.definition.push(l),K(u,"IGNORE_AMBIGUITIES")?l.ignoreAmbiguities=u.IGNORE_AMBIGUITIES:K(u,"GATE")&&(l.ignoreAmbiguities=!0),this.recordingProdStack.push(l),u.ALT.call(this),this.recordingProdStack.pop()}),yd}s(lS,"recordOrProd");function Fm(t){return t===0?"":`${t}`}s(Fm,"getIdxSuffix");function wu(t){if(t<0||t>Qv){const e=new Error(`Invalid DSL Method idx value: <${t}>
Idx value must be a none negative value smaller than ${Qv+1}`);throw e.KNOWN_RECORDER_ERROR=!0,e}}s(wu,"assertMethodIdxIsValid");var Ji,Y1=(Ji=class{initPerformanceTracer(e){if(K(e,"traceInitPerf")){const r=e.traceInitPerf,n=typeof r=="number";this.traceInitMaxIdent=n?r:1/0,this.traceInitPerf=n?r>0:r}else this.traceInitMaxIdent=0,this.traceInitPerf=Lr.traceInitPerf;this.traceInitIndent=-1}TRACE_INIT(e,r){if(this.traceInitPerf===!0){this.traceInitIndent++;const n=new Array(this.traceInitIndent+1).join(" ");this.traceInitIndent<this.traceInitMaxIdent&&console.log(`${n}--> <${e}>`);const{time:a,value:i}=Ky(r),o=a>10?console.warn:console.log;return this.traceInitIndent<this.traceInitMaxIdent&&o(`${n}<-- <${e}> time: ${a}ms`),this.traceInitIndent--,i}else return r()}},s(Ji,"PerformanceTracer"),Ji);function uS(t,e){e.forEach(r=>{const n=r.prototype;Object.getOwnPropertyNames(n).forEach(a=>{if(a==="constructor")return;const i=Object.getOwnPropertyDescriptor(n,a);i&&(i.get||i.set)?Object.defineProperty(t.prototype,a,i):t.prototype[a]=r.prototype[a]})})}s(uS,"applyMixins");var Tf=Zu(Jr,"",NaN,NaN,NaN,NaN,NaN,NaN);Object.freeze(Tf);var Lr=Object.freeze({recoveryEnabled:!1,maxLookahead:3,dynamicTokensEnabled:!1,outputCst:!0,errorMessageProvider:qa,nodeLocationTracking:"none",traceInitPerf:!1,skipValidations:!1}),$f=Object.freeze({recoveryValueFunc:s(()=>{},"recoveryValueFunc"),resyncEnabled:!0}),yt;(function(t){t[t.INVALID_RULE_NAME=0]="INVALID_RULE_NAME",t[t.DUPLICATE_RULE_NAME=1]="DUPLICATE_RULE_NAME",t[t.INVALID_RULE_OVERRIDE=2]="INVALID_RULE_OVERRIDE",t[t.DUPLICATE_PRODUCTIONS=3]="DUPLICATE_PRODUCTIONS",t[t.UNRESOLVED_SUBRULE_REF=4]="UNRESOLVED_SUBRULE_REF",t[t.LEFT_RECURSION=5]="LEFT_RECURSION",t[t.NONE_LAST_EMPTY_ALT=6]="NONE_LAST_EMPTY_ALT",t[t.AMBIGUOUS_ALTS=7]="AMBIGUOUS_ALTS",t[t.CONFLICT_TOKENS_RULES_NAMESPACE=8]="CONFLICT_TOKENS_RULES_NAMESPACE",t[t.INVALID_TOKEN_NAME=9]="INVALID_TOKEN_NAME",t[t.NO_NON_EMPTY_LOOKAHEAD=10]="NO_NON_EMPTY_LOOKAHEAD",t[t.AMBIGUOUS_PREFIX_ALTS=11]="AMBIGUOUS_PREFIX_ALTS",t[t.TOO_MANY_ALTS=12]="TOO_MANY_ALTS",t[t.CUSTOM_LOOKAHEAD_VALIDATION=13]="CUSTOM_LOOKAHEAD_VALIDATION"})(yt||(yt={}));function zm(t=void 0){return function(){return t}}s(zm,"EMPTY_ALT");var Fn,og=(Fn=class{static performSelfAnalysis(e){throw Error("The **static** `performSelfAnalysis` method has been deprecated. \nUse the **instance** method with the same name instead.")}performSelfAnalysis(){this.TRACE_INIT("performSelfAnalysis",()=>{let e;this.selfAnalysisDone=!0;const r=this.className;this.TRACE_INIT("toFastProps",()=>{Wy(this)}),this.TRACE_INIT("Grammar Recording",()=>{try{this.enableRecording(),V(this.definedRulesNames,a=>{const o=this[a].originalGrammarAction;let u;this.TRACE_INIT(`${a} Rule`,()=>{u=this.topLevelRuleRecord(a,o)}),this.gastProductionsCache[a]=u})}finally{this.disableRecording()}});let n=[];if(this.TRACE_INIT("Grammar Resolving",()=>{n=z_({rules:Ke(this.gastProductionsCache)}),this.definitionErrors=this.definitionErrors.concat(n)}),this.TRACE_INIT("Grammar Validations",()=>{if(Re(n)&&this.skipValidations===!1){const a=j_({rules:Ke(this.gastProductionsCache),tokenTypes:Ke(this.tokensMap),errMsgProvider:Ln,grammarName:r}),i=S_({lookaheadStrategy:this.lookaheadStrategy,rules:Ke(this.gastProductionsCache),tokenTypes:Ke(this.tokensMap),grammarName:r});this.definitionErrors=this.definitionErrors.concat(a,i)}}),Re(this.definitionErrors)&&(this.recoveryEnabled&&this.TRACE_INIT("computeAllProdsFollows",()=>{const a=Db(Ke(this.gastProductionsCache));this.resyncFollows=a}),this.TRACE_INIT("ComputeLookaheadFunctions",()=>{var a,i;(i=(a=this.lookaheadStrategy).initialize)===null||i===void 0||i.call(a,{rules:Ke(this.gastProductionsCache)}),this.preComputeLookaheadFunctions(Ke(this.gastProductionsCache))})),!Fn.DEFER_DEFINITION_ERRORS_HANDLING&&!Re(this.definitionErrors))throw e=j(this.definitionErrors,a=>a.message),new Error(`Parser Definition Errors detected:
${e.join(`
-------------------------------
`)}`)})}constructor(e,r){this.definitionErrors=[],this.selfAnalysisDone=!1;const n=this;if(n.initErrorHandler(r),n.initLexerAdapter(),n.initLooksAhead(r),n.initRecognizerEngine(e,r),n.initRecoverable(r),n.initTreeBuilder(r),n.initContentAssist(),n.initGastRecorder(r),n.initPerformanceTracer(r),K(r,"ignoredIssues"))throw new Error(`The <ignoredIssues> IParserConfig property has been deprecated.
Please use the <IGNORE_AMBIGUITIES> flag on the relevant DSL method instead.
See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#IGNORING_AMBIGUITIES
For further details.`);this.skipValidations=K(r,"skipValidations")?r.skipValidations:Lr.skipValidations}},s(Fn,"Parser"),Fn);og.DEFER_DEFINITION_ERRORS_HANDLING=!1;uS(og,[x1,G1,j1,B1,K1,U1,W1,V1,H1,Y1]);var Zi,X1=(Zi=class extends og{constructor(e,r=Lr){const n=it(r);n.outputCst=!1,super(e,n)}},s(Zi,"EmbeddedActionsParser"),Zi);function cS(t,e){for(var r=-1,n=t==null?0:t.length,a=Array(n);++r<n;)a[r]=e(t[r],r,t);return a}s(cS,"arrayMap");var fS=cS;function dS(){this.__data__=[],this.size=0}s(dS,"listCacheClear");var J1=dS;function pS(t,e){return t===e||t!==t&&e!==e}s(pS,"eq");var mS=pS;function hS(t,e){for(var r=t.length;r--;)if(mS(t[r][0],e))return r;return-1}s(hS,"assocIndexOf");var gd=hS,Z1=Array.prototype,Q1=Z1.splice;function yS(t){var e=this.__data__,r=gd(e,t);if(r<0)return!1;var n=e.length-1;return r==n?e.pop():Q1.call(e,r,1),--this.size,!0}s(yS,"listCacheDelete");var eG=yS;function gS(t){var e=this.__data__,r=gd(e,t);return r<0?void 0:e[r][1]}s(gS,"listCacheGet");var tG=gS;function vS(t){return gd(this.__data__,t)>-1}s(vS,"listCacheHas");var rG=vS;function TS(t,e){var r=this.__data__,n=gd(r,t);return n<0?(++this.size,r.push([t,e])):r[n][1]=e,this}s(TS,"listCacheSet");var nG=TS;function ia(t){var e=-1,r=t==null?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}s(ia,"ListCache");ia.prototype.clear=J1;ia.prototype.delete=eG;ia.prototype.get=tG;ia.prototype.has=rG;ia.prototype.set=nG;var vd=ia;function $S(){this.__data__=new vd,this.size=0}s($S,"stackClear");var aG=$S;function RS(t){var e=this.__data__,r=e.delete(t);return this.size=e.size,r}s(RS,"stackDelete");var iG=RS;function AS(t){return this.__data__.get(t)}s(AS,"stackGet");var sG=AS;function ES(t){return this.__data__.has(t)}s(ES,"stackHas");var oG=ES,lG=typeof global=="object"&&global&&global.Object===Object&&global,CS=lG,uG=typeof self=="object"&&self&&self.Object===Object&&self,cG=CS||uG||Function("return this")(),Fr=cG,fG=Fr.Symbol,pr=fG,bS=Object.prototype,dG=bS.hasOwnProperty,pG=bS.toString,Ol=pr?pr.toStringTag:void 0;function _S(t){var e=dG.call(t,Ol),r=t[Ol];try{t[Ol]=void 0;var n=!0}catch{}var a=pG.call(t);return n&&(e?t[Ol]=r:delete t[Ol]),a}s(_S,"getRawTag");var mG=_S,hG=Object.prototype,yG=hG.toString;function SS(t){return yG.call(t)}s(SS,"objectToString");var gG=SS,vG="[object Null]",TG="[object Undefined]",eT=pr?pr.toStringTag:void 0;function wS(t){return t==null?t===void 0?TG:vG:eT&&eT in Object(t)?mG(t):gG(t)}s(wS,"baseGetTag");var fl=wS;function IS(t){var e=typeof t;return t!=null&&(e=="object"||e=="function")}s(IS,"isObject");var lg=IS,$G="[object AsyncFunction]",RG="[object Function]",AG="[object GeneratorFunction]",EG="[object Proxy]";function NS(t){if(!lg(t))return!1;var e=fl(t);return e==RG||e==AG||e==$G||e==EG}s(NS,"isFunction");var PS=NS,CG=Fr["__core-js_shared__"],qd=CG,tT=(function(){var t=/[^.]+$/.exec(qd&&qd.keys&&qd.keys.IE_PROTO||"");return t?"Symbol(src)_1."+t:""})();function kS(t){return!!tT&&tT in t}s(kS,"isMasked");var bG=kS,_G=Function.prototype,SG=_G.toString;function OS(t){if(t!=null){try{return SG.call(t)}catch{}try{return t+""}catch{}}return""}s(OS,"toSource");var sa=OS,wG=/[\\^$.*+?()[\]{}|]/g,IG=/^\[object .+?Constructor\]$/,NG=Function.prototype,PG=Object.prototype,kG=NG.toString,OG=PG.hasOwnProperty,LG=RegExp("^"+kG.call(OG).replace(wG,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function LS(t){if(!lg(t)||bG(t))return!1;var e=PS(t)?LG:IG;return e.test(sa(t))}s(LS,"baseIsNative");var DG=LS;function DS(t,e){return t?.[e]}s(DS,"getValue");var xG=DS;function xS(t,e){var r=xG(t,e);return DG(r)?r:void 0}s(xS,"getNative");var dl=xS,MG=dl(Fr,"Map"),Iu=MG,GG=dl(Object,"create"),Nu=GG;function MS(){this.__data__=Nu?Nu(null):{},this.size=0}s(MS,"hashClear");var FG=MS;function GS(t){var e=this.has(t)&&delete this.__data__[t];return this.size-=e?1:0,e}s(GS,"hashDelete");var zG=GS,jG="__lodash_hash_undefined__",BG=Object.prototype,UG=BG.hasOwnProperty;function FS(t){var e=this.__data__;if(Nu){var r=e[t];return r===jG?void 0:r}return UG.call(e,t)?e[t]:void 0}s(FS,"hashGet");var KG=FS,WG=Object.prototype,VG=WG.hasOwnProperty;function zS(t){var e=this.__data__;return Nu?e[t]!==void 0:VG.call(e,t)}s(zS,"hashHas");var qG=zS,HG="__lodash_hash_undefined__";function jS(t,e){var r=this.__data__;return this.size+=this.has(t)?0:1,r[t]=Nu&&e===void 0?HG:e,this}s(jS,"hashSet");var YG=jS;function oa(t){var e=-1,r=t==null?0:t.length;for(this.clear();++e<r;){var n=t[e];this.set(n[0],n[1])}}s(oa,"Hash");oa.prototype.clear=FG;oa.prototype.delete=zG;oa.prototype.get=KG;oa.prototype.has=qG;oa.prototype.set=YG;var rT=oa;function BS(){this.size=0,this.__data__={hash:new rT,map:new(Iu||vd),string:new rT}}s(BS,"mapCacheClear");var XG=BS;function US(t){var e=typeof t;return e=="string"||e=="number"||e=="symbol"||e=="boolean"?t!=="__proto__":t===null}s(US,"isKeyable");var JG=US;function KS(t,e){var r=t.__data__;return JG(e)?r[typeof e=="string"?"string":"hash"]:r.map}s(KS,"getMapDat Line truncated
<${e}> may appears as a prefix path in all these alternatives.
`;return n=n+`See: https://chevrotain.io/docs/guide/resolving_grammar_errors.html#AMBIGUOUS_ALTERNATIVES
For Further details.`,n}s(uN,"buildAmbiguityError");function cN(t){if(t instanceof ht)return"SUBRULE";if(t instanceof at)return"OPTION";if(t instanceof St)return"OR";if(t instanceof Ot)return"AT_LEAST_ONE";if(t instanceof Lt)return"AT_LEAST_ONE_SEP";if(t instanceof _t)return"MANY_SEP";if(t instanceof xe)return"MANY";if(t instanceof Se)return"CONSUME";throw Error("non exhaustive match")}s(cN,"getProductionDslName");function fN(t,e,r){const n=Gj(e.configs.elements,i=>i.state.transitions),a=Jj(n.filter(i=>i instanceof vg).map(i=>i.tokenType),i=>i.tokenTypeIdx);return{actualToken:r,possibleTokenTypes:a,tokenPath:t}}s(fN,"buildAdaptivePredictError");function dN(t,e){return t.edges[e.tokenTypeIdx]}s(dN,"getExistingTargetState");function pN(t,e,r){const n=new Wm,a=[];for(const o of t.elements){if(r.is(o.alt)===!1)continue;if(o.state.type===tc){a.push(o);continue}const u=o.state.transitions.length;for(let l=0;l<u;l++){const c=o.state.transitions[l],f=mN(c,e);f!==void 0&&n.add({state:f,alt:o.alt,stack:o.stack})}}let i;if(a.length===0&&n.size===1&&(i=n),i===void 0){i=new Wm;for(const o of n.elements)ku(o,i)}if(a.length>0&&!vN(i))for(const o of a)i.add(o);return i}s(pN,"computeReachSet");function mN(t,e){if(t instanceof vg&&Zy(e,t.tokenType))return t.target}s(mN,"getReachableTarget");function hN(t,e){let r;for(const n of t.elements)if(e.is(n.alt)===!0){if(r===void 0)r=n.alt;else if(r!==n.alt)return}return r}s(hN,"getUniqueAlt");function bg(t){return{configs:t,edges:{},isAcceptState:!1,prediction:-1}}s(bg,"newDFAState");function qm(t,e,r,n){return n=_g(t,n),e.edges[r.tokenTypeIdx]=n,n}s(qm,"addDFAEdge");function _g(t,e){if(e===Af)return e;const r=e.configs.key,n=t.states[r];return n!==void 0?n:(e.configs.finalize(),t.states[r]=e,e)}s(_g,"addDFAState");function yN(t){const e=new Wm,r=t.transitions.length;for(let n=0;n<r;n++){const i={state:t.transitions[n].target,alt:n,stack:[]};ku(i,e)}return e}s(yN,"computeStartState");function ku(t,e){const r=t.state;if(r.type===tc){if(t.stack.length>0){const a=[...t.stack],o={state:a.pop(),alt:t.alt,stack:a};ku(o,e)}else e.add(t);return}r.epsilonOnlyTransitions||e.add(t);const n=r.transitions.length;for(let a=0;a<n;a++){const i=r.transitions[a],o=gN(t,i);o!==void 0&&ku(o,e)}}s(ku,"closure");function gN(t,e){if(e instanceof TI)return{state:e.target,alt:t.alt,stack:t.stack};if(e instanceof Tg){const r=[...t.stack,e.followState];return{state:e.target,alt:t.alt,stack:r}}}s(gN,"getEpsilonTarget");function vN(t){for(const e of t.elements)if(e.state.type===tc)return!0;return!1}s(vN,"hasConfigInRuleStopState");function TN(t){for(const e of t.elements)if(e.state.type!==tc)return!1;return!0}s(TN,"allConfigsInRuleStopStates");function $N(t){if(TN(t))return!0;const e=RN(t.elements);return AN(e)&&!EN(e)}s($N,"hasConflictTerminatingPrediction");function RN(t){const e=new Map;for(const r of t){const n=Eg(r,!1);let a=e.get(n);a===void 0&&(a={},e.set(n,a)),a[r.alt]=!0}return e}s(RN,"getConflictingAltSets");function AN(t){for(const e of Array.from(t.values()))if(Object.keys(e).length>1)return!0;return!1}s(AN,"hasConflictingAltSet");function EN(t){for(const e of Array.from(t.values()))if(Object.keys(e).length===1)return!0;return!1}s(EN,"hasStateAssociatedWithOneAlt");Du();var ss,CN=(ss=class{constructor(){this.nodeStack=[]}get current(){return this.nodeStack[this.nodeStack.length-1]??this.rootNode}buildRootNode(e){return this.rootNode=new wg(e),this.rootNode.root=this.rootNode,this.nodeStack=[this.rootNode],this.rootNode}buildCompositeNode(e){const r=new Nd;return r.grammarSource=e,r.root=this.rootNode,this.current.content.push(r),this.nodeStack.push(r),r}buildLeafNode(e,r){const n=new Ef(e.startOffset,e.image.length,Tu(e),e.tokenType,!r);return n.grammarSource=r,n.root=this.rootNode,this.current.content.push(n),n}removeNode(e){const r=e.container;if(r){const n=r.content.indexOf(e);n>=0&&r.content.splice(n,1)}}addHiddenNodes(e){const r=[];for(const i of e){const o=new Ef(i.startOffset,i.image.length,Tu(i),i.tokenType,!0);o.root=this.rootNode,r.push(o)}let n=this.current,a=!1;if(n.content.length>0){n.content.push(...r);return}for(;n.container;){const i=n.container.content.indexOf(n);if(i>0){n.container.content.splice(i,0,...r),a=!0;break}n=n.container}a||this.rootNode.content.unshift(...r)}construct(e){const r=this.current;typeof e.$type=="string"&&!e.$infixName&&(this.current.astNode=e),e.$cstNode=r;const n=this.nodeStack.pop();n?.content.length===0&&this.removeNode(n)}},s(ss,"CstNodeBuilder"),ss),os,Sg=(os=class{get hidden(){return!1}get astNode(){const e=typeof this._astNode?.$type=="string"?this._astNode:this.container?.astNode;if(!e)throw new Error("This node has no associated AST element");return e}set astNode(e){this._astNode=e}get text(){return this.root.fullText.substring(this.offset,this.end)}},s(os,"AbstractCstNode"),os),ls,Ef=(ls=class extends Sg{get offset(){return this._offset}get length(){return this._length}get end(){return this._offset+this._length}get hidden(){return this._hidden}get Line truncated
`;case"r":return"\r";case"t":return" ";case"v":return"\v";case"0":return"\0";default:return c}}s(r,"convertEscapeCharacter");function n(c){return c.charAt(0)==="^"?c.substring(1):c}s(n,"convertID"),t.convertID=n;function a(c){return parseInt(c)}s(a,"convertInt"),t.convertInt=a;function i(c){return BigInt(c)}s(i,"convertBigint"),t.convertBigint=i;function o(c){return new Date(c)}s(o,"convertDate"),t.convertDate=o;function u(c){return Number(c)}s(u,"convertNumber"),t.convertNumber=u;function l(c){return c.toLowerCase()==="true"}s(l,"convertBoolean"),t.convertBoolean=l})(or||(or={}));var $e={};kf($e,$h(Lf()));function Ld(){return new Promise(t=>{typeof setImmediate>"u"?setTimeout(t,0):setImmediate(t)})}s(Ld,"delayNextTick");var Fc=0,zN=10;function Dd(){return Fc=performance.now(),new $e.CancellationTokenSource}s(Dd,"startCancelableOperation");function Mg(t){zN=t}s(Mg,"setInterruptionPeriod");var cr=Symbol("OperationCancelled");function fa(t){return t===cr}s(fa,"isOperationCancelled");async function Ye(t){if(t===$e.CancellationToken.None)return;const e=performance.now();if(e-Fc>=zN&&(Fc=e,await Ld(),Fc=performance.now()),t.isCancellationRequested)throw cr}s(Ye,"interruptAndCheck");var $s,Dr=($s=class{constructor(){this.promise=new Promise((e,r)=>{this.resolve=n=>(e(n),this),this.reject=n=>(r(n),this)})}},s($s,"Deferred"),$s),Hr,_T=(Hr=class{constructor(e,r,n,a){this._uri=e,this._languageId=r,this._version=n,this._content=a,this._lineOffsets=void 0}get uri(){return this._uri}get languageId(){return this._languageId}get version(){return this._version}getText(e){if(e){const r=this.offsetAt(e.start),n=this.offsetAt(e.end);return this._content.substring(r,n)}return this._content}update(e,r){for(const n of e)if(Hr.isIncremental(n)){const a=Fg(n.range),i=this.offsetAt(a.start),o=this.offsetAt(a.end);this._content=this._content.substring(0,i)+n.text+this._content.substring(o,this._content.length);const u=Math.max(a.start.line,0),l=Math.max(a.end.line,0);let c=this._lineOffsets;const f=Hm(n.text,!1,i);if(l-u===f.length)for(let p=0,y=f.length;p<y;p++)c[p+u+1]=f[p];else f.length<1e4?c.splice(u+1,l-u,...f):this._lineOffsets=c=c.slice(0,u+1).concat(f,c.slice(l+1));const d=n.text.length-(o-i);if(d!==0)for(let p=u+1+f.length,y=c.length;p<y;p++)c[p]=c[p]+d}else if(Hr.isFull(n))this._content=n.text,this._lineOffsets=void 0;else throw new Error("Unknown change event received");this._version=r}getLineOffsets(){return this._lineOffsets===void 0&&(this._lineOffsets=Hm(this._content,!0)),this._lineOffsets}positionAt(e){e=Math.max(Math.min(e,this._content.length),0);const r=this.getLineOffsets();let n=0,a=r.length;if(a===0)return{line:0,character:e};for(;n<a;){const o=Math.floor((n+a)/2);r[o]>e?a=o:n=o+1}const i=n-1;return e=this.ensureBeforeEOL(e,r[i]),{line:i,character:e-r[i]}}offsetAt(e){const r=this.getLineOffsets();if(e.line>=r.length)return this._content.length;if(e.line<0)return 0;const n=r[e.line];if(e.character<=0)return n;const a=e.line+1<r.length?r[e.line+1]:this._content.length,i=Math.min(n+e.character,a);return this.ensureBeforeEOL(i,n)}ensureBeforeEOL(e,r){for(;e>r&&Gg(this._content.charCodeAt(e-1));)e--;return e}get lineCount(){return this.getLineOffsets().length}static isIncremental(e){const r=e;return r!=null&&typeof r.text=="string"&&r.range!==void 0&&(r.rangeLength===void 0||typeof r.rangeLength=="number")}static isFull(e){const r=e;return r!=null&&typeof r.text=="string"&&r.range===void 0&&r.rangeLength===void 0}},s(Hr,"FullTextDocument"),Hr),_f;(function(t){function e(a,i,o,u){return new _T(a,i,o,u)}s(e,"create"),t.create=e;function r(a,i,o){if(a instanceof _T)return a.update(i,o),a;throw new Error("TextDocument.update: document must be created by TextDocument.create")}s(r,"update"),t.update=r;function n(a,i){const o=a.getText(),u=Sf(i.map(jN),(f,d)=>{const p=f.range.start.line-d.range.start.line;return p===0?f.range.start.character-d.range.start.character:p});let l=0;const c=[];for(const f of u){const d=a.offsetAt(f.range.start);if(d<l)throw new Error("Overlapping edit");d>l&&c.push(o.substring(l,d)),f.newText.length&&c.push(f.newText),l=a.offsetAt(f.range.end)}return c.push(o.substr(l)),c.join("")}s(n,"applyEdits"),t.applyEdits=n})(_f||(_f={}));function Sf(t,e){if(t.length<=1)return t;const r=t.length/2|0,n=t.slice(0,r),a=t.slice(r);Sf(n,e),Sf(a,e);let i=0,o=0,u=0;for(;i<n.length&&o<a.length;)e(n[i],a[o])<=0?t[u++]=n[i++]:t[u++]=a[o++];for(;i<n.length;)t[u++]=n[i++];for(;o<a.length;)t[u++]=a[o++];return t}s(Sf,"mergeSort");function Hm(t,e,r=0){const n=e?[r]:[];for(let a=0;a<t.length;a++){const i=t.charCodeAt(a);Gg(i)&&(i===13&&a+1<t.length&&t.charCodeAt(a+1)===10&&a++,n.push(r+a+1))}return n}s(Hm,"computeLineOffsets");function Gg(t){return t===13||t===10}s(Gg,"isEOL");function Fg(t){const e=t.start,r=t.end;return e.line>r.line||e.line===r.line&&e.character>r.character?{start:r,end:e}:t}s(Fg,"getWellformedRange");function jN(t){const e=Fg(t.range);return e!==t.range?{newText:t.newText,range:e}:t}s(jN,"getWellfo Line truncated
${r}`),this.inline?`{${e}}`:e}toMarkdown(e){return e?.renderTag?.(this)??this.toMarkdownDefault(e)}toMarkdownDefault(e){const r=this.content.toMarkdown(e);if(this.inline){const i=vP(this.name,r,e??{});if(typeof i=="string")return i}let n="";e?.tag==="italic"||e?.tag===void 0?n="*":e?.tag==="bold"?n="**":e?.tag==="bold-italic"&&(n="***");let a=`${n}@${this.name}${n}`;return this.content.inlines.length===1?a=`${a} — ${r}`:this.content.inlines.length>1&&(a=`${a}
${r}`),this.inline?`{${a}}`:a}},s(Qs,"JSDocTagImpl"),Qs);function vP(t,e,r){if(t==="linkplain"||t==="linkcode"||t==="link"){const n=e.indexOf(" ");let a=e;if(n>0){const o=Pf(e,n);a=e.substring(o),e=e.substring(0,n)}return(t==="linkcode"||t==="link"&&r.link==="code")&&(a=`\`${a}\``),r.renderLink?.(e,a)??TP(e,a)}}s(vP,"renderInlineTag");function TP(t,e){try{return It.parse(t,!0),`[${e}](${t})`}catch{return t}}s(TP,"renderLinkDefault");var eo,Jm=(eo=class{constructor(e,r){this.inlines=e,this.range=r}toString(){let e="";for(let r=0;r<this.inlines.length;r++){const n=this.inlines[r],a=this.inlines[r+1];e+=n.toString(),a&&a.range.start.line>n.range.start.line&&(e+=`
`)}return e}toMarkdown(e){let r="";for(let n=0;n<this.inlines.length;n++){const a=this.inlines[n],i=this.inlines[n+1];r+=a.toMarkdown(e),i&&i.range.start.line>a.range.start.line&&(r+=`
`)}return r}},s(eo,"JSDocTextImpl"),eo),to,$P=(to=class{constructor(e,r){this.text=e,this.range=r}toString(){return this.text}toMarkdown(){return this.text}},s(to,"JSDocLineImpl"),to);function Zm(t){return t.endsWith(`
`)?`
`:`
`}s(Zm,"fillNewlines");var ro,RP=(ro=class{constructor(e){this.indexManager=e.shared.workspace.IndexManager,this.commentProvider=e.documentation.CommentProvider}getDocumentation(e){const r=this.commentProvider.getComment(e);if(r&&Xg(r))return Yg(r).toMarkdown({renderLink:s((a,i)=>this.documentationLinkRenderer(e,a,i),"renderLink"),renderTag:s(a=>this.documentationTagRenderer(e,a),"renderTag")})}documentationLinkRenderer(e,r,n){const a=this.findNameInLocalSymbols(e,r)??this.findNameInGlobalScope(e,r);if(a&&a.nameSegment){const i=a.nameSegment.range.start.line+1,o=a.nameSegment.range.start.character+1,u=a.documentUri.with({fragment:`L${i},${o}`});return`[${n}](${u.toString()})`}else return}documentationTagRenderer(e,r){}findNameInLocalSymbols(e,r){const a=Vt(e).localSymbols;if(!a)return;let i=e;do{const u=a.getStream(i).find(l=>l.name===r);if(u)return u;i=i.$container}while(i)}findNameInGlobalScope(e,r){return this.indexManager.allElements().find(a=>a.name===r)}},s(ro,"JSDocDocumentationProvider"),ro),no,AP=(no=class{constructor(e){this.grammarConfig=()=>e.parser.GrammarConfig}getComment(e){return Kg(e)?e.$comment:Zh(e.$cstNode,this.grammarConfig().multilineCommentRules)?.text}},s(no,"DefaultCommentProvider"),no),ao,EP=(ao=class{constructor(e){this.syncParser=e.parser.LangiumParser}parse(e,r){return Promise.resolve(this.syncParser.parse(e))}},s(ao,"DefaultAsyncParser"),ao),io,gB=(io=class{constructor(e){this.threadCount=8,this.terminationDelay=200,this.workerPool=[],this.queue=[],this.hydrator=e.serializer.Hydrator}initializeWorkers(){for(;this.workerPool.length<this.threadCount;){const e=this.createWorker();e.onReady(()=>{if(this.queue.length>0){const r=this.queue.shift();r&&(e.lock(),r.resolve(e))}}),this.workerPool.push(e)}}async parse(e,r){const n=await this.acquireParserWorker(r),a=new Dr;let i;const o=r.onCancellationRequested(()=>{i=setTimeout(()=>{this.terminateWorker(n)},this.terminationDelay)});return n.parse(e).then(u=>{const l=this.hydrator.hydrate(u);a.resolve(l)}).catch(u=>{a.reject(u)}).finally(()=>{o.dispose(),clearTimeout(i)}),a.promise}terminateWorker(e){e.terminate();const r=this.workerPool.indexOf(e);r>=0&&this.workerPool.splice(r,1)}async acquireParserWorker(e){this.initializeWorkers();for(const n of this.workerPool)if(n.ready)return n.lock(),n;const r=new Dr;return e.onCancellationRequested(()=>{const n=this.queue.indexOf(r);n>=0&&this.queue.splice(n,1),r.reject(cr)}),this.queue.push(r),r.promise}},s(io,"AbstractThreadedAsyncParser"),io),so,vB=(so=class{get ready(){return this._ready}get onReady(){return this.onReadyEmitter.event}constructor(e,r,n,a){this.onReadyEmitter=new Gd.Emitter,this.deferred=new Dr,this._ready=!0,this._parsing=!1,this.sendMessage=e,this._terminate=a,r(i=>{const o=i;this.deferred.resolve(o),this.unlock()}),n(i=>{this.deferred.reject(i),this.unlock()})}terminate(){this.deferred.reject(cr),this._terminate()}lock(){this._ready=!1}unlock(){this._parsing=!1,this._ready=!0,this.onReadyEmitter.fire()}parse(e){if(this._parsing)throw new Error("Parser worker is busy");return this._parsing=!0,this.deferred=new Dr,this.sendMessage(e),this.deferred.promise}},s(so,"ParserWorker"),so),oo,CP=(oo=class{constructor(){this.previousTokenSource=new $e.CancellationTokenSource,this.writeQueue=[],this.readQueue=[],this.done=!0}write(e){this.cancelWrite();const r=Dd();return this.previousTokenSource=r,this.enqueue(this.writeQueue,e,r.token)}read(e){return this.enqueue(this.readQueue,e)}enqueue(e,r,n=$e.CancellationToken.None){const a=new Dr,i={action:r,deferred:a,cancellationToken:n};return e.push(i),this.performNextOperation(),a.promise}async performNextOperation(){if(!this.done)return;const e=[];if(this.writeQueue.length>0)e.push(this.writeQueue.shift());else if(this.readQueue.length>0)e.push(...this.readQueue.splice(0,this.readQueue.length));else return;this.done=!1,await Promise.all(e.map(async({action:r,deferred:n,cancellationToken:a})=>{try{const i=await Promise.resolve().then(()=>r(a));n.resolve(i)}catch(i){fa(i)?n.resolve(void 0):n.reject(i)}})),this.done=!0,this.performNextOperation()}cancelWrite(){this.previousTokenSource.cancel()}},s(oo,"DefaultWorkspaceLock"),oo),lo,bP=(lo=class{constructor(e){this.grammarElementIdMap=new wf,this.tokenTypeIdMap=new wf,this.grammar=e.Grammar,this.lexer=e.parser.Lexer,this.linker=e.references.Linker}dehydrate(e){return{lexerErrors:e.lexerErrors,lexerReport:e.lexerReport?this.dehydrateLexerReport(e.lexerReport):void 0,parserErrors:e.parserErrors.map(r=>({...r,message:r.message})),value:this.dehydrateAstNode(e.value,this.createDehyrationContext(e.value))}}dehydrateLexerReport(e){return e}createDehyrationContext(e){const r=new Map,n=new Map;for(const a of qt(e))r.set(a,{});if(e.$cstNode)for(const a of Jo(e.$cstNode))n.set(a,{});return{astNodes:r,cstNodes:n}}dehydrateAstNode(e,r){const n=r.astNodes.get(e);n.$type=e.$type,n.$containerIndex=e.$containerIndex,n.$containerProperty=e.$containerProperty,e.$cstNode!==void 0&&(n.$cstNode=this.dehydrateCstN Line truncated
`.includes(e[r-1])}matchWhitespace(e,r,n,a){this.whitespaceRegExp.lastIndex=r;const i=this.whitespaceRegExp.exec(e);return{currIndentLevel:i?.[0].length??0,prevIndentLevel:this.indentationStack.at(-1),match:i}}createIndentationTokenInstance(e,r,n,a){const i=this.getLineNumber(r,a);return Zu(e,n,a,a+n.length,i,i,1,n.length)}getLineNumber(e,r){return e.substring(0,r).split(/\r\n|\r|\n/).length}indentMatcher(e,r,n,a){if(!this.isStartOfLine(e,r))return null;const{currIndentLevel:i,prevIndentLevel:o,match:u}=this.matchWhitespace(e,r,n,a);return i<=o?null:(this.indentationStack.push(i),u)}dedentMatcher(e,r,n,a){if(!this.isStartOfLine(e,r))return null;const{currIndentLevel:i,prevIndentLevel:o,match:u}=this.matchWhitespace(e,r,n,a);if(i>=o)return null;const l=this.indentationStack.lastIndexOf(i);if(l===-1)return this.diagnostics.push({severity:"error",message:`Invalid dedent level ${i} at offset: ${r}. Current indentation stack: ${this.indentationStack}`,offset:r,length:u?.[0]?.length??0,line:this.getLineNumber(e,r),column:1}),null;const c=this.indentationStack.length-l-1,f=e.substring(0,r).match(/[\r\n]+$/)?.[0].length??1;for(let d=0;d<c;d++){const p=this.createIndentationTokenInstance(this.dedentTokenType,e,"",r-(f-1));n.push(p),this.indentationStack.pop()}return null}buildTerminalToken(e){const r=super.buildTerminalToken(e),{indentTokenName:n,dedentTokenName:a,whitespaceTokenName:i}=this.options;return r.name===n?this.indentTokenType:r.name===a?this.dedentTokenType:r.name===i?Xa({name:i,pattern:this.whitespaceRegExp,group:pt.SKIPPED}):r}flushRemainingDedents(e){const r=[];for(;this.indentationStack.length>1;)r.push(this.createIndentationTokenInstance(this.dedentTokenType,e,"",e.length)),this.indentationStack.pop();return this.indentationStack=[0],r}},s(uo,"IndentationAwareTokenBuilder"),uo),co,TB=(co=class extends Hg{constructor(e){if(super(e),e.parser.TokenBuilder instanceof SP)this.indentationTokenBuilder=e.parser.TokenBuilder;else throw new Error("IndentationAwareLexer requires an accompanying IndentationAwareTokenBuilder")}tokenize(e,r=qg){const n=super.tokenize(e),a=n.report;r?.mode==="full"&&n.tokens.push(...a.remainingDedents),a.remainingDedents=[];const{indentTokenType:i,dedentTokenType:o}=this.indentationTokenBuilder,u=i.tokenTypeIdx,l=o.tokenTypeIdx,c=[],f=n.tokens.length-1;for(let d=0;d<f;d++){const p=n.tokens[d],y=n.tokens[d+1];if(p.tokenTypeIdx===u&&y.tokenTypeIdx===l){d++;continue}c.push(p)}return f>=0&&c.push(n.tokens[f]),n.tokens=c,n}},s(co,"IndentationAwareLexer"),co),nv={};en(nv,{AstUtils:()=>_h,BiMap:()=>wf,Cancellation:()=>$e,ContextCache:()=>Md,CstUtils:()=>Eh,DONE_RESULT:()=>ct,Deferred:()=>Dr,Disposable:()=>Gn,DisposableCache:()=>xd,DocumentCache:()=>XN,EMPTY_STREAM:()=>Vo,ErrorWithLocation:()=>Uf,GrammarUtils:()=>ry,MultiMap:()=>xr,OperationCancelled:()=>cr,Reduction:()=>vu,RegExpUtils:()=>ay,SimpleCache:()=>Bg,StreamImpl:()=>ur,TreeStreamImpl:()=>qo,URI:()=>It,UriTrie:()=>zg,UriUtils:()=>dt,WorkspaceCache:()=>Ug,assertCondition:()=>ny,assertUnreachable:()=>tn,delayNextTick:()=>Ld,interruptAndCheck:()=>Ye,isOperationCancelled:()=>fa,loadGrammarFromJson:()=>Ze,setInterruptionPeriod:()=>Mg,startCancelableOperation:()=>Dd,stream:()=>de});kf(nv,Gd);var fo,wP=(fo=class{stat(e){throw new Error("No file system is available.")}statSync(e){throw new Error("No file system is available.")}async exists(){return!1}existsSync(){return!1}readBinary(){throw new Error("No file system is available.")}readBinarySync(){throw new Error("No file system is available.")}readFile(){throw new Error("No file system is available.")}readFileSync(){throw new Error("No file system is available.")}async readDirectory(){return[]}readDirectorySync(){return[]}},s(fo,"EmptyFileSystemProvider"),fo),st={fileSystemProvider:s(()=>new wP,"fileSystemProvider")},$B={Grammar:s(()=>{},"Grammar"),LanguageMetaData:s(()=>({caseInsensitive:!1,fileExtensions:[".langium"],languageId:"langium"}),"LanguageMetaData")},RB={AstReflection:s(()=>new qh,"AstReflection")};function IP(){const t=re(Je(st),RB),e=re(Xe({shared:t}),$B);return t.ServiceRegistry.register(e),e}s(IP,"createMinimalGrammarServices");function Ze(t){const e=IP(),r=e.serializer.JsonSerializer.deserialize(t);return e.shared.workspace.LangiumDocumentFactory.fromModel(r,It.parse(`memory:/${r.name??"grammar"}.langium`)),r}s(Ze,"loadGrammarFromJson");kf(z$,nv);var po,AB=(po=class{constructor(e){this.activeCategories=new Set,this.allCategories=new Set(["validating","parsing","linking"]),this.activeCategories=e??new Set(this.allCategories),this.records=new xr}isActive(e){return this.activeCategories.has(e)}start(...e){e?e.forEach(r=>this.activeCategories.add(r)):this.activeCategories=new Set(this.allCategories)}stop(...e){e?e.forEach(r=>this.activeCategories.delete(r)):this.activeCategories.clear()}createTask(e,r){if(!this.isActive(e))throw new Error(`Category "${e}" is not active.`);return console.log(`Creating profiling task for '${e}.${r}'.`),new NP(n=>this.records.add(e,this.dumpLine truncated
`)}}},s(yo,"AbstractMermaidValueConverter"),yo),go,pl=(go=class extends vr{runCustomConverter(e,r,n){}},s(go,"CommonValueConverter"),go),vo,$t=(vo=class extends Od{constructor(e){super(),this.keywords=new Set(e)}buildKeywordTokens(e,r,n){const a=super.buildKeywordTokens(e,r,n);return a.forEach(i=>{this.keywords.has(i.name)&&i.PATTERN!==void 0&&(i.PATTERN=new RegExp(i.PATTERN.toString()+"(?:(?=%%)|(?!\\S))"))}),a}},s(vo,"AbstractMermaidTokenBuilder"),vo),To;To=class extends $t{},s(To,"CommonTokenBuilder");var $o,zU=($o=class extends $t{constructor(){super(["radar-beta"])}},s($o,"RadarTokenBuilder"),$o),kP={parser:{TokenBuilder:s(()=>new zU,"TokenBuilder"),ValueConverter:s(()=>new pl,"ValueConverter")}};function OP(t=st){const e=re(Je(t),Tt),r=re(Xe({shared:e}),wU,kP);return e.ServiceRegistry.register(r),{shared:e,Radar:r}}s(OP,"createRadarServices");var Ro,jU=(Ro=class extends $t{constructor(){super(["railroad-beta"])}},s(Ro,"RailroadTokenBuilder"),Ro),w$=s(t=>{const e=t.slice(1,-1);let r="";for(let n=0;n<e.length;n++){const a=e[n];if(a==="\\"&&n+1<e.length){n++;const i=e[n];switch(i){case"n":r+=`
`;break;case"r":r+="\r";break;case"t":r+=" ";break;default:r+=i}continue}r+=a}return r},"decodeEscapedString"),Ao,BU=(Ao=class extends vr{runConverter(e,r,n){const a=super.runConverter(e,r,n);if(e.name==="TITLE"&&typeof a=="string"){const i=a.trim();if(i.startsWith('"')&&i.endsWith('"')||i.startsWith("'")&&i.endsWith("'"))return w$(i)}return a}runCustomConverter(e,r,n){if(e.name==="RR_STRING")return w$(r)}},s(Ao,"RailroadValueConverter"),Ao),LP={parser:{TokenBuilder:s(()=>new jU,"TokenBuilder"),ValueConverter:s(()=>new BU,"ValueConverter")}};function DP(t=st){const e=re(Je(t),Tt),r=re(Xe({shared:e}),PU,LP);return e.ServiceRegistry.register(r),{shared:e,Railroad:r}}s(DP,"createRailroadServices");var Eo,UU=(Eo=class extends $t{constructor(){super(["railroad-ebnf-beta"])}},s(Eo,"RailroadEbnfTokenBuilder"),Eo),I$=s(t=>{const e=t.slice(1,-1);let r="";for(let n=0;n<e.length;n++){const a=e[n];if(a==="\\"&&n+1<e.length){n++;const i=e[n];switch(i){case"n":r+=`
`;break;case"r":r+="\r";break;case"t":r+=" ";break;default:r+=i}continue}r+=a}return r},"decodeEscapedString"),Co,KU=(Co=class extends vr{runConverter(e,r,n){const a=super.runConverter(e,r,n);if(e.name==="TITLE"&&typeof a=="string"){const i=a.trim();if(i.startsWith('"')&&i.endsWith('"')||i.startsWith("'")&&i.endsWith("'"))return I$(i)}return a}runCustomConverter(e,r,n){if(e.name==="EBNF_STRING")return I$(r);if(e.name==="EBNF_SPECIAL_SEQUENCE")return r.slice(1,-1).trim()}},s(Co,"RailroadEbnfValueConverter"),Co),xP={parser:{TokenBuilder:s(()=>new UU,"TokenBuilder"),ValueConverter:s(()=>new KU,"ValueConverter")}};function MP(t=st){const e=re(Je(t),Tt),r=re(Xe({shared:e}),NU,xP);return e.ServiceRegistry.register(r),{shared:e,RailroadEbnf:r}}s(MP,"createRailroadEbnfServices");var bo,WU=(bo=class extends $t{constructor(){super(["railroad-abnf-beta"])}},s(bo,"RailroadAbnfTokenBuilder"),bo),_o,VU=(_o=class extends vr{runConverter(e,r,n){const a=super.runConverter(e,r,n);if(e.name==="TITLE"&&typeof a=="string"){const i=a.trim();if(i.startsWith('"')&&i.endsWith('"')||i.startsWith("'")&&i.endsWith("'"))return i.slice(1,-1)}return a}runCustomConverter(e,r,n){if(e.name==="ABNF_STRING")return r.slice(1,-1)}},s(_o,"RailroadAbnfValueConverter"),_o),GP={parser:{TokenBuilder:s(()=>new WU,"TokenBuilder"),ValueConverter:s(()=>new VU,"ValueConverter")}};function FP(t=st){const e=re(Je(t),Tt),r=re(Xe({shared:e}),IU,GP);return e.ServiceRegistry.register(r),{shared:e,RailroadAbnf:r}}s(FP,"createRailroadAbnfServices");var So,qU=(So=class extends $t{constructor(){super(["railroad-peg-beta"])}},s(So,"RailroadPegTokenBuilder"),So),N$=s(t=>{const e=t.slice(1,-1);let r="";for(let n=0;n<e.length;n++){const a=e[n];if(a==="\\"&&n+1<e.length){n++;const i=e[n];switch(i){case"n":r+=`
`;break;case"r":r+="\r";break;case"t":r+=" ";break;default:r+=i}continue}r+=a}return r},"decodeEscapedString"),wo,HU=(wo=class extends vr{runConverter(e,r,n){const a=super.runConverter(e,r,n);if(e.name==="TITLE"&&typeof a=="string"){const i=a.trim();if(i.startsWith('"')&&i.endsWith('"')||i.startsWith("'")&&i.endsWith("'"))return N$(i)}return a}runCustomConverter(e,r,n){if(e.name==="PEG_STRING")return N$(r)}},s(wo,"RailroadPegValueConverter"),wo),zP={parser:{TokenBuilder:s(()=>new qU,"TokenBuilder"),ValueConverter:s(()=>new HU,"ValueConverter")}};function jP(t=st){const e=re(Je(t),Tt),r=re(Xe({shared:e}),kU,zP);return e.ServiceRegistry.register(r),{shared:e,RailroadPeg:r}}s(jP,"createRailroadPegServices");var Io,YU=(Io=class extends $t{constructor(){super(["treemap"])}},s(Io,"TreemapTokenBuilder"),Io),XU=/classDef\s+([A-Z_a-z]\w+)(?:\s+([^\n\r;]*))?;?/,No,JU=(No=class extends vr{runCustomConverter(e,r,n){if(e.name==="NUMBER2")return parseFloat(r.replace(/,/g,""));if(e.name==="SEPARATOR")return r.substring(1,r.length-1);if(e.name==="STRING2")return r.substring(1,r.length-1);if(e.name==="INDENTATION")return r.length;if(e.name==="ClassDef"){if(typeof r!="string")return r;const a=XU.exec(r);if(a)return{$type:"ClassDefStatement",className:a[1],styleText:a[2]||void 0}}}},s(No,"TreemapValueConverter"),No);function BP(t){const e=t.validation.TreemapValidator,r=t.validation.ValidationRegistry;if(r){const n={Treemap:e.checkSingleRoot.bind(e)};r.register(n,e)}}s(BP,"registerValidationChecks");var Po,ZU=(Po=class{checkSingleRoot(e,r){let n;for(const a of e.TreemapRows)a.item&&(n===void 0&&a.indent===void 0?n=0:a.indent===void 0?r("error","Multiple root nodes are not allowed in a treemap.",{node:a,property:"item"}):n!==void 0&&n>=parseInt(a.indent,10)&&r("error","Multiple root nodes are not allowed in a treemap.",{node:a,property:"item"}))}},s(Po,"TreemapValidator"),Po),UP={parser:{TokenBuilder:s(()=>new YU,"TokenBuilder"),ValueConverter:s(()=>new JU,"ValueConverter")},validation:{TreemapValidator:s(()=>new ZU,"TreemapValidator")}};function KP(t=st){const e=re(Je(t),Tt),r=re(Xe({shared:e}),OU,UP);return e.ServiceRegistry.register(r),BP(r),{shared:e,Treemap:r}}s(KP,"createTreemapServices");var ko,QU=(ko=class extends vr{runCustomConverter(e,r,n){if(e.name.toUpperCase()==="LINK_LABEL")return r.substring(1).trim()}},s(ko,"WardleyValueConverter"),ko),WP={parser:{ValueConverter:s(()=>new QU,"ValueConverter")}};function VP(t=st){const e=re(Je(t),Tt),r=re(Xe({shared:e}),DU,WP);return e.ServiceRegistry.register(r),{shared:e,Wardley:r}}s(VP,"createWardleyServices");var Oo,eK=(Oo=class extends $t{constructor(){super(["cynefin-beta"])}},s(Oo,"CynefinTokenBuilder"),Oo),qP={parser:{TokenBuilder:s(()=>new eK,"TokenBuilder"),ValueConverter:s(()=>new pl,"ValueConverter")}};function HP(t=st){const e=re(Je(t),Tt),r=re(Xe({shared:e}),AU,qP);return e.ServiceRegistry.register(r),{shared:e,Cynefin:r}}s(HP,"createCynefinServices");var Lo,tK=(Lo=class extends $t{constructor(){super(["gitGraph"])}},s(Lo,"GitGraphTokenBuilder"),Lo),YP={parser:{TokenBuilder:s(()=>new tK,"TokenBuilder"),ValueConverter:s(()=>new pl,"ValueConverter")}};function XP(t=st){const e=re(Je(t),Tt),r=re(Xe({shared:e}),CU,YP);return e.ServiceRegistry.register(r),{shared:e,GitGraph:r}}s(XP,"createGitGraphServices");var Do,rK=(Do=class extends $t{constructor(){super(["info","showInfo"])}},s(Do,"InfoTokenBuilder"),Do),JP={parser:{TokenBuilder:s(()=>new rK,"TokenBuilder"),ValueConverter:s(()=>new pl,"ValueConverter")}};function ZP(t=st){const e=re(Je(t),Tt),r=re(Xe({shared:e}),bU,JP);return e.ServiceRegistry.register(r),{shared:e,Info:r}}s(ZP,"createInfoServices");var xo,nK=(xo=class extends $t{constructor(){super(["packet"])}},s(xo,"PacketTokenBuilder"),xo),QP={parser:{TokenBuilder:s(()=>new nK,"TokenBuilder"),ValueConverter:s(()=>new pl,"ValueConverter")}};function ek(t=st){const e=re(Je(t),Tt),r=re(Xe({shared:e}),_U,QP);return e.ServiceRegistry.register(r),{shared:e,Packet:r}}s(ek,"createPacketServices");var Mo,aK=(Mo=class extends $t{constructor(){super(["pie","showData"])}},s(Mo,"PieTokenBuilder"),Mo),Go,iK=(Go=class extends vr{runCustomConverter(e,r,n){if(e.name==="PIE_SECTION_LABEL")return r.replace(/"/g,"").trim()}},s(Go,"PieValueConverter"),Go),tk={parser:{TokenBuilder:s(()=>new aK,"TokenBuilder"),ValueConverter:s(()=>new iK,"ValueConverter")}};function rk(t=st){const e=re(Je(t),Tt),r=re(Xe({shared:e}),SU,tk);return e.ServiceRegistry.register(r),{shared:e,Pie:r}}s(rk,"createPieServices");var Fo,sK=(Fo=class extends vr{runCustomConverter(e,r,n){if(e.name==="INDENTATION")return r?.length||0;if(e.name==="QUOTED_NAME")return r.substring(1,r.length-1);if(e.name==="BARE_NAME")return r.replace(/[\t ]+$/,"");if(e.name==="CLASS_ANNOTATION")return r.trim().substring(3).trim();if(e.name==="ICON_ANNOTATION"){const a=r.trim();return a.substring(5,a.length-1)}if(e.name==="DESC_ANNOTATION")return r.trim().substring(2).trim()}},s(Fo,"TreeViewValueConverter"),Fo),zo,oK=(zo=class extends Line truncated
`),n=e.parserErrors.map(a=>{const i=a.token.startLine!==void 0&&!isNaN(a.token.startLine)?a.token.startLine:"?",o=a.token.startColumn!==void 0&&!isNaN(a.token.startColumn)?a.token.startColumn:"?";return`Parse error on line ${i}, column ${o}: ${a.message}`}).join(`
`);super(`Parsing failed: ${r} ${n}`),this.result=e}},s(Wo,"MermaidParseError"),Wo);const hK=Object.freeze(Object.defineProperty({__proto__:null,InfoModule:JP,createInfoServices:ZP},Symbol.toStringTag,{value:"Module"})),yK=Object.freeze(Object.defineProperty({__proto__:null,PacketModule:QP,createPacketServices:ek},Symbol.toStringTag,{value:"Module"})),gK=Object.freeze(Object.defineProperty({__proto__:null,PieModule:tk,createPieServices:rk},Symbol.toStringTag,{value:"Module"})),vK=Object.freeze(Object.defineProperty({__proto__:null,TreeViewModule:nk,createTreeViewServices:ak},Symbol.toStringTag,{value:"Module"})),TK=Object.freeze(Object.defineProperty({__proto__:null,ArchitectureModule:ik,createArchitectureServices:sk},Symbol.toStringTag,{value:"Module"})),$K=Object.freeze(Object.defineProperty({__proto__:null,GitGraphModule:YP,createGitGraphServices:XP},Symbol.toStringTag,{value:"Module"})),RK=Object.freeze(Object.defineProperty({__proto__:null,EventModelingModule:lk,createEventModelingServices:uk},Symbol.toStringTag,{value:"Module"})),AK=Object.freeze(Object.defineProperty({__proto__:null,RadarModule:kP,createRadarServices:OP},Symbol.toStringTag,{value:"Module"})),EK=Object.freeze(Object.defineProperty({__proto__:null,RailroadModule:LP,createRailroadServices:DP},Symbol.toStringTag,{value:"Module"})),CK=Object.freeze(Object.defineProperty({__proto__:null,RailroadEbnfModule:xP,createRailroadEbnfServices:MP},Symbol.toStringTag,{value:"Module"})),bK=Object.freeze(Object.defineProperty({__proto__:null,RailroadAbnfModule:GP,createRailroadAbnfServices:FP},Symbol.toStringTag,{value:"Module"})),_K=Object.freeze(Object.defineProperty({__proto__:null,RailroadPegModule:zP,createRailroadPegServices:jP},Symbol.toStringTag,{value:"Module"})),SK=Object.freeze(Object.defineProperty({__proto__:null,TreemapModule:UP,createTreemapServices:KP},Symbol.toStringTag,{value:"Module"})),wK=Object.freeze(Object.defineProperty({__proto__:null,WardleyModule:WP,createWardleyServices:VP},Symbol.toStringTag,{value:"Module"})),IK=Object.freeze(Object.defineProperty({__proto__:null,CynefinModule:qP,createCynefinServices:HP},Symbol.toStringTag,{value:"Module"}));export{mK as M,MP as a,FP as b,DP as c,jP as d,NB as i,pK as p};
+62
View File
@@ -0,0 +1,62 @@
import{p as xt}from"./chunk-JWPE2WC7.js";import{s as gt,g as $t,o as bt,n as wt,a as Ct,b as vt,_ as s,l as O,D as Dt,d as kt,p as At,A as U,y as Q,B as Tt,E as ot}from"./mermaid.core.js";import{p as Bt}from"./cynefin-OW5HDTMX.js";import"./index.js";var rt=s(()=>({domains:new Map,transitions:[]}),"createDefaultData"),H=rt(),St=s(()=>H.domains,"getDomains"),Mt=s(()=>H.transitions,"getTransitions"),zt=s(t=>{if(t)for(const e of t){const n=e.domain,a=(e.items??[]).map(c=>({label:c.label}));H.domains.set(n,{name:n,items:a})}},"setDomains"),Lt=s(t=>{t&&(H.transitions=t.filter(e=>e.from===e.to?(O.warn(`Cynefin: self-loop transition on domain "${e.from}" is not meaningful and will be skipped.`),!1):!0).map(e=>({from:e.from,to:e.to,label:e.label||void 0})))},"setTransitions"),Nt=s(()=>U({...Tt.cynefin,...Q().cynefin}),"getConfig"),Pt=s(()=>{At(),H=rt()},"clear"),Y={getDomains:St,getTransitions:Mt,setDomains:zt,setTransitions:Lt,getConfig:Nt,clear:Pt,setAccTitle:vt,getAccTitle:Ct,setDiagramTitle:wt,getDiagramTitle:bt,getAccDescription:$t,setAccDescription:gt},It=s(t=>{xt(t,Y),Y.setDomains(t.domains),Y.setTransitions(t.transitions)},"populate"),Wt={parse:s(async t=>{const e=await Bt("cynefin",t);O.debug(e),It(e)},"parse")};function V(t){let e=t+1831565813|0;return e=Math.imul(e^e>>>15,e|1),e^=e+Math.imul(e^e>>>7,e|61),((e^e>>>14)>>>0)/4294967296}s(V,"seededRandom");function st(t){let e=0;for(let n=0;n<t.length;n++){const a=t.charCodeAt(n);e=(e<<5)-e+a,e|=0}return e}s(st,"hashString");function it(t,e){return typeof t=="number"&&Number.isFinite(t)&&t!==0?t:st(e)}s(it,"resolveSeed");function ct(t,e,n,a){const c=t/2,m=a??t*.015,v=7,W=e/v,d=[];for(let o=0;o<=v;o++){const p=V(n+o*17)*m*2-m;d.push({x:c+p,y:o*W})}let D=`M${d[0].x},${d[0].y}`;for(let o=0;o<d.length-1;o++){const p=d[o],i=d[o+1],f=(p.y+i.y)/2,b=o%2===0?1:-1,h=m*1.5*b*V(n+o*31+7),R=p.x+h,_=f,E=i.x-h;D+=` C${R},${_} ${E},${f} ${i.x},${i.y}`}return D}s(ct,"generateFoldPath");function lt(t,e,n,a){const c=e/2,m=a??e*.015,v=7,W=t/v,d=[];for(let o=0;o<=v;o++){const p=V(n+o*23)*m*2-m;d.push({x:o*W,y:c+p})}let D=`M${d[0].x},${d[0].y}`;for(let o=0;o<d.length-1;o++){const p=d[o],i=d[o+1],f=(p.x+i.x)/2,b=o%2===0?1:-1,h=m*1.5*b*V(n+o*37+11),R=f,_=p.y+h,E=f,z=i.y-h;D+=` C${R},${_} ${E},${z} ${i.x},${i.y}`}return D}s(lt,"generateHorizontalBoundary");function dt(t,e){const n=t/2,a=e*.5,c=e,m=t*.03;return[`M${n},${a}`,`C${n+m},${a+(c-a)*.2}`,`${n-m*1.5},${a+(c-a)*.55}`,`${n+m*.5},${a+(c-a)*.75}`,`C${n-m},${a+(c-a)*.85}`,`${n+m*.3},${a+(c-a)*.95}`,`${n},${c}`].join(" ")}s(dt,"generateCliffPath");function ft(t,e,n,a){return[`M${t-n},${e}`,`A${n},${a} 0 1,1 ${t+n},${e}`,`A${n},${a} 0 1,1 ${t-n},${e}`,"Z"].join(" ")}s(ft,"generateConfusionPath");var at={complex:{model:"Probe → Sense → Respond",practice:"Emergent Practices"},complicated:{model:"Sense → Analyse → Respond",practice:"Good Practices"},clear:{model:"Sense → Categorise → Respond",practice:"Best Practices"},chaotic:{model:"Act → Sense → Respond",practice:"Novel Practices"},confusion:{model:"",practice:"Disorder"}},Rt=s((t,e)=>{const n=t/2,a=e/2;return{complex:{cx:n/2,cy:a/2,x:0,y:0,w:n,h:a},complicated:{cx:n+n/2,cy:a/2,x:n,y:0,w:n,h:a},chaotic:{cx:n/2,cy:a+a/2,x:0,y:a,w:n,h:a},clear:{cx:n+n/2,cy:a+a/2,x:n,y:a,w:n,h:a},confusion:{cx:n,cy:a,x:n*.7,y:a*.7,w:n*.6,h:a*.6}}},"getDomainLayouts"),_t=s(()=>{const t=ot(),e=Q();return U(t,e.themeVariables).cynefin},"getCynefinDomainColors"),q=3,Et=s((t,e,n,a)=>{const c=a.db,m=c.getDomains(),v=c.getTransitions(),W=c.getDiagramTitle(),d=c.getAccTitle(),D=c.getAccDescription(),o=c.getConfig(),p=_t();O.debug("Rendering Cynefin diagram");const i=o.width,f=o.height,b=o.padding,h=o.showDomainDescriptions,R=o.boundaryAmplitude,_=i+b*2,E=f+b*2,z={complex:p.complexBg,complicated:p.complicatedBg,clear:p.clearBg,chaotic:p.chaoticBg,confusion:p.confusionBg},k=Dt(e);kt(k,E,_,o.useMaxWidth??!0),k.attr("viewBox",`0 0 ${_} ${E}`),d&&k.append("title").text(d),D&&k.append("desc").text(D);const A=k.append("g").attr("transform",`translate(${b}, ${b})`),F=Rt(i,f),Z=it(o.seed,e),mt=A.append("g").attr("class","cynefin-backgrounds"),X=["complex","complicated","chaotic","clear"];for(const l of X){const r=F[l];mt.append("rect").attr("class","cynefinDomain").attr("x",r.x).attr("y",r.y).attr("width",r.w).attr("height",r.h).attr("fill",z[l]).attr("fill-opacity",.4).attr("stroke","none")}const j=A.append("g").attr("class","cynefin-boundaries");j.append("path").attr("class","cynefinBoundary").attr("d",ct(i,f,Z,R)).attr("fill","none"),j.append("path").attr("class","cynefinBoundary").attr("d",lt(i,f,Z+100,R)).attr("fill","none"),j.append("path").attr("class","cynefinCliff").attr("d",dt(i,f)).attr("fill","none");const pt=i*.15,yt=f*.15;A.append("path").attr("class","cynefinConfusion").attr("d",ft(i/2,f/2,pt,yt)).attr("fill",z.confusion).attr("fill-opacity",.5);const J=A.append("g").attr("class","cynefin-labels");for(const l of X){const r=F[l];J.append("text").attr("class","cynefinDomainLabel").attr("x"Line truncated
.cynefinDomain {
stroke: none;
}
.cynefinDomainLabel {
font-size: ${t.domainFontSize}px;
font-weight: bold;
fill: ${t.labelColor};
}
.cynefinSubtitle {
font-size: ${t.itemFontSize-1}px;
fill: ${t.textColor};
font-style: italic;
}
.cynefinItem {
fill-opacity: 0.95;
stroke: ${t.boundaryColor};
stroke-width: 1;
}
.cynefinItemText {
font-size: ${t.itemFontSize}px;
fill: ${t.textColor};
}
.cynefinItemOverflow {
fill-opacity: 0.6;
stroke: ${t.boundaryColor};
stroke-width: 1;
stroke-dasharray: 3 2;
}
.cynefinBoundary {
stroke: ${t.boundaryColor};
stroke-width: ${t.boundaryWidth};
stroke-dasharray: 6 3;
}
.cynefinCliff {
stroke: ${t.cliffColor};
stroke-width: ${t.cliffWidth};
}
.cynefinConfusion {
stroke: ${t.boundaryColor};
stroke-width: 1.5;
stroke-dasharray: 4 2;
}
.cynefinArrowLine {
stroke: ${t.arrowColor};
stroke-width: ${t.arrowWidth};
fill: none;
}
.cynefinArrowHead {
fill: ${t.arrowColor};
stroke: none;
}
.cynefinArrowLabel {
font-size: ${t.itemFontSize-1}px;
fill: ${t.textColor};
}
.cynefinTitle {
font-size: ${t.domainFontSize+2}px;
font-weight: bold;
fill: ${t.labelColor};
}
`},"styles"),Gt=Ht,qt={parser:Wt,db:Y,renderer:Ft,styles:Gt};export{qt as diagram};
+321
View File
@@ -0,0 +1,321 @@
function Ds(r,e){(e==null||e>r.length)&&(e=r.length);for(var t=0,a=Array(e);t<e;t++)a[t]=r[t];return a}function tc(r){if(Array.isArray(r))return r}function ac(r){if(Array.isArray(r))return Ds(r)}function ct(r,e){if(!(r instanceof e))throw new TypeError("Cannot call a class as a function")}function nc(r,e){for(var t=0;t<e.length;t++){var a=e[t];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(r,Jl(a.key),a)}}function dt(r,e,t){return e&&nc(r.prototype,e),Object.defineProperty(r,"prototype",{writable:!1}),r}function Cr(r,e){var t=typeof Symbol<"u"&&r[Symbol.iterator]||r["@@iterator"];if(!t){if(Array.isArray(r)||(t=Ks(r))||e){t&&(r=t);var a=0,n=function(){};return{s:n,n:function(){return a>=r.length?{done:!0}:{done:!1,value:r[a++]}},e:function(u){throw u},f:n}}throw new TypeError(`Invalid attempt to iterate non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}var i,s=!0,o=!1;return{s:function(){t=t.call(r)},n:function(){var u=t.next();return s=u.done,u},e:function(u){o=!0,i=u},f:function(){try{s||t.return==null||t.return()}finally{if(o)throw i}}}}function Ql(r,e,t){return(e=Jl(e))in r?Object.defineProperty(r,e,{value:t,enumerable:!0,configurable:!0,writable:!0}):r[e]=t,r}function ic(r){if(typeof Symbol<"u"&&r[Symbol.iterator]!=null||r["@@iterator"]!=null)return Array.from(r)}function sc(r,e){var t=r==null?null:typeof Symbol<"u"&&r[Symbol.iterator]||r["@@iterator"];if(t!=null){var a,n,i,s,o=[],u=!0,l=!1;try{if(i=(t=t.call(r)).next,e===0){if(Object(t)!==t)return;u=!1}else for(;!(u=(a=i.call(t)).done)&&(o.push(a.value),o.length!==e);u=!0);}catch(v){l=!0,n=v}finally{try{if(!u&&t.return!=null&&(s=t.return(),Object(s)!==s))return}finally{if(l)throw n}}return o}}function oc(){throw new TypeError(`Invalid attempt to destructure non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function uc(){throw new TypeError(`Invalid attempt to spread non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function Xe(r,e){return tc(r)||sc(r,e)||Ks(r,e)||oc()}function yn(r){return ac(r)||ic(r)||Ks(r)||uc()}function lc(r,e){if(typeof r!="object"||!r)return r;var t=r[Symbol.toPrimitive];if(t!==void 0){var a=t.call(r,e);if(typeof a!="object")return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(r)}function Jl(r){var e=lc(r,"string");return typeof e=="symbol"?e:e+""}function je(r){"@babel/helpers - typeof";return je=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},je(r)}function Ks(r,e){if(r){if(typeof r=="string")return Ds(r,e);var t={}.toString.call(r).slice(8,-1);return t==="Object"&&r.constructor&&(t=r.constructor.name),t==="Map"||t==="Set"?Array.from(r):t==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?Ds(r,e):void 0}}var Qe=typeof window>"u"?null:window,Co=Qe?Qe.navigator:null;Qe&&Qe.document;var vc=je(""),jl=je({}),fc=je(function(){}),cc=typeof HTMLElement>"u"?"undefined":je(HTMLElement),La=function(e){return e&&e.instanceString&&He(e.instanceString)?e.instanceString():null},he=function(e){return e!=null&&je(e)==vc},He=function(e){return e!=null&&je(e)===fc},Fe=function(e){return!Tr(e)&&(Array.isArray?Array.isArray(e):e!=null&&e instanceof Array)},Me=function(e){return e!=null&&je(e)===jl&&!Fe(e)&&e.constructor===Object},dc=function(e){return e!=null&&je(e)===jl},ae=function(e){return e!=null&&je(e)===je(1)&&!isNaN(e)},ev=function(e){return ae(e)&&Math.floor(e)===e},mn=function(e){if(cc!=="undefined")return e!=null&&e instanceof HTMLElement},Tr=function(e){return Ia(e)||rv(e)},Ia=function(e){return La(e)==="collection"&&e._private.single},rv=function(e){return La(e)==="collection"&&!e._private.single},Xs=function(e){return La(e)==="core"},tv=function(e){return La(e)==="stylesheet"},hc=function(e){return La(e)==="event"},st=function(e){return e==null?!0:!!(e===""||e.match(/^\s+$/))},gc=function(e){return typeof HTMLElement>"u"?!1:e instanceof HTMLElement},pc=function(e){return Me(e)&&ae(e.x1)&&ae(e.x2)&&ae(e.y1)&&ae(e.y2)},yc=function(e){return dc(e)&&He(e.then)},mc=function(){return Co&&Co.userAgent.match(/msie|trident|edge/i)},Yt=function(e,t){t||(t=function(){if(arguments.length===1)return arguments[0];if(arguments.length===0)return"undefined";for(var i=[],s=0;s<arguments.length;s++)i.push(arguments[s]);return i.join("$")});var a=function(){var i=this,s=arguments,o,u=t.apply(i,s),l=a.cache;return(o=l[u])||(o=l[u]=e.apply(i,s)),o};return a.cache={},a},Ys=Yt(function(r){return r.replace(/([A-Z])/g,function(e){return"-"+e.toLowerCase()})}),Rn=Yt(function(r){return r.replace(/(-\w)/g,function(e){return e[1].toUpperCase()})}),av=Yt(function(r,e){return r+e[0].toUpperCase()+e.substring(1)},function(r,e){return r+"$"+e}),To=function(e){return st(e)?e:e.charAt(0).toUpperCase()+e.substring(1)},rt=function(e,t){return e.slice(-1*t.length)===t},Je="(?:[-+]?(?:(?:\\d+|\\d*\\.\\d+)(?:[Ee][+-]?\\d+)?))",bc="rgb[a]?\\(("+Je+"[%]?)\\s*,\\s*("+Je+"[%]?)\\s*,\\s*("+Je+"[%]?)(?:\\s*,\\s*("+Je+"))?\\)",wc="rgb[a]?\\((?:"+Je+"[%]?)\\s*,\\s*(?:"+Je+"[%]?)\\s*,\\s*(?:"+Je+"[%]?)(?:\\s*,\\s*(?:"+Je+"))?\\)",xc="hsl[a]?\\(("+Je+")\\s*,\\s*("+Je+"[%])\\s*,\\s*("+Je+"[%])(?:\\s*,\\s*("+Je+"))?\\)",Ec="hsl[a]?\\((?:"+Je+")\\s*,\\s*(?:"+Je+"[%])\\s*,\\s*(?:"+Je+"[%])(?:\\s*,\\s*(?:"+Je+"))?\\)",Cc="\\#[0-9a-fA-F]{3}",Tc="\\#[0-9a-fA-F]{6}",nv=function(e,t){return e<t?-1:e>t?1:0},Sc=function(e,t){return-1*nv(e,t)},me=Object.assign!=null?Object.assign.bind(Object):function(r){for(var e=arguments,t=1;t<e.length;t++){var a=e[t];if(a!=null)for(var n=Object.keys(a),i=0;i<n.length;i++){var s=n[i];r[s]=a[s]}}return r},kc=function(e){if(!(!(e.length===4||e.length===7)||e[0]!=="#")){var t=e.length===4,a,n,i,s=16;return t?(a=parseInt(e[1]+e[1],s),n=parseInt(e[2]+e[2],s),i=parseInt(e[3]+e[3],s)):(a=parseInt(e[1]+e[2],s),n=parseInt(e[3]+e[4],s),i=parseInt(e[5]+e[6],s)),[a,n,i]}},Dc=function(e){var t,a,n,i,s,o,u,l;function v(d,y,g){return g<0&&(g+=1),g>1&&(g-=1),g<1/6?d+(y-d)*6*g:g<1/2?y:g<2/3?d+(y-d)*(2/3-g)*6:d}var f=new RegExp("^"+xc+"$").exec(e);if(f){if(a=parseInt(f[1]),a<0?a=(360- -1*a%360)%360:a>360&&(a=a%360),a/=360,n=parseFloat(f[2]),n<0||n>100||(n=n/100,i=parseFloat(f[3]),i<0||i>100)||(i=i/100,s=f[4],s!==void 0&&(s=parseFloat(s),s<0||s>1)))return;if(n===0)o=u=l=Math.round(i*255);else{var c=i<.5?i*(1+n):i+n-i*n,h=2*i-c;o=Math.round(255*v(h,c,a+1/3)),u=Math.round(255*v(h,c,a)),l=Math.round(255*v(h,c,a-1/3))}t=[o,u,l,s]}return t},Bc=function(e){var t,a=new RegExp("^"+bc+"$").exec(e);if(a){t=[];for(var n=[],i=1;i<=3;i++){var s=a[i];if(s[s.length-1]==="%"&&(n[i]=!0),s=parseFloat(s),n[i]&&(s=s/100*255),s<0||s>255)return;t.push(Math.floor(s))}var o=n[1]||n[2]||n[3],u=n[1]&&n[2]&&n[3];if(o&&!u)return;var l=a[4];if(l!==void 0){if(l=parseFloat(l),l<0||l>1)re Line truncated
`),f=r.pstyle("text-max-width").pfValue,c=r.pstyle("text-overflow-wrap").value,h=c==="anywhere",d=[],y=/[\s\u200b]+|$/g,g=0;g<v.length;g++){var p=v[g],m=this.calculateLabelDimensions(r,p),b=m.width;if(h){var w=p.split("").join(l);p=w}if(b>f){var E=p.matchAll(y),C="",x=0,T=Cr(E),k;try{for(T.s();!(k=T.n()).done;){var B=k.value,D=B[0],P=p.substring(x,B.index);x=B.index+D.length;var A=C.length===0?P:C+P+D,R=this.calculateLabelDimensions(r,A),L=R.width;L<=f?C+=P+D:(C&&d.push(C),C=P+D)}}catch(q){T.e(q)}finally{T.f()}C.match(/^[\s\u200b]+$/)||d.push(C)}else d.push(p)}s("labelWrapCachedLines",d),n=s("labelWrapCachedText",d.join(`
`)),s("labelWrapKey",u)}else if(o==="ellipsis"){var I=r.pstyle("text-max-width").pfValue,M="",N="…",F=!1;if(this.calculateLabelDimensions(r,n).width<I)return n;for(var _=0;_<n.length;_++){var z=this.calculateLabelDimensions(r,M+n[_]+N).width;if(z>I)break;M+=n[_],_===n.length-1&&(F=!0)}return F||(M+=N),M}return n};Hr.getLabelJustification=function(r){var e=r.pstyle("text-justification").strValue,t=r.pstyle("text-halign").strValue;return e==="auto"?r.isNode()?Ug(t):"center":e};Hr.calculateLabelDimensions=function(r,e){var t=this,a=t.cy.window(),n=a.document,i=0,s=r.pstyle("font-style").strValue,o=r.pstyle("font-size").pfValue,u=r.pstyle("font-family").strValue,l=r.pstyle("font-weight").strValue,v=r.pstyle("text-metrics").strValue||"font",f=this.labelCalcCanvas,c=this.labelCalcCanvasContext;if(!f){f=this.labelCalcCanvas=n.createElement("canvas"),c=this.labelCalcCanvasContext=f.getContext("2d");var h=f.style;h.position="absolute",h.left="-9999px",h.top="-9999px",h.zIndex="-1",h.visibility="hidden",h.pointerEvents="none"}c.font="".concat(s," ").concat(l," ").concat(o,"px ").concat(u);for(var d=0,y=0,g=e.split(`
`),p=g.length,m=0,b=0,w=0;w<p;w++){var E=g[w],C=c.measureText(E),x=Math.ceil(C.width),T=o;v==="glyph"&&(w===0&&(b=C.actualBoundingBoxAscent),w===p-1&&(m=C.actualBoundingBoxDescent)),d=Math.max(x,d),y+=T}return v==="glyph"&&(y-=o-b-m),d+=i,y+=i,{width:d,height:y,labelActualAscent:b,labelActualDescent:m}};Hr.calculateLabelAngle=function(r,e){var t=r._private,a=t.rscratch,n=r.isEdge(),i=e?e+"-":"",s=r.pstyle(i+"text-rotation"),o=s.strValue;return o==="none"?0:n&&o==="autorotate"?a.labelAutoAngle:o==="autorotate"?0:s.pfValue};Hr.calculateLabelAngles=function(r){var e=this,t=r.isEdge(),a=r._private,n=a.rscratch;n.labelAngle=e.calculateLabelAngle(r),t&&(n.sourceLabelAngle=e.calculateLabelAngle(r,"source"),n.targetLabelAngle=e.calculateLabelAngle(r,"target"))};var xf={},Ml=28,Ll=!1;xf.getNodeShape=function(r){var e=this,t=r.pstyle("shape").value;if(t==="cutrectangle"&&(r.width()<Ml||r.height()<Ml))return Ll||(Ne("The `cutrectangle` node shape can not be used at small sizes so `rectangle` is used instead"),Ll=!0),"rectangle";if(r.isParent())return t==="rectangle"||t==="roundrectangle"||t==="round-rectangle"||t==="cutrectangle"||t==="cut-rectangle"||t==="barrel"?t:"rectangle";if(t==="polygon"){var a=r.pstyle("shape-polygon-points").value;return e.nodeShapes.makePolygon(a).name}return t};var Kn={};Kn.registerCalculationListeners=function(){var r=this.cy,e=r.collection(),t=this,a=function(s){var o=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;if(e.merge(s),o)for(var u=0;u<s.length;u++){var l=s[u],v=l._private,f=v.rstyle;f.clean=!1,f.cleanConnected=!1}};t.binder(r).on("bounds.* dirty.*",function(s){var o=s.target;a(o)}).on("style.* background.*",function(s){var o=s.target;a(o,!1)});var n=function(s){if(s){var o=t.onUpdateEleCalcsFns;e.cleanStyle();for(var u=0;u<e.length;u++){var l=e[u],v=l._private.rstyle;l.isNode()&&!v.cleanConnected&&(a(l.connectedEdges()),v.cleanConnected=!0)}if(o)for(var f=0;f<o.length;f++){var c=o[f];c(s,e)}t.recalculateRenderedStyle(e),e=r.collection()}};t.flushRenderedStyleQueue=function(){n(!0)},t.beforeRender(n,t.beforeRenderPriorities.eleCalcs)};Kn.onUpdateEleCalcs=function(r){var e=this.onUpdateEleCalcsFns=this.onUpdateEleCalcsFns||[];e.push(r)};Kn.recalculateRenderedStyle=function(r,e){var t=function(w){return w._private.rstyle.cleanConnected};if(r.length!==0){var a=[],n=[];if(!this.destroyed){e===void 0&&(e=!0);for(var i=0;i<r.length;i++){var s=r[i],o=s._private,u=o.rstyle;s.isEdge()&&(!t(s.source())||!t(s.target()))&&(u.clean=!1),s.isEdge()&&s.isBundledBezier()&&s.parallelEdges().some(function(b){return!b._private.rstyle.clean&&b.isBundledBezier()})&&(u.clean=!1),!(e&&u.clean||s.removed())&&s.pstyle("display").value!=="none"&&(o.group==="nodes"?n.push(s):a.push(s),u.clean=!0)}for(var l=0;l<n.length;l++){var v=n[l],f=v._private,c=f.rstyle,h=v.position();this.recalculateNodeLabelProjection(v),c.nodeX=h.x,c.nodeY=h.y,c.nodeW=v.pstyle("width").pfValue,c.nodeH=v.pstyle("height").pfValue}this.recalculateEdgeProjections(a);for(var d=0;d<a.length;d++){var y=a[d],g=y._private,p=g.rstyle,m=g.rscratch;p.srcX=m.arrowStartX,p.srcY=m.arrowStartY,p.tgtX=m.arrowEndX,p.tgtY=m.arrowEndY,p.midX=m.midX,p.midY=m.midY,p.labelAngle=m.labelAngle,p.sourceLabelAngle=m.sourceLabelAngle,p.targetLabelAngle=m.targetLabelAngle}}}};var Xn={};Xn.updateCachedGrabbedEles=function(){var r=this.cachedZSortedEles;if(r){r.drag=[],r.nondrag=[];for(var e=[],t=0;t<r.length;t++){var a=r[t],n=a._private.rscratch;a.grabbed()&&!a.isParent()?e.push(a):n.inDragLayer?r.drag.push(a):r.nondrag.push(a)}for(var t=0;t<e.length;t++){var a=e[t];r.drag.push(a)}}};Xn.invalidateCachedZSortedEles=function(){this.cachedZSortedEles=null};Xn.getCachedZSortedEles=function(r){if(r||!this.cachedZSortedEles){var e=this.cy.mutableElements().toArray();e.sort(rf),e.interactive=e.filter(function(t){return t.interactive()}),this.cachedZSortedEles=e,this.updateCachedGrabbedEles()}else e=this.cachedZSortedEles;return e};var Ef={};[At,Dn,hr,Ga,po,Hr,xf,Kn,Xn].forEach(function(r){me(Ef,r)});var Cf={};Cf.getCachedImage=function(r,e,t){var a=this,n=a.imageCache=a.imageCache||{},i=n[r];if(i)return i.image.complete||i.image.addEventListener("load",t),i.image;i=n[r]=n[r]||{};var s=i.image=new Image;s.addEventListener("load",t),s.addEventListener("error",function(){s.error=!0});var o="data:",u=r.substring(0,o.length).toLowerCase()===o;return u||(e=e==="null"?null:e,s.crossOrigin=e),s.src=r,s};var Tf=function(e,t){var a=e[0];!a||a._private.grabbed===t||(a._private.grabbed=t,e.updateStyle(!1))},sy=function(e){Tf(e,!0)},oy=function(e){Tf(e,!1)},ia={};ia.registerBinding=function(r,e,t,a){var n=Array.prototype.slice.apply(arguments,[1]);if(Array.isArray(r)){for(var i=[],s=0;s<r.length;s++){var o=r[s];if(o!==void 0){var u=this.binder(o);i.push(u.on.apply(u,n))}}return i}var u=this.binder(r);return u.on.apply(u,n)};ia.binder=function(r){var e=this,t=e.cy.window(),a=r===t||r===t.document||r===t.document.body||gc(r);if(e.supportsPassiveEvents==null){var n=!1;try{va Line truncated
float circleSD(vec2 p, float r) {
return distance(vec2(0), p) - r; // signed distance
}
`,dm=`
float rectangleSD(vec2 p, vec2 b) {
vec2 d = abs(p)-b;
return distance(vec2(0),max(d,0.0)) + min(max(d.x,d.y),0.0);
}
`,hm=`
float roundRectangleSD(vec2 p, vec2 b, vec4 cr) {
cr.xy = (p.x > 0.0) ? cr.xy : cr.zw;
cr.x = (p.y > 0.0) ? cr.x : cr.y;
vec2 q = abs(p) - b + cr.x;
return min(max(q.x, q.y), 0.0) + distance(vec2(0), max(q, 0.0)) - cr.x;
}
`,gm=`
float ellipseSD(vec2 p, vec2 ab) {
p = abs( p ); // symmetry
// find root with Newton solver
vec2 q = ab*(p-ab);
float w = (q.x<q.y)? 1.570796327 : 0.0;
for( int i=0; i<5; i++ ) {
vec2 cs = vec2(cos(w),sin(w));
vec2 u = ab*vec2( cs.x,cs.y);
vec2 v = ab*vec2(-cs.y,cs.x);
w = w + dot(p-u,v)/(dot(p-u,u)+dot(v,v));
}
// compute final point and distance
float d = length(p-ab*vec2(cos(w),sin(w)));
// return signed distance
return (dot(p/ab,p/ab)>1.0) ? d : -d;
}
`,Ea={SCREEN:{name:"screen",screen:!0},PICKING:{name:"picking",picking:!0}},Pn={IGNORE:1,USE_BB:2},Es=0,Ul=1,Kl=2,Cs=3,Vt=4,nn=5,ga=6,pa=7,pm=(function(){function r(e,t,a){ct(this,r),this.r=e,this.gl=t,this.maxInstances=a.webglBatchSize,this.atlasSize=a.webglTexSize,this.bgColor=a.bgColor,this.debug=a.webglDebug,this.batchDebugInfo=[],a.enableWrapping=!0,a.createTextureCanvas=Xy,this.atlasManager=new vm(e,a),this.batchManager=new fm(a),this.simpleShapeOptions=new Map,this.program=this._createShaderProgram(Ea.SCREEN),this.pickingProgram=this._createShaderProgram(Ea.PICKING),this.vao=this._createVAO()}return dt(r,[{key:"addAtlasCollection",value:function(t,a){this.atlasManager.addAtlasCollection(t,a)}},{key:"addTextureAtlasRenderType",value:function(t,a){this.atlasManager.addRenderType(t,a)}},{key:"addSimpleShapeRenderType",value:function(t,a){this.simpleShapeOptions.set(t,a)}},{key:"invalidate",value:function(t){var a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=a.type,i=this.atlasManager;return n?i.invalidate(t,{filterType:function(o){return o===n},forceRedraw:!0}):i.invalidate(t)}},{key:"gc",value:function(){this.atlasManager.gc()}},{key:"_createShaderProgram",value:function(t){var a=this.gl,n=`#version 300 es
precision highp float;
uniform mat3 uPanZoomMatrix;
uniform int uAtlasSize;
// instanced
in vec2 aPosition; // a vertex from the unit square
in mat3 aTransform; // used to transform verticies, eg into a bounding box
in int aVertType; // the type of thing we are rendering
// the z-index that is output when using picking mode
in vec4 aIndex;
// For textures
in int aAtlasId; // which shader unit/atlas to use
in vec4 aTex; // x/y/w/h of texture in atlas
// for edges
in vec4 aPointAPointB;
in vec4 aPointCPointD;
in vec2 aLineWidth; // also used for node border width
// simple shapes
in vec4 aCornerRadius; // for round-rectangle [top-right, bottom-right, top-left, bottom-left]
in vec4 aColor; // also used for edges
in vec4 aBorderColor; // aLineWidth is used for border width
// output values passed to the fragment shader
out vec2 vTexCoord;
out vec4 vColor;
out vec2 vPosition;
// flat values are not interpolated
flat out int vAtlasId;
flat out int vVertType;
flat out vec2 vTopRight;
flat out vec2 vBotLeft;
flat out vec4 vCornerRadius;
flat out vec4 vBorderColor;
flat out vec2 vBorderWidth;
flat out vec4 vIndex;
void main(void) {
int vid = gl_VertexID;
vec2 position = aPosition; // TODO make this a vec3, simplifies some code below
if(aVertType == `.concat(Es,`) {
float texX = aTex.x; // texture coordinates
float texY = aTex.y;
float texW = aTex.z;
float texH = aTex.w;
if(vid == 1 || vid == 2 || vid == 4) {
texX += texW;
}
if(vid == 2 || vid == 4 || vid == 5) {
texY += texH;
}
float d = float(uAtlasSize);
vTexCoord = vec2(texX / d, texY / d); // tex coords must be between 0 and 1
gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0);
}
else if(aVertType == `).concat(Vt," || aVertType == ").concat(pa,`
|| aVertType == `).concat(nn," || aVertType == ").concat(ga,`) { // simple shapes
// the bounding box is needed by the fragment shader
vBotLeft = (aTransform * vec3(0, 0, 1)).xy; // flat
vTopRight = (aTransform * vec3(1, 1, 1)).xy; // flat
vPosition = (aTransform * vec3(position, 1)).xy; // will be interpolated
// calculations are done in the fragment shader, just pass these along
vColor = aColor;
vCornerRadius = aCornerRadius;
vBorderColor = aBorderColor;
vBorderWidth = aLineWidth;
gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0);
}
else if(aVertType == `).concat(Ul,`) {
vec2 source = aPointAPointB.xy;
vec2 target = aPointAPointB.zw;
// adjust the geometry so that the line is centered on the edge
position.y = position.y - 0.5;
// stretch the unit square into a long skinny rectangle
vec2 xBasis = target - source;
vec2 yBasis = normalize(vec2(-xBasis.y, xBasis.x));
vec2 point = source + xBasis * position.x + yBasis * aLineWidth[0] * position.y;
gl_Position = vec4(uPanZoomMatrix * vec3(point, 1.0), 1.0);
vColor = aColor;
}
else if(aVertType == `).concat(Kl,`) {
vec2 pointA = aPointAPointB.xy;
vec2 pointB = aPointAPointB.zw;
vec2 pointC = aPointCPointD.xy;
vec2 pointD = aPointCPointD.zw;
// adjust the geometry so that the line is centered on the edge
position.y = position.y - 0.5;
vec2 p0, p1, p2, pos;
if(position.x == 0.0) { // The left side of the unit square
p0 = pointA;
p1 = pointB;
p2 = pointC;
pos = position;
} else { // The right side of the unit square, use same approach but flip the geometry upside down
p0 = pointD;
p1 = pointC;
p2 = pointB;
pos = vec2(0.0, -position.y);
}
vec2 p01 = p1 - p0;
vec2 p12 = p2 - p1;
vec2 p21 = p1 - p2;
// Find the normal vector.
vec2 tangent = normalize(normalize(p12) + normalize(p01));
vec2 normal = vec2(-tangent.y, tangent.x);
// Find the vector perpendicular to p0 -> p1.
vec2 p01Norm = normalize(vec2(-p01.y, p01.x));
// Determine the bend direction.
float sigma = sign(dot(p01 + p21, normal));
float width = aLineWidth[0];
if(sign(pos.y) == -sigma) {
// This is an intersecting vertex. Adjust the position so that there's no overlap.
vec2 point = 0.5 * width * normal * -sigma / dot(normal, p01Norm);
gl_Position = vec4(uPanZoomMatrix * vec3(p1 + point, 1.0), 1.0);
} else {
// This is a non-intersecting vertex. Treat it like a mitre join.
vec2 point = 0.5 * width * normal * sigma * dot(normal, p01Norm);
gl_Position = vec4(uPanZoomMatrix * vec3(p1 + point, 1.0), 1.0);
}
vColor = aColor;
}
else if(aVertType == `).concat(Cs,` && vid < 3) {
// massage the first triangle into an edge arrow
if(vid == 0)
position = vec2(-0.15, -0.3);
if(vid == 1)
position = vec2( 0.0, 0.0);
if(vid == 2)
position = vec2( 0.15, -0.3);
gl_Position = vec4(uPanZoomMatrix * aTransform * vec3(position, 1.0), 1.0);
vColor = aColor;
}
else {
gl_Position = vec4(2.0, 0.0, 0.0, 1.0); // discard vertex by putting it outside webgl clip space
}
vAtlasId = aAtlasId;
vVertType = aVertType;
vIndex = aIndex;
}
`),i=this.batchManager.getIndexArray(),s=`#version 300 es
precision highp float;
// declare texture unit for each texture atlas in the batch
`.concat(i.map(function(l){return"uniform sampler2D uTexture".concat(l,";")}).join(`
`),`
uniform vec4 uBGColor;
uniform float uZoom;
in vec2 vTexCoord;
in vec4 vColor;
in vec2 vPosition; // model coordinates
flat in int vAtlasId;
flat in vec4 vIndex;
flat in int vVertType;
flat in vec2 vTopRight;
flat in vec2 vBotLeft;
flat in vec4 vCornerRadius;
flat in vec4 vBorderColor;
flat in vec2 vBorderWidth;
out vec4 outColor;
`).concat(cm,`
`).concat(dm,`
`).concat(hm,`
`).concat(gm,`
vec4 blend(vec4 top, vec4 bot) { // blend colors with premultiplied alpha
return vec4(
top.rgb + (bot.rgb * (1.0 - top.a)),
top.a + (bot.a * (1.0 - top.a))
);
}
vec4 distInterp(vec4 cA, vec4 cB, float d) { // interpolate color using Signed Distance
// scale to the zoom level so that borders don't look blurry when zoomed in
// note 1.5 is an aribitrary value chosen because it looks good
return mix(cA, cB, 1.0 - smoothstep(0.0, 1.5 / uZoom, abs(d)));
}
void main(void) {
if(vVertType == `).concat(Es,`) {
// look up the texel from the texture unit
`).concat(i.map(function(l){return"if(vAtlasId == ".concat(l,") outColor = texture(uTexture").concat(l,", vTexCoord);")}).join(`
else `),`
}
else if(vVertType == `).concat(Cs,`) {
// mimics how canvas renderer uses context.globalCompositeOperation = 'destination-out';
outColor = blend(vColor, uBGColor);
outColor.a = 1.0; // make opaque, masks out line under arrow
}
else if(vVertType == `).concat(Vt,` && vBorderWidth == vec2(0.0)) { // simple rectangle with no border
outColor = vColor; // unit square is already transformed to the rectangle, nothing else needs to be done
}
else if(vVertType == `).concat(Vt," || vVertType == ").concat(pa,`
|| vVertType == `).concat(nn," || vVertType == ").concat(ga,`) { // use SDF
float outerBorder = vBorderWidth[0];
float innerBorder = vBorderWidth[1];
float borderPadding = outerBorder * 2.0;
float w = vTopRight.x - vBotLeft.x - borderPadding;
float h = vTopRight.y - vBotLeft.y - borderPadding;
vec2 b = vec2(w/2.0, h/2.0); // half width, half height
vec2 p = vPosition - vec2(vTopRight.x - b[0] - outerBorder, vTopRight.y - b[1] - outerBorder); // translate to center
float d; // signed distance
if(vVertType == `).concat(Vt,`) {
d = rectangleSD(p, b);
} else if(vVertType == `).concat(pa,` && w == h) {
d = circleSD(p, b.x); // faster than ellipse
} else if(vVertType == `).concat(pa,`) {
d = ellipseSD(p, b);
} else {
d = roundRectangleSD(p, b, vCornerRadius.wzyx);
}
// use the distance to interpolate a color to smooth the edges of the shape, doesn't need multisampling
// we must smooth colors inwards, because we can't change pixels outside the shape's bounding box
if(d > 0.0) {
if(d > outerBorder) {
discard;
} else {
outColor = distInterp(vBorderColor, vec4(0), d - outerBorder);
}
} else {
if(d > innerBorder) {
vec4 outerColor = outerBorder == 0.0 ? vec4(0) : vBorderColor;
vec4 innerBorderColor = blend(vBorderColor, vColor);
outColor = distInterp(innerBorderColor, outerColor, d);
}
else {
vec4 outerColor;
if(innerBorder == 0.0 && outerBorder == 0.0) {
outerColor = vec4(0);
} else if(innerBorder == 0.0) {
outerColor = vBorderColor;
} else {
outerColor = blend(vBorderColor, vColor);
}
outColor = distInterp(vColor, outerColor, d - innerBorder);
}
}
}
else {
outColor = vColor;
}
`).concat(t.picking?`if(outColor.a == 0.0) discard;
else outColor = vIndex;`:"",`
}
`),o=Ky(a,n,s);o.aPosition=a.getAttribLocation(o,"aPosition"),o.aIndex=a.getAttribLocation(o,"aIndex"),o.aVertType=a.getAttribLocation(o,"aVertType"),o.aTransform=a.getAttribLocation(o,"aTransform"),o.aAtlasId=a.getAttribLocation(o,"aAtlasId"),o.aTex=a.getAttribLocation(o,"aTex"),o.aPointAPointB=a.getAttribLocation(o,"aPointAPointB"),o.aPointCPointD=a.getAttribLocation(o,"aPointCPointD"),o.aLineWidth=a.getAttribLocation(o,"aLineWidth"),o.aColor=a.getAttribLocation(o,"aColor"),o.aCornerRadius=a.getAttribLocation(o,"aCornerRadius"),o.aBorderColor=a.getAttribLocation(o,"aBorderColor"),o.uPanZoomMatrix=a.getUniformLocation(o,"uPanZoomMatrix"),o.uAtlasSize=a.getUniformLocation(o,"uAtlasSize"),o.uBGColor=a.getUniformLocation(o,"uBGColor"),o.uZoom=a.getUniformLocation(o,"uZoom"),o.uTextures=[];for(var u=0;u<this.batchManager.getMaxAtlasesPerBatch();u++)o.uTextures.push(a.getUniformLocation(o,"uTexture".concat(u)));return o}},{key:"_createVAO",value:function(){var t=[0,0,1,0,1,1,0,0,1,1,0,1];this.vertexCount=t.length/2;var a=this.maxInstances,n=this.gl,i=this.program,s=n.createVertexArray();return n.bindVertexArray(s),tm(n,"vec2",i.aPosition,t),this.transformBuffer=am(n,a,i.aTransform),this.indexBuffer=Fr(n,a,"vec4",i.aIndex),this.vertTypeBuffer=Fr(n,a,"int",i.aVertType),this.atlasIdBuffer=Fr(n,a,"int",i.aAtlasId),this.texBuffer=Fr(n,a,"vec4",i.aTex),this.pointAPointBBuffer=Fr(n,a,"vec4",i.aPointAPointB),this.pointCPointDBuffer=Fr(n,a,"vec4",i.aPointCPointD),this.lineWidthBuffer=Fr(n,a,"vec2",i.aLineWidth),this.colorBuffer=Fr(n,a,"vec4",i.aColor),this.cornerRadiusBuffer=Fr(n,a,"vec4",i.aCornerRadius),this.borderColorBuffer=Fr(n,a,"vec4",i.aBorderColor),n.bindVertexArray(null),s}},{key:"buffers",get:function(){var t=this;return this._buffers||(this._buffers=Object.keys(this).filter(function(a){return rt(a,"Buffer")}).map(function(a){return t[a]})),this._buffers}},{key:"startFrame",value:function(t){var a=arguments.length>1&&arguments[1]!==void 0?arguments[1]:Ea.SCREEN;this.panZoomMatrix=t,this.renderTarget=a,this.batchDebugInfo=[],this.wrappedCount=0,this.simpleCount=0,this.startBatch()}},{key:"startBatch",value:function(){this.instanceCount=0,this.batchManager.startBatch()}},{key:"endFrame",value:function(){this.endBatch()}},{key:"_isVisible",value:function(t,a){return t.visible()?a&&a.isVisible?a.isVisible(t):!0:!1}},{key:"drawTexture",value:function(t,a,n){var i=this.atlasManager,s=this.batchManager,o=i.getRenderTypeOpts(n);if(this._isVisible(t,o)&&!(t.isEdge()&&!this._isValidEdge(t))){if(this.renderTarget.picking&&o.getTexPickingMode){var u=o.getTexPickingMode(t);if(u===Pn.IGNORE)return;if(u==Pn.USE_BB){this.drawPickingRectangle(t,a,n);return}}var l=i.getAtlasInfo(t,n),v=Cr(l),f;try{for(v.s();!(f=v.n()).done;){var c=f.value,h=c.atlas,d=c.tex1,y=c.tex2;s.canAddToCurrentBatch(h)||this.endBatch();for(var g=s.getAtlasIndexForBatch(h),p=0,m=[[d,!0],[y,!1]];p<m.length;p++){var b=Xe(m[p],2),w=b[0],E=b[1];if(w.w!=0){var C=this.instanceCount;this.vertTypeBuffer.getView(C)[0]=Es;var x=this.indexBuffer.getView(C);Ft(a,x);var T=this.atlasIdBuffer.getView(C);T[0]=g;var k=this.texBuffer.getView(C);k[0]=w.x,k[1]=w.y,k[2]=w.w,k[3]=w.h;var B=this.transformBuffer.getMatrixView(C);this.setTransformMatrix(t,B,o,c,E),this.instanceCount++,E||this.wrappedCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}}}}catch(D){v.e(D)}finally{v.f()}}}},{key:"setTransformMatrix",value:function(t,a,n,i){var s=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,o=0;if(n.shapeProps&&n.shapeProps.padding&&(o=t.pstyle(n.shapeProps.padding).pfValue),i){var u=i.bb,l=i.tex1,v=i.tex2,f=l.w/(l.w+v.w);s||(f=1-f);var c=this._getAdjustedBB(u,o,s,f);this._applyTransformMatrix(a,c,n,t)}else{var h=n.getBoundingBox(t),d=this._getAdjustedBB(h,o,!0,1);this._applyTransformMatrix(a,d,n,t)}}},{key:"_applyTransformMatrix",value:function(t,a,n,i){var s,o;Wl(t);var u=n.getRotation?n.getRotation(i):0;if(u!==0){var l=n.getRotationPoint(i),v=l.x,f=l.y;pn(t,t,[v,f]),$l(t,t,u);var c=n.getRotationOffset(i);s=c.x+(a.xOffset||0),o=c.y+(a.yOffset||0)}else s=a.x1,o=a.y1;pn(t,t,[s,o]),Hs(t,t,[a.w,a.h])}},{key:"_getAdjustedBB",value:function(t,a,n,i){var s=t.x1,o=t.y1,u=t.w,l=t.h,v=t.yOffset;a&&(s-=a,o-=a,u+=2*a,l+=2*a);var f=0,c=u*i;return n&&i<1?u=c:!n&&i<1&&(f=u-c,s+=f,u=c),{x1:s,y1:o,w:u,h:l,xOffset:f,yOffset:v}}},{key:"drawPickingRectangle",value:function(t,a,n){var i=this.atlasManager.getRenderTypeOpts(n),s=this.instanceCount;this.vertTypeBuffer.getView(s)[0]=Vt;var o=this.indexBuffer.getView(s);Ft(a,o);var u=this.colorBuffer.getView(s);bt([0,0,0],1,u);var l=this.transformBuffer.getMatrixView(s);this.setTransformMatrix(t,l,i),this.simpleCount++,this.instanceCount++,this.instanceCount>=this.maxInstances&&this.endBatch()}},{key:"drawNode",value:function(t,a,n){var i=this.simpleShapeOptions.get(n);if(this._isVisible(t,i)){var s=i.shapeProps,o=this._getVertTypeForShape(t,s.shape);if(o===void 0||i.isSimple&&!i.isSimple(t,this.renderTarget)){this.drawTexture(t, Line truncated
+4
View File
@@ -0,0 +1,4 @@
import{_ as m,ao as x,c as k,Q as O,l as p,ap as A,aq as Y,ar as b,as as _,at as z,au as H,av as D,aw as J,ax as T,ay as X,ah as R,af as F,az as q,aA as W}from"./mermaid.core.js";import{l as j}from"./layout.js";import"./index.js";var C=m((t,e,r)=>Math.max(e,Math.min(r,t)),"clamp"),P=m((t="TB")=>{switch(t){case"BT":return"bottom";case"LR":return"right";case"RL":return"left";default:return"top"}},"getDefaultSelfLoopSide"),Q=m(t=>t==="flowchart"||t==="flowchart-v2"||t==="stateDiagram"||t==="er"||t==="classDiagram","shouldMergeSelfLoopSegments"),U=["x","y","width","height","labelBBox","intersect","calcIntersect","diff","clusterNode"],K=m((t,e,r,d,a)=>{const f=[],h=new Set;if(r.forEach(({start:i,end:o})=>{i!==d&&h.add(i),o!==d&&h.add(o)}),h.forEach(i=>{const o=t.node(i);typeof o?.x=="number"&&typeof o?.y=="number"&&f.push(o)}),f.length===0&&r.forEach(({edge:i})=>{(i.points??[]).forEach(o=>{typeof o?.x=="number"&&typeof o?.y=="number"&&f.push(o)})}),f.length===0)return P(a);const c=f.reduce((i,o)=>({x:i.x+o.x/f.length,y:i.y+o.y/f.length}),{x:0,y:0}),l=c.x-e.x,s=c.y-e.y;return Math.abs(l)>Math.abs(s)?l>0?"right":"left":Math.abs(s)>0?s>0?"bottom":"top":P(a)},"getSelfLoopSide"),V=m((t,e="top",r=0,d=0)=>{const a=t.x,f=t.y-r,h=t.width/2,c=t.height/2,l=Math.max(36,Math.min(100,t.width*.8)),s=C(Math.max(d,t.width*.35),36,l),i=C(Math.min(t.width,t.height)*.45,24,48);switch(e){case"bottom":{const o=f+c;return[{x:a-s/2,y:o},{x:a-s/2,y:o+i},{x:a+s/2,y:o+i},{x:a+s/2,y:o}]}case"right":{const o=a+h;return[{x:o,y:f-s/2},{x:o+i,y:f-s/2},{x:o+i,y:f+s/2},{x:o,y:f+s/2}]}case"left":{const o=a-h;return[{x:o,y:f-s/2},{x:o-i,y:f-s/2},{x:o-i,y:f+s/2},{x:o,y:f+s/2}]}default:{const o=f-c;return[{x:a-s/2,y:o},{x:a-s/2,y:o-i},{x:a+s/2,y:o-i},{x:a+s/2,y:o}]}}},"getSelfLoopPoints"),Z=m((t,e,r="top",d=0,a={})=>{const h=t.x,c=t.y-d,l=a.width??0,s=a.height??0;switch(r){case"bottom":return{x:h,y:Math.max(...e.map(i=>i.y))+s/2+4};case"right":return{x:Math.max(...e.map(i=>i.x))+l/2+4,y:c};case"left":return{x:Math.min(...e.map(i=>i.x))-l/2-4,y:c};default:return{x:h,y:Math.min(...e.map(i=>i.y))-s/2-4}}},"getSelfLoopLabelPosition"),B=m((t,e=0,{mergeSelfLoops:r=!0}={})=>{const d=new Map,a=[],f=t.graph()?.rankdir;return t.edges().forEach(h=>{const c=t.edge(h);if(r&&c.selfLoop){const l=c.selfLoop.id;d.has(l)||d.set(l,[]),d.get(l).push({edge:c,start:h.v,end:h.w})}else a.push({edge:c,start:h.v,end:h.w})}),d.forEach(h=>{if(h.length!==3){h.forEach(u=>a.push(u));return}h.sort((u,E)=>u.edge.selfLoop.order-E.edge.selfLoop.order);const[c,l,s]=h,i=c.edge.originalEdge??l.edge.originalEdge??s.edge.originalEdge??l.edge,o=t.node(i.start);if(!o){h.forEach(u=>a.push(u));return}const n={width:l.edge.width,height:l.edge.height},L=K(t,o,h,i.start,f),w=V(o,L,e,n.width??0),y=Z(o,w,L,e,n),g={...l.edge,...i,id:i.id,points:w,start:i.start,end:i.end,x:y.x,y:y.y,width:n.width,height:n.height,labelStyle:l.edge.labelStyle,fromCluster:c.edge.fromCluster??l.edge.fromCluster??s.edge.fromCluster,toCluster:c.edge.toCluster??l.edge.toCluster??s.edge.toCluster};delete g.selfLoop,delete g.originalEdge,a.push({edge:g,start:g.start,end:g.end})}),a},"getEdgesToRender"),I=m(async({element:t,graph:e,diagramType:r,id:d,parentCluster:a,siteConfig:f})=>{const h=e.graph().rankdir;p.trace("Dir in recursive render - dir:",h);const{clusters:c,edgePaths:l,edgeLabels:s,nodes:i,rootGroups:o}=_(t,{edgePathsClass:"edgePaths"});e.nodes()?p.info("Recursive render XXX",e.nodes()):p.info("No nodes found for",e),e.edges().length>0&&p.info("Recursive edges",e.edge(e.edges()[0]));const n=Q(r);await Promise.all(e.nodes().map(async function(y){const g=e.node(y);if(a!==void 0){const u=JSON.parse(JSON.stringify(a.clusterData));p.trace(`Setting data for parent cluster XXX
Node.id = `,y,`
data=`,u.height,`
Parent cluster`,a.height),e.setNode(a.id,u),e.parent(y)||(p.trace("Setting parent",y,a.id),e.setParent(y,a.id,u))}if(p.info("(Insert) Node XXX"+y+": "+JSON.stringify(e.node(y))),g?.clusterNode){p.info("Cluster identified XBX",y,g.width,e.node(y));const{ranksep:u,nodesep:E}=e.graph();g.graph.setGraph({...g.graph.graph(),ranksep:u+25,nodesep:E});const S=await oe({element:i,graph:g.graph,diagramType:r,id:d,parentCluster:e.node(y),siteConfig:f}),N=S.elem;z(g,N),g.diff=S.diff||0,p.info("New compound node after recursive render XAX",y,"width",g.width,"height",g.height),H(N,g)}else e.children(y).length>0?(p.trace("Cluster - the non recursive path XBX",y,g.id,g,g.width,"Graph:",e),p.trace(D(g.id,e)),b.set(g.id,{id:D(g.id,e),node:g})):(p.trace("Node - the non recursive path XAX",y,i,e.node(y),h),await J(i,e.node(y),{config:f,dir:h}))})),await m(async()=>{const y=e.edges().map(async function(g){const u=e.edge(g.v,g.w,g.name);if(p.info("Edge "+g.v+" -> "+g.w+": "+JSON.stringify(g)),p.info("Edge "+g.v+" -> "+g.w+": ",g," ",JSON.stringify(e.edge(g))),p.info("Fix",b,"ids:",g.v,g.w,"Translating: ",b.get(g.v),b.get(g.w)),n&&u.selfLoop){if(u.selfLoop.order!==1)return;const E={...u.originalEdge,...u,id:u.selfLoop.id,startLabelLeft:u.originalEdge?.startLabelLeft??u.startLabelLeft,startLabelRight:u.originalEdge?.startLabelRight??u.startLabelRight,endLabelLeft:u.originalEdge?.endLabelLeft??u.endLabelLeft,endLabelRight:u.originalEdge?.endLabelRight??u.endLabelRight};await X(s,E),u.width=E.width,u.height=E.height,u.labelStyle=E.labelStyle;return}await X(s,u)});await Promise.all(y)},"processEdges")();const{subGraphTitleTotalMargin:w}=T(f);return{elem:o,graph:e,groups:{clusters:c,edgePaths:l,edgeLabels:s,nodes:i,rootGroups:o},diagramType:r,id:d,mergeSelfLoops:n,subGraphTitleTotalMargin:w}},"measureDagreGraph"),M=m(t=>{p.info("############################################# XXX"),p.info("### Layout ### XXX"),p.info("############################################# XXX"),j(t)},"runDagreGraphLayout"),$=m((t,e,r)=>{const d=t.node(e);if(!d)return;const a={...d};return d?.clusterNode?a.y=(d.y??0)+r:t.children(e).length>0?a.height=(d.height??0)+r:a.y=(d.y??0)+r/2,a},"normalizeDagreNode"),v=m((t,e)=>{U.forEach(r=>{e[r]!==void 0&&(t[r]=e[r])})},"applyDagreNodeLayout"),ee=m((t,e,r,d)=>({...t,start:t.start??e,end:t.end??r,points:(t.points??[]).map(a=>({...a,y:typeof a.y=="number"?a.y+d:a.y}))}),"normalizeDagreEdge"),te=m((t,e)=>{const{graph:r,mergeSelfLoops:d,subGraphTitleTotalMargin:a=0}=e,f=new Map(t.nodes.map(c=>[c.id,c]));x(r).forEach(c=>{const l=$(r,c,a);if(!l)return;v(r.node(c),l);const s=f.get(c);s&&v(s,l)});const h=a/2;return t.edges=B(r,h,{mergeSelfLoops:d}).map(({edge:c,start:l,end:s})=>ee(c,l,s,h)),t},"applyDagreLayoutResult"),re=m(async({elem:t,graph:e,groups:{clusters:r,edgePaths:d},diagramType:a,id:f,mergeSelfLoops:h,subGraphTitleTotalMargin:c})=>{let l=0;await Promise.all(x(e).map(async function(o){const n=e.node(o);if(p.info("Position XBX => "+o+": ("+n.x,","+n.y,") width: ",n.width," height: ",n.height),n?.clusterNode)n.y+=c,p.info("A tainted cluster node XBX1",o,n.id,n.width,n.height,n.x,n.y,e.parent(o)),b.get(n.id).node=n,R(n);else if(e.children(o).length>0){p.info("A pure cluster node XBX1",o,n.id,n.x,n.y,n.width,n.height,e.parent(o)),n.height+=c,e.node(n.parentId);const L=n?.padding/2||0,w=n?.labelBBox?.height||0,y=w-L||0;p.debug("OffsetY",y,"labelHeight",w,"halfPadding",L),await F(r,n),b.get(n.id).node=n}else{const L=e.node(n.parentId);n.y+=c/2,p.info("A regular node XBX1 - using the padding",n.id,"parent",n.parentId,n.width,n.height,n.x,n.y,"offsetY",n.offsetY,"parent",L,L?.offsetY,n),R(n)}}));const s=c/2;return B(e,s,{mergeSelfLoops:h}).forEach(function({edge:o,start:n,end:L}){p.info("Edge "+n+" -> "+L+": "+JSON.stringify(o),o),o.points.forEach(u=>u.y+=s);const w=e.node(n),y=e.node(L),g=q(d,o,b,a,w,y,f);W(o,g)}),e.nodes().forEach(function(o){const n=e.node(o);p.info(o,n.type,n.diff),n.isGroup&&(l=n.diff)}),p.warn("Returning from recursive render XAX",t,l),{elem:t,diff:l}},"paintDagreLayoutCore"),oe=m(async t=>{const e=await I(t);return M(e.graph),await re(e)},"renderDagreSubgraph"),G=m(t=>{const e=new O({multigraph:!0,compound:!0}).setGraph({rankdir:t.direction,nodesep:t.config?.nodeSpacing||t.nodeSpacing||t.config?.flowchart?.nodeSpacing,ranksep:t.config?.rankSpacing||t.rankSpacing||t.config?.flowchart?.rankSpacing,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}});return t.nodes.forEach(r=>{e.setNode(r.id,{...r}),r.parentId&&e.setParent(r.id,r.parentId)}),p.debug("Edges:",t.edges),t.edges.forEach(r=>{if(r.start===r.end){const d=r.start,a=d+"---"+d+"---1",f=d+"---"+d+"---2",h=e.node(d);e.setNode(a,{domId:a,id:a,parentId:h.parentId,labelStyle:"",label:"",padding:0,shape:"labelRect",style:"",width:10,height:10}),e.setParent(a,h.parentId),e.setNode(f,{domId:f,id:f,parentId:h.parentId,labelStyle:"",padding:0,shape:"labelRect",label:"",style:"",width:10,height:10}),e.setParent(f,h.pa Line truncated
+1
View File
@@ -0,0 +1 @@
function J(n){return Math.abs(n=Math.round(n))>=1e21?n.toLocaleString("en").replace(/,/g,""):n.toString(10)}function j(n,t){if(!isFinite(n)||n===0)return null;var e=(n=t?n.toExponential(t-1):n.toExponential()).indexOf("e"),i=n.slice(0,e);return[i.length>1?i[0]+i.slice(2):i,+n.slice(e+1)]}function K(n){return n=j(Math.abs(n)),n?n[1]:NaN}function Q(n,t){return function(e,i){for(var o=e.length,a=[],c=0,h=n[0],M=0;o>0&&h>0&&(M+h+1>i&&(h=Math.max(1,i-M)),a.push(e.substring(o-=h,o+h)),!((M+=h+1)>i));)h=n[c=(c+1)%n.length];return a.reverse().join(t)}}function V(n){return function(t){return t.replace(/[0-9]/g,function(e){return n[+e]})}}var W=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function $(n){if(!(t=W.exec(n)))throw new Error("invalid format: "+n);var t;return new L({fill:t[1],align:t[2],sign:t[3],symbol:t[4],zero:t[5],width:t[6],comma:t[7],precision:t[8]&&t[8].slice(1),trim:t[9],type:t[10]})}$.prototype=L.prototype;function L(n){this.fill=n.fill===void 0?" ":n.fill+"",this.align=n.align===void 0?">":n.align+"",this.sign=n.sign===void 0?"-":n.sign+"",this.symbol=n.symbol===void 0?"":n.symbol+"",this.zero=!!n.zero,this.width=n.width===void 0?void 0:+n.width,this.comma=!!n.comma,this.precision=n.precision===void 0?void 0:+n.precision,this.trim=!!n.trim,this.type=n.type===void 0?"":n.type+""}L.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function _(n){n:for(var t=n.length,e=1,i=-1,o;e<t;++e)switch(n[e]){case".":i=o=e;break;case"0":i===0&&(i=e),o=e;break;default:if(!+n[e])break n;i>0&&(i=0);break}return i>0?n.slice(0,i)+n.slice(o+1):n}var N;function v(n,t){var e=j(n,t);if(!e)return N=void 0,n.toPrecision(t);var i=e[0],o=e[1],a=o-(N=Math.max(-8,Math.min(8,Math.floor(o/3)))*3)+1,c=i.length;return a===c?i:a>c?i+new Array(a-c+1).join("0"):a>0?i.slice(0,a)+"."+i.slice(a):"0."+new Array(1-a).join("0")+j(n,Math.max(0,t+a-1))[0]}function X(n,t){var e=j(n,t);if(!e)return n+"";var i=e[0],o=e[1];return o<0?"0."+new Array(-o).join("0")+i:i.length>o+1?i.slice(0,o+1)+"."+i.slice(o+1):i+new Array(o-i.length+2).join("0")}const O={"%":(n,t)=>(n*100).toFixed(t),b:n=>Math.round(n).toString(2),c:n=>n+"",d:J,e:(n,t)=>n.toExponential(t),f:(n,t)=>n.toFixed(t),g:(n,t)=>n.toPrecision(t),o:n=>Math.round(n).toString(8),p:(n,t)=>X(n*100,t),r:X,s:v,X:n=>Math.round(n).toString(16).toUpperCase(),x:n=>Math.round(n).toString(16)};function R(n){return n}var U=Array.prototype.map,Y=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function nn(n){var t=n.grouping===void 0||n.thousands===void 0?R:Q(U.call(n.grouping,Number),n.thousands+""),e=n.currency===void 0?"":n.currency[0]+"",i=n.currency===void 0?"":n.currency[1]+"",o=n.decimal===void 0?".":n.decimal+"",a=n.numerals===void 0?R:V(U.call(n.numerals,String)),c=n.percent===void 0?"%":n.percent+"",h=n.minus===void 0?"−":n.minus+"",M=n.nan===void 0?"NaN":n.nan+"";function T(f,g){f=$(f);var b=f.fill,p=f.align,m=f.sign,w=f.symbol,S=f.zero,E=f.width,F=f.comma,y=f.precision,C=f.trim,d=f.type;d==="n"?(F=!0,d="g"):O[d]||(y===void 0&&(y=12),C=!0,d="g"),(S||b==="0"&&p==="=")&&(S=!0,b="0",p="=");var q=(g&&g.prefix!==void 0?g.prefix:"")+(w==="$"?e:w==="#"&&/[boxX]/.test(d)?"0"+d.toLowerCase():""),B=(w==="$"?i:/[%p]/.test(d)?c:"")+(g&&g.suffix!==void 0?g.suffix:""),D=O[d],H=/[defgprs%]/.test(d);y=y===void 0?6:/[gprs]/.test(d)?Math.max(1,Math.min(21,y)):Math.max(0,Math.min(20,y));function G(r){var l=q,u=B,x,I,k;if(d==="c")u=D(r)+u,r="";else{r=+r;var P=r<0||1/r<0;if(r=isNaN(r)?M:D(Math.abs(r),y),C&&(r=_(r)),P&&+r==0&&m!=="+"&&(P=!1),l=(P?m==="("?m:h:m==="-"||m==="("?"":m)+l,u=(d==="s"&&!isNaN(r)&&N!==void 0?Y[8+N/3]:"")+u+(P&&m==="("?")":""),H){for(x=-1,I=r.length;++x<I;)if(k=r.charCodeAt(x),48>k||k>57){u=(k===46?o+r.slice(x+1):r.slice(x))+u,r=r.slice(0,x);break}}}F&&!S&&(r=t(r,1/0));var z=l.length+r.length+u.length,s=z<E?new Array(E-z+1).join(b):"";switch(F&&S&&(r=t(s+r,s.length?E-u.length:1/0),s=""),p){case"<":r=l+r+u+s;break;case"=":r=l+s+r+u;break;case"^":r=s.slice(0,z=s.length>>1)+l+r+u+s.slice(z);break;default:r=s+l+r+u;break}return a(r)}return G.toString=function(){return f+""},G}function Z(f,g){var b=Math.max(-8,Math.min(8,Math.floor(K(g)/3)))*3,p=Math.pow(10,-b),m=T((f=$(f),f.type="f",f),{suffix:Y[8+b/3]});return function(w){return m(p*w)}}return{format:T,formatPrefix:Z}}var A,tn,rn;en({thousands:",",grouping:[3],currency:["$",""]});function en(n){return A=nn(n),tn=A.format,rn=A.formatPrefix,A}export{rn as a,tn as b,K as e,$ as f};
+30
View File
@@ -0,0 +1,30 @@
import{I as X}from"./chunk-2Q5K7J3B.js";import{p as z}from"./chunk-JWPE2WC7.js";import{n as O,b as G,s as Y,o as P,g as F,a as Z,_ as g,A as N,l as A,D as q,d as U,y as E,p as j,i as J,ak as K,B as Q,al as ee}from"./mermaid.core.js";import{p as te}from"./cynefin-OW5HDTMX.js";import"./index.js";var D=/[─━│┃└┗├┣]/,L=/[└┗├┣]/,ne=/[─━]/,k=/^[\s│┃]+$/,T=/^\s*(title[\t ]|accTitle[\t ]*:|accDescr[\t ]*[:{])/,V=/^\s*%%/,re=" ";function _(n){return n.some(t=>D.test(t))}g(_,"isBoxDrawingFormat");function M(n){for(const t of n){const e=L.exec(t);if(e?.index&&e.index>0)return e.index}return 4}g(M,"inferSegmentWidth");function S(n,t){return n.replace(/\bline\s+(\d+)\b/gi,(e,r)=>{const s=parseInt(r,10),i=t.get(s);return i?`line ${i}`:e})}g(S,"remapErrorLines");function R(n){const t=n.split(`
`),e=new Map;let r=-1;for(const[p,c]of t.entries())if(c.trim()==="treeView-beta"){r=p;break}if(r===-1)return{text:n,lineMap:e};const s=[];for(let p=r+1;p<t.length;p++){const c=t[p];c.trim()===""||V.test(c)||T.test(c)||k.test(c)||s.push(c.replace(/\t/g," "))}if(!_(s))return{text:n,lineMap:e};const i=M(s),o=[];let a=0;for(let p=0;p<=r;p++)o.push(t[p]),a++,e.set(a,p+1);for(let p=r+1;p<t.length;p++){const c=t[p],d=c.trim(),h=p+1;if(d===""){o.push(c),a++,e.set(a,h);continue}if(V.test(c)){o.push(c),a++,e.set(a,h);continue}if(T.test(c)){o.push(c),a++,e.set(a,h);continue}if(k.test(c))continue;const l=c.replace(/\t/g," "),w=L.exec(l);if(w?.index!==void 0){const f=w.index,m=Math.round(f/i)+1;let u=f+1;for(;u<l.length&&ne.test(l[u]);)u++;for(;u<l.length&&l[u]===" ";)u++;const v=l.slice(u).trimEnd();if(!v)throw new Error(`Line ${h}: Empty node — expected a filename or directory name after the box-drawing prefix`);const W=re.repeat(m);o.push(W+v),a++,e.set(a,h)}else{if(/^[\s─━│┃└┗├┣]+$/.test(l))continue;if(D.test(l))o.push(c),a++,e.set(a,h);else{if(/^\s+/.test(l))throw new Error(`Line ${h}: Unexpected indentation without box-drawing characters. In box-drawing format, use ├── or └── prefixes for indented nodes.`);o.push(c),a++,e.set(a,h)}}}return{text:o.join(`
`),lineMap:e}}g(R,"preprocessBoxDrawing");var x=new X(()=>({cnt:1,stack:[{id:0,level:-1,name:"/",nodeType:"directory",children:[]}]})),ie=g(()=>{x.reset(),j()},"clear"),oe=g(()=>x.records.stack[0],"getRoot"),se=g(()=>x.records.cnt,"getCount"),ae=Q.treeView,ce=g(()=>N(ae,E().treeView),"getConfig"),le=g((n,t,e,r,s,i)=>{for(;n<=x.records.stack[x.records.stack.length-1].level;)x.records.stack.pop();const o={id:x.records.cnt++,level:n,name:t,nodeType:e,icon:s,cssClass:r,description:i,children:[]};x.records.stack[x.records.stack.length-1].children.push(o),x.records.stack.push(o)},"addNode"),de={clear:ie,addNode:le,getRoot:oe,getCount:se,getConfig:ce,getAccTitle:Z,getAccDescription:F,getDiagramTitle:P,setAccDescription:Y,setAccTitle:G,setDiagramTitle:O},I=de,he=g(n=>{z(n,I);for(const t of n.nodes){const e=typeof t.indent=="number"?t.indent:0;let r=t.name;const s=r.endsWith("/");s&&(r=r.slice(0,-1));const i=s?"directory":"file",o=t.classAnnotation||void 0,a=t.iconAnnotation,p=a!==void 0?a||"none":void 0,c=t.descAnnotation||void 0,d=c?J(c,E()):void 0;I.addNode(e,r,i,o,p,d)}},"populate"),pe={parse:g(async n=>{const{text:t,lineMap:e}=R(n);try{const r=await te("treeView",t);A.debug(r),he(r)}catch(r){throw e.size>0&&r instanceof Error&&(r.message=S(r.message,e)),r}},"parse")},b={prefix:"mermaid-treeview",height:24,width:24,icons:{folder:{body:'<path fill="currentColor" d="M10.59 4.59A2 2 0 0 0 9.17 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.17z"/>'},file:{body:'<path fill="currentColor" fill-rule="evenodd" d="M6 2a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8.83a2 2 0 0 0-.59-1.42l-4.82-4.82A2 2 0 0 0 13.17 2H6Zm7.5 1.9l4.6 4.6h-3.6a1 1 0 0 1-1-1V3.9Z" clip-rule="evenodd"/>'}}};function H(n,t){const e=t?.filenameIcons?.[n];if(e)return e;const r=n.lastIndexOf(".");if(r>0){const s=n.substring(r).toLowerCase(),i=t?.extensionIcons;return i?.[s]??i?.[s.slice(1)]}}g(H,"detectIcon");function C(n,t){return n.includes(":")?n:n in b.icons||!t?`${b.prefix}:${n}`:`${t}:${n}`}g(C,"qualifyIcon");function B(n,t){if(n.icon!=="none"){if(n.icon)return C(n.icon,t.defaultIconPack);if(t.showIcons){if(n.nodeType==="file"){const e=H(n.name,t);if(e==="none")return;if(e)return C(e,t.defaultIconPack)}return`${b.prefix}:${n.nodeType==="directory"?"folder":"file"}`}}}g(B,"getNodeIcon");ee([{name:b.prefix,icons:b}]);var y=14,ge=4,fe=16,ue=g(async(n,t)=>{const e=[],r=g(i=>{const o=B(i,t);o&&e.push({icon:o,node:i}),i.children.forEach(r)},"collect");r(n);const s=await Promise.all(e.map(async({icon:i,node:o})=>({id:o.id,svg:await K(i,{height:y,width:y})})));return new Map(s.map(({id:i,svg:o})=>[i,o]))},"resolveNodeIcons"),we=g((n,t,e,r,s,i)=>{const o=r.append("g");let a="treeView-node-label";e.nodeType==="directory"&&(a+=" treeView-node-dir"),e.cssClass&&(a+=` ${e.cssClass}`);const p=y+ge,c=B(e,s),d=c!==void 0;c&&o.append("g").attr("class","treeView-node-icon").attr("transform",`translate(${n+s.paddingX}, ${t+s.paddingY})`).html(i.get(e.id)??"");const h=o.append("text").text(e.name).attr("dominant-baseline","middle").attr("class",a),{height:l,width:w}=h.node().getBBox(),f=l+s.paddingY*2,m=n+s.paddingX+(d?p:0);h.attr("x",m),h.attr("y",t+f/2);const u=m+w,v=w+s.paddingX*2+(d?p:0);return e.BBox={x:n,y:t,width:v,height:f},e.cssClass?.split(/\s+/).includes("highlight")&&o.insert("rect",":first-child").attr("x",n).attr("y",t+1).attr("width",0).attr("height",f-2).attr("rx",3).attr("class","treeView-highlight-bg"),{node:e,nodeGroup:o,labelRightEdge:u,centerY:t+f/2}},"positionLabel"),$=g((n,t,e,r,s,i)=>n.append("line").attr("x1",t).attr("y1",e).attr("x2",r).attr("y2",s).attr("stroke-width",i).attr("class","treeView-node-line"),"positionLine"),me=g((n,t,e,r)=>{let s=0,i=0;const o=[],a=g((d,h,l,w)=>{const f=w*(l.rowIndent+l.paddingX),m=we(f,s,h,d,l,r);o.push(m);const{height:u,width:v}=h.BBox;$(d,f-l.rowIndent,s+u/2,f,s+u/2,l.lineThickness),i=Math.max(i,f+v),s+=u},"drawNode"),p=g((d,h=0)=>{a(n,d,e,h),d.children.forEach(m=>{p(m,h+1)});const{x:l,y:w,height:f}=d.BBox;if(d.children.length){const{y:m,height:u}=d.children[d.children.length-1].BBox;$(n,l+e.paddingX,w+f,l+e.paddingX,m+u/2+e.lineThickness/2,e.lineThickness)}},"processNode");p(t);const c=o.filter(d=>d.node.description);if(c.length>0){const h=Math.max(...o.map(l=>l.labelRightEdge))+fe;for(const l of c){const f=l.nodeGroup.append("text").text(l.node.description).attr("dominant-baseline","middle").attr("class","treeView-node-description").attr("x",h).attr("y",l.centerY).node().getBBox();i=Math.max(i,h+f.width+e.paddingX)}}for(const d of o)if(d.node.cssClass?.split(/\s+/).includes("highlight")){const h=d.nodeGroup.select(".treeView-highlight-bg");if(!h.empty()){const l=i-d.node.BBox.x+8;h.attr("width",l),i=Math.max(i,d.node.BBox.x+l+2)}}return{totalHeight:s,totalWidth:i}},"drawTree"),xe=g(async(n,t,e,r)=>{A.debug(`Rendering treeView diagram
`+n);const s=r.db,i=s.getRoot(),o=s.getConfig(),a=q(t),p=a.append("g");p.attr("class","tree-view");const c=await ue(i,o),{totalHeight:d,totalWidth:h}=me(p,i,o,c);a.attr("viewBox",`-${o.lineThickness/2} 0 ${h} ${d}`),U(a,d,h,o.useMaxWidth)},"draw"),ve={draw:xe},be=ve,Ie={labelFontSize:"16px",labelColor:"black",lineColor:"black",iconColor:"#546e7a",descriptionColor:"#6a9955",highlightBg:"rgba(255, 193, 7, 0.15)",highlightStroke:"#ffc107"},Ce=g(({treeView:n})=>{const{labelFontSize:t,labelColor:e,lineColor:r,iconColor:s,descriptionColor:i,highlightBg:o,highlightStroke:a}=N(Ie,n);return`
.treeView-node-label {
font-size: ${t};
fill: ${e};
white-space: pre;
}
.treeView-node-dir {
font-weight: bold;
}
.treeView-node-line {
stroke: ${r};
}
.treeView-node-icon {
color: ${s};
}
.treeView-node-description {
font-size: ${t};
fill: ${i};
font-style: italic;
white-space: pre;
}
.treeView-highlight-bg {
fill: ${o};
stroke: ${a};
stroke-width: 1;
}
`},"styles"),ye=Ce,Ne={db:I,renderer:be,parser:pe,styles:ye};export{Ne as diagram};
+41
View File
@@ -0,0 +1,41 @@
import{p as I}from"./chunk-JWPE2WC7.js";import{s as _,g as E,o as D,n as F,a as P,b as z,_ as c,D as G,p as B,A as w,y as C,B as W,l as b,E as V,d as H}from"./mermaid.core.js";import{p as j}from"./cynefin-OW5HDTMX.js";import"./index.js";var x={showLegend:!0,ticks:5,max:null,min:0,graticule:"circle"},y=32,A={axes:[],curves:[],options:x},m=structuredClone(A),U=W.radar,X=c(()=>w({...U,...C().radar}),"getConfig"),M=c(()=>m.axes,"getAxes"),K=c(()=>m.curves,"getCurves"),N=c(()=>m.options,"getOptions"),Y=c(a=>{m.axes=a.map(t=>({name:t.name,label:t.label??t.name}))},"setAxes"),Z=c(a=>{m.curves=a.map(t=>({name:t.name,label:t.label??t.name,entries:q(t.entries)}))},"setCurves"),q=c(a=>{if(a[0].axis==null)return a.map(e=>e.value);const t=M();if(t.length===0)throw new Error("Axes must be populated before curves for reference entries");return t.map(e=>{const r=a.find(s=>s.axis?.$refText===e.name);if(r===void 0)throw new Error("Missing entry for axis "+e.label);return r.value})},"computeCurveEntries"),J=c(a=>{const t=a.reduce((e,r)=>(e[r.name]=r,e),{});m.options={showLegend:t.showLegend?.value??x.showLegend,ticks:t.ticks?.value??x.ticks,max:t.max?.value??x.max,min:t.min?.value??x.min,graticule:t.graticule?.value??x.graticule},m.options.ticks>y&&(b.warn(`Radar diagram ticks (${m.options.ticks}) exceeds maximum allowed (${y}). Using ${y} instead.`),m.options.ticks=y)},"setOptions"),Q=c(()=>{B(),m=structuredClone(A)},"clear"),$={getAxes:M,getCurves:K,getOptions:N,setAxes:Y,setCurves:Z,setOptions:J,getConfig:X,clear:Q,setAccTitle:z,getAccTitle:P,setDiagramTitle:F,getDiagramTitle:D,getAccDescription:E,setAccDescription:_},tt=c(a=>{I(a,$);const{axes:t,curves:e,options:r}=a;$.setAxes(t),$.setCurves(e),$.setOptions(r)},"populate"),et={parse:c(async a=>{const t=await j("radar",a);b.debug(t),tt(t)},"parse")},at=c((a,t,e,r)=>{const s=r.db,i=s.getAxes(),l=s.getCurves(),n=s.getOptions(),o=s.getConfig(),d=s.getDiagramTitle(),p=G(t),u=rt(p,o),g=n.max??Math.max(...l.map(f=>Math.max(...f.entries))),h=n.min,v=Math.min(o.width,o.height)/2;st(u,i,v,n.ticks,n.graticule),nt(u,i,v,o),L(u,i,l,h,g,n.graticule,o),k(u,l,n.showLegend,o),u.append("text").attr("class","radarTitle").text(d).attr("x",0).attr("y",-o.height/2-o.marginTop)},"draw"),rt=c((a,t)=>{const e=t.width+t.marginLeft+t.marginRight,r=t.height+t.marginTop+t.marginBottom,s={x:t.marginLeft+t.width/2,y:t.marginTop+t.height/2};return H(a,r,e,t.useMaxWidth??!0),a.attr("viewBox",`0 0 ${e} ${r}`).attr("overflow","visible"),a.append("g").attr("transform",`translate(${s.x}, ${s.y})`)},"drawFrame"),st=c((a,t,e,r,s)=>{if(s==="circle")for(let i=0;i<r;i++){const l=e*(i+1)/r;a.append("circle").attr("r",l).attr("class","radarGraticule")}else if(s==="polygon"){const i=t.length;for(let l=0;l<r;l++){const n=e*(l+1)/r,o=t.map((d,p)=>{const u=2*p*Math.PI/i-Math.PI/2,g=n*Math.cos(u),h=n*Math.sin(u);return`${g},${h}`}).join(" ");a.append("polygon").attr("points",o).attr("class","radarGraticule")}}},"drawGraticule"),nt=c((a,t,e,r)=>{const s=t.length;for(let i=0;i<s;i++){const l=t[i].label,n=2*i*Math.PI/s-Math.PI/2,o=Math.cos(n),d=Math.sin(n);a.append("line").attr("x1",0).attr("y1",0).attr("x2",e*r.axisScaleFactor*o).attr("y2",e*r.axisScaleFactor*d).attr("class","radarAxisLine");const p=o>.01?"start":o<-.01?"end":"middle",u=d>.01?"hanging":d<-.01?"auto":"central",g=4;a.append("text").text(l).attr("x",e*r.axisLabelFactor*o+g*o).attr("y",e*r.axisLabelFactor*d+g*d).attr("text-anchor",p).attr("dominant-baseline",u).attr("class","radarAxisLabel")}},"drawAxes");function L(a,t,e,r,s,i,l){const n=t.length,o=Math.min(l.width,l.height)/2;e.forEach((d,p)=>{if(d.entries.length!==n)return;const u=d.entries.map((g,h)=>{const v=2*Math.PI*h/n-Math.PI/2,f=T(g,r,s,o),O=f*Math.cos(v),R=f*Math.sin(v);return{x:O,y:R}});i==="circle"?a.append("path").attr("d",S(u,l.curveTension)).attr("class",`radarCurve-${p}`):i==="polygon"&&a.append("polygon").attr("points",u.map(g=>`${g.x},${g.y}`).join(" ")).attr("class",`radarCurve-${p}`)})}c(L,"drawCurves");function T(a,t,e,r){const s=Math.min(Math.max(a,t),e);return r*(s-t)/(e-t)}c(T,"relativeRadius");function S(a,t){const e=a.length;let r=`M${a[0].x},${a[0].y}`;for(let s=0;s<e;s++){const i=a[(s-1+e)%e],l=a[s],n=a[(s+1)%e],o=a[(s+2)%e],d={x:l.x+(n.x-i.x)*t,y:l.y+(n.y-i.y)*t},p={x:n.x-(o.x-l.x)*t,y:n.y-(o.y-l.y)*t};r+=` C${d.x},${d.y} ${p.x},${p.y} ${n.x},${n.y}`}return`${r} Z`}c(S,"closedRoundCurve");function k(a,t,e,r){if(!e)return;const s=(r.width/2+r.marginRight)*3/4,i=-(r.height/2+r.marginTop)*3/4,l=20;t.forEach((n,o)=>{const d=a.append("g").attr("transform",`translate(${s}, ${i+o*l})`);d.append("rect").attr("width",12).attr("height",12).attr("class",`radarLegendBox-${o}`),d.append("text").attr("x",16).attr("y",0).attr("class","radarLegendText").text(n.label)})}c(k,"drawLegend");var ot={draw:at},it=c((a,t)=>{let e="";for(let r=0;r<a.THEME_COLOR_LIMIT;r++){const s=a[`cScale${r}`];e+=`
.radarCurve-${r} {
color: ${s};
fill: ${s};
fill-opacity: ${t.curveOpacity};
stroke: ${s};
stroke-width: ${t.curveStrokeWidth};
}
.radarLegendBox-${r} {
fill: ${s};
fill-opacity: ${t.curveOpacity};
stroke: ${s};
}
`}return e},"genIndexStyles"),lt=c(a=>{const t=V(),e=C(),r=w(t,e.themeVariables),s=w(r.radar,a);return{themeVariables:r,radarOptions:s}},"buildRadarStyleOptions"),ct=c(({radar:a}={})=>{const{themeVariables:t,radarOptions:e}=lt(a);return`
.radarTitle {
font-size: ${t.fontSize};
color: ${t.titleColor};
dominant-baseline: hanging;
text-anchor: middle;
}
.radarAxisLine {
stroke: ${e.axisColor};
stroke-width: ${e.axisStrokeWidth};
}
.radarAxisLabel {
font-size: ${e.axisLabelFontSize}px;
color: ${e.axisColor};
}
.radarGraticule {
fill: ${e.graticuleColor};
fill-opacity: ${e.graticuleOpacity};
stroke: ${e.graticuleColor};
stroke-width: ${e.graticuleStrokeWidth};
}
.radarLegendText {
text-anchor: start;
font-size: ${e.legendFontSize}px;
dominant-baseline: hanging;
}
${it(t,e)}
`},"styles"),mt={parser:et,db:$,renderer:ot,styles:ct};export{mt as diagram};
+3
View File
@@ -0,0 +1,3 @@
import{p as re}from"./chunk-JWPE2WC7.js";import{o as oe,n as se,s as de,g as le,a as ce,b as me,_ as o,l as g,c as T,j as ue,z as xe,p as fe,A as ge,y as M,B as he,i as y,w as P,am as pe}from"./mermaid.core.js";import{p as be,i as ve}from"./cynefin-OW5HDTMX.js";import"./index.js";var $="position frame",D="frame positioned",S="position relation",N="relation positioned",we=o(function(e){g.debug("options str",e)},"setOptions"),ye=o(function(){return{}},"getOptions"),Pe=o(function(){C(),fe()},"clear");function C(){B={}}o(C,"reset");var Se=he.eventmodeling,ke=o(()=>ge({...Se,...M().eventmodeling}),"getConfig"),B={};function O(){let e=Fe;const{ast:n}=B,t=E();if(!n)throw new Error("No data for EventModel");return n.frames.forEach((i,a)=>{const r=G(i,n.dataEntities,t);e=v(e,{$kind:$,index:a,frame:i,textProps:r});let d;K(i)?(g.debug("source frame",i.sourceFrames),d=n.frames.filter(l=>i.sourceFrames.some(c=>c.$refText===l.name)),d.forEach(l=>{e=v(e,{$kind:S,index:a,frame:i,sourceFrame:l})})):e=v(e,{$kind:S,index:a,frame:i})}),e={...e,sortedSwimlanesArray:A(e.swimlanes)},e}o(O,"getState");function I(e){B.ast=e}o(I,"setAst");var s={swimlaneMinHeight:70,swimlanePadding:15,swimlaneGap:10,boxPadding:10,boxOverlap:90,boxDefaultY:0,boxMinWidth:80,boxMaxWidth:450,boxMinHeight:80,boxMaxHeight:750,contentStartX:250,textMaxWidth:430,boxTextFontWeight:"bold",boxTextPadding:10,swimlaneTextFontWeight:"bold",labelUiAutomation:"UI/Automation",labelUiAutomationPrefix:"UI/A: ",labelCommandReadModel:"Command/Read Model",labelCommandReadModelPrefix:"C/RM: ",labelEvents:"Events",labelEventsPrefix:"Stream: "};function E(){return s}o(E,"getDiagramProps");var Fe={boxes:[],swimlanes:{},relations:[],maxR:0,sortedSwimlanesArray:[]};function W(e){const n=e.split(".");if(n.length===2)return n[0]}o(W,"extractNamespace");function H(e){const n=e.split(".");return n.length===2?n[1]:e}o(H,"extractName");function U(e,n){if(!(!n||n.length===0))return Object.values(e).find(t=>t.namespace===n)}o(U,"findSwimlaneByNamespace");function b(e,n,t){return Math.max(n,...Object.keys(e).filter(i=>{const a=Number.parseInt(i);return a>n&&a<t}).map(i=>Number.parseInt(i)))+1}o(b,"findNextAvailableIndex");function _(e,n){const t=W(e.entityIdentifier),i=U(n,t);switch(e.modelEntityType){case"ui":case"pcr":case"processor":return i?{index:i.index,label:i.namespace||s.labelUiAutomation}:t?{index:b(n,0,100),label:s.labelUiAutomationPrefix+t}:{index:0,label:s.labelUiAutomation};case"rmo":case"readmodel":case"cmd":case"command":return i?{index:i.index,label:i.namespace||s.labelCommandReadModel}:t?{index:b(n,100,200),label:s.labelCommandReadModelPrefix+t}:{index:100,label:s.labelCommandReadModel};default:return i?{index:i.index,label:i.namespace||s.labelEvents}:t?{index:b(n,200,300),label:s.labelEventsPrefix+t}:{index:200,label:s.labelEvents}}}o(_,"calculateSwimlaneProps");function L(e){const{themeVariables:n}=M();switch(e.modelEntityType){case"ui":return{fill:n.emUiFill??"white",stroke:n.emUiStroke??"#dbdada"};case"pcr":case"processor":return{fill:n.emProcessorFill??"#edb3f6",stroke:n.emProcessorStroke??"#b88cbf"};case"rmo":case"readmodel":return{fill:n.emReadModelFill??"#d3f1a2",stroke:n.emReadModelStroke??"#a3b732"};case"cmd":case"command":return{fill:n.emCommandFill??"#bcd6fe",stroke:n.emCommandStroke??"#679ac3"};case"evt":case"event":return{fill:n.emEventFill??"#ffb778",stroke:n.emEventStroke??"#c19a0f"};default:return{fill:"red",stroke:"black"}}}o(L,"calculateEntityVisualProps");function G(e,n,t){const i=M(),a=y(H(e.entityIdentifier)??"",i);let r;const d={fontSize:16,fontWeight:700,fontFamily:'"trebuchet ms", verdana, arial, sans-serif',joinWith:"<br/>"};let c=`<b>${P(a,t.textMaxWidth,d)}</b>`;if(e.dataInlineValue&&(r=e.dataInlineValue,r=r.substring(r.indexOf("{")+1),r=r.substring(0,r.lastIndexOf("}")-1),r=y(r,i),r=P(r,t.textMaxWidth,d),r=r.replaceAll(" ","&nbsp;")),e.dataReference){const p=n.find(w=>w.name===e.dataReference?.$refText);p&&(r=p.dataBlockValue,r=r.substring(r.indexOf(`{
`)+2),r=r.substring(0,r.lastIndexOf("}")-1),r=y(r,i),r=P(r,t.textMaxWidth,d),r=r.replaceAll(" ","&nbsp;"),r+="<br/>")}const m=r!==void 0;m&&(c+=`<br/><br/><code style="text-align: left; display: block;max-width:${t.textMaxWidth}px">${r}</code>`);const x={fontSize:d.fontSize,fontWeight:d.fontWeight,fontFamily:d.fontFamily},u=pe(c,x),h=m?u.width/3:u.width,f={content:c,width:h,height:u.height};return g.debug(`[${e.name}] ${e.entityIdentifier} text`,f),f}o(G,"calculateTextProps");function V(e,n){const t=n,i=L(t.frame),a={width:t.textProps.width+2*s.boxTextPadding,height:t.textProps.height+2*s.boxTextPadding};return[{$kind:D,frame:t.frame,index:t.index,visual:i,dimension:a,textProps:t.textProps}]}o(V,"decidePositionFrame");function X(e,n,t){return n===void 0?s.contentStartX:n.index===e.index&&e.r?e.r+s.boxPadding:t===void 0?s.contentStartX:t.r-s.boxOverlap+s.boxPadding}o(X,"calculateX");function j(e,n){const t=[...e.map(i=>i.r),n];return Math.max(...t)}o(j,"calculateMaxRight");function A(e){return Object.values(e).sort((n,t)=>n.index-t.index)}o(A,"sortedSwimlanesArray");function Y(e,n){const t=n,i=_(t.frame,e.swimlanes);let a;i.index in e.swimlanes?a=e.swimlanes[i.index]:a={index:i.index,label:i.label,r:0,y:i.index*s.swimlaneMinHeight+s.swimlaneGap,height:s.swimlaneMinHeight,maxHeight:s.swimlaneMinHeight};const r=e.boxes.length>0?e.boxes[e.boxes.length-1]:void 0,d=e.previousSwimlaneNumber!==void 0?e.swimlanes[e.previousSwimlaneNumber]:void 0,l={width:Math.max(s.boxMinWidth,Math.min(s.boxMaxWidth,t.dimension.width))+2*s.boxPadding,height:Math.max(s.boxMinHeight,Math.min(s.boxMaxHeight,t.dimension.height))+2*s.boxPadding},c=X(a,d,r),m=c+l.width+s.boxPadding,x=j(Object.values(e.swimlanes),m);a.r=c+l.width,a.maxHeight=Math.max(a.maxHeight,l.height),a.height=Math.max(s.swimlaneMinHeight,a.maxHeight)+2*s.swimlanePadding;const u={x:c,y:s.swimlanePadding+a.y,r:m,dimension:l,leftSibling:!1,swimlane:a,visual:t.visual,text:t.textProps.content,frame:t.frame,index:t.index},h={...e,boxes:[...e.boxes,u],swimlanes:{...e.swimlanes,[`${a.index}`]:a},previousSwimlaneNumber:i.index,previousFrame:t.frame,maxR:x},f=A(h.swimlanes);f.length>0&&(f[0].y=0);for(let p=1;p<f.length;p++){const w=f[p],R=f[p-1];w.y=R.y+R.height+s.swimlaneGap}return h}o(Y,"evolveFramePositioned");function z(e,n){return e===0&&n.sourceFrames.length===0}o(z,"isFirstFrame");function K(e){return e.sourceFrames!==void 0&&e.sourceFrames!==null&&e.sourceFrames.length>0}o(K,"hasSourceFrame");function k(e,n){if(n!=null)return e.find(t=>t.frame.name===n.name)}o(k,"findBoxByFrame");function q(e,n,t){if(!(t<0))for(let i=t;i>=0;i--){const a=e[i];if(a.swimlane.index!==n)return a}}o(q,"findBoxByLineIndex");function J(e,n){const t=n;if(ve(t.frame)||z(t.index,t.frame))return[];const i=k(e.boxes,t.frame);if(i===void 0)throw new Error(`Target box not found for frame ${t.frame.name}`);let a;return t.sourceFrame?a=k(e.boxes,t.sourceFrame):a=q(e.boxes,i.swimlane.index,t.index-1),a===void 0?[]:[{$kind:N,frame:t.frame,index:t.index,sourceBox:a,targetBox:i}]}o(J,"decidePositionRelation");function Q(e,n){const t=n,i={visual:{fill:"none",stroke:"#000"},source:{x:t.sourceBox.x,y:t.sourceBox.y},target:{x:t.targetBox.x,y:t.targetBox.y},sourceBox:t.sourceBox,targetBox:t.targetBox};return{...e,relations:[...e.relations,i]}}o(Q,"evolveRelationPositioned");var Me={[$]:V,[S]:J},Be={[D]:Y,[N]:Q};function Z(e,n){const t=Me[n.$kind];if(t==null)return[];const i=t(e,n);return g.debug("decided events",i),i}o(Z,"decide");function ee(e,n){const t=n.reduce((i,a)=>{const r=Be[a.$kind];return r==null?i:r(i,a)},e);return g.debug("evolve events",{state:e,newState:t,events:n}),t}o(ee,"evolve");function v(e,n){const t=Z(e,n);return ee(e,t)}o(v,"dispatch");var F={getConfig:ke,setOptions:we,getOptions:ye,clear:Pe,setAccTitle:me,getAccTitle:ce,getAccDescription:le,setAccDescription:de,setDiagramTitle:se,getDiagramTitle:oe,setAst:I,getDiagramProps:E,getState:O},Ee={parse:o(async e=>{const n=await be("eventmodeling",e);g.debug(n),F.setAst(n),re(n,F)},"parse")},Ae=T(),Re=Ae?.eventmodeling;function te(e,n){return t=>{const i=t.swimlane.y+n.swimlanePadding,a=e.append("g").attr("class","em-box");a.append("rect").attr("x",t.x).attr("y",i).attr("rx","3").attr("width",t.dimension.width).attr("height",t.dimension.height).attr("stroke",t.visual.stroke).attr("fill",t.visual.fill),a.append("foreignObject").attr("x",t.x+n.boxPadding).attr("y",i+10).attr("width",t.dimension.width-2*n.boxPadding).attr("height",t.dimension.height-2*n.boxPadding).append("xhtml:div").style("display","table").style("height","100%").style("width","100%").append("span").style("display","table-cell").style("text-align","center").style("vertical-align","middle").html(t.text)}}o(te,"renderD3Box");function ne(e,n){return e>n}o(ne,"dirUpwards");function ie(e,n,t,i){return a=>{const r=a.sourceBox.swimlane.y+n.swimlanePadding,d=a.targetBox.swimlane.y+n.swimlanePadding,l=ne(r,d),c=a.sourceBox.x+a.sourceBox.dimension.width*2/3,m=a.targetBox.x+a.targetBox.dimeLine truncated
`,"id:",n,t),!Re)throw new Error("EventModeling config not found");const a=i.db,{themeVariables:r,eventmodeling:d}=T(),l=ue(`[id="${n}"]`),c=a.getDiagramProps(),m=a.getState(),x=`em-arrowhead-${n}`,u=r.emArrowhead??"#000000";m.sortedSwimlanesArray.forEach(ae(l,m.maxR,c,r)),m.boxes.forEach(te(l,c)),m.relations.forEach(ie(l,c,x,r)),l.append("defs").append("marker").attr("id",x).attr("markerWidth","10").attr("markerHeight","7").attr("refX","10").attr("refY","3.5").attr("orient","auto").append("polygon").attr("points","0 0, 10 3.5, 0 7").attr("fill",u),xe(void 0,l,d?.padding??30,d?.useMaxWidth)},"draw"),$e={draw:Te},De=o(e=>"","getStyles"),Ne=De,He={parser:Ee,db:F,renderer:$e,styles:Ne};export{He as diagram};
+24
View File
@@ -0,0 +1,24 @@
import{p as ge}from"./chunk-JWPE2WC7.js";import{_ as w,E as ye,y as ae,A as ee,D as Se,d as ve,l as te,bd as B,j as U,b as xe,a as be,n as we,o as Ce,g as Te,s as Le,B as $e,be as Ae,p as Fe}from"./mermaid.core.js";import{s as Ne}from"./chunk-POPQ4Y6H.js";import{p as Me}from"./cynefin-OW5HDTMX.js";import{b as O}from"./defaultLocale.js";import{o as Q}from"./ordinal.js";import"./index.js";import"./init.js";function _e(t){var a=0,l=t.children,n=l&&l.length;if(!n)a=1;else for(;--n>=0;)a+=l[n].value;t.value=a}function ke(){return this.eachAfter(_e)}function ze(t,a){let l=-1;for(const n of this)t.call(a,n,++l,this);return this}function Ve(t,a){for(var l=this,n=[l],r,i,h=-1;l=n.pop();)if(t.call(a,l,++h,this),r=l.children)for(i=r.length-1;i>=0;--i)n.push(r[i]);return this}function De(t,a){for(var l=this,n=[l],r=[],i,h,d,g=-1;l=n.pop();)if(r.push(l),i=l.children)for(h=0,d=i.length;h<d;++h)n.push(i[h]);for(;l=r.pop();)t.call(a,l,++g,this);return this}function Pe(t,a){let l=-1;for(const n of this)if(t.call(a,n,++l,this))return n}function Be(t){return this.eachAfter(function(a){for(var l=+t(a.data)||0,n=a.children,r=n&&n.length;--r>=0;)l+=n[r].value;a.value=l})}function Ee(t){return this.eachBefore(function(a){a.children&&a.children.sort(t)})}function Re(t){for(var a=this,l=We(a,t),n=[a];a!==l;)a=a.parent,n.push(a);for(var r=n.length;t!==l;)n.splice(r,0,t),t=t.parent;return n}function We(t,a){if(t===a)return t;var l=t.ancestors(),n=a.ancestors(),r=null;for(t=l.pop(),a=n.pop();t===a;)r=t,t=l.pop(),a=n.pop();return r}function He(){for(var t=this,a=[t];t=t.parent;)a.push(t);return a}function Ie(){return Array.from(this)}function Oe(){var t=[];return this.eachBefore(function(a){a.children||t.push(a)}),t}function Ge(){var t=this,a=[];return t.each(function(l){l!==t&&a.push({source:l.parent,target:l})}),a}function*qe(){var t=this,a,l=[t],n,r,i;do for(a=l.reverse(),l=[];t=a.pop();)if(yield t,n=t.children)for(r=0,i=n.length;r<i;++r)l.push(n[r]);while(l.length)}function ne(t,a){t instanceof Map?(t=[void 0,t],a===void 0&&(a=Ye)):a===void 0&&(a=je);for(var l=new Z(t),n,r=[l],i,h,d,g;n=r.pop();)if((h=a(n.data))&&(g=(h=Array.from(h)).length))for(n.children=h,d=g-1;d>=0;--d)r.push(i=h[d]=new Z(h[d])),i.parent=n,i.depth=n.depth+1;return l.eachBefore(Ze)}function Xe(){return ne(this).eachBefore(Ue)}function je(t){return t.children}function Ye(t){return Array.isArray(t)?t[1]:null}function Ue(t){t.data.value!==void 0&&(t.value=t.data.value),t.data=t.data.data}function Ze(t){var a=0;do t.height=a;while((t=t.parent)&&t.height<++a)}function Z(t){this.data=t,this.depth=this.height=0,this.parent=null}Z.prototype=ne.prototype={constructor:Z,count:ke,each:ze,eachAfter:De,eachBefore:Ve,find:Pe,sum:Be,sort:Ee,path:Re,ancestors:He,descendants:Ie,leaves:Oe,links:Ge,copy:Xe,[Symbol.iterator]:qe};function Je(t){if(typeof t!="function")throw new Error;return t}function G(){return 0}function q(t){return function(){return t}}function Ke(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)}function Qe(t,a,l,n,r){for(var i=t.children,h,d=-1,g=i.length,c=t.value&&(n-a)/t.value;++d<g;)h=i[d],h.y0=l,h.y1=r,h.x0=a,h.x1=a+=h.value*c}function et(t,a,l,n,r){for(var i=t.children,h,d=-1,g=i.length,c=t.value&&(r-l)/t.value;++d<g;)h=i[d],h.x0=a,h.x1=n,h.y0=l,h.y1=l+=h.value*c}var tt=(1+Math.sqrt(5))/2;function at(t,a,l,n,r,i){for(var h=[],d=a.children,g,c,p=0,b=0,s=d.length,x,S,v=a.value,u,y,N,$,V,W,M;p<s;){x=r-l,S=i-n;do u=d[b++].value;while(!u&&b<s);for(y=N=u,W=Math.max(S/x,x/S)/(v*t),M=u*u*W,V=Math.max(N/M,M/y);b<s;++b){if(u+=c=d[b].value,c<y&&(y=c),c>N&&(N=c),M=u*u*W,$=Math.max(N/M,M/y),$>V){u-=c;break}V=$}h.push(g={value:u,dice:x<S,children:d.slice(p,b)}),g.dice?Qe(g,l,n,r,v?n+=S*u/v:i):et(g,l,n,v?l+=x*u/v:r,i),v-=u,p=b}return h}const nt=(function t(a){function l(n,r,i,h,d){at(a,n,r,i,h,d)}return l.ratio=function(n){return t((n=+n)>1?n:1)},l})(tt);function lt(){var t=nt,a=!1,l=1,n=1,r=[0],i=G,h=G,d=G,g=G,c=G;function p(s){return s.x0=s.y0=0,s.x1=l,s.y1=n,s.eachBefore(b),r=[0],a&&s.eachBefore(Ke),s}function b(s){var x=r[s.depth],S=s.x0+x,v=s.y0+x,u=s.x1-x,y=s.y1-x;u<S&&(S=u=(S+u)/2),y<v&&(v=y=(v+y)/2),s.x0=S,s.y0=v,s.x1=u,s.y1=y,s.children&&(x=r[s.depth+1]=i(s)/2,S+=c(s)-x,v+=h(s)-x,u-=d(s)-x,y-=g(s)-x,u<S&&(S=u=(S+u)/2),y<v&&(v=y=(v+y)/2),t(s,S,v,u,y))}return p.round=function(s){return arguments.length?(a=!!s,p):a},p.size=function(s){return arguments.length?(l=+s[0],n=+s[1],p):[l,n]},p.tile=function(s){return arguments.length?(t=Je(s),p):t},p.padding=function(s){return arguments.length?p.paddingInner(s).paddingOuter(s):p.paddingInner()},p.paddingInner=function(s){return arguments.length?(i=typeof s=="function"?s:q(+s),p):i},p.paddingOuter=function(s){return arguments.length?p.paddingTop(s).paddingRight(s).paddingBottom(s).paddingLeft(s):p.paddingTop()},p.paddingTop=function(s){return arguments.length?(h=typeof s=="function"?s:q(+s),p):h},p.paddingRight=function(s){return arguments.length?(d=typeof s=="function"?s:q(+s),p)Line truncated
.treemapNode.section {
stroke: ${r.sectionStrokeColor};
stroke-width: ${r.sectionStrokeWidth};
fill: ${r.sectionFillColor};
}
.treemapNode.leaf {
stroke: ${r.leafStrokeColor};
stroke-width: ${r.leafStrokeWidth};
fill: ${r.leafFillColor};
}
.treemapLabel {
fill: ${h};
font-size: ${r.labelFontSize};
}
.treemapValue {
fill: ${d};
font-size: ${r.valueFontSize};
}
.treemapTitle {
fill: ${i};
font-size: ${r.titleFontSize};
}
`},"getStyles"),ut=pt,Ct={parser:he,get db(){return new oe},renderer:ht,styles:ut};export{Ct as diagram};
+24
View File
@@ -0,0 +1,24 @@
import{p as $}from"./chunk-JWPE2WC7.js";import{_ as b,A as m,D as C,d as S,l as w,b as D,a as T,n as P,o as z,g as A,s as E,y as F,B as W,p as _}from"./mermaid.core.js";import{p as N}from"./cynefin-OW5HDTMX.js";import"./index.js";var L=W.packet,u,v=(u=class{constructor(){this.packet=[],this.setAccTitle=D,this.getAccTitle=T,this.setDiagramTitle=P,this.getDiagramTitle=z,this.getAccDescription=A,this.setAccDescription=E}getConfig(){const t=m({...L,...F().packet});return t.showBits&&(t.paddingY+=10),t}getPacket(){return this.packet}pushWord(t){t.length>0&&this.packet.push(t)}clear(){_(),this.packet=[]}},b(u,"PacketDB"),u),M=1e4,Y=b((e,t)=>{$(e,t);let r=-1,s=[],n=1;const{bitsPerRow:l}=t.getConfig();for(let{start:a,end:i,bits:d,label:c}of e.blocks){if(a!==void 0&&i!==void 0&&i<a)throw new Error(`Packet block ${a} - ${i} is invalid. End must be greater than start.`);if(a??=r+1,a!==r+1)throw new Error(`Packet block ${a} - ${i??a} is not contiguous. It should start from ${r+1}.`);if(d===0)throw new Error(`Packet block ${a} is invalid. Cannot have a zero bit field.`);for(i??=a+(d??1)-1,d??=i-a+1,r=i,w.debug(`Packet block ${a} - ${r} with label ${c}`);s.length<=l+1&&t.getPacket().length<M;){const[p,o]=I({start:a,end:i,bits:d,label:c},n,l);if(s.push(p),p.end+1===n*l&&(t.pushWord(s),s=[],n++),!o)break;({start:a,end:i,bits:d,label:c}=o)}}t.pushWord(s)},"populate"),I=b((e,t,r)=>{if(e.start===void 0)throw new Error("start should have been set during first phase");if(e.end===void 0)throw new Error("end should have been set during first phase");if(e.start>e.end)throw new Error(`Block start ${e.start} is greater than block end ${e.end}.`);if(e.end+1<=t*r)return[e,void 0];const s=t*r-1,n=t*r;return[{start:e.start,end:s,label:e.label,bits:s-e.start},{start:n,end:e.end,label:e.label,bits:e.end-n}]},"getNextFittingBlock"),x={parser:{yy:void 0},parse:b(async e=>{const t=await N("packet",e),r=x.parser?.yy;if(!(r instanceof v))throw new Error("parser.parser?.yy was not a PacketDB. This is due to a bug within Mermaid, please report this issue at https://github.com/mermaid-js/mermaid/issues.");w.debug(t),Y(t,r)},"parse")},O=b((e,t,r,s)=>{const n=s.db,l=n.getConfig(),{rowHeight:a,paddingY:i,bitWidth:d,bitsPerRow:c}=l,p=n.getPacket(),o=n.getDiagramTitle(),h=a+i,g=h*(p.length+1)-(o?0:a),k=d*c+2,f=C(t);f.attr("viewBox",`0 0 ${k} ${g}`),S(f,g,k,l.useMaxWidth);for(const[y,B]of p.entries())j(f,B,y,l);f.append("text").text(o).attr("x",k/2).attr("y",g-h/2).attr("dominant-baseline","middle").attr("text-anchor","middle").attr("class","packetTitle")},"draw"),j=b((e,t,r,{rowHeight:s,paddingX:n,paddingY:l,bitWidth:a,bitsPerRow:i,showBits:d})=>{const c=e.append("g"),p=r*(s+l)+l;for(const o of t){const h=o.start%i*a+1,g=(o.end-o.start+1)*a-n;if(c.append("rect").attr("x",h).attr("y",p).attr("width",g).attr("height",s).attr("class","packetBlock"),c.append("text").attr("x",h+g/2).attr("y",p+s/2).attr("class","packetLabel").attr("dominant-baseline","middle").attr("text-anchor","middle").text(o.label),!d)continue;const k=o.end===o.start,f=p-2;c.append("text").attr("x",h+(k?g/2:0)).attr("y",f).attr("class","packetByte start").attr("dominant-baseline","auto").attr("text-anchor",k?"middle":"start").text(o.start),k||c.append("text").attr("x",h+g).attr("y",f).attr("class","packetByte end").attr("dominant-baseline","auto").attr("text-anchor","end").text(o.end)}},"drawWord"),G={draw:O},H={byteFontSize:"10px",startByteColor:"black",endByteColor:"black",labelColor:"black",labelFontSize:"12px",titleColor:"black",titleFontSize:"14px",blockStrokeColor:"black",blockStrokeWidth:"1",blockFillColor:"#efefef"},K=b(({packet:e}={})=>{const t=m(H,e);return`
.packetByte {
font-size: ${t.byteFontSize};
}
.packetByte.start {
fill: ${t.startByteColor};
}
.packetByte.end {
fill: ${t.endByteColor};
}
.packetLabel {
fill: ${t.labelColor};
font-size: ${t.labelFontSize};
}
.packetTitle {
fill: ${t.titleColor};
font-size: ${t.titleFontSize};
}
.packetBlock {
stroke: ${t.blockStrokeColor};
stroke-width: ${t.blockStrokeWidth};
fill: ${t.blockFillColor};
}
`},"styles"),J={parser:x,get db(){return new v},renderer:G,styles:K};export{J as diagram};
+1
View File
@@ -0,0 +1 @@
import{g as l,r as m,d as n}from"./chunk-SVP7TREG.js";import{p}from"./chunk-JWPE2WC7.js";import{_ as t,l as o}from"./mermaid.core.js";import{M as u,a as f}from"./cynefin-OW5HDTMX.js";import"./index.js";var c=f().RailroadEbnf.parser.LangiumParser,s=t(e=>{const r=e.alternatives.map(E);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformChoice"),E=t(e=>{const r=e.elements.map(d);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformSequence"),i=t(e=>{switch(e.$type){case"EbnfTerminal":return{type:"terminal",value:e.value};case"EbnfNonTerminal":return{type:"nonterminal",name:e.name};case"EbnfSpecial":return{type:"special",text:e.text};case"EbnfGroup":return s(e.element);case"EbnfOptional":return{type:"optional",element:s(e.element)};case"EbnfRepetition":return{type:"repetition",element:s(e.element),min:0,max:1/0};default:throw new Error(`Unsupported EBNF primary node: ${e.$type}`)}},"transformPrimary"),b=t((e,r)=>{switch(r.$type){case"EbnfOptionalPostfix":return{type:"optional",element:e};case"EbnfZeroOrMorePostfix":return{type:"repetition",element:e,min:0,max:1/0};case"EbnfOneOrMorePostfix":return{type:"repetition",element:e,min:1,max:1/0};case"EbnfExceptionPostfix":return{type:"sequence",elements:[e,{type:"terminal",value:"-"},i(r.except)]};default:throw new Error(`Unsupported EBNF postfix node: ${r.$type}`)}},"transformPostfix"),d=t(e=>e.postfixes.reduce((r,a)=>b(r,a),i(e.base)),"transformTerm"),y=t(e=>({name:e.name,definition:s(e.definition)}),"transformRule"),v=t(e=>{p(e,n),e.title&&n.setTitle(e.title),e.rules.map(r=>n.addRule(y(r)))},"populateDb"),g={parse:t(e=>{n.clear(),o.debug("[EBNF Parser] Starting Langium parse");const r=c.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new u(r);const a=r.value;o.debug("[EBNF Parser] Parsed rules:",a.rules.length),v(a),o.debug("[EBNF Parser] Parse complete")},"parse"),parser:{yy:n}},R={parser:g,db:n,renderer:m,styles:l};export{R as diagram};
+99
View File
@@ -0,0 +1,99 @@
import{g as Ut}from"./chunk-XXDRQBXY.js";import{s as Kt}from"./chunk-POPQ4Y6H.js";import{_ as f,b as Zt,a as jt,s as qt,g as Wt,n as Ht,o as Qt,c as tt,l as F,k as Xt,p as Jt,q as $t,r as te,t as ee,u as se,v as ie,j as re,x as ne}from"./mermaid.core.js";import{c as ae}from"./channel.js";import"./index.js";var Ot=(function(){var s=f(function(G,a,l,d){for(l=l||{},d=G.length;d--;l[G[d]]=a);return l},"o"),n=[6,9,21,23,25,27,34,37,38,39,40,41,43,46,47,51,53,54,55],o=[2,2],c=[1,7],r=[1,9],h=[1,10],y=[1,11],b=[1,12],k=[1,30],R=[1,23],p=[1,24],g=[1,25],C=[1,26],v=[1,27],O=[1,19],x=[1,28],A=[1,29],N=[1,20],D=[1,18],L=[1,21],w=[1,22],xt=[2,6],u=[6,9,21,23,25,27,33,34,37,38,39,40,41,43,46,47,51,53,54,55],pt=[1,36],ft=[1,37],bt=[1,38],gt=[1,39],yt=[1,40],Z=[6,9,12,14,16,19,20,21,23,25,27,33,34,37,38,39,40,41,43,46,47,50,51,53,54,55,69,70,71,72,73],V=[1,46],M=[1,47],j=[1,57],q=[43,51,53,54,55,74,75],W=[1,70],H=[1,68],B=[1,65],Q=[1,69],X=[1,71],et=[6,9,12,16,21,23,25,27,33,34,37,38,39,40,41,43,44,45,46,47,51,52,53,54,55,69,70,71,72,73],st=[1,78],it=[1,77],rt=[1,76],Nt=[69,70,71,72,73],Ct=[1,91],At=[6,9,45,50],z=[6,9,12,44,45,50,51,52],nt=[1,101],at=[1,100],ot=[1,99],J=[18,61],It=[1,110],Rt=[1,109],vt=[20,43,51,53,54,55],_t=[18,61,64,66],kt={trace:f(function(){},"trace"),yy:{},symbols_:{error:2,start:3,ER_DIAGRAM:4,document:5,EOF:6,line:7,statement:8,NEWLINE:9,entityName:10,relSpec:11,COLON:12,role:13,STYLE_SEPARATOR:14,idList:15,BLOCK_START:16,attributes:17,BLOCK_STOP:18,SQS:19,SQE:20,title:21,title_value:22,acc_title:23,acc_title_value:24,acc_descr:25,acc_descr_value:26,acc_descr_multiline_value:27,direction:28,classDefStatement:29,classStatement:30,styleStatement:31,subgraphHeader:32,END:33,SUBGRAPH:34,separator:35,subgraphTitle:36,direction_tb:37,direction_bt:38,direction_rl:39,direction_lr:40,CLASSDEF:41,stylesOpt:42,UNICODE_TEXT:43,STYLE_TEXT:44,COMMA:45,CLASS:46,STYLE:47,style:48,styleComponent:49,SEMI:50,NUM:51,BRKT:52,ENTITY_NAME:53,DECIMAL_NUM:54,ENTITY_ONE:55,attribute:56,attributeType:57,attributeName:58,attributeKeyTypeList:59,attributeComment:60,ATTRIBUTE_WORD:61,"?":62,attributeKeyType:63,",":64,ATTRIBUTE_KEY:65,COMMENT:66,cardinality:67,relType:68,ZERO_OR_ONE:69,ZERO_OR_MORE:70,ONE_OR_MORE:71,ONLY_ONE:72,MD_PARENT:73,NON_IDENTIFYING:74,IDENTIFYING:75,WORD:76,$accept:0,$end:1},terminals_:{2:"error",4:"ER_DIAGRAM",6:"EOF",9:"NEWLINE",12:"COLON",14:"STYLE_SEPARATOR",16:"BLOCK_START",18:"BLOCK_STOP",19:"SQS",20:"SQE",21:"title",22:"title_value",23:"acc_title",24:"acc_title_value",25:"acc_descr",26:"acc_descr_value",27:"acc_descr_multiline_value",33:"END",34:"SUBGRAPH",37:"direction_tb",38:"direction_bt",39:"direction_rl",40:"direction_lr",41:"CLASSDEF",43:"UNICODE_TEXT",44:"STYLE_TEXT",45:"COMMA",46:"CLASS",47:"STYLE",50:"SEMI",51:"NUM",52:"BRKT",53:"ENTITY_NAME",54:"DECIMAL_NUM",55:"ENTITY_ONE",61:"ATTRIBUTE_WORD",62:"?",64:",",65:"ATTRIBUTE_KEY",66:"COMMENT",69:"ZERO_OR_ONE",70:"ZERO_OR_MORE",71:"ONE_OR_MORE",72:"ONLY_ONE",73:"MD_PARENT",74:"NON_IDENTIFYING",75:"IDENTIFYING",76:"WORD"},productions_:[0,[3,3],[5,0],[5,2],[7,1],[7,1],[7,1],[8,5],[8,9],[8,7],[8,7],[8,4],[8,6],[8,3],[8,5],[8,1],[8,3],[8,7],[8,9],[8,6],[8,8],[8,4],[8,6],[8,2],[8,2],[8,2],[8,1],[8,1],[8,1],[8,1],[8,1],[8,3],[32,3],[32,6],[36,1],[36,2],[28,1],[28,1],[28,1],[28,1],[29,4],[15,1],[15,1],[15,3],[15,3],[30,3],[31,4],[42,1],[42,3],[48,1],[48,2],[35,1],[35,1],[35,1],[49,1],[49,1],[49,1],[49,1],[10,1],[10,1],[10,1],[10,1],[10,1],[17,1],[17,2],[56,2],[56,3],[56,3],[56,4],[57,1],[57,2],[58,1],[59,1],[59,3],[63,1],[60,1],[11,3],[67,1],[67,1],[67,1],[67,1],[67,1],[68,1],[68,1],[13,1],[13,1],[13,1]],performAction:f(function(a,l,d,i,_,t,$){var e=t.length-1;switch(_){case 1:break;case 2:this.$=[];break;case 3:this.$=t[e-1].concat(t[e]);break;case 4:this.$=t[e];break;case 5:case 6:this.$=[];break;case 7:i.addEntity(t[e-4]),i.addEntity(t[e-2]),i.addRelationship(t[e-4],t[e],t[e-2],t[e-3]),this.$=[t[e-4],t[e-2]];break;case 8:i.addEntity(t[e-8]),i.addEntity(t[e-4]),i.addRelationship(t[e-8],t[e],t[e-4],t[e-5]),i.setClass([t[e-8]],t[e-6]),i.setClass([t[e-4]],t[e-2]),this.$=[t[e-8],t[e-4]];break;case 9:i.addEntity(t[e-6]),i.addEntity(t[e-2]),i.addRelationship(t[e-6],t[e],t[e-2],t[e-3]),i.setClass([t[e-6]],t[e-4]),this.$=[t[e-6],t[e-2]];break;case 10:i.addEntity(t[e-6]),i.addEntity(t[e-4]),i.addRelationship(t[e-6],t[e],t[e-4],t[e-5]),i.setClass([t[e-4]],t[e-2]),this.$=[t[e-6],t[e-4]];break;case 11:i.addEntity(t[e-3]),i.addAttributes(t[e-3],t[e-1]),this.$=[t[e-3]];break;case 12:i.addEntity(t[e-5]),i.addAttributes(t[e-5],t[e-1]),i.setClass([t[e-5]],t[e-3]),this.$=[t[e-5]];break;case 13:i.addEntity(t[e-2]),this.$=[t[e-2]];break;case 14:i.addEntity(t[e-4]),i.setClass([t[e-4]],t[e-2]),this.$=[t[e-4]];break;case 15:i.addEntity(t[e]),this.$=[t[e]];break;case 16:i.addEntity(t[e-2]),i.setClass([t[e-2]],t[e]),this.$=[t[e-2]];break;case 17:i.addEntity(t[e-6],t[e-4]),i.addAttributes(t[e-6],t[e-1]),this.$=[t[e-6]];break;case 18:i.addEntity(t[e-8],t[e-6]),i.addAttribuLine truncated
`+m.showPosition()+`
Expecting `+ut.join(", ")+", got '"+(this.terminals_[E]||E)+"'":Tt="Parse error on line "+(lt+1)+": Unexpected "+(E==Lt?"end of input":"'"+(this.terminals_[E]||E)+"'"),this.parseError(Tt,{text:m.match,token:this.terminals_[E]||E,line:m.yylineno,loc:Et,expected:ut})}if(T[0]instanceof Array&&T.length>1)throw new Error("Parse Error: multiple actions possible at state: "+P+", token: "+E);switch(T[0]){case 1:d.push(E),_.push(m.yytext),t.push(m.yylloc),d.push(T[1]),E=null,Dt=m.yyleng,e=m.yytext,lt=m.yylineno,Et=m.yylloc;break;case 2:if(I=this.productions_[T[1]][1],U.$=_[_.length-I],U._$={first_line:t[t.length-(I||1)].first_line,last_line:t[t.length-1].last_line,first_column:t[t.length-(I||1)].first_column,last_column:t[t.length-1].last_column},Pt&&(U._$.range=[t[t.length-(I||1)].range[0],t[t.length-1].range[1]]),St=this.performAction.apply(U,[e,Dt,lt,Y.yy,T[1],_,t].concat(Yt)),typeof St<"u")return St;I&&(d=d.slice(0,-1*I*2),_=_.slice(0,-1*I),t=t.slice(0,-1*I)),d.push(this.productions_[T[1]][0]),_.push(U.$),t.push(U._$),Vt=$[d[d.length-2]][d[d.length-1]],d.push(Vt);break;case 3:return!0}}return!0},"parse")},Gt=(function(){var G={EOF:1,parseError:f(function(l,d){if(this.yy.parser)this.yy.parser.parseError(l,d);else throw new Error(l)},"parseError"),setInput:f(function(a,l){return this.yy=l||this.yy||{},this._input=a,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:f(function(){var a=this._input[0];this.yytext+=a,this.yyleng++,this.offset++,this.match+=a,this.matched+=a;var l=a.match(/(?:\r\n?|\n).*/g);return l?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),a},"input"),unput:f(function(a){var l=a.length,d=a.split(/(?:\r\n?|\n)/g);this._input=a+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-l),this.offset-=l;var i=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),d.length-1&&(this.yylineno-=d.length-1);var _=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:d?(d.length===i.length?this.yylloc.first_column:0)+i[i.length-d.length].length-d[0].length:this.yylloc.first_column-l},this.options.ranges&&(this.yylloc.range=[_[0],_[0]+this.yyleng-l]),this.yyleng=this.yytext.length,this},"unput"),more:f(function(){return this._more=!0,this},"more"),reject:f(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:f(function(a){this.unput(this.match.slice(a))},"less"),pastInput:f(function(){var a=this.matched.substr(0,this.matched.length-this.match.length);return(a.length>20?"...":"")+a.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:f(function(){var a=this.match;return a.length<20&&(a+=this._input.substr(0,20-a.length)),(a.substr(0,20)+(a.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:f(function(){var a=this.pastInput(),l=new Array(a.length+1).join("-");return a+this.upcomingInput()+`
`+l+"^"},"showPosition"),test_match:f(function(a,l){var d,i,_;if(this.options.backtrack_lexer&&(_={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(_.yylloc.range=this.yylloc.range.slice(0))),i=a[0].match(/(?:\r\n?|\n).*/g),i&&(this.yylineno+=i.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:i?i[i.length-1].length-i[i.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+a[0].length},this.yytext+=a[0],this.match+=a[0],this.matches=a,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(a[0].length),this.matched+=a[0],d=this.performAction.call(this,this.yy,this,l,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),d)return d;if(this._backtrack){for(var t in _)this[t]=_[t];return!1}return!1},"test_match"),next:f(function(){if(this.done)return this.EOF;this._input||(this.done=!0);var a,l,d,i;this._more||(this.yytext="",this.match="");for(var _=this._currentRules(),t=0;t<_.length;t++)if(d=this._input.match(this.rules[_[t]]),d&&(!l||d[0].length>l[0].length)){if(l=d,i=t,this.options.backtrack_lexer){if(a=this.test_match(d,_[t]),a!==!1)return a;if(this._backtrack){l=!1;continue}else return!1}else if(!this.options.flex)break}return l?(a=this.test_match(l,_[i]),a!==!1?a:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text.
`+this.showPosition(),{text:"",token:null,line:this.yylineno})},"next"),lex:f(function(){var l=this.next();return l||this.lex()},"lex"),begin:f(function(l){this.conditionStack.push(l)},"begin"),popState:f(function(){var l=this.conditionStack.length-1;return l>0?this.conditionStack.pop():this.conditionStack[0]},"popState"),_currentRules:f(function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},"_currentRules"),topState:f(function(l){return l=this.conditionStack.length-1-Math.abs(l||0),l>=0?this.conditionStack[l]:"INITIAL"},"topState"),pushState:f(function(l){this.begin(l)},"pushState"),stateStackSize:f(function(){return this.conditionStack.length},"stateStackSize"),options:{"case-insensitive":!0},performAction:f(function(l,d,i,_){switch(i){case 0:return this.begin("acc_title"),23;case 1:return this.popState(),"acc_title_value";case 2:return this.begin("acc_descr"),25;case 3:return this.popState(),"acc_descr_value";case 4:this.begin("acc_descr_multiline");break;case 5:this.popState();break;case 6:return"acc_descr_multiline_value";case 7:return 37;case 8:return 38;case 9:return 39;case 10:return 40;case 11:break;case 12:return 9;case 13:return 53;case 14:return 76;case 15:return 4;case 16:return this.begin("block"),16;case 17:return 52;case 18:return 52;case 19:return 45;case 20:return 14;case 21:return 12;case 22:break;case 23:return 65;case 24:return 61;case 25:return 61;case 26:this.begin("block_bq");break;case 27:return 61;case 28:this.popState();break;case 29:return 66;case 30:break;case 31:return this.popState(),18;case 32:return d.yytext[0];case 33:return 19;case 34:return 20;case 35:return this.begin("style"),47;case 36:return this.popState(),9;case 37:break;case 38:return 12;case 39:return 45;case 40:return 52;case 41:return this.begin("style"),41;case 42:return 46;case 43:return 34;case 44:return 33;case 45:return 69;case 46:return 71;case 47:return 71;case 48:return 71;case 49:return 69;case 50:return 69;case 51:return 70;case 52:return 70;case 53:return 70;case 54:return 70;case 55:return 70;case 56:return 71;case 57:return 70;case 58:return 71;case 59:return 72;case 60:return 72;case 61:return 54;case 62:return 72;case 63:return 72;case 64:return 72;case 65:return 55;case 66:return 51;case 67:return 72;case 68:return 69;case 69:return 70;case 70:return 71;case 71:return 73;case 72:return 74;case 73:return 75;case 74:return 75;case 75:return 74;case 76:return 74;case 77:return 74;case 78:return 44;case 79:return 50;case 80:return 43;case 81:return d.yytext[0];case 82:return 6}},"anonymous"),rules:[/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*direction\s+BT[^\n]*)/i,/^(?:.*direction\s+RL[^\n]*)/i,/^(?:.*direction\s+LR[^\n]*)/i,/^(?:[ \t\r]+)/i,/^(?:[\n]+)/i,/^(?:"[^"%\r\n\v\b\\]+")/i,/^(?:"[^"]*")/i,/^(?:erDiagram\b)/i,/^(?:\{)/i,/^(?:#)/i,/^(?:#)/i,/^(?:,)/i,/^(?::::)/i,/^(?::)/i,/^(?:\s+)/i,/^(?:\b((?:PK)|(?:FK)|(?:UK))\b)/i,/^(?:([^\s]*)[~].*[~]([^\s]*))/i,/^(?:([\*A-Za-z_\u00C0-\uFFFF][A-Za-z0-9\-\_\[\]\(\)\.,\u00C0-\uFFFF\*]*))/i,/^(?:[`])/i,/^(?:[^`]+)/i,/^(?:[`])/i,/^(?:"[^"]*")/i,/^(?:[\n]+)/i,/^(?:\})/i,/^(?:.)/i,/^(?:\[)/i,/^(?:\])/i,/^(?:style\b)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?::)/i,/^(?:,)/i,/^(?:#)/i,/^(?:classDef\b)/i,/^(?:class\b)/i,/^(?:subgraph\b)/i,/^(?:end\b\s*)/i,/^(?:one or zero\b)/i,/^(?:one or more\b)/i,/^(?:one or many\b)/i,/^(?:1\+)/i,/^(?:\|o\b)/i,/^(?:zero or one\b)/i,/^(?:zero or more\b)/i,/^(?:zero or many\b)/i,/^(?:0\+)/i,/^(?:\}o\b)/i,/^(?:many\(0\))/i,/^(?:many\(1\))/i,/^(?:many\b)/i,/^(?:\}\|)/i,/^(?:one\b)/i,/^(?:only one\b)/i,/^(?:[0-9]+\.[0-9]+)/i,/^(?:1(?=\s+[A-Za-z_"']))/i,/^(?:1(?=\s+[0-9]))/i,/^(?:1(?=(--|\.\.|\.-|-\.)))/i,/^(?:1\b)/i,/^(?:[0-9]+)/i,/^(?:\|\|)/i,/^(?:o\|)/i,/^(?:o\{)/i,/^(?:\|\{)/i,/^(?:u(?=[\.\-\|]))/i,/^(?:\.\.)/i,/^(?:--)/i,/^(?:to\b)/i,/^(?:optionally to\b)/i,/^(?:\.-)/i,/^(?:-\.)/i,/^(?:([^\x00-\x7F]|\w|-|\*)+)/i,/^(?:;)/i,/^(?:([^\x00-\x7F]|\w|-|\*|\.)+)/i,/^(?:.)/i,/^(?:$)/i],conditions:{style:{rules:[36,37,38,39,40,78,79],inclusive:!1},acc_descr_multiline:{rules:[5,6],inclusive:!1},acc_descr:{rules:[3],inclusive:!1},acc_title:{rules:[1],inclusive:!1},block_bq:{rules:[27,28],inclusive:!1},block:{rules:[22,23,24,25,26,29,30,31,32],inclusive:!1},INITIAL:{rules:[0,2,4,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,33,34,35,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,80,81,82],inclusive:!0}}};return G})();kt.lexer=Gt;function ct(){this.yy={}}return f(ct,"Parser"),ct.prototype=kt,kt.Parser=ct,new ct})();Ot.parser=Ot;var oe=Ot,K,ce=(K=class{constructor(){this.entities=new Map,this.relationships=[],this.classes=new Map,this.subgraphDepth=0,this.subGraphs=[],this.subGraphLookup=new Map,this.subCount=0Line truncated
[data-look="${o}"][data-color-id="color-${b}"].node path {
stroke: ${r[b]};
${h?`fill: ${c[b]};`:""}
}
[data-look="${o}"][data-color-id="color-${b}"].node rect {
stroke: ${r[b]};
${h?`fill: ${c[b]};`:""}
}
`;return y},"genColor"),ue=f(s=>{const{look:n,theme:o,erEdgeLabelBackground:c,strokeWidth:r}=s;return`
${he(s)}
.entityBox {
fill: ${s.mainBkg};
stroke: ${s.nodeBorder};
}
.relationshipLabelBox {
fill: ${s.tertiaryColor};
opacity: 0.7;
background-color: ${s.tertiaryColor};
rect {
opacity: 0.5;
}
}
.labelBkg {
background-color: ${dt.has(o)&&c?c:Mt(s.tertiaryColor,.5)};
}
.edgeLabel {
background-color: ${dt.has(o)&&c?c:s.edgeLabelBackground};
}
.edgeLabel .label rect {
fill: ${dt.has(o)&&c?c:s.edgeLabelBackground};
}
.edgeLabel .label text {
fill: ${s.textColor};
}
.edgeLabel .label {
fill: ${s.nodeBorder};
font-size: 14px;
}
.label {
font-family: ${s.fontFamily};
color: ${s.nodeTextColor||s.textColor};
}
.edge-pattern-dashed {
stroke-dasharray: 8,8;
}
.node rect,
.node circle,
.node ellipse,
.node polygon
{
fill: ${s.mainBkg};
stroke: ${s.nodeBorder};
stroke-width: ${n==="neo"?r:"1px"};
}
.relationshipLine {
stroke: ${s.lineColor};
stroke-width: ${n==="neo"?r:"1px"};
fill: none;
}
.marker {
fill: none !important;
stroke: ${s.lineColor} !important;
stroke-width: 1;
}
[data-look=neo].labelBkg {
background-color: ${Mt(s.tertiaryColor,.5)};
}
.cluster rect {
fill: ${s.clusterBkg??s.mainBkg};
stroke: ${s.clusterBorder??s.nodeBorder};
stroke-width: 1px;
}
.cluster text {
fill: ${s.titleColor??s.textColor};
}
.cluster-label text {
fill: ${s.titleColor??s.textColor};
}
`},"getStyles"),de=ue,_e={parser:oe,get db(){return new ce},renderer:Bt,styles:de};export{_e as diagram};
+168
View File
@@ -0,0 +1,168 @@
import{g as Xt}from"./chunk-5VM5RSS4.js";import{g as Qt}from"./chunk-XXDRQBXY.js";import{s as Jt}from"./chunk-POPQ4Y6H.js";import{_ as k,b4 as Zt,F as Mt,l as $,c as ke,u as $t,v as e1,x as rt,b as t1,s as s1,n as i1,a as r1,g as a1,o as n1,k as u1,H as o1,J as l1,ca as c1,q as st,j as it,O as h1,p as d1,b7 as p1,r as f1}from"./mermaid.core.js";import{f as g1}from"./chunk-F27PBJKO.js";import{c as b1}from"./channel.js";var A1="flowchart-",Pe,k1=(Pe=class{constructor(){this.vertexCounter=0,this.config=ke(),this.diagramId="",this.vertices=new Map,this.edges=[],this.classes=new Map,this.subGraphs=[],this.subGraphLookup=new Map,this.tooltips=new Map,this.subCount=0,this.firstGraphFlag=!0,this.secCount=-1,this.posCrossRef=[],this.funs=[],this.setAccTitle=t1,this.setAccDescription=s1,this.setDiagramTitle=i1,this.getAccTitle=r1,this.getAccDescription=a1,this.getDiagramTitle=n1,this.funs.push(this.setupToolTips.bind(this)),this.addVertex=this.addVertex.bind(this),this.firstGraph=this.firstGraph.bind(this),this.setDirection=this.setDirection.bind(this),this.addSubGraph=this.addSubGraph.bind(this),this.addLink=this.addLink.bind(this),this.setLink=this.setLink.bind(this),this.updateLink=this.updateLink.bind(this),this.addClass=this.addClass.bind(this),this.setClass=this.setClass.bind(this),this.destructLink=this.destructLink.bind(this),this.setClickEvent=this.setClickEvent.bind(this),this.setTooltip=this.setTooltip.bind(this),this.updateLinkInterpolate=this.updateLinkInterpolate.bind(this),this.setClickFun=this.setClickFun.bind(this),this.bindFunctions=this.bindFunctions.bind(this),this.lex={firstGraph:this.firstGraph.bind(this)},this.clear(),this.setGen("gen-2")}sanitizeText(i){return u1.sanitizeText(i,this.config)}sanitizeNodeLabelType(i){switch(i){case"markdown":case"string":case"text":return i;default:return"markdown"}}setDiagramId(i){this.diagramId=i}lookUpDomId(i){for(const r of this.vertices.values())if(r.id===i)return this.diagramId?`${this.diagramId}-${r.domId}`:r.domId;return this.diagramId?`${this.diagramId}-${i}`:i}addVertex(i,r,a,n,c,g,l={},m){if(!i||i.trim().length===0)return;let p;if(m!==void 0){let u;m.includes(`
`)?u=m+`
`:u=`{
`+m+`
}`,p=o1(u,{schema:l1})}const F=this.subGraphLookup.get(i);if(F&&p){F.metadata={...F.metadata,...p};return}const _=this.edges.find(u=>u.id===i);if(_){const u=p;u?.animate!==void 0&&(_.animate=u.animate),u?.animation!==void 0&&(_.animation=u.animation),u?.curve!==void 0&&(_.interpolate=u.curve);return}let L,A=this.vertices.get(i);if(A===void 0&&(r===void 0&&a===void 0&&n!==void 0&&n!==null&&$.warn(`Style applied to unknown node "${i}". This may indicate a typo. The node will be created automatically.`),A={id:i,labelType:"text",domId:A1+i+"-"+this.vertexCounter,styles:[],classes:[]},this.vertices.set(i,A)),this.vertexCounter++,r!==void 0?(this.config=ke(),L=this.sanitizeText(r.text.trim()),A.labelType=r.type,L.startsWith('"')&&L.endsWith('"')&&(L=L.substring(1,L.length-1)),A.text=L):A.text===void 0&&(A.text=i),a!==void 0&&(A.type=a),n?.forEach(u=>{A.styles.push(u)}),c?.forEach(u=>{A.classes.push(u)}),g!==void 0&&(A.dir=g),A.props===void 0?A.props=l:l!==void 0&&Object.assign(A.props,l),p!==void 0){if(p.shape){if(p.shape!==p.shape.toLowerCase()||p.shape.includes("_"))throw new Error(`No such shape: ${p.shape}. Shape names should be lowercase.`);if(!c1(p.shape))throw new Error(`No such shape: ${p.shape}.`);A.type=p?.shape}p?.label&&(A.text=p?.label,A.labelType=this.sanitizeNodeLabelType(p?.labelType)),p?.icon&&(A.icon=p?.icon,!p.label?.trim()&&A.text===i&&(A.text="")),p?.form&&(A.form=p?.form),p?.pos&&(A.pos=p?.pos),p?.img&&(A.img=p?.img,!p.label?.trim()&&A.text===i&&(A.text="")),p?.constraint&&(A.constraint=p.constraint),p.w&&(A.assetWidth=Number(p.w)),p.h&&(A.assetHeight=Number(p.h))}}addSingleLink(i,r,a,n){const l={start:i,end:r,type:void 0,text:"",labelType:"text",classes:[],isUserDefinedId:!1,interpolate:this.edges.defaultInterpolate};$.info("abc78 Got edge...",l);const m=a.text;if(m!==void 0&&(l.text=this.sanitizeText(m.text.trim()),l.text.startsWith('"')&&l.text.endsWith('"')&&(l.text=l.text.substring(1,l.text.length-1)),l.labelType=this.sanitizeNodeLabelType(m.type)),a!==void 0&&(l.type=a.type,l.stroke=a.stroke,l.length=a.length>10?10:a.length),n&&!this.edges.some(p=>p.id===n))l.id=n,l.isUserDefinedId=!0;else{const p=this.edges.filter(F=>F.start===l.start&&F.end===l.end);p.length===0?l.id=st(l.start,l.end,{counter:0,prefix:"L"}):l.id=st(l.start,l.end,{counter:p.length+1,prefix:"L"})}if(this.edges.length<(this.config.maxEdges??500))$.info("Pushing edge..."),this.edges.push(l);else throw new Error(`Edge limit exceeded. ${this.edges.length} edges found, but the limit is ${this.config.maxEdges}.
Initialize mermaid with maxEdges set to a higher number to allow more edges.
You cannot set this config via configuration inside the diagram as it is a secure config.
You have to call mermaid.initialize.`)}isLinkData(i){return i!==null&&typeof i=="object"&&"id"in i&&typeof i.id=="string"}addLink(i,r,a){const n=this.isLinkData(a)?a.id.replace("@",""):void 0;$.info("addLink",i,r,n);for(const c of i)for(const g of r){const l=c===i[i.length-1],m=g===r[0];l&&m?this.addSingleLink(c,g,a,n):this.addSingleLink(c,g,a,void 0)}}updateLinkInterpolate(i,r){i.forEach(a=>{a==="default"?this.edges.defaultInterpolate=r:this.edges[a].interpolate=r})}updateLink(i,r){i.forEach(a=>{if(typeof a=="number"&&a>=this.edges.length)throw new Error(`The index ${a} for linkStyle is out of bounds. Valid indices for linkStyle are between 0 and ${this.edges.length-1}. (Help: Ensure that the index is within the range of existing edges.)`);a==="default"?this.edges.defaultStyle=r:(this.edges[a].style=r,(this.edges[a]?.style?.length??0)>0&&!this.edges[a]?.style?.some(n=>n?.startsWith("fill"))&&this.edges[a]?.style?.push("fill:none"))})}addClass(i,r){const a=r.join().replace(/\\,/g,"§§§").replace(/,/g,";").replace(/§§§/g,",").split(";");i.split(",").forEach(n=>{let c=this.classes.get(n);c===void 0&&(c={id:n,styles:[],textStyles:[]},this.classes.set(n,c)),a?.forEach(g=>{if(/color/.exec(g)){const l=g.replace("fill","bgFill");c.textStyles.push(l)}c.styles.push(g)})})}setDirection(i){this.direction=i.trim(),/.*</.exec(this.direction)&&(this.direction="RL"),/.*\^/.exec(this.direction)&&(this.direction="BT"),/.*>/.exec(this.direction)&&(this.direction="LR"),/.*v/.exec(this.direction)&&(this.direction="TB"),this.direction==="TD"&&(this.direction="TB")}setClass(i,r){for(const a of i.split(",")){const n=this.vertices.get(a);n&&n.classes.push(r);const c=this.edges.find(l=>l.id===a);c&&c.classes.push(r);const g=this.subGraphLookup.get(a);g&&g.classes.push(r)}}setTooltip(i,r){if(r!==void 0){r=this.sanitizeText(r);for(const a of i.split(","))this.tooltips.set(this.version==="gen-1"?this.lookUpDomId(a):a,r)}}setClickFun(i,r,a){if(ke().securityLevel!=="loose"||r===void 0)return;let n=[];if(typeof a=="string"){n=a.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);for(let g=0;g<n.length;g++){let l=n[g].trim();l.startsWith('"')&&l.endsWith('"')&&(l=l.substr(1,l.length-2)),n[g]=l}}n.length===0&&n.push(i);const c=this.vertices.get(i);c&&(c.haveCallback=!0,this.funs.push(()=>{const g=this.lookUpDomId(i),l=document.querySelector(`[id="${g}"]`);l!==null&&l.addEventListener("click",()=>{rt.runFunc(r,...n)},!1)}))}setLink(i,r,a){i.split(",").forEach(n=>{const c=this.vertices.get(n);c!==void 0&&(c.link=rt.formatUrl(r,this.config),c.linkTarget=a)}),this.setClass(i,"clickable")}getTooltip(i){return this.tooltips.get(i)}setClickEvent(i,r,a){i.split(",").forEach(n=>{this.setClickFun(n,r,a)}),this.setClass(i,"clickable")}bindFunctions(i){this.funs.forEach(r=>{r(i)})}getDirection(){return this.direction?.trim()}getVertices(){return this.vertices}getEdges(){return this.edges}getClasses(){return this.classes}setupToolTips(i){const r=g1();it(i).select("svg").selectAll("g.node").on("mouseover",c=>{const g=it(c.currentTarget),l=g.attr("title");if(l===null)return;const m=c.currentTarget?.getBoundingClientRect();r.transition().duration(200).style("opacity",".9"),r.text(g.attr("title")).style("left",window.scrollX+m.left+(m.right-m.left)/2+"px").style("top",window.scrollY+m.bottom+"px"),r.html(h1.sanitize(l)),g.classed("hover",!0)}).on("mouseout",c=>{r.transition().duration(500).style("opacity",0),it(c.currentTarget).classed("hover",!1)})}clear(i="gen-2"){this.vertices=new Map,this.classes=new Map,this.edges=[],this.funs=[this.setupToolTips.bind(this)],this.diagramId="",this.subGraphs=[],this.subGraphLookup=new Map,this.subCount=0,this.tooltips=new Map,this.firstGraphFlag=!0,this.version=i,this.config=ke(),d1()}setGen(i){this.version=i||"gen-2"}defaultStyle(){return"fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;"}addSubGraph(i,r,a){let n=i.text.trim(),c=a.text;i===a&&/\s/.exec(a.text)&&(n=void 0);const l=k(L=>{const A={boolean:{},number:{},string:{}},u=[];let h;return{nodeList:L.filter(function(B){const J=typeof B;return B.stmt&&B.stmt==="dir"?(h=B.value,!1):B.trim()===""?!1:J in A?A[J].hasOwnProperty(B)?!1:A[J][B]=!0:u.includes(B)?!1:u.push(B)}),dir:h}},"uniq")(r.flat()),m=l.nodeList;let p=l.dir;const F=ke().flowchart??{};if(p=p??(F.inheritDir?this.getDirection()??ke().direction??void 0:void 0),this.version==="gen-1")for(let L=0;L<m.length;L++)m[L]=this.lookUpDomId(m[L]);n=n??"subGraph"+this.subCount,c=c||"",c=this.sanitizeText(c),this.subCount=this.subCount+1;const _={id:n,nodes:m,title:c.trim(),classes:[],dir:p,labelType:this.sanitizeNodeLabelType(a?.type)};return $.info("Adding",_.id,_.nodes,_.dir),_.nodes=this.makeUniq(_,this.subGraphs).nodes,this.subGraphs.push(_),this.subGraphLookup.set(n,_),n}getPosForId(i){for(const[r,a]of this.subGraphs.entries())if(a.id===i)return r;return-1}indexNodes2(i,r){const a=this.subGraphs[r].nodes;if(this.secCount=this.secCount+1,this.secCount>2e3)return{result:!1,count:0}; Line truncated
`+z.showPosition()+`
Expecting `+Xe.join(", ")+", got '"+(this.terminals_[Y]||Y)+"'":tt="Parse error on line "+(I+1)+": Unexpected "+(Y==Gt?"end of input":"'"+(this.terminals_[Y]||Y)+"'"),this.parseError(tt,{text:z.match,token:this.terminals_[Y]||Y,line:z.yylineno,loc:$e,expected:Xe})}if(Z[0]instanceof Array&&Z.length>1)throw new Error("Parse Error: multiple actions possible at state: "+De+", token: "+Y);switch(Z[0]){case 1:b.push(Y),x.push(z.yytext),e.push(z.yylloc),b.push(Z[1]),Y=null,Nt=z.yyleng,t=z.yytext,I=z.yylineno,$e=z.yylloc;break;case 2:if(de=this.productions_[Z[1]][1],Ge.$=x[x.length-de],Ge._$={first_line:e[e.length-(de||1)].first_line,last_line:e[e.length-1].last_line,first_column:e[e.length-(de||1)].first_column,last_column:e[e.length-1].last_column},Yt&&(Ge._$.range=[e[e.length-(de||1)].range[0],e[e.length-1].range[1]]),et=this.performAction.apply(Ge,[t,Nt,I,Ce.yy,Z[1],x,e].concat(Ht)),typeof et<"u")return et;de&&(b=b.slice(0,-1*de*2),x=x.slice(0,-1*de),e=e.slice(0,-1*de)),b.push(this.productions_[Z[1]][0]),x.push(Ge.$),e.push(Ge._$),Ot=Oe[b[b.length-2]][b[b.length-1]],b.push(Ot);break;case 3:return!0}}return!0},"parse")},jt=(function(){var Ae={EOF:1,parseError:k(function(f,b){if(this.yy.parser)this.yy.parser.parseError(f,b);else throw new Error(f)},"parseError"),setInput:k(function(d,f){return this.yy=f||this.yy||{},this._input=d,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:k(function(){var d=this._input[0];this.yytext+=d,this.yyleng++,this.offset++,this.match+=d,this.matched+=d;var f=d.match(/(?:\r\n?|\n).*/g);return f?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),d},"input"),unput:k(function(d){var f=d.length,b=d.split(/(?:\r\n?|\n)/g);this._input=d+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-f),this.offset-=f;var o=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),b.length-1&&(this.yylineno-=b.length-1);var x=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:b?(b.length===o.length?this.yylloc.first_column:0)+o[o.length-b.length].length-b[0].length:this.yylloc.first_column-f},this.options.ranges&&(this.yylloc.range=[x[0],x[0]+this.yyleng-f]),this.yyleng=this.yytext.length,this},"unput"),more:k(function(){return this._more=!0,this},"more"),reject:k(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:k(function(d){this.unput(this.match.slice(d))},"less"),pastInput:k(function(){var d=this.matched.substr(0,this.matched.length-this.match.length);return(d.length>20?"...":"")+d.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:k(function(){var d=this.match;return d.length<20&&(d+=this._input.substr(0,20-d.length)),(d.substr(0,20)+(d.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:k(function(){var d=this.pastInput(),f=new Array(d.length+1).join("-");return d+this.upcomingInput()+`
`+f+"^"},"showPosition"),test_match:k(function(d,f){var b,o,x;if(this.options.backtrack_lexer&&(x={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(x.yylloc.range=this.yylloc.range.slice(0))),o=d[0].match(/(?:\r\n?|\n).*/g),o&&(this.yylineno+=o.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:o?o[o.length-1].length-o[o.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+d[0].length},this.yytext+=d[0],this.match+=d[0],this.matches=d,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(d[0].length),this.matched+=d[0],b=this.performAction.call(this,this.yy,this,f,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),b)return b;if(this._backtrack){for(var e in x)this[e]=x[e];return!1}return!1},"test_match"),next:k(function(){if(this.done)return this.EOF;this._input||(this.done=!0);var d,f,b,o;this._more||(this.yytext="",this.match="");for(var x=this._currentRules(),e=0;e<x.length;e++)if(b=this._input.match(this.rules[x[e]]),b&&(!f||b[0].length>f[0].length)){if(f=b,o=e,this.options.backtrack_lexer){if(d=this.test_match(b,x[e]),d!==!1)return d;if(this._backtrack){f=!1;continue}else return!1}else if(!this.options.flex)break}return f?(d=this.test_match(f,x[o]),d!==!1?d:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text.
`+this.showPosition(),{text:"",token:null,line:this.yylineno})},"next"),lex:k(function(){var f=this.next();return f||this.lex()},"lex"),begin:k(function(f){this.conditionStack.push(f)},"begin"),popState:k(function(){var f=this.conditionStack.length-1;return f>0?this.conditionStack.pop():this.conditionStack[0]},"popState"),_currentRules:k(function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},"_currentRules"),topState:k(function(f){return f=this.conditionStack.length-1-Math.abs(f||0),f>=0?this.conditionStack[f]:"INITIAL"},"topState"),pushState:k(function(f){this.begin(f)},"pushState"),stateStackSize:k(function(){return this.conditionStack.length},"stateStackSize"),options:{},performAction:k(function(f,b,o,x){switch(o){case 0:return this.begin("acc_title"),34;case 1:return this.popState(),"acc_title_value";case 2:return this.begin("acc_descr"),36;case 3:return this.popState(),"acc_descr_value";case 4:this.begin("acc_descr_multiline");break;case 5:this.popState();break;case 6:return"acc_descr_multiline_value";case 7:return this.pushState("shapeData"),b.yytext="",40;case 8:return this.pushState("shapeDataStr"),40;case 9:return this.popState(),40;case 10:const e=/\n\s*/g;return b.yytext=b.yytext.replace(e,"<br/>"),40;case 11:return 40;case 12:this.popState();break;case 13:this.begin("callbackname");break;case 14:this.popState();break;case 15:this.popState(),this.begin("callbackargs");break;case 16:return 95;case 17:this.popState();break;case 18:return 96;case 19:return"MD_STR";case 20:this.popState();break;case 21:this.begin("md_string");break;case 22:return"STR";case 23:this.popState();break;case 24:this.pushState("string");break;case 25:return 84;case 26:return 102;case 27:return 85;case 28:return 104;case 29:return 86;case 30:return 87;case 31:return 97;case 32:this.begin("click");break;case 33:this.popState();break;case 34:return 88;case 35:return f.lex.firstGraph()&&this.begin("dir"),12;case 36:return f.lex.firstGraph()&&this.begin("dir"),12;case 37:return f.lex.firstGraph()&&this.begin("dir"),12;case 38:return f.lex.firstGraph()&&this.begin("dir"),12;case 39:return 27;case 40:return 32;case 41:return 98;case 42:return 98;case 43:return 98;case 44:return 98;case 45:return this.popState(),13;case 46:return this.popState(),14;case 47:return this.popState(),14;case 48:return this.popState(),14;case 49:return this.popState(),14;case 50:return this.popState(),14;case 51:return this.popState(),14;case 52:return this.popState(),14;case 53:return this.popState(),14;case 54:return this.popState(),14;case 55:return this.popState(),14;case 56:return 121;case 57:return 122;case 58:return 123;case 59:return 124;case 60:return 125;case 61:return 78;case 62:return 105;case 63:return 111;case 64:return 46;case 65:return 60;case 66:return 44;case 67:return 8;case 68:return 106;case 69:return 115;case 70:return this.popState(),77;case 71:return this.pushState("edgeText"),75;case 72:return 119;case 73:return this.popState(),77;case 74:return this.pushState("thickEdgeText"),75;case 75:return 119;case 76:return this.popState(),77;case 77:return this.pushState("dottedEdgeText"),75;case 78:return 119;case 79:return 77;case 80:return this.popState(),53;case 81:return"TEXT";case 82:return this.pushState("ellipseText"),52;case 83:return this.popState(),55;case 84:return this.pushState("text"),54;case 85:return this.popState(),57;case 86:return this.pushState("text"),56;case 87:return 58;case 88:return this.pushState("text"),67;case 89:return this.popState(),64;case 90:return this.pushState("text"),63;case 91:return this.popState(),49;case 92:return this.pushState("text"),48;case 93:return this.popState(),69;case 94:return this.popState(),71;case 95:return 117;case 96:return this.pushState("trapText"),68;case 97:return this.pushState("trapText"),70;case 98:return 118;case 99:return 67;case 100:return 90;case 101:return"SEP";case 102:return 89;case 103:return 115;case 104:return 111;case 105:return 44;case 106:return 109;case 107:return 114;case 108:return 116;case 109:return this.popState(),62;case 110:return this.pushState("text"),62;case 111:return this.popState(),51;case 112:return this.pushState("text"),50;case 113:return this.popState(),31;case 114:return this.pushState("text"),29;case 115:return this.popState(),66;case 116:return this.pushState("text"),65;case 117:return"TEXT";case 118:return"QUOTE";case 119:return 9;case 120:return 10;case 121:return 11}},"anonymous"),rules:[/^(?:accTitle\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*\{\s*)/,/^(?:[\}])/,/^(?:[^\}]*)/,/^(?:@\{)/,/^(?:["])/,/^(?:["])/,/^(?:[^\"]+)/,/^(?:[^}^"]+)/,/^(?:\})/,/^(?:call[\s]+)/,/^(?:\([\s]*\))/,/^(?:\()/,/^(?:[^(]*)/,/^(?:\))/,/^(?:[^)]*)/,/^(?:[^`"]+)/,/^(?:[`]["])/,/^(?:["][`])/,/^(?:[^"]+)/,/^(?:["])/,/^(?:["])/,/^(?:style\b)/,/^(?:default\b)/,/^(?:linkStylLine truncated
`);return Ut.parse(i)};var T1=zt,S1=k((s,i)=>{const r=b1,a=r(s,"r"),n=r(s,"g"),c=r(s,"b");return f1(a,n,c,i)},"fade"),E1=k(s=>`.label {
font-family: ${s.fontFamily};
color: ${s.nodeTextColor||s.textColor};
}
.cluster-label text {
fill: ${s.titleColor};
}
.cluster-label span {
color: ${s.titleColor};
}
.cluster-label span p {
background-color: transparent;
}
.label text,span {
fill: ${s.nodeTextColor||s.textColor};
color: ${s.nodeTextColor||s.textColor};
}
.node rect,
.node circle,
.node ellipse,
.node polygon,
.node path {
fill: ${s.mainBkg};
stroke: ${s.nodeBorder};
stroke-width: ${s.strokeWidth??1}px;
}
.rough-node .label text , .node .label text, .image-shape .label, .icon-shape .label {
text-anchor: middle;
}
.node .katex path {
fill: #000;
stroke: #000;
stroke-width: 1px;
}
.rough-node .label,.node .label, .image-shape .label, .icon-shape .label {
text-align: center;
}
.node.clickable {
cursor: pointer;
}
.root .anchor path {
fill: ${s.lineColor} !important;
stroke-width: 0;
stroke: ${s.lineColor};
}
.arrowheadPath {
fill: ${s.arrowheadColor};
}
.edgePaths .path {
stroke: ${s.lineColor};
stroke-width: ${s.strokeWidth??2}px;
}
.flowchart-link {
stroke: ${s.lineColor};
fill: none;
}
.edgeLabel {
background-color: ${s.edgeLabelBackground};
p {
background-color: ${s.edgeLabelBackground};
}
rect {
opacity: 0.5;
background-color: ${s.edgeLabelBackground};
fill: ${s.edgeLabelBackground};
}
text-align: center;
}
/* For html labels only */
.labelBkg {
background-color: ${S1(s.edgeLabelBackground,.5)};
// background-color:
}
.cluster rect {
fill: ${s.clusterBkg};
stroke: ${s.clusterBorder};
stroke-width: 1px;
}
.cluster text {
fill: ${s.titleColor};
}
.cluster span {
color: ${s.titleColor};
}
/* .cluster div {
color: ${s.titleColor};
} */
/* Collapsed subgraph node (@{ view: collapsed }) */
.node .collapsed-indicator {
fill: ${s.clusterBorder};
stroke: none;
opacity: 0.6;
}
.node .collapsed-separator {
stroke: ${s.clusterBorder};
stroke-width: 0.75px;
}
div.mermaidTooltip {
position: absolute;
text-align: center;
max-width: 200px;
padding: 2px;
font-family: ${s.fontFamily};
font-size: 12px;
background: ${s.tertiaryColor};
border: 1px solid ${s.border2};
border-radius: 2px;
pointer-events: none;
z-index: 100;
}
.flowchartTitleText {
text-anchor: middle;
font-size: 18px;
fill: ${s.textColor};
}
rect.text {
fill: none;
stroke-width: 0;
}
.icon-shape, .image-shape {
background-color: ${s.edgeLabelBackground};
p {
background-color: ${s.edgeLabelBackground};
padding: 2px;
}
.label rect {
opacity: 0.5;
background-color: ${s.edgeLabelBackground};
fill: ${s.edgeLabelBackground};
}
text-align: center;
}
${Xt()}
`,"getStyles"),y1=E1,Wt=k(({defaultLayout:s,styles:i=y1}={})=>({parser:T1,get db(){return new k1},renderer:D1,styles:i,init:k(r=>{r.flowchart||(r.flowchart={});const a=Zt().layout??s??r.layout;a&&Mt({layout:a}),r.flowchart.arrowMarkerAbsolute=r.arrowMarkerAbsolute,Mt({flowchart:{arrowMarkerAbsolute:r.arrowMarkerAbsolute}})},"init")}),"createFlowDiagram"),x1=Wt();const I1=Object.freeze(Object.defineProperty({__proto__:null,createFlowDiagram:Wt,diagram:x1},Symbol.toStringTag,{value:"Module"}));export{Wt as c,I1 as f,y1 as s};
+292
View File
@@ -0,0 +1,292 @@
import{bf as on,bg as On,bh as cn,bi as un,bj as ln,bk as ue,bl as Hn,g as Nn,s as Pn,o as Vn,n as Rn,a as zn,b as qn,_ as d,c as Yt,j as Zt,d as Bn,bm as it,l as Tt,k as Zn,G as Xn,p as Gn,x as jn}from"./mermaid.core.js";import{g as oe}from"./index.js";import{b as Qn,t as Ne,c as Jn,a as Kn,l as tr}from"./linear.js";import{i as er}from"./init.js";import"./defaultLocale.js";function nr(t,e){let n;if(e===void 0)for(const r of t)r!=null&&(n<r||n===void 0&&r>=r)&&(n=r);else{let r=-1;for(let i of t)(i=e(i,++r,t))!=null&&(n<i||n===void 0&&i>=i)&&(n=i)}return n}function rr(t,e){let n;if(e===void 0)for(const r of t)r!=null&&(n>r||n===void 0&&r>=r)&&(n=r);else{let r=-1;for(let i of t)(i=e(i,++r,t))!=null&&(n>i||n===void 0&&i>=i)&&(n=i)}return n}function ir(t){return t}var Gt=1,le=2,xe=3,Xt=4,Pe=1e-6;function sr(t){return"translate("+t+",0)"}function ar(t){return"translate(0,"+t+")"}function or(t){return e=>+t(e)}function cr(t,e){return e=Math.max(0,t.bandwidth()-e*2)/2,t.round()&&(e=Math.round(e)),n=>+t(n)+e}function ur(){return!this.__axis}function fn(t,e){var n=[],r=null,i=null,s=6,a=6,y=3,F=typeof window<"u"&&window.devicePixelRatio>1?0:.5,S=t===Gt||t===Xt?-1:1,w=t===Xt||t===le?"x":"y",P=t===Gt||t===xe?sr:ar;function _(Y){var X=r??(e.ticks?e.ticks.apply(e,n):e.domain()),B=i??(e.tickFormat?e.tickFormat.apply(e,n):ir),v=Math.max(s,0)+y,U=e.range(),R=+U[0]+F,E=+U[U.length-1]+F,z=(e.bandwidth?cr:or)(e.copy(),F),G=Y.selection?Y.selection():Y,T=G.selectAll(".domain").data([null]),k=G.selectAll(".tick").data(X,e).order(),p=k.exit(),L=k.enter().append("g").attr("class","tick"),x=k.select("line"),C=k.select("text");T=T.merge(T.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),k=k.merge(L),x=x.merge(L.append("line").attr("stroke","currentColor").attr(w+"2",S*s)),C=C.merge(L.append("text").attr("fill","currentColor").attr(w,S*v).attr("dy",t===Gt?"0em":t===xe?"0.71em":"0.32em")),Y!==G&&(T=T.transition(Y),k=k.transition(Y),x=x.transition(Y),C=C.transition(Y),p=p.transition(Y).attr("opacity",Pe).attr("transform",function(M){return isFinite(M=z(M))?P(M+F):this.getAttribute("transform")}),L.attr("opacity",Pe).attr("transform",function(M){var D=this.parentNode.__axis;return P((D&&isFinite(D=D(M))?D:z(M))+F)})),p.remove(),T.attr("d",t===Xt||t===le?a?"M"+S*a+","+R+"H"+F+"V"+E+"H"+S*a:"M"+F+","+R+"V"+E:a?"M"+R+","+S*a+"V"+F+"H"+E+"V"+S*a:"M"+R+","+F+"H"+E),k.attr("opacity",1).attr("transform",function(M){return P(z(M)+F)}),x.attr(w+"2",S*s),C.attr(w,S*v).text(B),G.filter(ur).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===le?"start":t===Xt?"end":"middle"),G.each(function(){this.__axis=z})}return _.scale=function(Y){return arguments.length?(e=Y,_):e},_.ticks=function(){return n=Array.from(arguments),_},_.tickArguments=function(Y){return arguments.length?(n=Y==null?[]:Array.from(Y),_):n.slice()},_.tickValues=function(Y){return arguments.length?(r=Y==null?null:Array.from(Y),_):r&&r.slice()},_.tickFormat=function(Y){return arguments.length?(i=Y,_):i},_.tickSize=function(Y){return arguments.length?(s=a=+Y,_):s},_.tickSizeInner=function(Y){return arguments.length?(s=+Y,_):s},_.tickSizeOuter=function(Y){return arguments.length?(a=+Y,_):a},_.tickPadding=function(Y){return arguments.length?(y=+Y,_):y},_.offset=function(Y){return arguments.length?(F=+Y,_):F},_}function lr(t){return fn(Gt,t)}function fr(t){return fn(xe,t)}const dr=Math.PI/180,hr=180/Math.PI,ne=18,dn=.96422,hn=1,mn=.82521,gn=4/29,Ft=6/29,yn=3*Ft*Ft,mr=Ft*Ft*Ft;function kn(t){if(t instanceof ft)return new ft(t.l,t.a,t.b,t.opacity);if(t instanceof ht)return pn(t);t instanceof on||(t=On(t));var e=me(t.r),n=me(t.g),r=me(t.b),i=fe((.2225045*e+.7168786*n+.0606169*r)/hn),s,a;return e===n&&n===r?s=a=i:(s=fe((.4360747*e+.3850649*n+.1430804*r)/dn),a=fe((.0139322*e+.0971045*n+.7141733*r)/mn)),new ft(116*i-16,500*(s-i),200*(i-a),t.opacity)}function gr(t,e,n,r){return arguments.length===1?kn(t):new ft(t,e,n,r??1)}function ft(t,e,n,r){this.l=+t,this.a=+e,this.b=+n,this.opacity=+r}cn(ft,gr,un(ln,{brighter(t){return new ft(this.l+ne*(t??1),this.a,this.b,this.opacity)},darker(t){return new ft(this.l-ne*(t??1),this.a,this.b,this.opacity)},rgb(){var t=(this.l+16)/116,e=isNaN(this.a)?t:t+this.a/500,n=isNaN(this.b)?t:t-this.b/200;return e=dn*de(e),t=hn*de(t),n=mn*de(n),new on(he(3.1338561*e-1.6168667*t-.4906146*n),he(-.9787684*e+1.9161415*t+.033454*n),he(.0719453*e-.2289914*t+1.4052427*n),this.opacity)}}));function fe(t){return t>mr?Math.pow(t,1/3):t/yn+gn}function de(t){return t>Ft?t*t*t:yn*(t-gn)}function he(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function me(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function yr(t){if(t instanceof ht)return new ht(t.h,t.c,t.l,t.opacity);if(t instanceof ft||(t=kn(t)),t.a===0&&t.b===0)return new ht(NaN,0<t.l&&t.l<100?0:NaN,t.l,t.opacity);var e=Math.atan2(t.b,t.a)*hr;return new ht(e<0?e+360:e,Math.sqrt(t.a*t.a+t.b*t.b),t.l,t.opacity)}fuLine truncated
`+H.showPosition()+`
Expecting `+Bt.join(", ")+", got '"+(this.terminals_[A]||A)+"'":ce="Parse error on line "+(K+1)+": Unexpected "+(A==O?"end of input":"'"+(this.terminals_[A]||A)+"'"),this.parseError(ce,{text:H.match,token:this.terminals_[A]||A,line:H.yylineno,loc:N,expected:Bt})}if(Z[0]instanceof Array&&Z.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Q+", token: "+A);switch(Z[0]){case 1:b.push(A),I.push(H.yytext),o.push(H.yylloc),b.push(Z[1]),A=null,l=H.yyleng,u=H.yytext,K=H.yylineno,N=H.yylloc;break;case 2:if(ut=this.productions_[Z[1]][1],at.$=I[I.length-ut],at._$={first_line:o[o.length-(ut||1)].first_line,last_line:o[o.length-1].last_line,first_column:o[o.length-(ut||1)].first_column,last_column:o[o.length-1].last_column},V&&(at._$.range=[o[o.length-(ut||1)].range[0],o[o.length-1].range[1]]),st=this.performAction.apply(at,[u,l,K,J.yy,Z[1],I,o].concat(j)),typeof st<"u")return st;ut&&(b=b.slice(0,-1*ut*2),I=I.slice(0,-1*ut),o=o.slice(0,-1*ut)),b.push(this.productions_[Z[1]][0]),I.push(at.$),o.push(at._$),He=W[b[b.length-2]][b[b.length-1]],b.push(He);break;case 3:return!0}}return!0},"parse")},C=(function(){var D={EOF:1,parseError:d(function(g,b){if(this.yy.parser)this.yy.parser.parseError(g,b);else throw new Error(g)},"parseError"),setInput:d(function(c,g){return this.yy=g||this.yy||{},this._input=c,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},"setInput"),input:d(function(){var c=this._input[0];this.yytext+=c,this.yyleng++,this.offset++,this.match+=c,this.matched+=c;var g=c.match(/(?:\r\n?|\n).*/g);return g?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),c},"input"),unput:d(function(c){var g=c.length,b=c.split(/(?:\r\n?|\n)/g);this._input=c+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-g),this.offset-=g;var m=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),b.length-1&&(this.yylineno-=b.length-1);var I=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:b?(b.length===m.length?this.yylloc.first_column:0)+m[m.length-b.length].length-b[0].length:this.yylloc.first_column-g},this.options.ranges&&(this.yylloc.range=[I[0],I[0]+this.yyleng-g]),this.yyleng=this.yytext.length,this},"unput"),more:d(function(){return this._more=!0,this},"more"),reject:d(function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).
`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},"reject"),less:d(function(c){this.unput(this.match.slice(c))},"less"),pastInput:d(function(){var c=this.matched.substr(0,this.matched.length-this.match.length);return(c.length>20?"...":"")+c.substr(-20).replace(/\n/g,"")},"pastInput"),upcomingInput:d(function(){var c=this.match;return c.length<20&&(c+=this._input.substr(0,20-c.length)),(c.substr(0,20)+(c.length>20?"...":"")).replace(/\n/g,"")},"upcomingInput"),showPosition:d(function(){var c=this.pastInput(),g=new Array(c.length+1).join("-");return c+this.upcomingInput()+`
`+g+"^"},"showPosition"),test_match:d(function(c,g){var b,m,I;if(this.options.backtrack_lexer&&(I={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(I.yylloc.range=this.yylloc.range.slice(0))),m=c[0].match(/(?:\r\n?|\n).*/g),m&&(this.yylineno+=m.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:m?m[m.length-1].length-m[m.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+c[0].length},this.yytext+=c[0],this.match+=c[0],this.matches=c,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(c[0].length),this.matched+=c[0],b=this.performAction.call(this,this.yy,this,g,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),b)return b;if(this._backtrack){for(var o in I)this[o]=I[o];return!1}return!1},"test_match"),next:d(function(){if(this.done)return this.EOF;this._input||(this.done=!0);var c,g,b,m;this._more||(this.yytext="",this.match="");for(var I=this._currentRules(),o=0;o<I.length;o++)if(b=this._input.match(this.rules[I[o]]),b&&(!g||b[0].length>g[0].length)){if(g=b,m=o,this.options.backtrack_lexer){if(c=this.test_match(b,I[o]),c!==!1)return c;if(this._backtrack){g=!1;continue}else return!1}else if(!this.options.flex)break}return g?(c=this.test_match(g,I[m]),c!==!1?c:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text.
`+this.showPosition(),{text:"",token:null,line:this.yylineno})},"next"),lex:d(function(){var g=this.next();return g||this.lex()},"lex"),begin:d(function(g){this.conditionStack.push(g)},"begin"),popState:d(function(){var g=this.conditionStack.length-1;return g>0?this.conditionStack.pop():this.conditionStack[0]},"popState"),_currentRules:d(function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},"_currentRules"),topState:d(function(g){return g=this.conditionStack.length-1-Math.abs(g||0),g>=0?this.conditionStack[g]:"INITIAL"},"topState"),pushState:d(function(g){this.begin(g)},"pushState"),stateStackSize:d(function(){return this.conditionStack.length},"stateStackSize"),options:{"case-insensitive":!0},performAction:d(function(g,b,m,I){switch(m){case 0:return this.begin("open_directive"),"open_directive";case 1:return this.begin("acc_title"),31;case 2:return this.popState(),"acc_title_value";case 3:return this.begin("acc_descr"),33;case 4:return this.popState(),"acc_descr_value";case 5:this.begin("acc_descr_multiline");break;case 6:this.popState();break;case 7:return"acc_descr_multiline_value";case 8:break;case 9:break;case 10:break;case 11:return 10;case 12:break;case 13:break;case 14:this.begin("href");break;case 15:this.popState();break;case 16:return 43;case 17:this.begin("callbackname");break;case 18:this.popState();break;case 19:this.popState(),this.begin("callbackargs");break;case 20:return 41;case 21:this.popState();break;case 22:return 42;case 23:this.begin("click");break;case 24:this.popState();break;case 25:return 40;case 26:return 4;case 27:return 22;case 28:return 23;case 29:return 24;case 30:return 25;case 31:return 26;case 32:return 28;case 33:return 27;case 34:return 29;case 35:return 12;case 36:return 13;case 37:return 14;case 38:return 15;case 39:return 16;case 40:return 17;case 41:return 18;case 42:return 20;case 43:return 21;case 44:return"date";case 45:return 30;case 46:return"accDescription";case 47:return 36;case 48:return 38;case 49:return 39;case 50:return":";case 51:return 6;case 52:return"INVALID"}},"anonymous"),rules:[/^(?:%%\{)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:%%(?!\{)*[^\n]*)/i,/^(?:[^\}]%%*[^\n]*)/i,/^(?:%%*[^\n]*[\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:%[^\n]*)/i,/^(?:href[\s]+["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:call[\s]+)/i,/^(?:\([\s]*\))/i,/^(?:\()/i,/^(?:[^(]*)/i,/^(?:\))/i,/^(?:[^)]*)/i,/^(?:click[\s]+)/i,/^(?:[\s\n])/i,/^(?:[^\s\n]*)/i,/^(?:gantt\b)/i,/^(?:dateFormat\s[^#\n;]+)/i,/^(?:inclusiveEndDates\b)/i,/^(?:topAxis\b)/i,/^(?:axisFormat\s[^#\n;]+)/i,/^(?:tickInterval\s[^#\n;]+)/i,/^(?:includes\s[^#\n;]+)/i,/^(?:excludes\s[^#\n;]+)/i,/^(?:todayMarker\s[^\n;]+)/i,/^(?:weekday\s+monday\b)/i,/^(?:weekday\s+tuesday\b)/i,/^(?:weekday\s+wednesday\b)/i,/^(?:weekday\s+thursday\b)/i,/^(?:weekday\s+friday\b)/i,/^(?:weekday\s+saturday\b)/i,/^(?:weekday\s+sunday\b)/i,/^(?:weekend\s+friday\b)/i,/^(?:weekend\s+saturday\b)/i,/^(?:\d\d\d\d-\d\d-\d\d\b)/i,/^(?:title\s[^\n]+)/i,/^(?:accDescription\s[^#\n;]+)/i,/^(?:section\s[^\n]+)/i,/^(?:[^:\n]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{acc_descr_multiline:{rules:[6,7],inclusive:!1},acc_descr:{rules:[4],inclusive:!1},acc_title:{rules:[2],inclusive:!1},callbackargs:{rules:[21,22],inclusive:!1},callbackname:{rules:[18,19,20],inclusive:!1},href:{rules:[15,16],inclusive:!1},click:{rules:[24,25],inclusive:!1},INITIAL:{rules:[0,1,3,5,8,9,10,11,12,13,14,17,23,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52],inclusive:!0}}};return D})();x.lexer=C;function M(){this.yy={}}return d(M,"Parser"),M.prototype=x,x.Parser=M,new M})();we.parser=we;var Qi=we;it.extend(Oi);it.extend(Vi);it.extend(Bi);var rn={friday:5,saturday:6},lt="",Ye="",Fe=void 0,Ue="",Lt=[],At=[],Ee=new Map,Ie=[],se=[],Wt="",Le="",Yn=["active","done","crit","milestone","vert"],Ae=[],_t="",qt=!1,We=!1,$e="sunday",ae="saturday",De=0,Ji=d(function(){Ie=[],se=[],Wt="",Ae=[],te=0,Ce=void 0,ee=void 0,et=[],lt="",Ye="",Le="",Fe=void 0,Ue="",Lt=[],At=[],qt=!1,We=!1,De=0,Ee=new Map,_t="",Gn(),$e="sunday",ae="saturday"},"clear"),Ki=d(function(t){_t=t},"setDiagramId"),ts=d(function(t){Ye=t},"setAxisFormat"),es=d(function(){return Ye},"getAxisFormat"),ns=d(function(t){Fe=t},"setTickInterval"),rs=d(function(){return Fe},"getTickInterval"),is=d(function(t){Ue=t},"setTodayMarker"),ss=d(function(){return Ue},"getTodayMarker"),as=d(function(t){lt=t},"setDateFormat"),os=d(function(){qt=!0},"enableInclusiveEndDates"),cs=d(function(){return qt},"endDatesAreInclusive"),us=d(function(){We=!0},"enableTopAxis"),ls=d(function(){return We},"topAxisEnabled"),fs=d(function(t){Le=t},"setDisplayMode"),ds=d(function(){return Le},"getDisplayMode"),hs=d(function(){return lt},"getDateFormat"),Fn=d((t,e)= Line truncated
.mermaid-main-font {
font-family: ${t.fontFamily};
}
.exclude-range {
fill: ${t.excludeBkgColor};
}
.section {
stroke: none;
opacity: 0.2;
}
.section0 {
fill: ${t.sectionBkgColor};
}
.section2 {
fill: ${t.sectionBkgColor2};
}
.section1,
.section3 {
fill: ${t.altSectionBkgColor};
opacity: 0.2;
}
.sectionTitle0 {
fill: ${t.titleColor};
}
.sectionTitle1 {
fill: ${t.titleColor};
}
.sectionTitle2 {
fill: ${t.titleColor};
}
.sectionTitle3 {
fill: ${t.titleColor};
}
.sectionTitle {
text-anchor: start;
font-family: ${t.fontFamily};
}
/* Grid and axis */
.grid .tick {
stroke: ${t.gridColor};
opacity: 0.8;
shape-rendering: crispEdges;
}
.grid .tick text {
font-family: ${t.fontFamily};
fill: ${t.textColor};
}
.grid path {
stroke-width: 0;
}
/* Today line */
.today {
fill: none;
stroke: ${t.todayLineColor};
stroke-width: 2px;
}
/* Task styling */
/* Default task */
.task {
stroke-width: 2;
}
.taskText {
text-anchor: middle;
font-family: ${t.fontFamily};
}
.taskTextOutsideRight {
fill: ${t.taskTextDarkColor};
text-anchor: start;
font-family: ${t.fontFamily};
}
.taskTextOutsideLeft {
fill: ${t.taskTextDarkColor};
text-anchor: end;
}
/* Special case clickable */
.task.clickable {
cursor: pointer;
}
.taskText.clickable {
cursor: pointer;
fill: ${t.taskTextClickableColor} !important;
font-weight: bold;
}
.taskTextOutsideLeft.clickable {
cursor: pointer;
fill: ${t.taskTextClickableColor} !important;
font-weight: bold;
}
.taskTextOutsideRight.clickable {
cursor: pointer;
fill: ${t.taskTextClickableColor} !important;
font-weight: bold;
}
/* Specific task settings for the sections*/
.taskText0,
.taskText1,
.taskText2,
.taskText3 {
fill: ${t.taskTextColor};
}
.task0,
.task1,
.task2,
.task3 {
fill: ${t.taskBkgColor};
stroke: ${t.taskBorderColor};
}
.taskTextOutside0,
.taskTextOutside2
{
fill: ${t.taskTextOutsideColor};
}
.taskTextOutside1,
.taskTextOutside3 {
fill: ${t.taskTextOutsideColor};
}
/* Active task */
.active0,
.active1,
.active2,
.active3 {
fill: ${t.activeTaskBkgColor};
stroke: ${t.activeTaskBorderColor};
}
.activeText0,
.activeText1,
.activeText2,
.activeText3 {
fill: ${t.taskTextDarkColor} !important;
}
/* Completed task */
.done0,
.done1,
.done2,
.done3 {
stroke: ${t.doneTaskBorderColor};
fill: ${t.doneTaskBkgColor};
stroke-width: 2;
}
.doneText0,
.doneText1,
.doneText2,
.doneText3 {
fill: ${t.taskTextDarkColor} !important;
}
/* Done task text displayed outside the bar sits against the diagram background,
not against the done-task bar, so it must use the outside/contrast color. */
.doneText0.taskTextOutsideLeft,
.doneText0.taskTextOutsideRight,
.doneText1.taskTextOutsideLeft,
.doneText1.taskTextOutsideRight,
.doneText2.taskTextOutsideLeft,
.doneText2.taskTextOutsideRight,
.doneText3.taskTextOutsideLeft,
.doneText3.taskTextOutsideRight {
fill: ${t.taskTextOutsideColor} !important;
}
/* Tasks on the critical line */
.crit0,
.crit1,
.crit2,
.crit3 {
stroke: ${t.critBorderColor};
fill: ${t.critBkgColor};
stroke-width: 2;
}
.activeCrit0,
.activeCrit1,
.activeCrit2,
.activeCrit3 {
stroke: ${t.critBorderColor};
fill: ${t.activeTaskBkgColor};
stroke-width: 2;
}
.doneCrit0,
.doneCrit1,
.doneCrit2,
.doneCrit3 {
stroke: ${t.critBorderColor};
fill: ${t.doneTaskBkgColor};
stroke-width: 2;
cursor: pointer;
shape-rendering: crispEdges;
}
.milestone {
transform: rotate(45deg) scale(0.8,0.8);
}
.milestoneText {
font-style: italic;
}
.doneCritText0,
.doneCritText1,
.doneCritText2,
.doneCritText3 {
fill: ${t.taskTextDarkColor} !important;
}
/* Done-crit task text outside the bar — same reasoning as doneText above. */
.doneCritText0.taskTextOutsideLeft,
.doneCritText0.taskTextOutsideRight,
.doneCritText1.taskTextOutsideLeft,
.doneCritText1.taskTextOutsideRight,
.doneCritText2.taskTextOutsideLeft,
.doneCritText2.taskTextOutsideRight,
.doneCritText3.taskTextOutsideLeft,
.doneCritText3.taskTextOutsideRight {
fill: ${t.taskTextOutsideColor} !important;
}
.vert {
stroke: ${t.vertLineColor};
}
.vertText {
font-size: 15px;
text-anchor: middle;
fill: ${t.vertLineColor} !important;
}
.activeCritText0,
.activeCritText1,
.activeCritText2,
.activeCritText3 {
fill: ${t.taskTextDarkColor} !important;
}
.titleText {
text-anchor: middle;
font-size: 18px;
fill: ${t.titleColor||t.textColor};
font-family: ${t.fontFamily};
}
`,"getStyles"),Ns=Hs,Bs={parser:Qi,db:Ls,renderer:Os,styles:Ns};export{Bs as diagram};
+106
View File
@@ -0,0 +1,106 @@
import{I as le}from"./chunk-2Q5K7J3B.js";import{p as he}from"./chunk-JWPE2WC7.js";import{o as $e,n as fe,s as ge,g as ue,a as ye,b as xe,_ as h,y as J,l as w,j as me,c as q,x as pe,z as be,p as we,k as B,A as ke,B as ve,C as Ce}from"./mermaid.core.js";import{p as Ee}from"./cynefin-OW5HDTMX.js";import"./index.js";var m={NORMAL:0,REVERSE:1,HIGHLIGHT:2,MERGE:3,CHERRY_PICK:4},Be=ve.gitGraph,S=h(()=>ke({...Be,...J().gitGraph}),"getConfig"),d=new le(()=>{const e=S(),r=e.mainBranchName,t=e.mainBranchOrder;return{mainBranchName:r,commits:new Map,head:null,branchConfig:new Map([[r,{name:r,order:t}]]),branches:new Map([[r,null]]),currBranch:r,direction:"LR",seq:0,options:{}}});function Y(){return Ce({length:7})}h(Y,"getID");function te(e,r){const t=Object.create(null);return e.reduce((s,o)=>{const i=r(o);return t[i]||(t[i]=!0,s.push(o)),s},[])}h(te,"uniqBy");var Te=h(function(e){d.records.direction=e},"setDirection"),Le=h(function(e){w.debug("options str",e),e=e?.trim(),e=e||"{}";try{d.records.options=JSON.parse(e)}catch(r){w.error("error while parsing gitGraph options",r.message)}},"setOptions"),Me=h(function(){return d.records.options},"getOptions"),Re=h(function(e){let r=e.msg,t=e.id;const s=e.type;let o=e.tags;w.info("commit",r,t,s,o),w.debug("Entering commit:",r,t,s,o);const i=S();t=B.sanitizeText(t,i),r=B.sanitizeText(r,i),o=o?.map(a=>B.sanitizeText(a,i));const n={id:t||d.records.seq+"-"+Y(),message:r,seq:d.records.seq++,type:s??m.NORMAL,tags:o??[],parents:d.records.head==null?[]:[d.records.head.id],branch:d.records.currBranch};d.records.head=n,w.info("main branch",i.mainBranchName),d.records.commits.has(n.id)&&w.warn(`Commit ID ${n.id} already exists`),d.records.commits.set(n.id,n),d.records.branches.set(d.records.currBranch,n.id),w.debug("in pushCommit "+n.id)},"commit"),Ie=h(function(e){let r=e.name;const t=e.order;if(r=B.sanitizeText(r,S()),d.records.branches.has(r))throw new Error(`Trying to create an existing branch. (Help: Either use a new name if you want create a new branch or try using "checkout ${r}")`);d.records.branches.set(r,d.records.head!=null?d.records.head.id:null),d.records.branchConfig.set(r,{name:r,order:t}),ae(r),w.debug("in createBranch")},"branch"),Oe=h(e=>{let r=e.branch,t=e.id;const s=e.type,o=e.tags,i=S();r=B.sanitizeText(r,i),t&&(t=B.sanitizeText(t,i));const n=d.records.branches.get(d.records.currBranch),a=d.records.branches.get(r),l=n?d.records.commits.get(n):void 0,f=a?d.records.commits.get(a):void 0;if(l&&f&&l.branch===r)throw new Error(`Cannot merge branch '${r}' into itself.`);if(d.records.currBranch===r){const c=new Error('Incorrect usage of "merge". Cannot merge a branch to itself');throw c.hash={text:`merge ${r}`,token:`merge ${r}`,expected:["branch abc"]},c}if(l===void 0||!l){const c=new Error(`Incorrect usage of "merge". Current branch (${d.records.currBranch})has no commits`);throw c.hash={text:`merge ${r}`,token:`merge ${r}`,expected:["commit"]},c}if(!d.records.branches.has(r)){const c=new Error('Incorrect usage of "merge". Branch to be merged ('+r+") does not exist");throw c.hash={text:`merge ${r}`,token:`merge ${r}`,expected:[`branch ${r}`]},c}if(f===void 0||!f){const c=new Error('Incorrect usage of "merge". Branch to be merged ('+r+") has no commits");throw c.hash={text:`merge ${r}`,token:`merge ${r}`,expected:['"commit"']},c}if(l===f){const c=new Error('Incorrect usage of "merge". Both branches have same head');throw c.hash={text:`merge ${r}`,token:`merge ${r}`,expected:["branch abc"]},c}if(t&&d.records.commits.has(t)){const c=new Error('Incorrect usage of "merge". Commit with id:'+t+" already exists, use different custom id");throw c.hash={text:`merge ${r} ${t} ${s} ${o?.join(" ")}`,token:`merge ${r} ${t} ${s} ${o?.join(" ")}`,expected:[`merge ${r} ${t}_UNIQUE ${s} ${o?.join(" ")}`]},c}const g=a||"",$={id:t||`${d.records.seq}-${Y()}`,message:`merged branch ${r} into ${d.records.currBranch}`,seq:d.records.seq++,parents:d.records.head==null?[]:[d.records.head.id,g],branch:d.records.currBranch,type:m.MERGE,customType:s,customId:!!t,tags:o??[]};d.records.head=$,d.records.commits.set($.id,$),d.records.branches.set(d.records.currBranch,$.id),w.debug(d.records.branches),w.debug("in mergeBranch")},"merge"),_e=h(function(e){let r=e.id,t=e.targetId,s=e.tags,o=e.parent;w.debug("Entering cherryPick:",r,t,s);const i=S();if(r=B.sanitizeText(r,i),t=B.sanitizeText(t,i),s=s?.map(l=>B.sanitizeText(l,i)),o=B.sanitizeText(o,i),!r||!d.records.commits.has(r)){const l=new Error('Incorrect usage of "cherryPick". Source commit id should exist and provided');throw l.hash={text:`cherryPick ${r} ${t}`,token:`cherryPick ${r} ${t}`,expected:["cherry-pick abc"]},l}const n=d.records.commits.get(r);if(n===void 0||!n)throw new Error('Incorrect usage of "cherryPick". Source commit id should exist and provided');if(o&&!(Array.isArray(n.parents)&&n.parents.includes(o)))throw new Error("Invalid operation: The specified parent commit is not an immediate parent of the cherry-picked commit.");const a=n.braLine truncated
${s-i/2-L/2},${x+R}
${s-i/2-L/2},${x-R}
${t.posWithOffset-i/2-L},${x-c-R}
${t.posWithOffset+i/2+L},${x-c-R}
${t.posWithOffset+i/2+L},${x+c+R}
${t.posWithOffset-i/2-L},${x+c+R}`),f.attr("cy",x).attr("cx",s-i/2+L/2).attr("r",1.5).attr("class","tag-hole"),y==="TB"||y==="BT"){const u=s+$;g.attr("class","tag-label-bkg").attr("points",`
${t.x},${u+2}
${t.x},${u-2}
${t.x+O},${u-c-2}
${t.x+O+i+4},${u-c-2}
${t.x+O+i+4},${u+c+2}
${t.x+O},${u+c+2}`).attr("transform","translate(12,12) rotate(45, "+t.x+","+s+")"),f.attr("cx",t.x+L/2).attr("cy",u).attr("transform","translate(12,12) rotate(45, "+t.x+","+s+")"),l.attr("x",t.x+5).attr("y",u+3).attr("transform","translate(14,14) rotate(45, "+t.x+","+s+")")}}}},"drawCommitTags"),cr=h(e=>{switch(e.customType??e.type){case m.NORMAL:return"commit-normal";case m.REVERSE:return"commit-reverse";case m.HIGHLIGHT:return"commit-highlight";case m.MERGE:return"commit-merge";case m.CHERRY_PICK:return"commit-cherry-pick";default:return"commit-normal"}},"getCommitClassType"),ir=h((e,r,t,s)=>{const o={x:0,y:0};if(e.parents.length>0){const i=ce(e.parents);if(i){const n=s.get(i)??o;return r==="TB"?n.y+_:r==="BT"?(s.get(e.id)??o).y-_:n.x+_}}else return r==="TB"?F:r==="BT"?(s.get(e.id)??o).y-_:0;return 0},"calculatePosition"),dr=h((e,r,t)=>{const s=y==="BT"&&t?r:r+O,o=C.get(e.branch)?.pos,i=y==="TB"||y==="BT"?C.get(e.branch)?.pos:s;if(i===void 0||o===void 0)throw new Error(`Position were undefined for commit ${e.id}`);const n=j.has(q().theme??""),a=y==="TB"||y==="BT"?s:o+(n?X/2+1:-2);return{x:i,y:a,posWithOffset:s}},"getCommitPosition"),re=h((e,r,t,s)=>{const o=e.append("g").attr("class","commit-bullets"),i=e.append("g").attr("class","commit-labels");let n=y==="TB"||y==="BT"?F:0;const a=[...r.keys()],l=s.parallelCommits??!1,f=h(($,c)=>{const x=r.get($)?.seq,u=r.get(c)?.seq;return x!==void 0&&u!==void 0?x-u:0},"sortKeys");let g=a.sort(f);y==="BT"&&(l&&Ze(g,r,n),g=g.reverse()),g.forEach($=>{const c=r.get($);if(!c)throw new Error(`Commit not found for key ${$}`);l&&(n=ir(c,y,n,E));const x=dr(c,n,l);if(t){const u=cr(c),p=c.customType??c.type,b=C.get(c.branch)?.index??0;nr(o,c,x,u,b,p),sr(i,c,x,n,s),or(i,c,x,n)}y==="TB"||y==="BT"?E.set(c.id,{x:x.x,y:x.posWithOffset}):E.set(c.id,{x:x.posWithOffset,y:x.y}),n=y==="BT"&&l?n+_:n+_+O,n>I&&(I=n)})},"drawCommits"),lr=h((e,r,t,s,o)=>{const n=(y==="TB"||y==="BT"?t.x<s.x:t.y<s.y)?r.branch:e.branch,a=h(f=>f.branch===n,"isOnBranchToGetCurve"),l=h(f=>f.seq>e.seq&&f.seq<r.seq,"isBetweenCommits");return[...o.values()].some(f=>l(f)&&a(f))},"shouldRerouteArrow"),W=h((e,r,t=0)=>{const s=e+Math.abs(e-r)/2;if(t>5)return s;if(z.every(n=>Math.abs(n-s)>=10))return z.push(s),s;const i=Math.abs(e-r);return W(e,r-i/5,t+1)},"findLane"),hr=h((e,r,t,s)=>{const{theme:o}=q(),i=Z.has(o??""),n=E.get(r.id),a=E.get(t.id);if(n===void 0||a===void 0)throw new Error(`Commit positions not found for commits ${r.id} and ${t.id}`);const l=lr(r,t,n,a,s);let f="",g="",$=0,c=0,x=C.get(t.branch)?.index;t.type===m.MERGE&&r.id!==t.parents[0]&&(x=C.get(r.branch)?.index);let u;if(l){f="A 10 10, 0, 0, 0,",g="A 10 10, 0, 0, 1,",$=10,c=10;const p=n.y<a.y?W(n.y,a.y):W(a.y,n.y),b=n.x<a.x?W(n.x,a.x):W(a.x,n.x);y==="TB"?n.x<a.x?u=`M ${n.x} ${n.y} L ${b-$} ${n.y} ${g} ${b} ${n.y+c} L ${b} ${a.y-$} ${f} ${b+c} ${a.y} L ${a.x} ${a.y}`:(x=C.get(r.branch)?.index,u=`M ${n.x} ${n.y} L ${b+$} ${n.y} ${f} ${b} ${n.y+c} L ${b} ${a.y-$} ${g} ${b-c} ${a.y} L ${a.x} ${a.y}`):y==="BT"?n.x<a.x?u=`M ${n.x} ${n.y} L ${b-$} ${n.y} ${f} ${b} ${n.y-c} L ${b} ${a.y+$} ${g} ${b+c} ${a.y} L ${a.x} ${a.y}`:(x=C.get(r.branch)?.index,u=`M ${n.x} ${n.y} L ${b+$} ${n.y} ${g} ${b} ${n.y-c} L ${b} ${a.y+$} ${f} ${b-c} ${a.y} L ${a.x} ${a.y}`):n.y<a.y?u=`M ${n.x} ${n.y} L ${n.x} ${p-$} ${f} ${n.x+c} ${p} L ${a.x-$} ${p} ${g} ${a.x} ${p+c} L ${a.x} ${a.y}`:(x=C.get(r.branch)?.index,u=`M ${n.x} ${n.y} L ${n.x} ${p+$} ${g} ${n.x+c} ${p} L ${a.x-$} ${p} ${f} ${a.x} ${p-c} L ${a.x} ${a.y}`)}else f="A 20 20, 0, 0, 0,",g="A 20 20, 0, 0, 1,",$=20,c=20,y==="TB"?(n.x<a.x&&(t.type===m.MERGE&&r.id!==t.parents[0]?u=`M ${n.x} ${n.y} L ${n.x} ${a.y-$} ${f} ${n.x+c} ${a.y} L ${a.x} ${a.y}`:u=`M ${n.x} ${n.y} L ${a.x-$} ${n.y} ${g} ${a.x} ${n.y+c} L ${a.x} ${a.y}`),n.x>a.x&&(f="A 20 20, 0, 0, 0,",g="A 20 20, 0, 0, 1,",$=20,c=20,t.type===m.MERGE&&r.id!==t.parents[0]?u=`M ${n.x} ${n.y} L ${n.x} ${a.y-$} ${g} ${n.x-c} ${a.y} L ${a.x} ${a.y}`:u=`M ${n.x} ${n.y} L ${a.x+$} ${n.y} ${f} ${a.x} ${n.y+c} L ${a.x} ${a.y}`),n.x===a.x&&(u=`M ${n.x} ${n.y} L ${a.x} ${a.y}`)):y==="BT"?(n.x<a.x&&(t.type===m.MERGE&&r.id!==t.parents[0]?u=`M ${n.x} ${n.y} L ${n.x} ${a.y+$} ${g} ${n.x+c} ${a.y} L ${a.x} ${a.y}`:u=`M ${n.x} ${n.y} L ${a.x-$} ${n.y} ${f} ${a.x} ${n.y-c} L ${a.x} ${a.y}`),n.x>a.x&&(f="A 20 20, 0, 0, 0,",g="A 20 20, 0, 0, 1,",$=20,c=20,t.type===m.MERGE&&r.id!==t.parents[0]?u=`M ${n.x} ${n.y} L ${n.x} ${a.y+$} ${f} ${n.x-c} ${a.y} L ${a.x} ${a.y}`:u=`M ${n.x} ${n.y} L ${a.x+$} ${n.y} ${g} ${a.x} ${n.y-c} L ${a.x} ${a.y}`),n.x===a.x&&(u=`M ${n.x} ${n.y} L ${a.x} ${a.y}`)):(n.y<a.y&&(t.type===m.MERGE&&r.id!==t.parents[0]?u=`M ${n.x} ${n.y} L ${a.x-$} ${n.y} ${g} ${a.x} ${n.y+c} L ${a.x} ${a.y}`:u=`M ${n.x} ${n.y} L ${n.x} ${a.y-$} ${f} ${n.x+c} ${a.y} L ${a.x} ${a.y}`),n.y>a.y&&(t.type===m.MERGE&&r.id!==t.parents[0]?u=`M ${n.x} ${n.y} L ${a.x-$} ${n.y} ${f} ${a.x} ${n.y-c} L ${a.x} ${a.y}`:u=`M ${n.x} ${n.y} L ${n.x} ${a.y+$} ${g} ${n.x+c} ${a.y} L ${a.x} ${a.y}`),n.y= Line truncated
`,"id:",r,t);const o=s.db;if(!o.getConfig){w.error("getConfig method is not available on db");return}const i=o.getConfig(),n=i.rotateCommitLabel??!1;P=o.getCommits();const a=o.getBranchesAsObjArray();y=o.getDirection();const l=me(`[id="${r}"]`),{look:f,theme:g,themeVariables:$}=q(),{useGradient:c,gradientStart:x,gradientStop:u,filterColor:p}=$;if(c){const k=l.append("defs").append("linearGradient").attr("id",r+"-gradient").attr("gradientUnits","objectBoundingBox").attr("x1","0%").attr("y1","0%").attr("x2","100%").attr("y2","0%");k.append("stop").attr("offset","0%").attr("stop-color",x).attr("stop-opacity",1),k.append("stop").attr("offset","100%").attr("stop-color",u).attr("stop-opacity",1)}f==="neo"&&j.has(g??"")&&l.append("defs").append("filter").attr("id",r+"-drop-shadow").attr("height","130%").attr("width","130%").append("feDropShadow").attr("dx","4").attr("dy","4").attr("stdDeviation",0).attr("flood-opacity","0.06").attr("flood-color",p);let b=0;a.forEach((k,U)=>{const D=oe(k.name),T=l.append("g"),K=T.insert("g").attr("class","branchLabel"),M=K.insert("g").attr("class","label branch-label");M.node()?.appendChild(D);const v=D.getBBox();b=gr(k.name,b,U,v,n),M.remove(),K.remove(),T.remove()}),re(l,P,!1,i),i.showBranches&&fr(l,a,i,r),$r(l,P),re(l,P,!0,i),pe.insertTitle(l,"gitTitleText",i.titleTopMargin??0,o.getDiagramTitle()),be(void 0,l,i.diagramPadding,i.useMaxWidth)},"draw"),yr={draw:ur},ie=8,de=new Set(["redux","redux-dark","redux-color","redux-dark-color"]),xr=new Set(["redux-color","redux-dark-color"]),mr=new Set(["neo","neo-dark"]),pr=new Set(["dark","redux-dark","redux-dark-color","neo-dark"]),br=new Set(["redux","redux-dark","redux-color","redux-dark-color","neo","neo-dark"]),wr=h(e=>{const{svgId:r}=e;let t="";if(e.useGradient&&r)for(let s=0;s<e.THEME_COLOR_LIMIT;s++)t+=`
.label${s} { fill: ${e.mainBkg}; stroke: url(${r}-gradient); stroke-width: ${e.strokeWidth};}
`;return t},"genGitGraphGradient"),kr=h(e=>{const r=J(),{theme:t,themeVariables:s}=r,{borderColorArray:o}=s,i=de.has(t);if(mr.has(t)){let n="";for(let a=0;a<e.THEME_COLOR_LIMIT;a++)if(a===0)n+=`
.branch-label${a} { fill: ${e.nodeBorder};}
.commit${a} { stroke: ${e.nodeBorder}; }
.commit-highlight${a} { stroke: ${e.nodeBorder}; fill: ${e.nodeBorder}; }
.arrow${a} { stroke: ${e.nodeBorder}; }
.commit-bullets { fill: ${e.nodeBorder}; }
.commit-cherry-pick${a} { stroke: ${e.nodeBorder}; }
${wr(e)}`;else{const l=a%ie;n+=`
.branch-label${a} { fill: ${e["gitBranchLabel"+l]}; }
.commit${a} { stroke: ${e["git"+l]}; fill: ${e["git"+l]}; }
.commit-highlight${a} { stroke: ${e["gitInv"+l]}; fill: ${e["gitInv"+l]}; }
.arrow${a} { stroke: ${e["git"+l]}; }
`}return n}else if(xr.has(t)){let n="";for(let a=0;a<e.THEME_COLOR_LIMIT;a++)if(a===0)n+=`
.branch-label${a} { fill: ${e.nodeBorder}; ${i?`font-weight:${e.noteFontWeight}`:""} }
.commit${a} { stroke: ${e.nodeBorder}; }
.commit-highlight${a} { stroke: ${e.nodeBorder}; fill: ${e.mainBkg}; }
.label${a} { fill: ${e.mainBkg}; stroke: ${e.nodeBorder}; stroke-width: ${e.strokeWidth}; ${i?`font-weight:${e.noteFontWeight}`:""} }
.arrow${a} { stroke: ${e.nodeBorder}; }
.commit-bullets { fill: ${e.nodeBorder}; }
`;else{const l=a%o.length;n+=`
.branch-label${a} { fill: ${e.nodeBorder}; ${i?`font-weight:${e.noteFontWeight}`:""} }
.commit${a} { stroke: ${o[l]}; fill: ${o[l]}; }
.commit-highlight${a} { stroke: ${o[l]}; fill: ${o[l]}; }
.label${a} { fill: ${pr.has(t)?e.mainBkg:o[l]}; stroke: ${o[l]}; stroke-width: ${e.strokeWidth}; }
.arrow${a} { stroke: ${o[l]}; }
`}return n}else{let n="";for(let a=0;a<e.THEME_COLOR_LIMIT;a++)n+=`
.branch-label${a} { fill: ${e.nodeBorder}; ${i?`font-weight:${e.noteFontWeight}`:""} }
.commit${a} { stroke: ${e.nodeBorder}; }
.commit-highlight${a} { stroke: ${e.nodeBorder}; fill: ${e.nodeBorder}; }
.label${a} { fill: ${e.mainBkg}; stroke: ${e.nodeBorder}; stroke-width: ${e.strokeWidth}; ${i?`font-weight:${e.noteFontWeight}`:""}}
.arrow${a} { stroke: ${e.nodeBorder}; }
.commit-bullets { fill: ${e.nodeBorder}; }
.commit-cherry-pick${a} { stroke: ${e.nodeBorder}; }
`;return n}},"genColor"),vr=h(e=>`${Array.from({length:e.THEME_COLOR_LIMIT},(r,t)=>t).map(r=>{const t=r%ie;return`
.branch-label${r} { fill: ${e["gitBranchLabel"+t]}; }
.commit${r} { stroke: ${e["git"+t]}; fill: ${e["git"+t]}; }
.commit-highlight${r} { stroke: ${e["gitInv"+t]}; fill: ${e["gitInv"+t]}; }
.label${r} { fill: ${e["git"+t]}; }
.arrow${r} { stroke: ${e["git"+t]}; }
`}).join(`
`)}`,"normalTheme"),Cr=h(e=>{const r=J(),{theme:t}=r,s=br.has(t);return`
.commit-id,
.commit-msg,
.branch-label {
fill: lightgrey;
color: lightgrey;
font-family: 'trebuchet ms', verdana, arial, sans-serif;
font-family: var(--mermaid-font-family);
}
${s?kr(e):vr(e)}
.branch {
stroke-width: ${e.strokeWidth};
stroke: ${e.commitLineColor??e.lineColor};
stroke-dasharray: ${s?"4 2":"2"};
}
.commit-label { font-size: ${e.commitLabelFontSize}; fill: ${s?e.nodeBorder:e.commitLabelColor}; ${s?`font-weight:${e.noteFontWeight};`:""}}
.commit-label-bkg { font-size: ${e.commitLabelFontSize}; fill: ${s?"transparent":e.commitLabelBackground}; opacity: ${s?"":.5}; }
.tag-label { font-size: ${e.tagLabelFontSize}; fill: ${e.tagLabelColor};}
.tag-label-bkg { fill: ${s?e.mainBkg:e.tagLabelBackground}; stroke: ${s?e.nodeBorder:e.tagLabelBorder}; ${s?`filter:${e.dropShadow}`:""} }
.tag-hole { fill: ${e.textColor}; }
.commit-merge {
stroke: ${s?e.mainBkg:e.primaryColor};
fill: ${s?e.mainBkg:e.primaryColor};
}
.commit-reverse {
stroke: ${s?e.mainBkg:e.primaryColor};
fill: ${s?e.mainBkg:e.primaryColor};
stroke-width: ${s?e.strokeWidth:3};
}
.commit-highlight-outer {
}
.commit-highlight-inner {
stroke: ${s?e.mainBkg:e.primaryColor};
fill: ${s?e.mainBkg:e.primaryColor};
}
.arrow {
/* Intentional: neo themes keep the bold 8px arrow (like classic themes); only redux-geometry themes use the thinner options.strokeWidth. */
stroke-width: ${de.has(t)?e.strokeWidth:8};
stroke-linecap: round;
fill: none
}
.gitTitleText {
text-anchor: middle;
font-size: 18px;
fill: ${e.textColor};
}
`},"getStyles"),Er=Cr,Ir={parser:Ve,db:se,renderer:yr,styles:Er};export{Ir as diagram};
+1
View File
@@ -0,0 +1 @@
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-content:"";--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-red-950:oklch(25.8% .092 26.042);--color-orange-50:oklch(98% .016 73.684);--color-orange-100:oklch(95.4% .038 75.164);--color-orange-200:oklch(90.1% .076 70.697);--color-orange-400:oklch(75% .183 55.934);--color-orange-600:oklch(64.6% .222 41.116);--color-orange-800:oklch(47% .157 37.304);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-yellow-50:oklch(98.7% .026 102.212);--color-yellow-200:oklch(94.5% .129 101.54);--color-yellow-500:oklch(79.5% .184 86.047);--color-yellow-600:oklch(68.1% .162 75.834);--color-yellow-800:oklch(47.6% .114 61.907);--color-green-50:oklch(98.2% .018 155.826);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-emerald-400:oklch(76.5% .177 163.223);--color-cyan-400:oklch(78.9% .154 211.53);--color-blue-50:oklch(97% .014 254.604);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-violet-500:oklch(60.6% .25 292.717);--color-purple-400:oklch(71.4% .203 305.504);--color-purple-500:oklch(62.7% .265 303.9);--color-pink-400:oklch(71.8% .202 349.761);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-black:#000;--color-white:#fff;--spacing:.25rem;--breakpoint-2xl:96rem;--contLine truncated
+110
View File
@@ -0,0 +1,110 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index3.js","assets/common-types.js","assets/index2.js"])))=>i.map(i=>d[i]);
function jL(e,t){for(var n=0;n<t.length;n++){const a=t[n];if(typeof a!="string"&&!Array.isArray(a)){for(const o in a)if(o!=="default"&&!(o in e)){const s=Object.getOwnPropertyDescriptor(a,o);s&&Object.defineProperty(e,o,s.get?s:{enumerable:!0,get:()=>a[o]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))a(o);new MutationObserver(o=>{for(const s of o)if(s.type==="childList")for(const u of s.addedNodes)u.tagName==="LINK"&&u.rel==="modulepreload"&&a(u)}).observe(document,{childList:!0,subtree:!0});function n(o){const s={};return o.integrity&&(s.integrity=o.integrity),o.referrerPolicy&&(s.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?s.credentials="include":o.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function a(o){if(o.ep)return;o.ep=!0;const s=n(o);fetch(o.href,s)}})();function wc(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var jf={exports:{}},bs={};var AA;function UL(){if(AA)return bs;AA=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function n(a,o,s){var u=null;if(s!==void 0&&(u=""+s),o.key!==void 0&&(u=""+o.key),"key"in o){s={};for(var c in o)c!=="key"&&(s[c]=o[c])}else s=o;return o=s.ref,{$$typeof:e,type:a,key:u,ref:o!==void 0?o:null,props:s}}return bs.Fragment=t,bs.jsx=n,bs.jsxs=n,bs}var kA;function FL(){return kA||(kA=1,jf.exports=UL()),jf.exports}var p=FL(),Uf={exports:{}},Re={};var _A;function BL(){if(_A)return Re;_A=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),a=Symbol.for("react.strict_mode"),o=Symbol.for("react.profiler"),s=Symbol.for("react.consumer"),u=Symbol.for("react.context"),c=Symbol.for("react.forward_ref"),f=Symbol.for("react.suspense"),g=Symbol.for("react.memo"),h=Symbol.for("react.lazy"),m=Symbol.for("react.activity"),E=Symbol.iterator;function S(M){return M===null||typeof M!="object"?null:(M=E&&M[E]||M["@@iterator"],typeof M=="function"?M:null)}var x={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},w=Object.assign,T={};function A(M,j,C){this.props=M,this.context=j,this.refs=T,this.updater=C||x}A.prototype.isReactComponent={},A.prototype.setState=function(M,j){if(typeof M!="object"&&typeof M!="function"&&M!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,M,j,"setState")},A.prototype.forceUpdate=function(M){this.updater.enqueueForceUpdate(this,M,"forceUpdate")};function _(){}_.prototype=A.prototype;function N(M,j,C){this.props=M,this.context=j,this.refs=T,this.updater=C||x}var L=N.prototype=new _;L.constructor=N,w(L,A.prototype),L.isPureReactComponent=!0;var U=Array.isArray;function D(){}var P={H:null,A:null,T:null,S:null},$=Object.prototype.hasOwnProperty;function Y(M,j,C){var J=C.ref;return{$$typeof:e,type:M,key:j,ref:J!==void 0?J:null,props:C}}function B(M,j){return Y(M.type,j,M.props)}function V(M){return typeof M=="object"&&M!==null&&M.$$typeof===e}function X(M){var j={"=":"=0",":":"=2"};return"$"+M.replace(/[=:]/g,function(C){return j[C]})}var ne=/\/+/g;function ie(M,j){return typeof M=="object"&&M!==null&&M.key!=null?X(""+M.key):j.toString(36)}function ee(M){switch(M.status){case"fulfilled":return M.value;case"rejected":throw M.reason;default:switch(typeof M.status=="string"?M.then(D,D):(M.status="pending",M.then(function(j){M.status==="pending"&&(M.status="fulfilled",M.value=j)},function(j){M.status==="pending"&&(M.status="rejected",M.reason=j)})),M.status){case"fulfilled":return M.value;case"rejected":throw M.reason}}throw M}function F(M,j,C,J,Q){var re=typeof M;(re==="undefined"||re==="boolean")&&(M=null);var oe=!1;if(M===null)oe=!0;else switch(re){case"bigint":case"string":case"number":oe=!0;break;case"object":switch(M.$$typeof){case e:case t:oe=!0;break;case h:return oe=M._init,F(oe(M._payload),j,C,J,Q)}}if(oe)return Q=Q(M),oe=J===""?"."+ie(M,0):J,U(Q)?(C="",oe!=null&&(C=oe.replace(ne,"$&/")+"/"),F(Q,j,C,"",function(ve){return ve})):Q!=null&&(V(Q)&&(Q=B(Q,C+(Q.key==null||M&&M.key===Q.key?"":(""+Q.key).replace(ne,"$&/")+"/")+oe)),j.push(Q)),1;oe=0;var he=J===""?".":J+":";if(U(M))for(var pe=0;pe<M.length;pe++)J=M[pe],re=he+ie(J,pe),oe+=F(J,j,C,re,Q);else if(pe=S(M),typeof pe=="function")for(M=pe.call(M),pe=0;!(J=M.next()).done;)J=J.value,re=he+ie(J,pe++),oe+=F(J,j,C,re,Q);else if(re==="object"){if(typeof M.then=="function")return F(ee(M),j,C,J,Q);throw j=String(M),Error("Objects are not valid as a React child (found: "+(j==="[object Object]"?"object with keys {"+Object.keys(M).join(", ")+"}":j)+"). If you meant to render a collection of children, use an array instead.")}return oe}functLine truncated
at`)?" (<anonymous>)":-1<l.stack.indexOf("@")?"@unknown:0:0":""}return`
`+je+r+qe}var Ie=!1;function kt(r,i){if(!r||Ie)return"";Ie=!0;var l=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{var d={DetermineComponentFrameRoot:function(){try{if(i){var de=function(){throw Error()};if(Object.defineProperty(de.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(de,[])}catch(ae){var Z=ae}Reflect.construct(r,[],de)}else{try{de.call()}catch(ae){Z=ae}r.call(de.prototype)}}else{try{throw Error()}catch(ae){Z=ae}(de=r())&&typeof de.catch=="function"&&de.catch(function(){})}}catch(ae){if(ae&&Z&&typeof ae.stack=="string")return[ae.stack,Z.stack]}return[null,null]}};d.DetermineComponentFrameRoot.displayName="DetermineComponentFrameRoot";var b=Object.getOwnPropertyDescriptor(d.DetermineComponentFrameRoot,"name");b&&b.configurable&&Object.defineProperty(d.DetermineComponentFrameRoot,"name",{value:"DetermineComponentFrameRoot"});var y=d.DetermineComponentFrameRoot(),k=y[0],R=y[1];if(k&&R){var z=k.split(`
`),K=R.split(`
`);for(b=d=0;d<z.length&&!z[d].includes("DetermineComponentFrameRoot");)d++;for(;b<K.length&&!K[b].includes("DetermineComponentFrameRoot");)b++;if(d===z.length||b===K.length)for(d=z.length-1,b=K.length-1;1<=d&&0<=b&&z[d]!==K[b];)b--;for(;1<=d&&0<=b;d--,b--)if(z[d]!==K[b]){if(d!==1||b!==1)do if(d--,b--,0>b||z[d]!==K[b]){var le=`
`+z[d].replace(" at new "," at ");return r.displayName&&le.includes("<anonymous>")&&(le=le.replace("<anonymous>",r.displayName)),le}while(1<=d&&0<=b);break}}}finally{Ie=!1,Error.prepareStackTrace=l}return(l=r?r.displayName||r.name:"")?Qe(l):""}function cn(r,i){switch(r.tag){case 26:case 27:case 5:return Qe(r.type);case 16:return Qe("Lazy");case 13:return r.child!==i&&i!==null?Qe("Suspense Fallback"):Qe("Suspense");case 19:return Qe("SuspenseList");case 0:case 15:return kt(r.type,!1);case 11:return kt(r.type.render,!1);case 1:return kt(r.type,!0);case 31:return Qe("Activity");default:return""}}function ml(r){try{var i="",l=null;do i+=cn(r,l),l=r,r=r.return;while(r);return i}catch(d){return`
Error generating stack: `+d.message+`
`+d.stack}}var ai=Object.prototype.hasOwnProperty,ii=e.unstable_scheduleCallback,Ao=e.unstable_cancelCallback,Ed=e.unstable_shouldYield,Sd=e.unstable_requestPaint,Vt=e.unstable_now,xd=e.unstable_getCurrentPriorityLevel,ue=e.unstable_ImmediatePriority,me=e.unstable_UserBlockingPriority,Ne=e.unstable_NormalPriority,Ue=e.unstable_LowPriority,Xe=e.unstable_IdlePriority,dn=e.log,dr=e.unstable_setDisableYieldValue,qt=null,wt=null;function Jt(r){if(typeof dn=="function"&&dr(r),wt&&typeof wt.setStrictMode=="function")try{wt.setStrictMode(qt,r)}catch{}}var at=Math.clz32?Math.clz32:x1,Mr=Math.log,Bn=Math.LN2;function x1(r){return r>>>=0,r===0?32:31-(Mr(r)/Bn|0)|0}var hl=256,bl=262144,yl=4194304;function Ta(r){var i=r&42;if(i!==0)return i;switch(r&-r){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return r&261888;case 262144:case 524288:case 1048576:case 2097152:return r&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return r&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return r}}function vl(r,i,l){var d=r.pendingLanes;if(d===0)return 0;var b=0,y=r.suspendedLanes,k=r.pingedLanes;r=r.warmLanes;var R=d&134217727;return R!==0?(d=R&~y,d!==0?b=Ta(d):(k&=R,k!==0?b=Ta(k):l||(l=R&~r,l!==0&&(b=Ta(l))))):(R=d&~y,R!==0?b=Ta(R):k!==0?b=Ta(k):l||(l=d&~r,l!==0&&(b=Ta(l)))),b===0?0:i!==0&&i!==b&&(i&y)===0&&(y=b&-b,l=i&-i,y>=l||y===32&&(l&4194048)!==0)?i:b}function ko(r,i){return(r.pendingLanes&~(r.suspendedLanes&~r.pingedLanes)&i)===0}function w1(r,i){switch(r){case 1:case 2:case 4:case 8:case 64:return i+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return i+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function CS(){var r=yl;return yl<<=1,(yl&62914560)===0&&(yl=4194304),r}function wd(r){for(var i=[],l=0;31>l;l++)i.push(r);return i}function _o(r,i){r.pendingLanes|=i,i!==268435456&&(r.suspendedLanes=0,r.pingedLanes=0,r.warmLanes=0)}function T1(r,i,l,d,b,y){var k=r.pendingLanes;r.pendingLanes=l,r.suspendedLanes=0,r.pingedLanes=0,r.warmLanes=0,r.expiredLanes&=l,r.entangledLanes&=l,r.errorRecoveryDisabledLanes&=l,r.shellSuspendCounter=0;var R=r.entanglements,z=r.expirationTimes,K=r.hiddenUpdates;for(l=k&~l;0<l;){var le=31-at(l),de=1<<le;R[le]=0,z[le]=-1;var Z=K[le];if(Z!==null)for(K[le]=null,le=0;le<Z.length;le++){var ae=Z[le];ae!==null&&(ae.lane&=-536870913)}l&=~de}d!==0&&RS(r,d,0),y!==0&&b===0&&r.tag!==0&&(r.suspendedLanes|=y&~(k&~i))}function RS(r,i,l){r.pendingLanes|=i,r.suspendedLanes&=~i;var d=31-at(i);r.entangledLanes|=i,r.entanglements[d]=r.entanglements[d]|1073741824|l&261930}function IS(r,i){var l=r.entangledLanes|=i;for(r=r.entanglements;l;){var d=31-at(l),b=1<<d;b&i|r[d]&i&&(r[d]|=i),l&=~b}}function OS(r,i){var l=i&-i;return l=(l&42)!==0?1:Td(l),(l&(r.suspendedLanes|i))!==0?0:l}function Td(r){switch(r){case 2:r=1;break;case 8:r=4;break;case 32:r=16;break;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:r=128;break;case 268435456:r=134217728;break;default:r=0}return r}function Ad(r){return r&=-r,2<r?8<r?(r&134217727)!==0?32:268435456:8:2}function DS(){var r=q.p;return r!==0?r:(r=window.event,r===void 0?32:yA(r.type))}function LS(r,i){var l=q.p;try{return q.p=r,i()}finally{q.p=l}}var jr=Math.random().toString(36).slice(2),Ot="__reactFiber$"+jr,en="__reactProps$"+jr,oi="__reactContainer$"+jr,kd="__reactEvents$"+jr,A1="__reactListeners$"+jr,k1="__reactHandles$"+jr,MS="__reactResources$"+jr,No="__reactMarker$"+jr;function _d(r){delete r[Ot],delete r[en],delete r[kd],delete r[A1],delete r[k1]}function si(r){var i=r[Ot];if(i)return i;for(var l=r.parentNode;l;){if(i=l[oi]||l[Ot]){if(l=i.alternate,i.child!==null||l!==null&&l.child!==null)for(r=nA(r);r!==null;){if(l=r[Ot])return l;r=nA(r)}return i}r=l,l=r.parentNode}return null}function li(r){if(r=r[Ot]||r[oi]){var i=r.tag;if(i===5||i===6||i===13||i===31||i===26||i===27||i===3)return r}return null}function Co(r){var i=r.tag;if(i===5||i===26||i===27||i===6)return r.stateNode;throw Error(a(33))}function ui(r){var i=r[MS];return i||(i=r[MS]={hoistableStyles:new Map,hoistableScripts:new Map}),i}function _t(r){r[No]=!0}var jS=new Set,US={};function Aa(r,i){ci(r,i),ci(r+"Capture",i)}function ci(r,i){for(US[r]=i,r=0;r<i.length;r++)jS.add(i[r])}var _1=RegExp("^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u20 Line truncated
`).replace(aL,"")}function qT(r,i){return i=VT(i),VT(r)===i}function nt(r,i,l,d,b,y){switch(l){case"children":typeof d=="string"?i==="body"||i==="textarea"&&d===""||pi(r,d):(typeof d=="number"||typeof d=="bigint")&&i!=="body"&&pi(r,""+d);break;case"className":Sl(r,"class",d);break;case"tabIndex":Sl(r,"tabindex",d);break;case"dir":case"role":case"viewBox":case"width":case"height":Sl(r,l,d);break;case"style":qS(r,d,y);break;case"data":if(i!=="object"){Sl(r,"data",d);break}case"src":case"href":if(d===""&&(i!=="a"||l!=="href")){r.removeAttribute(l);break}if(d==null||typeof d=="function"||typeof d=="symbol"||typeof d=="boolean"){r.removeAttribute(l);break}d=wl(""+d),r.setAttribute(l,d);break;case"action":case"formAction":if(typeof d=="function"){r.setAttribute(l,"javascript:throw new Error('A React form was unexpectedly submitted. If you called form.submit() manually, consider using form.requestSubmit() instead. If you\\'re trying to use event.stopPropagation() in a submit event handler, consider also calling event.preventDefault().')");break}else typeof y=="function"&&(l==="formAction"?(i!=="input"&&nt(r,i,"name",b.name,b,null),nt(r,i,"formEncType",b.formEncType,b,null),nt(r,i,"formMethod",b.formMethod,b,null),nt(r,i,"formTarget",b.formTarget,b,null)):(nt(r,i,"encType",b.encType,b,null),nt(r,i,"method",b.method,b,null),nt(r,i,"target",b.target,b,null)));if(d==null||typeof d=="symbol"||typeof d=="boolean"){r.removeAttribute(l);break}d=wl(""+d),r.setAttribute(l,d);break;case"onClick":d!=null&&(r.onclick=fr);break;case"onScroll":d!=null&&Be("scroll",r);break;case"onScrollEnd":d!=null&&Be("scrollend",r);break;case"dangerouslySetInnerHTML":if(d!=null){if(typeof d!="object"||!("__html"in d))throw Error(a(61));if(l=d.__html,l!=null){if(b.children!=null)throw Error(a(60));r.innerHTML=l}}break;case"multiple":r.multiple=d&&typeof d!="function"&&typeof d!="symbol";break;case"muted":r.muted=d&&typeof d!="function"&&typeof d!="symbol";break;case"suppressContentEditableWarning":case"suppressHydrationWarning":case"defaultValue":case"defaultChecked":case"innerHTML":case"ref":break;case"autoFocus":break;case"xlinkHref":if(d==null||typeof d=="function"||typeof d=="boolean"||typeof d=="symbol"){r.removeAttribute("xlink:href");break}l=wl(""+d),r.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",l);break;case"contentEditable":case"spellCheck":case"draggable":case"value":case"autoReverse":case"externalResourcesRequired":case"focusable":case"preserveAlpha":d!=null&&typeof d!="function"&&typeof d!="symbol"?r.setAttribute(l,""+d):r.removeAttribute(l);break;case"inert":case"allowFullScreen":case"async":case"autoPlay":case"controls":case"default":case"defer":case"disabled":case"disablePictureInPicture":case"disableRemotePlayback":case"formNoValidate":case"hidden":case"loop":case"noModule":case"noValidate":case"open":case"playsInline":case"readOnly":case"required":case"reversed":case"scoped":case"seamless":case"itemScope":d&&typeof d!="function"&&typeof d!="symbol"?r.setAttribute(l,""):r.removeAttribute(l);break;case"capture":case"download":d===!0?r.setAttribute(l,""):d!==!1&&d!=null&&typeof d!="function"&&typeof d!="symbol"?r.setAttribute(l,d):r.removeAttribute(l);break;case"cols":case"rows":case"size":case"span":d!=null&&typeof d!="function"&&typeof d!="symbol"&&!isNaN(d)&&1<=d?r.setAttribute(l,d):r.removeAttribute(l);break;case"rowSpan":case"start":d==null||typeof d=="function"||typeof d=="symbol"||isNaN(d)?r.removeAttribute(l):r.setAttribute(l,d);break;case"popover":Be("beforetoggle",r),Be("toggle",r),El(r,"popover",d);break;case"xlinkActuate":pr(r,"http://www.w3.org/1999/xlink","xlink:actuate",d);break;case"xlinkArcrole":pr(r,"http://www.w3.org/1999/xlink","xlink:arcrole",d);break;case"xlinkRole":pr(r,"http://www.w3.org/1999/xlink","xlink:role",d);break;case"xlinkShow":pr(r,"http://www.w3.org/1999/xlink","xlink:show",d);break;case"xlinkTitle":pr(r,"http://www.w3.org/1999/xlink","xlink:title",d);break;case"xlinkType":pr(r,"http://www.w3.org/1999/xlink","xlink:type",d);break;case"xmlBase":pr(r,"http://www.w3.org/XML/1998/namespace","xml:base",d);break;case"xmlLang":pr(r,"http://www.w3.org/XML/1998/namespace","xml:lang",d);break;case"xmlSpace":pr(r,"http://www.w3.org/XML/1998/namespace","xml:space",d);break;case"is":El(r,"is",d);break;case"innerText":case"textContent":break;default:(!(2<l.length)||l[0]!=="o"&&l[0]!=="O"||l[1]!=="n"&&l[1]!=="N")&&(l=O1.get(l)||l,El(r,l,d))}}function yf(r,i,l,d,b,y){switch(l){case"style":qS(r,d,y);break;case"dangerouslySetInnerHTML":if(d!=null){if(typeof d!="object"||!("__html"in d))throw Error(a(61));if(l=d.__html,l!=null){if(b.children!=null)throw Error(a(60));r.innerHTML=l}}break;case"children":typeof d=="string"?pi(r,d):(typeof d=="number"||typeof d=="bigint")&&pi(r,""+d);break;case"onScroll":d!=null&&Be("scroll",r);break;case"onScrollEnd":d!=null&&Be("scrollend",r);break;case"onClick":d!=null&&(r.onclick=fr);break;case"suppressContentEditableWarning":case"suppressHydrationWarning":case"inne Line truncated
.`.concat(HU,` {
overflow: hidden `).concat(a,`;
padding-right: `).concat(c,"px ").concat(a,`;
}
body[`).concat(to,`] {
overflow: hidden `).concat(a,`;
overscroll-behavior: contain;
`).concat([t&&"position: relative ".concat(a,";"),n==="margin"&&`
padding-left: `.concat(o,`px;
padding-top: `).concat(s,`px;
padding-right: `).concat(u,`px;
margin-left:0;
margin-top:0;
margin-right: `).concat(c,"px ").concat(a,`;
`),n==="padding"&&"padding-right: ".concat(c,"px ").concat(a,";")].filter(Boolean).join(""),`
}
.`).concat(Qu,` {
right: `).concat(c,"px ").concat(a,`;
}
.`).concat(Ju,` {
margin-right: `).concat(c,"px ").concat(a,`;
}
.`).concat(Qu," .").concat(Qu,` {
right: 0 `).concat(a,`;
}
.`).concat(Ju," .").concat(Ju,` {
margin-right: 0 `).concat(a,`;
}
body[`).concat(to,`] {
`).concat(VU,": ").concat(c,`px;
}
`)},fk=function(){var e=parseInt(document.body.getAttribute(to)||"0",10);return isFinite(e)?e:0},cF=function(){v.useEffect(function(){return document.body.setAttribute(to,(fk()+1).toString()),function(){var e=fk()-1;e<=0?document.body.removeAttribute(to):document.body.setAttribute(to,e.toString())}},[])},dF=function(e){var t=e.noRelative,n=e.noImportant,a=e.gapMode,o=a===void 0?"margin":a;cF();var s=v.useMemo(function(){return sF(o)},[o]);return v.createElement(lF,{styles:uF(s,!t,o,n?"":"!important")})},Dg=!1;if(typeof window<"u")try{var Fu=Object.defineProperty({},"passive",{get:function(){return Dg=!0,!0}});window.addEventListener("test",Fu,Fu),window.removeEventListener("test",Fu,Fu)}catch{Dg=!1}var Vi=Dg?{passive:!1}:!1,pF=function(e){return e.tagName==="TEXTAREA"},eC=function(e,t){if(!(e instanceof Element))return!1;var n=window.getComputedStyle(e);return n[t]!=="hidden"&&!(n.overflowY===n.overflowX&&!pF(e)&&n[t]==="visible")},fF=function(e){return eC(e,"overflowY")},gF=function(e){return eC(e,"overflowX")},gk=function(e,t){var n=t.ownerDocument,a=t;do{typeof ShadowRoot<"u"&&a instanceof ShadowRoot&&(a=a.host);var o=tC(e,a);if(o){var s=nC(e,a),u=s[1],c=s[2];if(u>c)return!0}a=a.parentNode}while(a&&a!==n.body);return!1},mF=function(e){var t=e.scrollTop,n=e.scrollHeight,a=e.clientHeight;return[t,n,a]},hF=function(e){var t=e.scrollLeft,n=e.scrollWidth,a=e.clientWidth;return[t,n,a]},tC=function(e,t){return e==="v"?fF(t):gF(t)},nC=function(e,t){return e==="v"?mF(t):hF(t)},bF=function(e,t){return e==="h"&&t==="rtl"?-1:1},yF=function(e,t,n,a,o){var s=bF(e,window.getComputedStyle(t).direction),u=s*a,c=n.target,f=t.contains(c),g=!1,h=u>0,m=0,E=0;do{if(!c)break;var S=nC(e,c),x=S[0],w=S[1],T=S[2],A=w-T-s*x;(x||A)&&tC(e,c)&&(m+=A,E+=x);var _=c.parentNode;c=_&&_.nodeType===Node.DOCUMENT_FRAGMENT_NODE?_.host:_}while(!f&&c!==document.body||f&&(t.contains(c)||t===c));return(h&&Math.abs(m)<1||!h&&Math.abs(E)<1)&&(g=!0),g},Bu=function(e){return"changedTouches"in e?[e.changedTouches[0].clientX,e.changedTouches[0].clientY]:[0,0]},mk=function(e){return[e.deltaX,e.deltaY]},hk=function(e){return e&&"current"in e?e.current:e},vF=function(e,t){return e[0]===t[0]&&e[1]===t[1]},EF=function(e){return`
.block-interactivity-`.concat(e,` {pointer-events: none;}
.allow-interactivity-`).concat(e,` {pointer-events: all;}
`)},SF=0,qi=[];function xF(e){var t=v.useRef([]),n=v.useRef([0,0]),a=v.useRef(),o=v.useState(SF++)[0],s=v.useState(JN)[0],u=v.useRef(e);v.useEffect(function(){u.current=e},[e]),v.useEffect(function(){if(e.inert){document.body.classList.add("block-interactivity-".concat(o));var w=GU([e.lockRef.current],(e.shards||[]).map(hk),!0).filter(Boolean);return w.forEach(function(T){return T.classList.add("allow-interactivity-".concat(o))}),function(){document.body.classList.remove("block-interactivity-".concat(o)),w.forEach(function(T){return T.classList.remove("allow-interactivity-".concat(o))})}}},[e.inert,e.lockRef.current,e.shards]);var c=v.useCallback(function(w,T){if("touches"in w&&w.touches.length===2||w.type==="wheel"&&w.ctrlKey)return!u.current.allowPinchZoom;var A=Bu(w),_=n.current,N="deltaX"in w?w.deltaX:_[0]-A[0],L="deltaY"in w?w.deltaY:_[1]-A[1],U,D=w.target,P=Math.abs(N)>Math.abs(L)?"h":"v";if("touches"in w&&P==="h"&&D.type==="range")return!1;var $=window.getSelection(),Y=$&&$.anchorNode,B=Y?Y===D||Y.contains(D):!1;if(B)return!1;var V=gk(P,D);if(!V)return!0;if(V?U=P:(U=P==="v"?"h":"v",V=gk(P,D)),!V)return!1;if(!a.current&&"changedTouches"in w&&(N||L)&&(a.current=U),!U)return!0;var X=a.current||U;return yF(X,T,w,X==="h"?N:L)},[]),f=v.useCallback(function(w){var T=w;if(!(!qi.length||qi[qi.length-1]!==s)){var A="deltaY"in T?mk(T):Bu(T),_=t.current.filter(function(U){return U.name===T.type&&(U.target===T.target||T.target===U.shadowParent)&&vF(U.delta,A)})[0];if(_&&_.should){T.cancelable&&T.preventDefault();return}if(!_){var N=(u.current.shards||[]).map(hk).filter(Boolean).filter(function(U){return U.contains(T.target)}),L=N.length>0?c(T,N[0]):!u.current.noIsolation;L&&T.cancelable&&T.preventDefault()}}},[]),g=v.useCallback(function(w,T,A,_){var N={name:w,delta:T,target:A,should:_,shadowParent:wF(A)};t.current.push(N),setTimeout(function(){t.current=t.current.filter(function(L){return L!==N})},1)},[]),h=v.useCallback(function(w){n.current=Bu(w),a.current=void 0},[]),m=v.useCallback(function(w){g(w.type,mk(w),w.target,c(w,e.lockRef.current))},[]),E=v.useCallback(function(w){g(w.type,Bu(w),w.target,c(w,e.lockRef.current))},[]);v.useEffect(function(){return qi.push(s),e.setCallbacks({onScrollCapture:m,onWheelCapture:m,onTouchMoveCapture:E}),document.addEventListener("wheel",f,Vi),document.addEventListener("touchmove",f,Vi),document.addEventListener("touchstart",h,Vi),function(){qi=qi.filter(function(w){return w!==s}),document.removeEventListener("wheel",f,Vi),document.removeEventListener("touchmove",f,Vi),document.removeEventListener("touchstart",h,Vi)}},[]);var S=e.removeScrollBar,x=e.inert;return v.createElement(v.Fragment,null,x?v.createElement(s,{styles:EF(o)}):null,S?v.createElement(dF,{noRelative:e.noRelative,gapMode:e.gapMode}):null)}function wF(e){for(var t=null;e!==null;)e instanceof ShadowRoot&&(t=e.host,e=e.host),e=e.parentNode;return t}const TF=QU(QN,xF);var Js=v.forwardRef(function(e,t){return v.createElement(jc,ar({},e,{ref:t,sideCar:TF}))});Js.classNames=jc.classNames;var Lg=["Enter"," "],AF=["ArrowDown","PageUp","Home"],rC=["ArrowUp","PageDown","End"],kF=[...AF,...rC],_F={ltr:[...Lg,"ArrowRight"],rtl:[...Lg,"ArrowLeft"]},NF={ltr:["ArrowLeft"],rtl:["ArrowRight"]},el="Menu",[js,CF,RF]=Ys(el),[ei,aC]=It(el,[RF,va,fo]),Uc=va(),iC=fo(),[IF,ti]=ei(el),[OF,tl]=ei(el),oC=e=>{const{__scopeMenu:t,open:n=!1,children:a,dir:o,onOpenChange:s,modal:u=!0}=e,c=Uc(t),[f,g]=v.useState(null),h=v.useRef(!1),m=Rt(s),E=ya(o);return v.useEffect(()=>{const S=()=>{h.current=!0,document.addEventListener("pointerdown",x,{capture:!0,once:!0}),document.addEventListener("pointermove",x,{capture:!0,once:!0})},x=()=>h.current=!1;return document.addEventListener("keydown",S,{capture:!0}),()=>{document.removeEventListener("keydown",S,{capture:!0}),document.removeEventListener("pointerdown",x,{capture:!0}),document.removeEventListener("pointermove",x,{capture:!0})}},[]),p.jsx(Oc,{...c,children:p.jsx(IF,{scope:t,open:n,onOpenChange:m,content:f,onContentChange:g,children:p.jsx(OF,{scope:t,onClose:v.useCallback(()=>m(!1),[m]),isUsingKeyboardRef:h,dir:E,modal:u,children:a})})})};oC.displayName=el;var DF="MenuAnchor",_m=v.forwardRef((e,t)=>{const{__scopeMenu:n,...a}=e,o=Uc(n);return p.jsx(Zs,{...o,...a,ref:t})});_m.displayName=DF;var Nm="MenuPortal",[LF,sC]=ei(Nm,{forceMount:void 0}),lC=e=>{const{__scopeMenu:t,forceMount:n,children:a,container:o}=e,s=ti(Nm,t);return p.jsx(LF,{scope:t,forceMount:n,children:p.jsx(xt,{present:n||s.open,children:p.jsx(po,{asChild:!0,container:o,children:a})})})};lC.displayName=Nm;var Un="MenuContent",[MF,Cm]=ei(Un),uC=v.forwardRef((e,t)=>{const n=sC(Un,e.__scopeMenu),{forceMount:a=n.forceMount,...o}=e,s=ti(Un,e.__scopeMenu),u=tl(Un,e.__scopeMenu);return p.jsx(js.Provider,{scope:e.__scopeMenu,children:p.jsx(xt,{present:a||s.open,children:p.jsx(js.Slot,{scope:e.__scopeMenu,children:u.modal?p.jsx(jF,{...o,ref:t}):p.jsx(UF,{...o,ref:t})})})})}),jF=v.forwardRef((e,t)=>{const n=ti(Un,e.__scopeMenu),a=v.useRef(n Line truncated
If you want to hide the \`${t.titleName}\`, you can wrap it with our VisuallyHidden component.
For more information, see https://radix-ui.com/primitives/docs/components/${t.docsSlug}`;return v.useEffect(()=>{e&&(document.getElementById(e)||console.error(n))},[n,e]),null},xP="DialogDescriptionWarning",wP=({contentRef:e,descriptionId:t})=>{const a=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${uR(xP).contentName}}.`;return v.useEffect(()=>{const o=e.current?.getAttribute("aria-describedby");t&&o&&(document.getElementById(t)||console.warn(a))},[a,e,t]),null},Pm=KC,TP=ZC,zm=JC,$m=eR,Gm=tR,cR=rR,AP=iR,dR=sR;function kP({...e}){return p.jsx(Pm,{"data-slot":"sheet",...e})}function _P({...e}){return p.jsx(zm,{"data-slot":"sheet-portal",...e})}function NP({className:e,...t}){return p.jsx($m,{"data-slot":"sheet-overlay",className:be("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",e),...t})}function CP({className:e,children:t,side:n="right",showCloseButton:a=!0,...o}){return p.jsxs(_P,{children:[p.jsx(NP,{}),p.jsxs(Gm,{"data-slot":"sheet-content",className:be("bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",n==="right"&&"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",n==="left"&&"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",n==="top"&&"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",n==="bottom"&&"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",e),...o,children:[t,a&&p.jsxs(dR,{className:"ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none",children:[p.jsx(J_,{className:"size-4"}),p.jsx("span",{className:"sr-only",children:"Close"})]})]})]})}function RP({className:e,...t}){return p.jsx("div",{"data-slot":"sheet-header",className:be("flex flex-col gap-1.5 p-4",e),...t})}function IP({className:e,...t}){return p.jsx(cR,{"data-slot":"sheet-title",className:be("text-foreground font-semibold",e),...t})}function Pt(e){return(e||"/").replace(/\/+$/,"")||"/"}function OP(e){if(!e||e.startsWith("#"))return e;try{const t=new URL(e,window.location.origin);return t.origin!==window.location.origin?e:Pt(t.pathname)+t.search+t.hash}catch{return e}}function DP(e){if(!e||e.startsWith("#"))return!1;if(e.startsWith("/docs"))return!0;try{const t=new URL(e,window.location.origin);return t.origin===window.location.origin&&t.pathname.startsWith("/docs")}catch{return!1}}function LP(e){const t=Pt(e);return t==="/"?"/docs/index.md":`${t}.md`}function pR({nav:e,activeItem:t,onItemClick:n}){const a=(o,s=0)=>{const u=(o.path||o.title)===t;if(o.children&&o.children.length>0)return p.jsxs("div",{className:"mb-4",children:[p.jsx("div",{className:"flex items-center gap-1 px-3 py-1.5 text-[11px] font-semibold text-muted-foreground/80 uppercase tracking-wider",children:o.title}),p.jsx("div",{className:"space-y-0.5 mt-1",children:o.children.map(g=>a(g,s+1))})]},o.title+(o.path||""));const f=Pt(o.path||"/");return p.jsxs("a",{href:f,"data-nav-path":o.path||"",onClick:g=>{g.preventDefault(),n(o)},className:`group flex items-center gap-1.5 w-full text-left px-3 py-1.5 text-[13px] rounded-md transition-colors ${u?"text-primary font-medium bg-primary/10":"text-muted-foreground hover:text-foreground hover:bg-muted/40"}`,style:{paddingLeft:`${12+s*10}px`},children:[s>0&&p.jsx(kc,{className:`h-3 w-3 shrink-0 opacity-0 group-hover:opacity-40 ${u?"opacity-60 text-primary":""}`}),p.jsx("span",{className:"truncate",children:o.title})]},o.title+(o.path||""))};return p.jsx("nav",{className:"space-y-0.5 pb-6",children:e.items?.map(o=>a(o))})}function Pu({nav:e,activeItem:t,onItemClick:n}){return p.jsx("aside",{className:"docs-sidebar w-[17rem] min-w-[17rem] shrink-0 hidden md:block border-r border-border/40",children:p.jsx(YC,{className:"h-[calc(100vh-3.5rem)] sticky top-14",children:p.jsx("div",{className:"py-5 px-2",children:p.jsx(pR,{nav:e,activeItem:t,onItemClick:n})})})})}function MP({open:e,onOpenChange:t,nav:n,activeItem:a,onItemClick:o,title:s="Navigation"}){return p.jsx(kP,{open:e,onOpenChange:t,children:p.jsxs(CP,{side:"left",className:"w-72 p-0",children:[p.jsx(RP,{className:"border-b px-4 py-3",children:p.jsx(IP,{children:s})}),p.jsx(YC,{className:"h-[calc(100vh-4rem)] px-2 py-4",children:p.jsx(pR,{nav:n,activeItem:a,onItemClick:u=>{o(u),t(!1)}})})]})})}function vk(e){const t=[],n=String(e||"");let a=n.indexOf(","),o=0,s=!1;for(;!s;){a===-1&&(a=n.length,s=!0);const u=n.slice(o,a).trim();(u||!s)&&t.pus Line truncated
`,g="/",h="*",m="",E="comment",S="declaration";function x(T,A){if(typeof T!="string")throw new TypeError("First argument must be a string");if(!T)return[];A=A||{};var _=1,N=1;function L(ie){var ee=ie.match(t);ee&&(_+=ee.length);var F=ie.lastIndexOf(f);N=~F?ie.length-F:N+ie.length}function U(){var ie={line:_,column:N};return function(ee){return ee.position=new D(ie),Y(),ee}}function D(ie){this.start=ie,this.end={line:_,column:N},this.source=A.source}D.prototype.content=T;function P(ie){var ee=new Error(A.source+":"+_+":"+N+": "+ie);if(ee.reason=ie,ee.filename=A.source,ee.line=_,ee.column=N,ee.source=T,!A.silent)throw ee}function $(ie){var ee=ie.exec(T);if(ee){var F=ee[0];return L(F),T=T.slice(F.length),ee}}function Y(){$(n)}function B(ie){var ee;for(ie=ie||[];ee=V();)ee!==!1&&ie.push(ee);return ie}function V(){var ie=U();if(!(g!=T.charAt(0)||h!=T.charAt(1))){for(var ee=2;m!=T.charAt(ee)&&(h!=T.charAt(ee)||g!=T.charAt(ee+1));)++ee;if(ee+=2,m===T.charAt(ee-1))return P("End of comment missing");var F=T.slice(2,ee-2);return N+=2,L(F),T=T.slice(ee),N+=2,ie({type:E,comment:F})}}function X(){var ie=U(),ee=$(a);if(ee){if(V(),!$(o))return P("property missing ':'");var F=$(s),q=ie({type:S,property:w(ee[0].replace(e,m)),value:F?w(F[0].replace(e,m)):m});return $(u),q}}function ne(){var ie=[];B(ie);for(var ee;ee=X();)ee!==!1&&(ie.push(ee),B(ie));return ie}return Y(),ne()}function w(T){return T?T.replace(c,m):m}return ng=x,ng}var kk;function QP(){if(kk)return Yi;kk=1;var e=Yi&&Yi.__importDefault||function(a){return a&&a.__esModule?a:{default:a}};Object.defineProperty(Yi,"__esModule",{value:!0}),Yi.default=n;const t=e(ZP());function n(a,o){let s=null;if(!a||typeof a!="string")return s;const u=(0,t.default)(a),c=typeof o=="function";return u.forEach(f=>{if(f.type!=="declaration")return;const{property:g,value:h}=f;c?o(g,h,f):h&&(s=s||{},s[g]=h)}),s}return Yi}var Es={},_k;function JP(){if(_k)return Es;_k=1,Object.defineProperty(Es,"__esModule",{value:!0}),Es.camelCase=void 0;var e=/^--[a-zA-Z0-9_-]+$/,t=/-([a-z])/g,n=/^[^-]+$/,a=/^-(webkit|moz|ms|o|khtml)-/,o=/^-(ms)-/,s=function(g){return!g||n.test(g)||e.test(g)},u=function(g,h){return h.toUpperCase()},c=function(g,h){return"".concat(h,"-")},f=function(g,h){return h===void 0&&(h={}),s(g)?g:(g=g.toLowerCase(),h.reactCompat?g=g.replace(o,c):g=g.replace(a,c),g.replace(t,u))};return Es.camelCase=f,Es}var Ss,Nk;function ez(){if(Nk)return Ss;Nk=1;var e=Ss&&Ss.__importDefault||function(o){return o&&o.__esModule?o:{default:o}},t=e(QP()),n=JP();function a(o,s){var u={};return!o||typeof o!="string"||(0,t.default)(o,function(c,f){c&&f&&(u[(0,n.camelCase)(c,s)]=f)}),u}return a.default=a,Ss=a,Ss}var tz=ez();const nz=wc(tz),xR=wR("end"),Vm=wR("start");function wR(e){return t;function t(n){const a=n&&n.position&&n.position[e]||{};if(typeof a.line=="number"&&a.line>0&&typeof a.column=="number"&&a.column>0)return{line:a.line,column:a.column,offset:typeof a.offset=="number"&&a.offset>-1?a.offset:void 0}}}function rz(e){const t=Vm(e),n=xR(e);if(t&&n)return{start:t,end:n}}function Rs(e){return!e||typeof e!="object"?"":"position"in e||"type"in e?Ck(e.position):"start"in e||"end"in e?Ck(e):"line"in e||"column"in e?Ug(e):""}function Ug(e){return Rk(e&&e.line)+":"+Rk(e&&e.column)}function Ck(e){return Ug(e&&e.start)+"-"+Ug(e&&e.end)}function Rk(e){return e&&typeof e=="number"?e:1}class $t extends Error{constructor(t,n,a){super(),typeof n=="string"&&(a=n,n=void 0);let o="",s={},u=!1;if(n&&("line"in n&&"column"in n?s={place:n}:"start"in n&&"end"in n?s={place:n}:"type"in n?s={ancestors:[n],place:n.position}:s={...n}),typeof t=="string"?o=t:!s.cause&&t&&(u=!0,o=t.message,s.cause=t),!s.ruleId&&!s.source&&typeof a=="string"){const f=a.indexOf(":");f===-1?s.ruleId=a:(s.source=a.slice(0,f),s.ruleId=a.slice(f+1))}if(!s.place&&s.ancestors&&s.ancestors){const f=s.ancestors[s.ancestors.length-1];f&&(s.place=f.position)}const c=s.place&&"start"in s.place?s.place.start:s.place;this.ancestors=s.ancestors||void 0,this.cause=s.cause||void 0,this.column=c?c.column:void 0,this.fatal=void 0,this.file="",this.message=o,this.line=c?c.line:void 0,this.name=Rs(s.place)||"1:1",this.place=s.place||void 0,this.reason=this.message,this.ruleId=s.ruleId||void 0,this.source=s.source||void 0,this.stack=u&&s.cause&&typeof s.cause.stack=="string"?s.cause.stack:"",this.actual=void 0,this.expected=void 0,this.note=void 0,this.url=void 0}}$t.prototype.file="";$t.prototype.name="";$t.prototype.reason="";$t.prototype.message="";$t.prototype.stack="";$t.prototype.column=void 0;$t.prototype.line=void 0;$t.prototype.ancestors=void 0;$t.prototype.cause=void 0;$t.prototype.fatal=void 0;$t.prototype.place=void 0;$t.prototype.ruleId=void 0;$t.prototype.source=void 0;const qm={}.hasOwnProperty,az=new Map,iz=/[A-Z]/g,oz=new Set(["table","tbody","thead","tfoot","tr"]),sz=new Set(["td","th"]),TR="https://github.com/syntax-tree/hast-util-to-jsx-runtime";function lz(e,t){if(!t||t.Fragment===void 0)throw new TypeError("Expected `Fragment` in options Line truncated
`;break}case-3:{u=`\r
`;break}case-2:{u=t?" ":" ";break}case-1:{if(!t&&o)continue;u=" ";break}default:u=String.fromCharCode(s)}o=s===-2,a.push(u)}return a.join("")}function h3(e){const a={constructs:CR([p3,...(e||{}).extensions||[]]),content:o(Iz),defined:[],document:o(Dz),flow:o(Z$),lazy:{},string:o(e3),text:o(t3)};return a;function o(s){return u;function u(c){return f3(a,s,c)}}}function b3(e){for(;!LR(e););return e}const Pk=/[\0\t\n\r]/g;function y3(){let e=1,t="",n=!0,a;return o;function o(s,u,c){const f=[];let g,h,m,E,S;for(s=t+(typeof s=="string"?s.toString():new TextDecoder(u||void 0).decode(s)),m=0,t="",n&&(s.charCodeAt(0)===65279&&m++,n=void 0);m<s.length;){if(Pk.lastIndex=m,g=Pk.exec(s),E=g&&g.index!==void 0?g.index:s.length,S=s.charCodeAt(E),!g){t=s.slice(m);break}if(S===10&&m===E&&a)f.push(-3),a=void 0;else switch(a&&(f.push(-5),a=void 0),m<E&&(f.push(s.slice(m,E)),e+=E-m),S){case 0:{f.push(65533),e++;break}case 9:{for(h=Math.ceil(e/4)*4,f.push(-2);e++<h;)f.push(-1);break}case 10:{f.push(-4),e=1;break}default:a=!0,e=1}m=E+1}return c&&(a&&f.push(-5),t&&f.push(t),f.push(null)),f}}const v3=/\\([!-/:-@[-`{-~])|&(#(?:\d{1,7}|x[\da-f]{1,6})|[\da-z]{1,31});/gi;function E3(e){return e.replace(v3,S3)}function S3(e,t,n){if(t)return t;if(n.charCodeAt(0)===35){const o=n.charCodeAt(1),s=o===120||o===88;return RR(n.slice(s?2:1),s?16:10)}return zs(n)||e}const PR={}.hasOwnProperty;function x3(e,t,n){return t&&typeof t=="object"&&(n=t,t=void 0),w3(n)(b3(h3(n).document().write(y3()(e,t,!0))))}function w3(e){const t={transforms:[],canContainEols:["emphasis","fragment","heading","paragraph","strong"],enter:{autolink:s(ai),autolinkProtocol:Y,autolinkEmail:Y,atxHeading:s(Ie),blockQuote:s(ve),characterEscape:Y,characterReference:Y,codeFenced:s(Ce),codeFencedFenceInfo:u,codeFencedFenceMeta:u,codeIndented:s(Ce,u),codeText:s(je,u),codeTextData:Y,data:Y,codeFlowValue:Y,definition:s(qe),definitionDestinationString:u,definitionLabelString:u,definitionTitleString:u,emphasis:s(Qe),hardBreakEscape:s(kt),hardBreakTrailing:s(kt),htmlFlow:s(cn,u),htmlFlowData:Y,htmlText:s(cn,u),htmlTextData:Y,image:s(ml),label:u,link:s(ai),listItem:s(Ao),listItemValue:E,listOrdered:s(ii,m),listUnordered:s(ii),paragraph:s(Ed),reference:C,referenceString:u,resourceDestinationString:u,resourceTitleString:u,setextHeading:s(Ie),strong:s(Sd),thematicBreak:s(xd)},exit:{atxHeading:f(),atxHeadingSequence:U,autolink:f(),autolinkEmail:pe,autolinkProtocol:he,blockQuote:f(),characterEscapeValue:B,characterReferenceMarkerHexadecimal:Q,characterReferenceMarkerNumeric:Q,characterReferenceValue:re,characterReference:oe,codeFenced:f(T),codeFencedFence:w,codeFencedFenceInfo:S,codeFencedFenceMeta:x,codeFlowValue:B,codeIndented:f(A),codeText:f(ee),codeTextData:B,data:B,definition:f(),definitionDestinationString:L,definitionLabelString:_,definitionTitleString:N,emphasis:f(),hardBreakEscape:f(X),hardBreakTrailing:f(X),htmlFlow:f(ne),htmlFlowData:B,htmlText:f(ie),htmlTextData:B,image:f(q),label:se,labelText:te,lineEnding:V,link:f(F),listItem:f(),listOrdered:f(),listUnordered:f(),paragraph:f(),referenceString:J,resourceDestinationString:I,resourceTitleString:M,resource:j,setextHeading:f($),setextHeadingLineSequence:P,setextHeadingText:D,strong:f(),thematicBreak:f()}};zR(t,(e||{}).mdastExtensions||[]);const n={};return a;function a(ue){let me={type:"root",children:[]};const Ne={stack:[me],tokenStack:[],config:t,enter:c,exit:g,buffer:u,resume:h,data:n},Ue=[];let Xe=-1;for(;++Xe<ue.length;)if(ue[Xe][1].type==="listOrdered"||ue[Xe][1].type==="listUnordered")if(ue[Xe][0]==="enter")Ue.push(Xe);else{const dn=Ue.pop();Xe=o(ue,dn,Xe)}for(Xe=-1;++Xe<ue.length;){const dn=t[ue[Xe][0]];PR.call(dn,ue[Xe][1].type)&&dn[ue[Xe][1].type].call(Object.assign({sliceSerialize:ue[Xe][2].sliceSerialize},Ne),ue[Xe][1])}if(Ne.tokenStack.length>0){const dn=Ne.tokenStack[Ne.tokenStack.length-1];(dn[1]||zk).call(Ne,void 0,dn[0])}for(me.position={start:la(ue.length>0?ue[0][1].start:{line:1,column:1,offset:0}),end:la(ue.length>0?ue[ue.length-2][1].end:{line:1,column:1,offset:0})},Xe=-1;++Xe<t.transforms.length;)me=t.transforms[Xe](me)||me;return me}function o(ue,me,Ne){let Ue=me-1,Xe=-1,dn=!1,dr,qt,wt,Jt;for(;++Ue<=Ne;){const at=ue[Ue];switch(at[1].type){case"listUnordered":case"listOrdered":case"blockQuote":{at[0]==="enter"?Xe++:Xe--,Jt=void 0;break}case"lineEndingBlank":{at[0]==="enter"&&(dr&&!Jt&&!Xe&&!wt&&(wt=Ue),Jt=void 0);break}case"linePrefix":case"listItemValue":case"listItemMarker":case"listItemPrefix":case"listItemPrefixWhitespace":break;default:Jt=void 0}if(!Xe&&at[0]==="enter"&&at[1].type==="listItemPrefix"||Xe===-1&&at[0]==="exit"&&(at[1].type==="listUnordered"||at[1].type==="listOrdered")){if(dr){let Mr=Ue;for(qt=void 0;Mr--;){const Bn=ue[Mr];if(Bn[1].type==="lineEnding"||Bn[1].type==="lineEndingBlank"){if(Bn[0]==="exit")continue;qt&&(ue[qt][1].type="lineEndingBlank",dn=!0),Bn[1].type="lineEnding",qt=Mr}else if(!(Bn[1].type==="linePrefix"||Bn[1].type==="blockQuotePrefix"||Bn[1].type==="blockQuotePrefixWhitespaLine truncated
`}]}function N3(e,t){const n=t.value?t.value+`
`:"",a={},o=t.lang?t.lang.split(/\s+/):[];o.length>0&&(a.className=["language-"+o[0]]);let s={type:"element",tagName:"code",properties:a,children:[{type:"text",value:n}]};return t.meta&&(s.data={meta:t.meta}),e.patch(t,s),s=e.applyData(t,s),s={type:"element",tagName:"pre",properties:{},children:[s]},e.patch(t,s),s}function C3(e,t){const n={type:"element",tagName:"del",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function R3(e,t){const n={type:"element",tagName:"em",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function I3(e,t){const n=typeof e.options.clobberPrefix=="string"?e.options.clobberPrefix:"user-content-",a=String(t.identifier).toUpperCase(),o=mo(a.toLowerCase()),s=e.footnoteOrder.indexOf(a);let u,c=e.footnoteCounts.get(a);c===void 0?(c=0,e.footnoteOrder.push(a),u=e.footnoteOrder.length):u=s+1,c+=1,e.footnoteCounts.set(a,c);const f={type:"element",tagName:"a",properties:{href:"#"+n+"fn-"+o,id:n+"fnref-"+o+(c>1?"-"+c:""),dataFootnoteRef:!0,ariaDescribedBy:["footnote-label"]},children:[{type:"text",value:String(u)}]};e.patch(t,f);const g={type:"element",tagName:"sup",properties:{},children:[f]};return e.patch(t,g),e.applyData(t,g)}function O3(e,t){const n={type:"element",tagName:"h"+t.depth,properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function D3(e,t){if(e.options.allowDangerousHtml){const n={type:"raw",value:t.value};return e.patch(t,n),e.applyData(t,n)}}function $R(e,t){const n=t.referenceType;let a="]";if(n==="collapsed"?a+="[]":n==="full"&&(a+="["+(t.label||t.identifier)+"]"),t.type==="imageReference")return[{type:"text",value:"!["+t.alt+a}];const o=e.all(t),s=o[0];s&&s.type==="text"?s.value="["+s.value:o.unshift({type:"text",value:"["});const u=o[o.length-1];return u&&u.type==="text"?u.value+=a:o.push({type:"text",value:a}),o}function L3(e,t){const n=String(t.identifier).toUpperCase(),a=e.definitionById.get(n);if(!a)return $R(e,t);const o={src:mo(a.url||""),alt:t.alt};a.title!==null&&a.title!==void 0&&(o.title=a.title);const s={type:"element",tagName:"img",properties:o,children:[]};return e.patch(t,s),e.applyData(t,s)}function M3(e,t){const n={src:mo(t.url)};t.alt!==null&&t.alt!==void 0&&(n.alt=t.alt),t.title!==null&&t.title!==void 0&&(n.title=t.title);const a={type:"element",tagName:"img",properties:n,children:[]};return e.patch(t,a),e.applyData(t,a)}function j3(e,t){const n={type:"text",value:t.value.replace(/\r?\n|\r/g," ")};e.patch(t,n);const a={type:"element",tagName:"code",properties:{},children:[n]};return e.patch(t,a),e.applyData(t,a)}function U3(e,t){const n=String(t.identifier).toUpperCase(),a=e.definitionById.get(n);if(!a)return $R(e,t);const o={href:mo(a.url||"")};a.title!==null&&a.title!==void 0&&(o.title=a.title);const s={type:"element",tagName:"a",properties:o,children:e.all(t)};return e.patch(t,s),e.applyData(t,s)}function F3(e,t){const n={href:mo(t.url)};t.title!==null&&t.title!==void 0&&(n.title=t.title);const a={type:"element",tagName:"a",properties:n,children:e.all(t)};return e.patch(t,a),e.applyData(t,a)}function B3(e,t,n){const a=e.all(t),o=n?P3(n):GR(t),s={},u=[];if(typeof t.checked=="boolean"){const h=a[0];let m;h&&h.type==="element"&&h.tagName==="p"?m=h:(m={type:"element",tagName:"p",properties:{},children:[]},a.unshift(m)),m.children.length>0&&m.children.unshift({type:"text",value:" "}),m.children.unshift({type:"element",tagName:"input",properties:{type:"checkbox",checked:t.checked,disabled:!0},children:[]}),s.className=["task-list-item"]}let c=-1;for(;++c<a.length;){const h=a[c];(o||c!==0||h.type!=="element"||h.tagName!=="p")&&u.push({type:"text",value:`
`}),h.type==="element"&&h.tagName==="p"&&!o?u.push(...h.children):u.push(h)}const f=a[a.length-1];f&&(o||f.type!=="element"||f.tagName!=="p")&&u.push({type:"text",value:`
`});const g={type:"element",tagName:"li",properties:s,children:u};return e.patch(t,g),e.applyData(t,g)}function P3(e){let t=!1;if(e.type==="list"){t=e.spread||!1;const n=e.children;let a=-1;for(;!t&&++a<n.length;)t=GR(n[a])}return t}function GR(e){const t=e.spread;return t??e.children.length>1}function z3(e,t){const n={},a=e.all(t);let o=-1;for(typeof t.start=="number"&&t.start!==1&&(n.start=t.start);++o<a.length;){const u=a[o];if(u.type==="element"&&u.tagName==="li"&&u.properties&&Array.isArray(u.properties.className)&&u.properties.className.includes("task-list-item")){n.className=["contains-task-list"];break}}const s={type:"element",tagName:t.ordered?"ol":"ul",properties:n,children:e.wrap(a,!0)};return e.patch(t,s),e.applyData(t,s)}function $3(e,t){const n={type:"element",tagName:"p",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function G3(e,t){const n={type:"root",children:e.wrap(e.all(t))};return e.patch(t,n),e.applyData(t,n)}function H3(e,t){const n={type:"element",tagName:"strong",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function V3(e,t){const n=e.all(t),a=n.shift(),o=[];if(a){const u={type:"element",tagName:"thead",properties:{},children:e.wrap([a],!0)};e.patch(t.children[0],u),o.push(u)}if(n.length>0){const u={type:"element",tagName:"tbody",properties:{},children:e.wrap(n,!0)},c=Vm(t.children[1]),f=xR(t.children[t.children.length-1]);c&&f&&(u.position={start:c,end:f}),o.push(u)}const s={type:"element",tagName:"table",properties:{},children:e.wrap(o,!0)};return e.patch(t,s),e.applyData(t,s)}function q3(e,t,n){const a=n?n.children:void 0,s=(a?a.indexOf(t):1)===0?"th":"td",u=n&&n.type==="table"?n.align:void 0,c=u?u.length:t.children.length;let f=-1;const g=[];for(;++f<c;){const m=t.children[f],E={},S=u?u[f]:void 0;S&&(E.align=S);let x={type:"element",tagName:s,properties:E,children:[]};m&&(x.children=e.all(m),e.patch(m,x),x=e.applyData(m,x)),g.push(x)}const h={type:"element",tagName:"tr",properties:{},children:e.wrap(g,!0)};return e.patch(t,h),e.applyData(t,h)}function Y3(e,t){const n={type:"element",tagName:"td",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}const $k=9,Gk=32;function W3(e){const t=String(e),n=/\r?\n|\r/g;let a=n.exec(t),o=0;const s=[];for(;a;)s.push(Hk(t.slice(o,a.index),o>0,!0),a[0]),o=a.index+a[0].length,a=n.exec(t);return s.push(Hk(t.slice(o),o>0,!1)),s.join("")}function Hk(e,t,n){let a=0,o=e.length;if(t){let s=e.codePointAt(a);for(;s===$k||s===Gk;)a++,s=e.codePointAt(a)}if(n){let s=e.codePointAt(o-1);for(;s===$k||s===Gk;)o--,s=e.codePointAt(o-1)}return o>a?e.slice(a,o):""}function K3(e,t){const n={type:"text",value:W3(String(t.value))};return e.patch(t,n),e.applyData(t,n)}function X3(e,t){const n={type:"element",tagName:"hr",properties:{},children:[]};return e.patch(t,n),e.applyData(t,n)}const Z3={blockquote:k3,break:_3,code:N3,delete:C3,emphasis:R3,footnoteReference:I3,heading:O3,html:D3,imageReference:L3,image:M3,inlineCode:j3,linkReference:U3,link:F3,listItem:B3,list:z3,paragraph:$3,root:G3,strong:H3,table:V3,tableCell:Y3,tableRow:q3,text:K3,thematicBreak:X3,toml:zu,yaml:zu,definition:zu,footnoteDefinition:zu};function zu(){}const HR=-1,qc=0,Os=1,hc=2,Zm=3,Qm=4,Jm=5,eh=6,VR=7,qR=8,Vk=typeof self=="object"?self:globalThis,Q3=(e,t)=>{const n=(o,s)=>(e.set(s,o),o),a=o=>{if(e.has(o))return e.get(o);const[s,u]=t[o];switch(s){case qc:case HR:return n(u,o);case Os:{const c=n([],o);for(const f of u)c.push(a(f));return c}case hc:{const c=n({},o);for(const[f,g]of u)c[a(f)]=a(g);return c}case Zm:return n(new Date(u),o);case Qm:{const{source:c,flags:f}=u;return n(new RegExp(c,f),o)}case Jm:{const c=n(new Map,o);for(const[f,g]of u)c.set(a(f),a(g));return c}case eh:{const c=n(new Set,o);for(const f of u)c.add(a(f));return c}case VR:{const{name:c,message:f}=u;return n(new Vk[c](f),o)}case qR:return n(BigInt(u),o);case"BigInt":return n(Object(BigInt(u)),o);case"ArrayBuffer":return n(new Uint8Array(u).buffer,u);case"DataView":{const{buffer:c}=new Uint8Array(u);return n(new DataView(c),u)}}return n(new Vk[s](u),o)};return a},qk=e=>Q3(new Map,e)(0),Wi="",{toString:J3}={},{keys:e4}=Object,ws=e=>{const t=typeof e;if(t!=="object"||!e)return[qc,t];const n=J3.call(e).slice(8,-1);switch(n){case"Array":return[Os,Wi];case"Object":return[hc,Wi];case"Date":return[Zm,Wi];case"RegExp":return[Qm,Wi];case"Map":return[Jm,Wi];case"Set":return[eh,Wi];case"DataView":return[Os,n]}return n.includes("Array")?[Os,n]:n.includes("Error")?[VR,n]:[hc,n]},$u=([e,t])=>e===qc&&(t==="function"||t==="symbol"),t4=(e,t,n,a)=>{const o=(u,c)=>{const f=a.push(u)-1;return n.set(c,f),f},s=u=>{if(n.has(u))return n.get(u);let[c,f]=ws(u);switch(c){case qc:{let h=u;switch(f){case"bigint":c=qR,h=u.toString();break;case"function":case"symbol":if(e)throw new TypeError("unable to serialize "+f);h=null;break;case"undefined":return o([HR],u)}return o([c,h],u)}case Os:{if(f){let E=u;return f==="DataView"?E=new Uint8Array(u.buffer):f==="ArrayBuffer"&&(E=new Uint8Array( Line truncated
`},{type:"element",tagName:"ol",properties:{},children:e.wrap(c,!0)},{type:"text",value:`
`}]}}const Yc=(function(e){if(e==null)return l4;if(typeof e=="function")return Wc(e);if(typeof e=="object")return Array.isArray(e)?i4(e):o4(e);if(typeof e=="string")return s4(e);throw new Error("Expected function, string, or object as test")});function i4(e){const t=[];let n=-1;for(;++n<e.length;)t[n]=Yc(e[n]);return Wc(a);function a(...o){let s=-1;for(;++s<t.length;)if(t[s].apply(this,o))return!0;return!1}}function o4(e){const t=e;return Wc(n);function n(a){const o=a;let s;for(s in e)if(o[s]!==t[s])return!1;return!0}}function s4(e){return Wc(t);function t(n){return n&&n.type===e}}function Wc(e){return t;function t(n,a,o){return!!(u4(n)&&e.call(this,n,typeof a=="number"?a:void 0,o||void 0))}}function l4(){return!0}function u4(e){return e!==null&&typeof e=="object"&&"type"in e}const YR=[],c4=!0,Pg=!1,d4="skip";function WR(e,t,n,a){let o;typeof t=="function"&&typeof n!="function"?(a=n,n=t):o=t;const s=Yc(o),u=a?-1:1;c(e,void 0,[])();function c(f,g,h){const m=f&&typeof f=="object"?f:{};if(typeof m.type=="string"){const S=typeof m.tagName=="string"?m.tagName:typeof m.name=="string"?m.name:void 0;Object.defineProperty(E,"name",{value:"node ("+(f.type+(S?"<"+S+">":""))+")"})}return E;function E(){let S=YR,x,w,T;if((!t||s(f,g,h[h.length-1]||void 0))&&(S=p4(n(f,h)),S[0]===Pg))return S;if("children"in f&&f.children){const A=f;if(A.children&&S[0]!==d4)for(w=(a?A.children.length:-1)+u,T=h.concat(A);w>-1&&w<A.children.length;){const _=A.children[w];if(x=c(_,w,T)(),x[0]===Pg)return x;w=typeof x[1]=="number"?x[1]:w+u}}return S}}}function p4(e){return Array.isArray(e)?e:typeof e=="number"?[c4,e]:e==null?YR:[e]}function th(e,t,n,a){let o,s,u;typeof t=="function"&&typeof n!="function"?(s=void 0,u=t,o=n):(s=t,u=n,o=a),WR(e,s,c,o);function c(f,g){const h=g[g.length-1],m=h?h.children.indexOf(f):void 0;return u(f,m,h)}}const zg={}.hasOwnProperty,f4={};function g4(e,t){const n=t||f4,a=new Map,o=new Map,s=new Map,u={...Z3,...n.handlers},c={all:g,applyData:h4,definitionById:a,footnoteById:o,footnoteCounts:s,footnoteOrder:[],handlers:u,one:f,options:n,patch:m4,wrap:y4};return th(e,function(h){if(h.type==="definition"||h.type==="footnoteDefinition"){const m=h.type==="definition"?a:o,E=String(h.identifier).toUpperCase();m.has(E)||m.set(E,h)}}),c;function f(h,m){const E=h.type,S=c.handlers[E];if(zg.call(c.handlers,E)&&S)return S(c,h,m);if(c.options.passThrough&&c.options.passThrough.includes(E)){if("children"in h){const{children:w,...T}=h,A=bc(T);return A.children=c.all(h),A}return bc(h)}return(c.options.unknownHandler||b4)(c,h,m)}function g(h){const m=[];if("children"in h){const E=h.children;let S=-1;for(;++S<E.length;){const x=c.one(E[S],h);if(x){if(S&&E[S-1].type==="break"&&(!Array.isArray(x)&&x.type==="text"&&(x.value=Wk(x.value)),!Array.isArray(x)&&x.type==="element")){const w=x.children[0];w&&w.type==="text"&&(w.value=Wk(w.value))}Array.isArray(x)?m.push(...x):m.push(x)}}}return m}}function m4(e,t){e.position&&(t.position=rz(e))}function h4(e,t){let n=t;if(e&&e.data){const a=e.data.hName,o=e.data.hChildren,s=e.data.hProperties;if(typeof a=="string")if(n.type==="element")n.tagName=a;else{const u="children"in n?n.children:[n];n={type:"element",tagName:a,properties:{},children:u}}n.type==="element"&&s&&Object.assign(n.properties,bc(s)),"children"in n&&n.children&&o!==null&&o!==void 0&&(n.children=o)}return n}function b4(e,t){const n=t.data||{},a="value"in t&&!(zg.call(n,"hProperties")||zg.call(n,"hChildren"))?{type:"text",value:t.value}:{type:"element",tagName:"div",properties:{},children:e.all(t)};return e.patch(t,a),e.applyData(t,a)}function y4(e,t){const n=[];let a=-1;for(t&&n.push({type:"text",value:`
`});++a<e.length;)a&&n.push({type:"text",value:`
`}),n.push(e[a]);return t&&e.length>0&&n.push({type:"text",value:`
`}),n}function Wk(e){let t=0,n=e.charCodeAt(t);for(;n===9||n===32;)t++,n=e.charCodeAt(t);return e.slice(t)}function Kk(e,t){const n=g4(e,t),a=n.one(e,void 0),o=a4(n),s=Array.isArray(a)?{type:"root",children:a}:a||{type:"root",children:[]};return o&&s.children.push({type:"text",value:`
`},o),s}function v4(e,t){return e&&"run"in e?async function(n,a){const o=Kk(n,{file:a,...t});await e.run(o,a)}:function(n,a){return Kk(n,{file:a,...e||t})}}function Xk(e){if(e)throw e}var og,Zk;function E4(){if(Zk)return og;Zk=1;var e=Object.prototype.hasOwnProperty,t=Object.prototype.toString,n=Object.defineProperty,a=Object.getOwnPropertyDescriptor,o=function(g){return typeof Array.isArray=="function"?Array.isArray(g):t.call(g)==="[object Array]"},s=function(g){if(!g||t.call(g)!=="[object Object]")return!1;var h=e.call(g,"constructor"),m=g.constructor&&g.constructor.prototype&&e.call(g.constructor.prototype,"isPrototypeOf");if(g.constructor&&!h&&!m)return!1;var E;for(E in g);return typeof E>"u"||e.call(g,E)},u=function(g,h){n&&h.name==="__proto__"?n(g,h.name,{enumerable:!0,configurable:!0,value:h.newValue,writable:!0}):g[h.name]=h.newValue},c=function(g,h){if(h==="__proto__")if(e.call(g,h)){if(a)return a(g,h).value}else return;return g[h]};return og=function f(){var g,h,m,E,S,x,w=arguments[0],T=1,A=arguments.length,_=!1;for(typeof w=="boolean"&&(_=w,w=arguments[1]||{},T=2),(w==null||typeof w!="object"&&typeof w!="function")&&(w={});T<A;++T)if(g=arguments[T],g!=null)for(h in g)m=c(w,h),E=c(g,h),w!==E&&(_&&E&&(s(E)||(S=o(E)))?(S?(S=!1,x=m&&o(m)?m:[]):x=m&&s(m)?m:{},u(w,{name:h,newValue:f(_,x,E)})):typeof E<"u"&&u(w,{name:h,newValue:E}));return w},og}var S4=E4();const sg=wc(S4);function $g(e){if(typeof e!="object"||e===null)return!1;const t=Object.getPrototypeOf(e);return(t===null||t===Object.prototype||Object.getPrototypeOf(t)===null)&&!(Symbol.toStringTag in e)&&!(Symbol.iterator in e)}function x4(){const e=[],t={run:n,use:a};return t;function n(...o){let s=-1;const u=o.pop();if(typeof u!="function")throw new TypeError("Expected function as last argument, not "+u);c(null,...o);function c(f,...g){const h=e[++s];let m=-1;if(f){u(f);return}for(;++m<o.length;)(g[m]===null||g[m]===void 0)&&(g[m]=o[m]);o=g,h?w4(h,c)(...g):u(null,...g)}}function a(o){if(typeof o!="function")throw new TypeError("Expected `middelware` to be a function, not "+o);return e.push(o),t}}function w4(e,t){let n;return a;function a(...u){const c=e.length>u.length;let f;c&&u.push(o);try{f=e.apply(this,u)}catch(g){const h=g;if(c&&n)throw h;return o(h)}c||(f&&f.then&&typeof f.then=="function"?f.then(s,o):f instanceof Error?o(f):s(f))}function o(u,...c){n||(n=!0,t(u,...c))}function s(u){o(null,u)}}const rr={basename:T4,dirname:A4,extname:k4,join:_4,sep:"/"};function T4(e,t){if(t!==void 0&&typeof t!="string")throw new TypeError('"ext" argument must be a string');al(e);let n=0,a=-1,o=e.length,s;if(t===void 0||t.length===0||t.length>e.length){for(;o--;)if(e.codePointAt(o)===47){if(s){n=o+1;break}}else a<0&&(s=!0,a=o+1);return a<0?"":e.slice(n,a)}if(t===e)return"";let u=-1,c=t.length-1;for(;o--;)if(e.codePointAt(o)===47){if(s){n=o+1;break}}else u<0&&(s=!0,u=o+1),c>-1&&(e.codePointAt(o)===t.codePointAt(c--)?c<0&&(a=o):(c=-1,a=u));return n===a?a=u:a<0&&(a=e.length),e.slice(n,a)}function A4(e){if(al(e),e.length===0)return".";let t=-1,n=e.length,a;for(;--n;)if(e.codePointAt(n)===47){if(a){t=n;break}}else a||(a=!0);return t<0?e.codePointAt(0)===47?"/":".":t===1&&e.codePointAt(0)===47?"//":e.slice(0,t)}function k4(e){al(e);let t=e.length,n=-1,a=0,o=-1,s=0,u;for(;t--;){const c=e.codePointAt(t);if(c===47){if(u){a=t+1;break}continue}n<0&&(u=!0,n=t+1),c===46?o<0?o=t:s!==1&&(s=1):o>-1&&(s=-1)}return o<0||n<0||s===0||s===1&&o===n-1&&o===a+1?"":e.slice(o,n)}function _4(...e){let t=-1,n;for(;++t<e.length;)al(e[t]),e[t]&&(n=n===void 0?e[t]:n+"/"+e[t]);return n===void 0?".":N4(n)}function N4(e){al(e);const t=e.codePointAt(0)===47;let n=C4(e,!t);return n.length===0&&!t&&(n="."),n.length>0&&e.codePointAt(e.length-1)===47&&(n+="/"),t?"/"+n:n}function C4(e,t){let n="",a=0,o=-1,s=0,u=-1,c,f;for(;++u<=e.length;){if(u<e.length)c=e.codePointAt(u);else{if(c===47)break;c=47}if(c===47){if(!(o===u-1||s===1))if(o!==u-1&&s===2){if(n.length<2||a!==2||n.codePointAt(n.length-1)!==46||n.codePointAt(n.length-2)!==46){if(n.length>2){if(f=n.lastIndexOf("/"),f!==n.length-1){f<0?(n="",a=0):(n=n.slice(0,f),a=n.length-1-n.lastIndexOf("/")),o=u,s=0;continue}}else if(n.length>0){n="",a=0,o=u,s=0;continue}}t&&(n=n.length>0?n+"/..":"..",a=2)}else n.length>0?n+="/"+e.slice(o+1,u):n=e.slice(o+1,u),a=u-o-1;o=u,s=0}else c===46&&s>-1?s++:s=-1}return n}function al(e){if(typeof e!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(e))}const R4={cwd:I4};function I4(){return"/"}function Gg(e){return!!(e!==null&&typeof e=="object"&&"href"in e&&e.href&&"protocol"in e&&e.protocol&&e.auth===void 0)}function O4(e){if(typeof e=="string")e=new URL(e);else if(!Gg(e)){const t=new TypeError('The "path" argument must be of type string or an instance of URL. Received `'+e+"`");throw t.code="ERR_INVALID_ARG_TYPE",t}if(e.protocol!=="file:"){const t=new TypeError("The URL must be of scheme file");throw t.code="ERR_INVALID_URL_SCHEME",t}return D4(e)}function D4(e){if(e.hostname!==""){consLine truncated
`:" ")+s.indentLines(s.containerFlow(a,c.current()),t?JR:xG))),g(),f}}function xG(e,t,n){return t===0?e:JR(e,t,n)}function JR(e,t,n){return(n?"":" ")+e}const wG=["autolink","destinationLiteral","destinationRaw","reference","titleQuote","titleApostrophe"];e0.peek=NG;function TG(){return{canContainEols:["delete"],enter:{strikethrough:kG},exit:{strikethrough:_G}}}function AG(){return{unsafe:[{character:"~",inConstruct:"phrasing",notInConstruct:wG}],handlers:{delete:e0}}}function kG(e){this.enter({type:"delete",children:[]},e)}function _G(e){this.exit(e)}function e0(e,t,n,a){const o=n.createTracker(a),s=n.enter("strikethrough");let u=o.move("~~");return u+=n.containerPhrasing(e,{...o.current(),before:u,after:"~"}),u+=o.move("~~"),s(),u}function NG(){return"~"}function CG(e){return e.length}function RG(e,t){const n=t||{},a=(n.align||[]).concat(),o=n.stringLength||CG,s=[],u=[],c=[],f=[];let g=0,h=-1;for(;++h<e.length;){const w=[],T=[];let A=-1;for(e[h].length>g&&(g=e[h].length);++A<e[h].length;){const _=IG(e[h][A]);if(n.alignDelimiters!==!1){const N=o(_);T[A]=N,(f[A]===void 0||N>f[A])&&(f[A]=N)}w.push(_)}u[h]=w,c[h]=T}let m=-1;if(typeof a=="object"&&"length"in a)for(;++m<g;)s[m]=a_(a[m]);else{const w=a_(a);for(;++m<g;)s[m]=w}m=-1;const E=[],S=[];for(;++m<g;){const w=s[m];let T="",A="";w===99?(T=":",A=":"):w===108?T=":":w===114&&(A=":");let _=n.alignDelimiters===!1?1:Math.max(1,f[m]-T.length-A.length);const N=T+"-".repeat(_)+A;n.alignDelimiters!==!1&&(_=T.length+_+A.length,_>f[m]&&(f[m]=_),S[m]=_),E[m]=N}u.splice(1,0,E),c.splice(1,0,S),h=-1;const x=[];for(;++h<u.length;){const w=u[h],T=c[h];m=-1;const A=[];for(;++m<g;){const _=w[m]||"";let N="",L="";if(n.alignDelimiters!==!1){const U=f[m]-(T[m]||0),D=s[m];D===114?N=" ".repeat(U):D===99?U%2?(N=" ".repeat(U/2+.5),L=" ".repeat(U/2-.5)):(N=" ".repeat(U/2),L=N):L=" ".repeat(U)}n.delimiterStart!==!1&&!m&&A.push("|"),n.padding!==!1&&!(n.alignDelimiters===!1&&_==="")&&(n.delimiterStart!==!1||m)&&A.push(" "),n.alignDelimiters!==!1&&A.push(N),A.push(_),n.alignDelimiters!==!1&&A.push(L),n.padding!==!1&&A.push(" "),(n.delimiterEnd!==!1||m!==g-1)&&A.push("|")}x.push(n.delimiterEnd===!1?A.join("").replace(/ +$/,""):A.join(""))}return x.join(`
`)}function IG(e){return e==null?"":String(e)}function a_(e){const t=typeof e=="string"?e.codePointAt(0):0;return t===67||t===99?99:t===76||t===108?108:t===82||t===114?114:0}function OG(e,t,n,a){const o=n.enter("blockquote"),s=n.createTracker(a);s.move("> "),s.shift(2);const u=n.indentLines(n.containerFlow(e,s.current()),DG);return o(),u}function DG(e,t,n){return">"+(n?"":" ")+e}function LG(e,t){return i_(e,t.inConstruct,!0)&&!i_(e,t.notInConstruct,!1)}function i_(e,t,n){if(typeof t=="string"&&(t=[t]),!t||t.length===0)return n;let a=-1;for(;++a<t.length;)if(e.includes(t[a]))return!0;return!1}function o_(e,t,n,a){let o=-1;for(;++o<n.unsafe.length;)if(n.unsafe[o].character===`
`&&LG(n.stack,n.unsafe[o]))return/[ \t]/.test(a.before)?"":" ";return`\\
`}function MG(e,t){const n=String(e);let a=n.indexOf(t),o=a,s=0,u=0;if(typeof t!="string")throw new TypeError("Expected substring");for(;a!==-1;)a===o?++s>u&&(u=s):s=1,o=a+t.length,a=n.indexOf(t,o);return u}function jG(e,t){return!!(t.options.fences===!1&&e.value&&!e.lang&&/[^ \r\n]/.test(e.value)&&!/^[\t ]*(?:[\r\n]|$)|(?:^|[\r\n])[\t ]*$/.test(e.value))}function UG(e){const t=e.options.fence||"`";if(t!=="`"&&t!=="~")throw new Error("Cannot serialize code with `"+t+"` for `options.fence`, expected `` ` `` or `~`");return t}function FG(e,t,n,a){const o=UG(n),s=e.value||"",u=o==="`"?"GraveAccent":"Tilde";if(jG(e,n)){const m=n.enter("codeIndented"),E=n.indentLines(s,BG);return m(),E}const c=n.createTracker(a),f=o.repeat(Math.max(MG(s,o)+1,3)),g=n.enter("codeFenced");let h=c.move(f);if(e.lang){const m=n.enter(`codeFencedLang${u}`);h+=c.move(n.safe(e.lang,{before:h,after:" ",encode:["`"],...c.current()})),m()}if(e.lang&&e.meta){const m=n.enter(`codeFencedMeta${u}`);h+=c.move(" "),h+=c.move(n.safe(e.meta,{before:h,after:`
`,encode:["`"],...c.current()})),m()}return h+=c.move(`
`),s&&(h+=c.move(s+`
`)),h+=c.move(f),g(),h}function BG(e,t,n){return(n?"":" ")+e}function rh(e){const t=e.options.quote||'"';if(t!=='"'&&t!=="'")throw new Error("Cannot serialize title with `"+t+"` for `options.quote`, expected `\"`, or `'`");return t}function PG(e,t,n,a){const o=rh(n),s=o==='"'?"Quote":"Apostrophe",u=n.enter("definition");let c=n.enter("label");const f=n.createTracker(a);let g=f.move("[");return g+=f.move(n.safe(n.associationId(e),{before:g,after:"]",...f.current()})),g+=f.move("]: "),c(),!e.url||/[\0- \u007F]/.test(e.url)?(c=n.enter("destinationLiteral"),g+=f.move("<"),g+=f.move(n.safe(e.url,{before:g,after:">",...f.current()})),g+=f.move(">")):(c=n.enter("destinationRaw"),g+=f.move(n.safe(e.url,{before:g,after:e.title?" ":`
`,...f.current()}))),c(),e.title&&(c=n.enter(`title${s}`),g+=f.move(" "+o),g+=f.move(n.safe(e.title,{before:g,after:o,...f.current()})),g+=f.move(o),c()),u(),g}function zG(e){const t=e.options.emphasis||"*";if(t!=="*"&&t!=="_")throw new Error("Cannot serialize emphasis with `"+t+"` for `options.emphasis`, expected `*`, or `_`");return t}function $s(e){return"&#x"+e.toString(16).toUpperCase()+";"}function yc(e,t,n){const a=io(e),o=io(t);return a===void 0?o===void 0?n==="_"?{inside:!0,outside:!0}:{inside:!1,outside:!1}:o===1?{inside:!0,outside:!0}:{inside:!1,outside:!0}:a===1?o===void 0?{inside:!1,outside:!1}:o===1?{inside:!0,outside:!0}:{inside:!1,outside:!1}:o===void 0?{inside:!1,outside:!1}:o===1?{inside:!0,outside:!1}:{inside:!1,outside:!1}}t0.peek=$G;function t0(e,t,n,a){const o=zG(n),s=n.enter("emphasis"),u=n.createTracker(a),c=u.move(o);let f=u.move(n.containerPhrasing(e,{after:o,before:c,...u.current()}));const g=f.charCodeAt(0),h=yc(a.before.charCodeAt(a.before.length-1),g,o);h.inside&&(f=$s(g)+f.slice(1));const m=f.charCodeAt(f.length-1),E=yc(a.after.charCodeAt(0),m,o);E.inside&&(f=f.slice(0,-1)+$s(m));const S=u.move(o);return s(),n.attentionEncodeSurroundingInfo={after:E.outside,before:h.outside},c+f+S}function $G(e,t,n){return n.options.emphasis||"*"}function GG(e,t){let n=!1;return th(e,function(a){if("value"in a&&/\r?\n|\r/.test(a.value)||a.type==="break")return n=!0,Pg}),!!((!e.depth||e.depth<3)&&Km(e)&&(t.options.setext||n))}function HG(e,t,n,a){const o=Math.max(Math.min(6,e.depth||1),1),s=n.createTracker(a);if(GG(e,n)){const h=n.enter("headingSetext"),m=n.enter("phrasing"),E=n.containerPhrasing(e,{...s.current(),before:`
`,after:`
`});return m(),h(),E+`
`+(o===1?"=":"-").repeat(E.length-(Math.max(E.lastIndexOf("\r"),E.lastIndexOf(`
`))+1))}const u="#".repeat(o),c=n.enter("headingAtx"),f=n.enter("phrasing");s.move(u+" ");let g=n.containerPhrasing(e,{before:"# ",after:`
`,...s.current()});return/^[\t ]/.test(g)&&(g=$s(g.charCodeAt(0))+g.slice(1)),g=g?u+" "+g:u,n.options.closeAtx&&(g+=" "+u),f(),c(),g}n0.peek=VG;function n0(e){return e.value||""}function VG(){return"<"}r0.peek=qG;function r0(e,t,n,a){const o=rh(n),s=o==='"'?"Quote":"Apostrophe",u=n.enter("image");let c=n.enter("label");const f=n.createTracker(a);let g=f.move("![");return g+=f.move(n.safe(e.alt,{before:g,after:"]",...f.current()})),g+=f.move("]("),c(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(c=n.enter("destinationLiteral"),g+=f.move("<"),g+=f.move(n.safe(e.url,{before:g,after:">",...f.current()})),g+=f.move(">")):(c=n.enter("destinationRaw"),g+=f.move(n.safe(e.url,{before:g,after:e.title?" ":")",...f.current()}))),c(),e.title&&(c=n.enter(`title${s}`),g+=f.move(" "+o),g+=f.move(n.safe(e.title,{before:g,after:o,...f.current()})),g+=f.move(o),c()),g+=f.move(")"),u(),g}function qG(){return"!"}a0.peek=YG;function a0(e,t,n,a){const o=e.referenceType,s=n.enter("imageReference");let u=n.enter("label");const c=n.createTracker(a);let f=c.move("![");const g=n.safe(e.alt,{before:f,after:"]",...c.current()});f+=c.move(g+"]["),u();const h=n.stack;n.stack=[],u=n.enter("reference");const m=n.safe(n.associationId(e),{before:f,after:"]",...c.current()});return u(),n.stack=h,s(),o==="full"||!g||g!==m?f+=c.move(m+"]"):o==="shortcut"?f=f.slice(0,-1):f+=c.move("]"),f}function YG(){return"!"}i0.peek=WG;function i0(e,t,n){let a=e.value||"",o="`",s=-1;for(;new RegExp("(^|[^`])"+o+"([^`]|$)").test(a);)o+="`";for(/[^ \r\n]/.test(a)&&(/^[ \r\n]/.test(a)&&/[ \r\n]$/.test(a)||/^`|`$/.test(a))&&(a=" "+a+" ");++s<n.unsafe.length;){const u=n.unsafe[s],c=n.compilePattern(u);let f;if(u.atBreak)for(;f=c.exec(a);){let g=f.index;a.charCodeAt(g)===10&&a.charCodeAt(g-1)===13&&g--,a=a.slice(0,g)+" "+a.slice(f.index+1)}}return o+a+o}function WG(){return"`"}function o0(e,t){const n=Km(e);return!!(!t.options.resourceLink&&e.url&&!e.title&&e.children&&e.children.length===1&&e.children[0].type==="text"&&(n===e.url||"mailto:"+n===e.url)&&/^[a-z][a-z+.-]+:/i.test(e.url)&&!/[\0- <>\u007F]/.test(e.url))}s0.peek=KG;function s0(e,t,n,a){const o=rh(n),s=o==='"'?"Quote":"Apostrophe",u=n.createTracker(a);let c,f;if(o0(e,n)){const h=n.stack;n.stack=[],c=n.enter("autolink");let m=u.move("<");return m+=u.move(n.containerPhrasing(e,{before:m,after:">",...u.current()})),m+=u.move(">"),c(),n.stack=h,m}c=n.enter("link"),f=n.enter("label");let g=u.move("[");return g+=u.move(n.containerPhrasing(e,{before:g,after:"](",...u.current()})),g+=u.move("]("),f(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(f=n.enter("destinationLiteral"),g+=u.move("<"),g+=u.move(n.safe(e.url,{before:g,after:">",...u.current()})),g+=u.move(">")):(f=n.enter("destinationRaw"),g+=u.move(n.safe(e.url,{before:g,after:e.title?" ":")",...u.current()}))),f(),e.title&&(f=n.enter(`title${s}`),g+=u.move(" "+o),g+=u.move(n.safe(e.title,{before:g,after:o,...u.current()})),g+=u.move(o),f()),g+=u.move(")"),c(),g}function KG(e,t,n){return o0(e,n)?"<":"["}l0.peek=XG;function l0(e,t,n,a){const o=e.referenceType,s=n.enter("linkReference");let u=n.enter("label");const c=n.createTracker(a);let f=c.move("[");const g=n.containerPhrasing(e,{before:f,after:"]",...c.current()});f+=c.move(g+"]["),u();const h=n.stack;n.stack=[],u=n.enter("reference");const m=n.safe(n.associationId(e),{before:f,after:"]",...c.current()});return u(),n.stack=h,s(),o==="full"||!g||g!==m?f+=c.move(m+"]"):o==="shortcut"?f=f.slice(0,-1):f+=c.move("]"),f}function XG(){return"["}function ah(e){const t=e.options.bullet||"*";if(t!=="*"&&t!=="+"&&t!=="-")throw new Error("Cannot serialize items with `"+t+"` for `options.bullet`, expected `*`, `+`, or `-`");return t}function ZG(e){const t=ah(e),n=e.options.bulletOther;if(!n)return t==="*"?"-":"*";if(n!=="*"&&n!=="+"&&n!=="-")throw new Error("Cannot serialize items with `"+n+"` for `options.bulletOther`, expected `*`, `+`, or `-`");if(n===t)throw new Error("Expected `bullet` (`"+t+"`) and `bulletOther` (`"+n+"`) to be different");return n}function QG(e){const t=e.options.bulletOrdered||".";if(t!=="."&&t!==")")throw new Error("Cannot serialize items with `"+t+"` for `options.bulletOrdered`, expected `.` or `)`");return t}function u0(e){const t=e.options.rule||"*";if(t!=="*"&&t!=="-"&&t!=="_")throw new Error("Cannot serialize rules with `"+t+"` for `options.rule`, expected `*`, `-`, or `_`");return t}function JG(e,t,n,a){const o=n.enter("list"),s=n.bulletCurrent;let u=e.ordered?QG(n):ah(n);const c=e.ordered?u==="."?")":".":ZG(n);let f=t&&n.bulletLastUsed?u===n.bulletLastUsed:!1;if(!e.ordered){const h=e.children?e.children[0]:void 0;if((u==="*"||u==="-")&&h&&(!h.children||!h.children[0])&&n.stack[n.stack.length-1]==="list"&&n.stack[n.stack.length-2]==="listItem"&&n.stack[n.stack.length-3]==="list"&&n.stack[n.stack.length-4]==="listItem"&&n.indexStack[n.indexStack.length-1]===0&&n.indexStack[n.indexStack.length-2]===0&&n.indexStack[n.indexStack.length-3]===0&&(f=!0),u0(n)===u&&h){let m=-1;for(;++m<e.chilLine truncated
`,inConstruct:"tableCell"},{atBreak:!0,character:"|",after:"[ :-]"},{character:"|",inConstruct:"tableCell"},{atBreak:!0,character:":",after:"-"},{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{inlineCode:E,table:u,tableCell:f,tableRow:c}};function u(S,x,w,T){return g(h(S,w,T),S.align)}function c(S,x,w,T){const A=m(S,w,T),_=g([A]);return _.slice(0,_.indexOf(`
`))}function f(S,x,w,T){const A=w.enter("tableCell"),_=w.enter("phrasing"),N=w.containerPhrasing(S,{...T,before:s,after:s});return _(),A(),N}function g(S,x){return RG(S,{align:x,alignDelimiters:a,padding:n,stringLength:o})}function h(S,x,w){const T=S.children;let A=-1;const _=[],N=x.enter("table");for(;++A<T.length;)_[A]=m(T[A],x,w);return N(),_}function m(S,x,w){const T=S.children;let A=-1;const _=[],N=x.enter("tableRow");for(;++A<T.length;)_[A]=f(T[A],S,x,w);return N(),_}function E(S,x,w){let T=d0.inlineCode(S,x,w);return w.stack.includes("tableCell")&&(T=T.replace(/\|/g,"\\$&")),T}}function bH(){return{exit:{taskListCheckValueChecked:l_,taskListCheckValueUnchecked:l_,paragraph:vH}}}function yH(){return{unsafe:[{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{listItem:EH}}}function l_(e){const t=this.stack[this.stack.length-2];t.type,t.checked=e.type==="taskListCheckValueChecked"}function vH(e){const t=this.stack[this.stack.length-2];if(t&&t.type==="listItem"&&typeof t.checked=="boolean"){const n=this.stack[this.stack.length-1];n.type;const a=n.children[0];if(a&&a.type==="text"){const o=t.children;let s=-1,u;for(;++s<o.length;){const c=o[s];if(c.type==="paragraph"){u=c;break}}u===n&&(a.value=a.value.slice(1),a.value.length===0?n.children.shift():n.position&&a.position&&typeof a.position.start.offset=="number"&&(a.position.start.column++,a.position.start.offset++,n.position.start=Object.assign({},a.position.start)))}}this.exit(e)}function EH(e,t,n,a){const o=e.children[0],s=typeof e.checked=="boolean"&&o&&o.type==="paragraph",u="["+(e.checked?"x":" ")+"] ",c=n.createTracker(a);s&&c.move(u);let f=d0.listItem(e,t,n,{...a,...c.current()});return s&&(f=f.replace(/^(?:[*+-]|\d+\.)([\r\n]| {1,3})/,g)),f;function g(h){return h+u}}function SH(){return[J4(),EG(),TG(),cH(),bH()]}function xH(e){return{extensions:[eG(),SG(e),AG(),hH(e),yH()]}}const wH={tokenize:CH,partial:!0},p0={tokenize:RH,partial:!0},f0={tokenize:IH,partial:!0},g0={tokenize:OH,partial:!0},TH={tokenize:DH,partial:!0},m0={name:"wwwAutolink",tokenize:_H,previous:b0},h0={name:"protocolAutolink",tokenize:NH,previous:y0},Lr={name:"emailAutolink",tokenize:kH,previous:v0},ur={};function AH(){return{text:ur}}let Ha=48;for(;Ha<123;)ur[Ha]=Lr,Ha++,Ha===58?Ha=65:Ha===91&&(Ha=97);ur[43]=Lr;ur[45]=Lr;ur[46]=Lr;ur[95]=Lr;ur[72]=[Lr,h0];ur[104]=[Lr,h0];ur[87]=[Lr,m0];ur[119]=[Lr,m0];function kH(e,t,n){const a=this;let o,s;return u;function u(m){return!Hg(m)||!v0.call(a,a.previous)||ih(a.events)?n(m):(e.enter("literalAutolink"),e.enter("literalAutolinkEmail"),c(m))}function c(m){return Hg(m)?(e.consume(m),c):m===64?(e.consume(m),f):n(m)}function f(m){return m===46?e.check(TH,h,g)(m):m===45||m===95||zt(m)?(s=!0,e.consume(m),f):h(m)}function g(m){return e.consume(m),o=!0,f}function h(m){return s&&o&&Kt(a.previous)?(e.exit("literalAutolinkEmail"),e.exit("literalAutolink"),t(m)):n(m)}}function _H(e,t,n){const a=this;return o;function o(u){return u!==87&&u!==119||!b0.call(a,a.previous)||ih(a.events)?n(u):(e.enter("literalAutolink"),e.enter("literalAutolinkWww"),e.check(wH,e.attempt(p0,e.attempt(f0,s),n),n)(u))}function s(u){return e.exit("literalAutolinkWww"),e.exit("literalAutolink"),t(u)}}function NH(e,t,n){const a=this;let o="",s=!1;return u;function u(m){return(m===72||m===104)&&y0.call(a,a.previous)&&!ih(a.events)?(e.enter("literalAutolink"),e.enter("literalAutolinkHttp"),o+=String.fromCodePoint(m),e.consume(m),c):n(m)}function c(m){if(Kt(m)&&o.length<5)return o+=String.fromCodePoint(m),e.consume(m),c;if(m===58){const E=o.toLowerCase();if(E==="http"||E==="https")return e.consume(m),f}return n(m)}function f(m){return m===47?(e.consume(m),s?g:(s=!0,f)):n(m)}function g(m){return m===null||mc(m)||ot(m)||Ka(m)||Hc(m)?n(m):e.attempt(p0,e.attempt(f0,h),n)(m)}function h(m){return e.exit("literalAutolinkHttp"),e.exit("literalAutolink"),t(m)}}function CH(e,t,n){let a=0;return o;function o(u){return(u===87||u===119)&&a<3?(a++,e.consume(u),o):u===46&&a===3?(e.consume(u),s):n(u)}function s(u){return u===null?n(u):t(u)}}function RH(e,t,n){let a,o,s;return u;function u(g){return g===46||g===95?e.check(g0,f,c)(g):g===null||ot(g)||Ka(g)||g!==45&&Hc(g)?f(g):(s=!0,e.consume(g),u)}function c(g){return g===95?a=!0:(o=a,a=void 0),e.consume(g),u}function f(g){return o||a||!s?n(g):t(g)}}function IH(e,t){let n=0,a=0;return o;function o(u){return u===40?(n++,e.consume(u),o):u===41&&a<n?s(u):u===33||u===34||u===38||u===39||u===41||u===42||u===44||u===46||u===58||u===59||u===60||u===63||u===93||u===95||u===126?e.check(g0,t,s)(u):u===null||ot(u)||Ka(u)?t(u):(e.consume(u),o)}function s(u){return u===41&&a++,e.consume(u),o}}function OH(e,t,n){return a;function a(c){return c===33||c===34||c===39||c===41||c===42||c===44||c===46||c===58||c===59||c===63||c===95||c===126?(e.consume(c),a):c===38?(e.consume(c),s):c===93?(e.consume(c),o):c===60||c===null||ot(c)||Ka(c)?t(c):n(c)}function o(c){return c===null||c===40||c===91||ot(c)||Ka(c)?t(c):a(c)}function s(c){return Kt(c)?u(c):n(c)}function u(c){re Line truncated
`),n=[];let a=0;for(;a<t.length;){const o=t[a].match(/^===\s+"([^"]+)"\s*$/);if(!o){n.push(t[a]),a++;continue}const s=o[1];for(a++;a<t.length&&t[a].trim()==="";)a++;const u=[];for(;a<t.length&&!(/^===\s+"[^"]+"\s*$/.test(t[a])||t[a].trim()===""&&a+1<t.length&&/^===\s+"[^"]+"\s*$/.test(t[a+1]));){if(t[a].startsWith(" ")||t[a].trimStart().startsWith("```")){u.push(t[a].replace(/^ /,"")),a++;continue}if(u.length>0&&t[a].trim()===""){u.push(""),a++;continue}break}n.push(`### ${p5}${s}`),n.push(""),n.push(...u),n.push("")}return n.join(`
`)}function h5(e){let t=g5(e);return t=f5(t),t=m5(t),t}const b5="modulepreload",y5=function(e){return"/"+e},d_={},Vg=function(t,n,a){let o=Promise.resolve();if(n&&n.length>0){let f=function(g){return Promise.all(g.map(h=>Promise.resolve(h).then(m=>({status:"fulfilled",value:m}),m=>({status:"rejected",reason:m}))))};document.getElementsByTagName("link");const u=document.querySelector("meta[property=csp-nonce]"),c=u?.nonce||u?.getAttribute("nonce");o=f(n.map(g=>{if(g=y5(g),g in d_)return;d_[g]=!0;const h=g.endsWith(".css"),m=h?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${g}"]${m}`))return;const E=document.createElement("link");if(E.rel=h?"stylesheet":b5,h||(E.as="script"),E.crossOrigin="",E.href=g,c&&E.setAttribute("nonce",c),document.head.appendChild(E),h)return new Promise((S,x)=>{E.addEventListener("load",S),E.addEventListener("error",()=>x(new Error(`Unable to preload CSS for ${g}`)))})}))}function s(u){const c=new Event("vite:preloadError",{cancelable:!0});if(c.payload=u,window.dispatchEvent(c),!c.defaultPrevented)throw u}return o.then(u=>{for(const c of u||[])c.status==="rejected"&&s(c.reason);return t().catch(s)})},v5={theme:"base",themeVariables:{background:"transparent",mainBkg:"#0d9488",primaryColor:"#0d9488",primaryBorderColor:"#14b8a6",primaryTextColor:"#ffffff",secondaryColor:"#6366f1",secondaryBorderColor:"#818cf8",secondaryTextColor:"#ffffff",tertiaryColor:"#e11d48",tertiaryBorderColor:"#fb7185",tertiaryTextColor:"#ffffff",textColor:"#f1f5f9",labelTextColor:"#f1f5f9",lineColor:"#94a3b8",arrowheadColor:"#cbd5e1",nodeBorder:"#14b8a6",clusterBkg:"rgba(13, 148, 136, 0.08)",clusterBorder:"rgba(20, 184, 166, 0.4)",defaultLinkColor:"#94a3b8",edgeLabelBackground:"rgba(15, 23, 42, 0.85)",nodeTextColor:"#ffffff",actorBkg:"#0d9488",actorBorder:"#14b8a6",actorTextColor:"#ffffff",actorLineColor:"#64748b",signalColor:"#cbd5e1",signalTextColor:"#f1f5f9",activationBorderColor:"#14b8a6",activationBkgColor:"rgba(13, 148, 136, 0.2)",sequenceNumberColor:"#ffffff",noteBkgColor:"rgba(99, 102, 241, 0.2)",noteBorderColor:"#818cf8",noteTextColor:"#f1f5f9",titleColor:"#f8fafc",fontFamily:'"Inter", system-ui, -apple-system, sans-serif',fontSize:"16px"}},E5={theme:"base",themeVariables:{background:"transparent",mainBkg:"#0d9488",primaryColor:"#0d9488",primaryBorderColor:"#0f766e",primaryTextColor:"#ffffff",secondaryColor:"#6366f1",secondaryBorderColor:"#4f46e5",secondaryTextColor:"#ffffff",tertiaryColor:"#e11d48",tertiaryBorderColor:"#be123c",tertiaryTextColor:"#ffffff",textColor:"#1e293b",labelTextColor:"#334155",lineColor:"#94a3b8",arrowheadColor:"#64748b",nodeBorder:"#0f766e",clusterBkg:"rgba(13, 148, 136, 0.06)",clusterBorder:"rgba(15, 118, 110, 0.3)",defaultLinkColor:"#94a3b8",edgeLabelBackground:"rgba(255, 255, 255, 0.9)",nodeTextColor:"#ffffff",actorBkg:"#0d9488",actorBorder:"#0f766e",actorTextColor:"#ffffff",actorLineColor:"#cbd5e1",signalColor:"#64748b",signalTextColor:"#1e293b",noteBkgColor:"rgba(99, 102, 241, 0.1)",noteBorderColor:"#6366f1",noteTextColor:"#1e293b",titleColor:"#0f172a",fontFamily:'"Inter", system-ui, -apple-system, sans-serif',fontSize:"16px"}};function S5(){return document.documentElement.classList.contains("dark")}function x5(e){return{startOnLoad:!1,securityLevel:"strict",...e?v5:E5,flowchart:{useMaxWidth:!0,htmlLabels:!0,curve:"basis"},sequence:{useMaxWidth:!0,wrap:!0},er:{useMaxWidth:!0},gantt:{useMaxWidth:!0}}}function w5(e,t){const n=Math.max(Math.floor(t),320);return e.replace(/<svg([^>]*)>/,(a,o)=>`<svg${o.replace(/\swidth="[^"]*"/g,"").replace(/\sheight="[^"]*"/g,"").replace(/\sstyle="[^"]*"/g,"")} width="${n}" style="width:100%;max-width:100%;height:auto;display:block;">`)}let p_=0;function T5(e){return p_+=1,`mermaid-${e.replace(/:/g,"")}-${p_}`}function yg({chart:e}){const t=v.useId(),n=v.useRef(null),a=v.useRef(null),o=v.useRef(void 0),[s,u]=v.useState("loading"),[c,f]=v.useState(""),[g,h]=v.useState("");return v.useEffect(()=>{const m=n.current;if(!m)return;let E=!1;const S=async()=>{u("loading"),f(""),h("");const T=(await Vg(async()=>{const{default:L}=await import("./mermaid.core.js").then(U=>U.cb);return{default:L}},[])).default;T.initialize(x5(S5()));const A=getComputedStyle(m),_=parseFloat(A.paddingLeft)+parseFloat(A.paddingRight),N=m.clientWidth-_;try{const{svg:L,bindFunctions:U}=await T.render(T5(t),e);if(E)return;o.current=U,h(w5(L,N)),u("ready")}catch(L){if(E)return;u("error"),f(L instanceof Error?L.message:"Failed to render diagram")}};S();const x=new ResizeObserver(()=>{S()});x.observe(m);const w=new MutationObserver(()=>{S()});return w.observe(document.documentElement,{attributes:!0,attributeFilter:["class"]}),()=>{E=!0,x.disconnect(),w.disconnect()}},[e,t]),v.useEffect(()=>{s!=="ready"||!a.current||o.current?.(a.current)},[s,g]),s==="error"?p.jsx("pre",{className:"mermaid-diagram mermaid-error text-destructive text-sm my-4 p-4 rounded-lg border border-destructive/30 bg-destructive/5 overflow-x-auto",children:c}):p.jsxs("div",{ref:n,className:`mermaiLine truncated
`)===-1?p.jsx("code",{className:"bg-primary/10 text-primary px-1.5 py-0.5 rounded text-sm font-mono",children:A}):p.jsx("code",{className:`block font-mono text-foreground ${T??""}`,children:A}),pre:({children:T})=>{if(v.isValidElement(T)&&T.type===yg)return T;const A=S(T);return A?p.jsx(yg,{chart:A}):p.jsx("pre",{className:"bg-muted text-foreground border border-border p-4 rounded-lg text-sm overflow-auto my-4 font-mono whitespace-pre",children:T})},table:({children:T})=>p.jsx("div",{className:"overflow-auto my-4",children:p.jsx("table",{className:"w-full border-collapse text-sm",children:T})}),thead:({children:T})=>p.jsx("thead",{className:"bg-muted/50",children:T}),tr:({children:T})=>p.jsx("tr",{className:"border-b",children:T}),th:({children:T})=>p.jsx("th",{className:"px-4 py-2 text-left font-medium",children:T}),td:({children:T})=>p.jsx("td",{className:"px-4 py-2 text-foreground",children:T}),hr:()=>p.jsx("hr",{className:"my-6 border-border"}),strong:({children:T})=>p.jsx("strong",{className:"font-semibold text-foreground",children:T}),em:({children:T})=>p.jsx("em",{children:T})},w=u===Pt(a)&&o.length>0;return n?p.jsx("main",{id:"main-content",className:"docs-main flex-1 min-w-0",children:p.jsxs("div",{className:"docs-main-inner mx-auto w-full max-w-[720px] px-6 py-8 lg:px-8",children:[p.jsx(B5,{selectedItem:n}),f&&p.jsx("div",{className:"text-muted-foreground animate-pulse",children:"Loading content..."}),w&&p.jsx("article",{ref:h,className:"prose prose-neutral dark:prose-invert max-w-none prose-pre:bg-muted prose-pre:text-foreground prose-code:text-foreground",children:p.jsx(XR,{remarkPlugins:[E0],components:x,children:o})},a),!f&&!w&&u===Pt(a)&&p.jsx("div",{className:"bg-muted/50 border rounded-lg p-6",children:p.jsxs("p",{className:"text-muted-foreground",children:["Content for ",p.jsx("strong",{className:"text-primary",children:n.title})," would be displayed here."]})})]})}):p.jsx("main",{id:"main-content",className:"docs-main flex-1 min-w-0",children:p.jsxs("div",{className:"docs-main-inner mx-auto w-full max-w-[720px] px-6 py-8 lg:px-8",children:[p.jsx("h1",{className:"text-4xl font-bold tracking-tight mb-4",children:e.site?.title||"Documentation"}),p.jsx("p",{className:"text-muted-foreground text-lg mb-8",children:e.site?.description||"Welcome to the documentation."}),p.jsx(Ns,{className:"my-8"}),p.jsx("h2",{className:"text-2xl font-semibold mb-4 text-primary",children:"Theme Configuration"}),p.jsxs("div",{className:"bg-muted/50 border rounded-lg p-4 mb-6",children:[p.jsx("p",{className:"text-sm text-muted-foreground mb-2",children:p.jsx("strong",{children:"Current theme from YAML:"})}),p.jsx("pre",{className:"bg-muted text-foreground border border-border p-3 rounded-lg text-sm overflow-auto",children:`site:
theme:
preset: "${m?.preset||"zinc"}"
radius: "${m?.radius||"md"}"
darkMode: ${m?.darkMode!==!1}`})]}),p.jsx("h3",{className:"text-lg font-medium mb-3",children:"Available Presets"}),p.jsx("div",{className:"flex flex-wrap gap-2 mb-6",children:Object.keys(KL).map(T=>p.jsx("span",{className:`px-3 py-1 rounded-full text-sm ${T===(m?.preset||"zinc")?"bg-primary text-primary-foreground":"bg-muted text-muted-foreground"}`,children:T},T))}),p.jsxs("p",{className:"text-muted-foreground mb-4",children:[p.jsx("strong",{children:"Click any item in the sidebar"})," to navigate."]}),p.jsx("h2",{className:"text-2xl font-semibold mt-8 mb-4",children:"Routes"}),p.jsxs("p",{className:"text-muted-foreground mb-4",children:[p.jsx("span",{className:"font-medium text-primary",children:t.routes?.length||0})," routes configured."]}),p.jsx("pre",{className:"bg-muted text-foreground border border-border p-4 rounded-lg text-sm overflow-auto",children:JSON.stringify(t.routes?.slice(0,3),null,2)})]})})}function Vu({config:e,templateKey:t="docs"}){const n=e.templates?.[t]?.slots?.footer,a=n?.ref,s=(a?e.components?.[a]:e.components?.footer)?.props||n?.props;return p.jsx("footer",{className:"border-t border-border/50 py-8 px-6 bg-muted/20",children:p.jsxs("div",{className:"max-w-screen-2xl mx-auto flex flex-col sm:flex-row justify-between items-center gap-4 text-sm text-muted-foreground",children:[p.jsxs("div",{className:"flex items-center gap-2",children:[p.jsx("div",{className:"w-5 h-5 rounded bg-gradient-to-br from-primary/60 to-primary flex items-center justify-center",children:p.jsx("span",{className:"text-primary-foreground text-[8px] font-bold",children:"AI"})}),p.jsx("span",{children:s?.text||`© ${new Date().getFullYear()} PraisonAIUI`})]}),p.jsx("nav",{className:"flex items-center gap-6",children:s?.links?.map(u=>p.jsx("a",{href:u.href,className:"hover:text-foreground transition-colors",children:u.label},u.href))})]})})}const P5=()=>({taskLists:[],collapsed:!1}),Vn=new Map,qg=100,z5=1440*60*1e3;function $5(){const e=Date.now(),t=Array.from(Vn.entries());for(const[n,a]of t)e-a.lastAccessed>z5&&Vn.delete(n);if(Vn.size>qg){const n=Array.from(Vn.entries()).sort(([,o],[,s])=>o.lastAccessed-s.lastAccessed),a=Vn.size-qg;for(let o=0;o<a;o++)Vn.delete(n[o][0])}}function Yg(e){if(!Vn.has(e))Vn.size>=qg&&$5(),Vn.set(e,{state:P5(),listeners:new Set,lastAccessed:Date.now()});else{const t=Vn.get(e);t.lastAccessed=Date.now()}return Vn.get(e)}function sh(e,t){const n=Yg(e),a=t(n.state);n.state=a,n.listeners.forEach(o=>o())}function G5(e,t){sh(e,n=>{const a=n.taskLists.filter(s=>s.id!==t.task_list_id),o={id:t.task_list_id,name:t.name,tasks:t.tasks,stats:T0(t.tasks),sequence:t.sequence,created_at:t.timestamp,updated_at:t.timestamp};return{...n,taskLists:[...a,o],collapsed:n.taskLists.length===0?t.tasks.length<=1:n.collapsed}})}function H5(e,t){sh(e,n=>{const a=n.taskLists.map(o=>o.id===t.task_list_id?{...o,tasks:t.tasks,stats:T0(t.tasks),sequence:t.sequence,updated_at:t.timestamp}:o);return{...n,taskLists:a}})}function T0(e){return e.reduce((t,n)=>(t.total+=1,t[n.status.toLowerCase()]+=1,t),{total:0,ready:0,running:0,done:0,failed:0})}function V5(e,t){sh(e,n=>({...n,collapsed:t}))}function q5(e){const[,t]=v.useState({});return v.useEffect(()=>{const n=Yg(e),a=()=>t({});return n.listeners.add(a),()=>{n.listeners.delete(a)}},[e]),Yg(e).state}function Y5(e,t){return t.type==="task_list.init"?(G5(e,t),!0):t.type==="task_list.update"?(H5(e,t),!0):!1}const A0=()=>({isStreaming:!1,currentResponse:"",toolCalls:[],thinkingSteps:[],pendingElements:[]}),qa=new Map;function Kc(e){return qa.has(e)||qa.set(e,{state:A0(),listeners:new Set,abortController:null,toolCallMap:new Map}),qa.get(e)}function qu(e){return e?Kc(e).state:A0()}function W5(e,t){const n=Kc(e);return n.listeners.add(t),()=>n.listeners.delete(t)}function Dn(e,t){const n=Kc(e);n.state={...n.state,...t},n.listeners.forEach(a=>a())}async function K5(e){const t=qa.get(e);if(t){t.abortController?.abort(),t.abortController=null,Dn(e,{isStreaming:!1});try{await fetch("/cancel",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({session_id:e})})}catch{}}}function X5(e,t,n,a){const o=Kc(e);if(o.state.isStreaming)return;Dn(e,{isStreaming:!0,currentResponse:"",toolCalls:[],thinkingSteps:[],pendingElements:[]}),o.toolCallMap=new Map;const s=new AbortController;o.abortController=s,Z5(e,t,n,s,a)}async function Z5(e,t,n,a,o){try{const s=await fetch("/run",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:t,session_id:e,agent:n}),signal:a.signal});if(!s.ok)throw new Error(`HTTP ${s.status}`);const u=s.body?.getReader();if(!u)throw new Error("No response body");const c=new TextDecoder;let f="";for(;;){const{done:g,value:h}=await u.read();if(g)break;f+=c.decode(h,{stream:!0});const m=f.split(`
`);f=m.pop()||"";for(const E of m)if(E.startsWith("data: "))try{const S=JSON.parse(E.slice(6));Q5(e,S,o)}catch{}}}catch(s){if(s.name!=="AbortError"){const u=qa.get(e);u&&Dn(e,{thinkingSteps:[...u.state.thinkingSteps,`Error: ${s.message}`]})}}finally{const s=qa.get(e);s&&(s.abortController=null),Dn(e,{isStreaming:!1}),o?.onEnd?.()}}function Q5(e,t,n){const a=qa.get(e);if(!a)return;const o=a.toolCallMap;switch(t.type){case"session":t.session_id&&typeof t.session_id=="string"&&n?.onSessionId?.(t.session_id);break;case"token":case"run_content":case"team_run_content":{const u=t.token??t.content??"";u&&Dn(e,{currentResponse:a.state.currentResponse+u});break}case"message":case"run_completed":case"team_run_completed":{const u=t.content;u&&Dn(e,{currentResponse:u});break}case"thinking":case"reasoning_step":case"team_reasoning_step":{const u=t.step;u&&Dn(e,{thinkingSteps:[...a.state.thinkingSteps,u]});break}case"reasoning_started":case"team_reasoning_started":Dn(e,{thinkingSteps:[...a.state.thinkingSteps,"Starting reasoning..."]});break;case"tool_call":case"tool_call_started":case"team_tool_call_started":{const u={name:t.name,description:t.description,icon:t.icon,step_number:t.step_number,status:"running",tool_call_id:t.tool_call_id,args:t.args};u.tool_call_id&&o.set(u.tool_call_id,u);const c=g_(a.state.toolCalls,u);Dn(e,{toolCalls:c});break}case"tool_call_completed":case"team_tool_call_completed":{const u=t.extra_data,c=t.a2ui??u?.a2ui,f=t.elements??u?.elements,g={name:t.name,description:t.description,icon:t.icon,step_number:t.step_number,status:"done",tool_call_id:t.tool_call_id,args:t.args,formatted_result:t.formatted_result,result:t.result,surface_id:t.surface_id??u?.surface_id,a2ui:c?.length?{messages:c,surface_id:t.surface_id??u?.surface_id}:void 0,elements:f};g.tool_call_id&&o.set(g.tool_call_id,g);const h=g_(a.state.toolCalls,g),m=f?.length?[...a.state.pendingElements,...f]:a.state.pendingElements;Dn(e,{toolCalls:h,pendingElements:m});break}case"message_element":{const u=t.extra_data,c=t.element??u?.element;c&&Dn(e,{pendingElements:[...a.state.pendingElements,c]});break}case"error":case"run_error":case"team_run_error":{const u=t.error;u&&Dn(e,{thinkingSteps:[...a.state.thinkingSteps,`Error: ${u}`]});break}case"approval_required":case"approval_pending":case"run_paused":{const u=t.extra_data;if(u?.type==="approval_required"){const c=u;window.dispatchEvent(new CustomEvent("aiui:approval-required",{detail:c}))}break}case"end":case"done":case"run_cancelled":case"team_run_cancelled":break;default:Y5(e,t);break}}function g_(e,t){if(t.tool_call_id){const n=e.findIndex(a=>a.tool_call_id===t.tool_call_id);if(n>=0){const a=[...e];return a[n]={...a[n],...t},a}}return[...e,t]}function k0(e={}){const{externalSessionId:t}=e,[n,a]=v.useState(()=>qu(t));v.useEffect(()=>{if(!t){a(qu(null));return}return a(qu(t)),W5(t,()=>{a(qu(t))})},[t]);const o=v.useCallback((u,c)=>{const f=t??`new-${Date.now()}`;X5(f,u,c,{onSessionId:g=>{e.onSessionId?.(g)},onEnd:e.onEnd})},[t,e.onSessionId,e.onEnd]),s=v.useCallback(()=>{t&&K5(t)},[t]);return{isStreaming:n.isStreaming,currentResponse:n.currentResponse,toolCalls:n.toolCalls,thinkingSteps:n.thinkingSteps,pendingElements:n.pendingElements,sendMessage:o,cancel:s}}function J5(e,t){if(e==null)return{};var n={};for(var a in e)if({}.hasOwnProperty.call(e,a)){if(t.indexOf(a)!==-1)continue;n[a]=e[a]}return n}function e6(e,t){if(e==null)return{};var n,a,o=J5(e,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a<s.length;a++)n=s[a],t.indexOf(n)===-1&&{}.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function Wg(e,t){(t==null||t>e.length)&&(t=e.length);for(var n=0,a=Array(t);n<t;n++)a[n]=e[n];return a}function t6(e){if(Array.isArray(e))return Wg(e)}function n6(e){if(typeof Symbol<"u"&&e[Symbol.iterator]!=null||e["@@iterator"]!=null)return Array.from(e)}function r6(e,t){if(e){if(typeof e=="string")return Wg(e,t);var n={}.toString.call(e).slice(8,-1);return n==="Object"&&e.constructor&&(n=e.constructor.name),n==="Map"||n==="Set"?Array.from(e):n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Wg(e,t):void 0}}function a6(){throw new TypeError(`Invalid attempt to spread non-iterable instance.
In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function Kg(e){return t6(e)||n6(e)||r6(e)||a6()}function Gs(e){"@babel/helpers - typeof";return Gs=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(t){return typeof t}:function(t){return t&&typeof Symbol=="function"&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},Gs(e)}function i6(e,t){if(Gs(e)!="object"||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var a=n.call(e,t);if(Gs(a)!="object")return a;throw new TypeError("@@toPrimitive must return a primitive value.")}return(t==="string"?String:Number)(e)}function o6(e){var t=i6(e,"string");return Gs(t)=="symbol"?t:t+""}function _0(e,t,n){return(t=o6(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Xg(){return Xg=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)({}).hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e},Xg.apply(null,arguments)}function m_(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter(function(o){return Object.getOwnPropertyDescriptor(e,o).enumerable})),n.push.apply(n,a)}return n}function Ji(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]!=null?arguments[t]:{};t%2?m_(Object(n),!0).forEach(function(a){_0(e,a,n[a])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):m_(Object(n)).forEach(function(a){Object.defineProperty(e,a,Object.getOwnPropertyDescriptor(n,a))})}return e}function s6(e){var t=e.length;if(t===0||t===1)return e;if(t===2)return[e[0],e[1],"".concat(e[0],".").concat(e[1]),"".concat(e[1],".").concat(e[0])];if(t===3)return[e[0],e[1],e[2],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0])];if(t>=4)return[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[ Line truncated
`))})}function h6(e){var t=e.codeString,n=e.codeStyle,a=e.containerStyle,o=a===void 0?{float:"left",paddingRight:"10px"}:a,s=e.numberStyle,u=s===void 0?{}:s,c=e.startingLineNumber;return Ze.createElement("code",{style:Object.assign({},n,o)},m6({lines:t.replace(/\n$/,"").split(`
`),style:u,startingLineNumber:c}))}function b6(e){return"".concat(e.toString().length,".25em")}function C0(e,t){return{type:"element",tagName:"span",properties:{key:"line-number--".concat(e),className:["comment","linenumber","react-syntax-highlighter-line-number"],style:t},children:[{type:"text",value:e}]}}function R0(e,t,n){var a={display:"inline-block",minWidth:b6(n),paddingRight:"1em",textAlign:"right",userSelect:"none"},o=typeof e=="function"?e(t):e,s=pa(pa({},a),o);return s}function tc(e){var t=e.children,n=e.lineNumber,a=e.lineNumberStyle,o=e.largestLineNumber,s=e.showInlineLineNumbers,u=e.lineProps,c=u===void 0?{}:u,f=e.className,g=f===void 0?[]:f,h=e.showLineNumbers,m=e.wrapLongLines,E=e.wrapLines,S=E===void 0?!1:E,x=S?pa({},typeof c=="function"?c(n):c):{};if(x.className=x.className?[].concat(Kg(x.className.trim().split(/\s+/)),Kg(g)):g,n&&s){var w=R0(a,n,o);t.unshift(C0(n,w))}return m&h&&(x.style=pa({display:"flex"},x.style)),{type:"element",tagName:"span",properties:x,children:t}}function I0(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:[],n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:[];e.length===void 0&&(e=[e]);for(var a=0;a<e.length;a++){var o=e[a];if(o.type==="text")n.push(tc({children:[o],className:Kg(new Set(t))}));else if(o.children){var s,u=t.concat(((s=o.properties)===null||s===void 0?void 0:s.className)||[]);I0(o.children,u).forEach(function(c){return n.push(c)})}}return n}function y6(e,t,n,a,o,s,u,c,f){var g,h=I0(e.value),m=[],E=-1,S=0;function x(U,D){var P=arguments.length>2&&arguments[2]!==void 0?arguments[2]:[];return tc({children:U,lineNumber:D,lineNumberStyle:c,largestLineNumber:u,showInlineLineNumbers:o,lineProps:n,className:P,showLineNumbers:a,wrapLongLines:f,wrapLines:t})}function w(U,D){if(a&&D&&o){var P=R0(c,D,u);U.unshift(C0(D,P))}return U}function T(U,D){var P=arguments.length>2&&arguments[2]!==void 0?arguments[2]:[];return t||P.length>0?x(U,D,P):w(U,D)}for(var A=function(){var D=h[S],P=D.children[0].value,$=g6(P);if($){var Y=P.split(`
`);Y.forEach(function(B,V){var X=a&&m.length+s,ne={type:"text",value:"".concat(B,`
`)};if(V===0){var ie=h.slice(E+1,S).concat(tc({children:[ne],className:D.properties.className})),ee=T(ie,X);m.push(ee)}else if(V===Y.length-1){var F=h[S+1]&&h[S+1].children&&h[S+1].children[0],q={type:"text",value:"".concat(B)};if(F){var te=tc({children:[q],className:D.properties.className});h.splice(S+1,0,te)}else{var se=[q],I=T(se,X,D.properties.className);m.push(I)}}else{var M=[ne],j=T(M,X,D.properties.className);m.push(j)}}),E=S}S++};S<h.length;)A();if(E!==h.length-1){var _=h.slice(E+1,h.length);if(_&&_.length){var N=a&&m.length+s,L=T(_,N);m.push(L)}}return t?m:(g=[]).concat.apply(g,m)}function v6(e){var t=e.rows,n=e.stylesheet,a=e.useInlineStyles;return t.map(function(o,s){return N0({node:o,stylesheet:n,useInlineStyles:a,key:"code-segment-".concat(s)})})}function O0(e){return e&&typeof e.highlightAuto<"u"}function E6(e){var t=e.astGenerator,n=e.language,a=e.code,o=e.defaultCodeValue;if(O0(t)){var s=d6(t,n);return n==="text"?{value:o,language:"text"}:s?t.highlight(n,a):t.highlightAuto(a)}try{return n&&n!=="text"?{value:t.highlight(a,n)}:{value:o}}catch{return{value:o}}}function S6(e,t){return function(a){var o,s,u=a.language,c=a.children,f=a.style,g=f===void 0?t:f,h=a.customStyle,m=h===void 0?{}:h,E=a.codeTagProps,S=E===void 0?{className:u?"language-".concat(u):void 0,style:pa(pa({},g['code[class*="language-"]']),g['code[class*="language-'.concat(u,'"]')])}:E,x=a.useInlineStyles,w=x===void 0?!0:x,T=a.showLineNumbers,A=T===void 0?!1:T,_=a.showInlineLineNumbers,N=_===void 0?!0:_,L=a.startingLineNumber,U=L===void 0?1:L,D=a.lineNumberContainerStyle,P=a.lineNumberStyle,$=P===void 0?{}:P,Y=a.wrapLines,B=a.wrapLongLines,V=B===void 0?!1:B,X=a.lineProps,ne=X===void 0?{}:X,ie=a.renderer,ee=a.PreTag,F=ee===void 0?"pre":ee,q=a.CodeTag,te=q===void 0?"code":q,se=a.code,I=se===void 0?(Array.isArray(c)?c[0]:c)||"":se,M=a.astGenerator,j=e6(a,p6);M=M||e;var C=A?Ze.createElement(h6,{containerStyle:D,codeStyle:S.style||{},numberStyle:$,startingLineNumber:U,codeString:I}):null,J=g.hljs||g['pre[class*="language-"]']||{backgroundColor:"#fff"},Q=O0(M)?"hljs":"prismjs",re=w?Object.assign({},j,{style:Object.assign({},J,m)}):Object.assign({},j,{className:j.className?"".concat(Q," ").concat(j.className):Q,style:Object.assign({},m)});if(V?S.style=pa({whiteSpace:"pre-wrap"},S.style):S.style=pa({whiteSpace:"pre"},S.style),!M)return Ze.createElement(F,re,C,Ze.createElement(te,S,I));(Y===void 0&&ie||V)&&(Y=!0),ie=ie||v6;var oe=[{type:"text",value:I}],he=E6({astGenerator:M,language:u,code:I,defaultCodeValue:oe});he.language===null&&(he.value=oe);var pe=(o=(s=I.match(/\n/g))===null||s===void 0?void 0:s.length)!==null&&o!==void 0?o:0,ve=U+pe,Ce=y6(he,Y,ne,A,N,U,ve,$,V);return Ze.createElement(F,re,Ze.createElement(te,S,!N&&C,ie({rows:Ce,stylesheet:g,useInlineStyles:w})))}}const x6=["abap","abnf","actionscript","ada","agda","al","antlr4","apacheconf","apex","apl","applescript","aql","arduino","arff","armasm","arturo","asciidoc","asm6502","asmatmel","aspnet","autohotkey","autoit","avisynth","avro-idl","awk","bash","basic","batch","bbcode","bbj","bicep","birb","bison","bnf","bqn","brainfuck","brightscript","bro","bsl","c","cfscript","chaiscript","cil","cilkc","cilkcpp","clike","clojure","cmake","cobol","coffeescript","concurnas","cooklang","coq","cpp","crystal","csharp","cshtml","csp","css-extras","css","csv","cue","cypher","d","dart","dataweave","dax","dhall","diff","django","dns-zone-file","docker","dot","ebnf","editorconfig","eiffel","ejs","elixir","elm","erb","erlang","etlua","excel-formula","factor","false","firestore-security-rules","flow","fortran","fsharp","ftl","gap","gcode","gdscript","gedcom","gettext","gherkin","git","glsl","gml","gn","go-module","go","gradle","graphql","groovy","haml","handlebars","haskell","haxe","hcl","hlsl","hoon","hpkp","hsts","http","ichigojam","icon","icu-message-format","idris","iecst","ignore","inform7","ini","io","j","java","javadoc","javadoclike","javascript","javastacktrace","jexl","jolie","jq","js-extras","js-templates","jsdoc","json","json5","jsonp","jsstacktrace","jsx","julia","keepalived","keyman","kotlin","kumir","kusto","latex","latte","less","lilypond","linker-script","liquid","lisp","livescript","llvm","log","lolcode","lua","magma","makefile","markdown","markup-templating","markup","mata","matlab","maxscript","mel","mermaid","metafont","mizar","mongodb","monkey","moonscript","n1ql","n4js","nand2tetris-hdl","naniscript","nasm","neon","nevod","nginx","nim","nix","nsis","objectivec","ocaml","odin","opencl","openqasm","oz","parigp","parser","pascal","pascaligo","pcaxis","peoplecode","perl","php-extras","php","phpdoc","plant-uml","plsql","powerquery","powershell","processing","prolog","promql","properties","protobuf","psl","pug","puppet","pure","purebasic","purescript","python","q","qml","qore","qsharp","r","racket","reason","regex","rego","renpy","rescript","rest","rip","roboconf","robotframework","ruby","rust","sas","sass","scala","scheme","scss","shell-session","smali","smalltalk","smarty","sml Line truncated
?|
|(?![\\s\\S])))+`,"m"),alias:s,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(a)[0]}}}}),Object.defineProperty(t.languages.diff,"PREFIXES",{value:n})})(e)}Ht.displayName="markup-templating";Ht.aliases=[];function Ht(e){e.register(Ft),(function(t){function n(a,o){return"___"+a.toUpperCase()+o+"___"}Object.defineProperties(t.languages["markup-templating"]={},{buildPlaceholders:{value:function(a,o,s,u){if(a.language===o){var c=a.tokenStack=[];a.code=a.code.replace(s,function(f){if(typeof u=="function"&&!u(f))return f;for(var g=c.length,h;a.code.indexOf(h=n(o,g))!==-1;)++g;return c[g]=f,h}),a.grammar=t.languages.markup}}},tokenizePlaceholders:{value:function(a,o){if(a.language!==o||!a.tokenStack)return;a.grammar=t.languages[o];var s=0,u=Object.keys(a.tokenStack);function c(f){for(var g=0;g<f.length&&!(s>=u.length);g++){var h=f[g];if(typeof h=="string"||h.content&&typeof h.content=="string"){var m=u[s],E=a.tokenStack[m],S=typeof h=="string"?h:h.content,x=n(o,m),w=S.indexOf(x);if(w>-1){++s;var T=S.substring(0,w),A=new t.Token(o,t.tokenize(E,a.grammar),"language-"+o,E),_=S.substring(w+x.length),N=[];T&&N.push.apply(N,c([T])),N.push(A),_&&N.push.apply(N,c([_])),typeof h=="string"?f.splice.apply(f,[g,1].concat(N)):h.content=N}}else h.content&&c(h.content)}return f}c(a.tokens)}}})})(e)}bb.displayName="django";bb.aliases=["jinja2"];function bb(e){e.register(Ht),(function(t){t.languages.django={comment:/^\{#[\s\S]*?#\}$/,tag:{pattern:/(^\{%[+-]?\s*)\w+/,lookbehind:!0,alias:"keyword"},delimiter:{pattern:/^\{[{%][+-]?|[+-]?[}%]\}$/,alias:"punctuation"},string:{pattern:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},filter:{pattern:/(\|)\w+/,lookbehind:!0,alias:"function"},test:{pattern:/(\bis\s+(?:not\s+)?)(?!not\b)\w+/,lookbehind:!0,alias:"function"},function:/\b[a-z_]\w+(?=\s*\()/i,keyword:/\b(?:and|as|by|else|for|if|import|in|is|loop|not|or|recursive|with|without)\b/,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,number:/\b\d+(?:\.\d+)?\b/,boolean:/[Ff]alse|[Nn]one|[Tt]rue/,variable:/\b\w+\b/,punctuation:/[{}[\](),.:;]/};var n=/\{\{[\s\S]*?\}\}|\{%[\s\S]*?%\}|\{#[\s\S]*?#\}/g,a=t.languages["markup-templating"];t.hooks.add("before-tokenize",function(o){a.buildPlaceholders(o,"django",n)}),t.hooks.add("after-tokenize",function(o){a.tokenizePlaceholders(o,"django")}),t.languages.jinja2=t.languages.django,t.hooks.add("before-tokenize",function(o){a.buildPlaceholders(o,"jinja2",n)}),t.hooks.add("after-tokenize",function(o){a.tokenizePlaceholders(o,"jinja2")})})(e)}yb.displayName="dns-zone-file";yb.aliases=["dns-zone"];function yb(e){e.languages["dns-zone-file"]={comment:/;.*/,string:{pattern:/"(?:\\.|[^"\\\r\n])*"/,greedy:!0},variable:[{pattern:/(^\$ORIGIN[ \t]+)\S+/m,lookbehind:!0},{pattern:/(^|\s)@(?=\s|$)/,lookbehind:!0}],keyword:/^\$(?:INCLUDE|ORIGIN|TTL)(?=\s|$)/m,class:{pattern:/(^|\s)(?:CH|CS|HS|IN)(?=\s|$)/,lookbehind:!0,alias:"keyword"},type:{pattern:/(^|\s)(?:A|A6|AAAA|AFSDB|APL|ATMA|CAA|CDNSKEY|CDS|CERT|CNAME|DHCID|DLV|DNAME|DNSKEY|DS|EID|GID|GPOS|HINFO|HIP|IPSECKEY|ISDN|KEY|KX|LOC|MAILA|MAILB|MB|MD|MF|MG|MINFO|MR|MX|NAPTR|NB|NBSTAT|NIMLOC|NINFO|NS|NSAP|NSAP-PTR|NSEC|NSEC3|NSEC3PARAM|NULL|NXT|OPENPGPKEY|PTR|PX|RKEY|RP|RRSIG|RT|SIG|SINK|SMIMEA|SOA|SPF|SRV|SSHFP|TA|TKEY|TLSA|TSIG|TXT|UID|UINFO|UNSPEC|URI|WKS|X25)(?=\s|$)/,lookbehind:!0,alias:"keyword"},punctuation:/[()]/},e.languages["dns-zone"]=e.languages["dns-zone-file"]}vb.displayName="docker";vb.aliases=["dockerfile"];function vb(e){(function(t){var n=/\\[\r\n](?:\s|\\[\r\n]|#.*(?!.))*(?![\s#]|\\[\r\n])/.source,a=/(?:[ \t]+(?![ \t])(?:<SP_BS>)?|<SP_BS>)/.source.replace(/<SP_BS>/g,function(){return n}),o=/"(?:[^"\\\r\n]|\\(?:\r\n|[\s\S]))*"|'(?:[^'\\\r\n]|\\(?:\r\n|[\s\S]))*'/.source,s=/--[\w-]+=(?:<STR>|(?!["'])(?:[^\s\\]|\\.)+)/.source.replace(/<STR>/g,function(){return o}),u={pattern:RegExp(o),greedy:!0},c={pattern:/(^[ \t]*)#.*/m,lookbehind:!0,greedy:!0};function f(g,h){return g=g.replace(/<OPT>/g,function(){return s}).replace(/<SP>/g,function(){return a}),RegExp(g,h)}t.languages.docker={instruction:{pattern:/(^[ \t]*)(?:ADD|ARG|CMD|COPY|ENTRYPOINT|ENV|EXPOSE|FROM|HEALTHCHECK|LABEL|MAINTAINER|ONBUILD|RUN|SHELL|STOPSIGNAL|USER|VOLUME|WORKDIR)(?=\s)(?:\\.|[^\r\n\\])*(?:\\$(?:\s|#.*$)*(?![\s#])(?:\\.|[^\r\n\\])*)*/im,lookbehind:!0,greedy:!0,inside:{options:{pattern:f(/(^(?:ONBUILD<SP>)?\w+<SP>)<OPT>(?:<SP><OPT>)*/.source,"i"),lookbehind:!0,greedy:!0,inside:{property:{pattern:/(^|\s)--[\w-]+/,lookbehind:!0},string:[u,{pattern:/(=)(?!["'])(?:[^\s\\]|\\.)+/,lookbehind:!0}],operator:/\\$/m,punctuation:/=/}},keyword:[{pattern:f(/(^(?:ONBUILD<SP>)?HEALTHCHECK<SP>(?:<OPT><SP>)*)(?:CMD|NONE)\b/.source,"i"),lookbehind:!0,greedy:!0},{pattern:f(/(^(?:ONBUILD<SP>)?FROM<SP>(?:<OPT><SP>)*(?!--)[^ \t\\]+<SP>)AS/.source,"i"),lookbehind:!0,greedy:!0},{pattern:f(/(^ONBUILD<SP>)\w+/.source,"i"),lookbehind:!0,greedy:!0},{pattern:/^\w+/,greedy:!0}],comment:c,string:u,variable:/\$(?:\w+|\{[^{}"'\\]*\})/,oper Line truncated
]))(?:`+(/[^\s\\]/.source+'|[ ]+(?:(?![ "])|'+a+")|"+/\\[\r\n]+(?:[#;].*[\r\n]+)*(?![#;])/.source)+")*"),lookbehind:!0,greedy:!0,alias:"attr-value",inside:{comment:n,quoted:{pattern:RegExp(/(^|\s)/.source+a),lookbehind:!0,greedy:!0},punctuation:/\\$/m,boolean:{pattern:/^(?:false|no|off|on|true|yes)$/,greedy:!0}}},punctuation:/=/}})(e)}cl.displayName="t4-templating";cl.aliases=[];function cl(e){(function(t){function n(o,s,u){return{pattern:RegExp("<#"+o+"[\\s\\S]*?#>"),alias:"block",inside:{delimiter:{pattern:RegExp("^<#"+o+"|#>$"),alias:"important"},content:{pattern:/[\s\S]+/,inside:s,alias:u}}}}function a(o){var s=t.languages[o],u="language-"+o;return{block:{pattern:/<#[\s\S]+?#>/,inside:{directive:n("@",{"attr-value":{pattern:/=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/,inside:{punctuation:/^=|^["']|["']$/}},keyword:/\b\w+(?=\s)/,"attr-name":/\b\w+/}),expression:n("=",s,u),"class-feature":n("\\+",s,u),standard:n("",s,u)}}}}t.languages["t4-templating"]=Object.defineProperty({},"createT4",{value:a})})(e)}OE.displayName="t4-cs";OE.aliases=["t4"];function OE(e){e.register(bo),e.register(cl),e.languages.t4=e.languages["t4-cs"]=e.languages["t4-templating"].createT4("csharp")}ad.displayName="vbnet";ad.aliases=[];function ad(e){e.register(Qc),e.languages.vbnet=e.languages.extend("basic",{comment:[{pattern:/(?:!|REM\b).+/i,inside:{keyword:/^REM/i}},{pattern:/(^|[^\\:])'.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(^|[^"])"(?:""|[^"])*"(?!")/,lookbehind:!0,greedy:!0},keyword:/(?:\b(?:ADDHANDLER|ADDRESSOF|ALIAS|AND|ANDALSO|AS|BEEP|BLOAD|BOOLEAN|BSAVE|BYREF|BYTE|BYVAL|CALL(?: ABSOLUTE)?|CASE|CATCH|CBOOL|CBYTE|CCHAR|CDATE|CDBL|CDEC|CHAIN|CHAR|CHDIR|CINT|CLASS|CLEAR|CLNG|CLOSE|CLS|COBJ|COM|COMMON|CONST|CONTINUE|CSBYTE|CSHORT|CSNG|CSTR|CTYPE|CUINT|CULNG|CUSHORT|DATA|DATE|DECIMAL|DECLARE|DEF(?: FN| SEG|DBL|INT|LNG|SNG|STR)|DEFAULT|DELEGATE|DIM|DIRECTCAST|DO|DOUBLE|ELSE|ELSEIF|END|ENUM|ENVIRON|ERASE|ERROR|EVENT|EXIT|FALSE|FIELD|FILES|FINALLY|FOR(?: EACH)?|FRIEND|FUNCTION|GET|GETTYPE|GETXMLNAMESPACE|GLOBAL|GOSUB|GOTO|HANDLES|IF|IMPLEMENTS|IMPORTS|IN|INHERITS|INPUT|INTEGER|INTERFACE|IOCTL|IS|ISNOT|KEY|KILL|LET|LIB|LIKE|LINE INPUT|LOCATE|LOCK|LONG|LOOP|LSET|ME|MKDIR|MOD|MODULE|MUSTINHERIT|MUSTOVERRIDE|MYBASE|MYCLASS|NAME|NAMESPACE|NARROWING|NEW|NEXT|NOT|NOTHING|NOTINHERITABLE|NOTOVERRIDABLE|OBJECT|OF|OFF|ON(?: COM| ERROR| KEY| TIMER)?|OPEN|OPERATOR|OPTION(?: BASE)?|OPTIONAL|OR|ORELSE|OUT|OVERLOADS|OVERRIDABLE|OVERRIDES|PARAMARRAY|PARTIAL|POKE|PRIVATE|PROPERTY|PROTECTED|PUBLIC|PUT|RAISEEVENT|READ|READONLY|REDIM|REM|REMOVEHANDLER|RESTORE|RESUME|RETURN|RMDIR|RSET|RUN|SBYTE|SELECT(?: CASE)?|SET|SHADOWS|SHARED|SHELL|SHORT|SINGLE|SLEEP|STATIC|STEP|STOP|STRING|STRUCTURE|SUB|SWAP|SYNCLOCK|SYSTEM|THEN|THROW|TIMER|TO|TROFF|TRON|TRUE|TRY|TRYCAST|TYPE|TYPEOF|UINTEGER|ULONG|UNLOCK|UNTIL|USHORT|USING|VIEW PRINT|WAIT|WEND|WHEN|WHILE|WIDENING|WITH|WITHEVENTS|WRITE|WRITEONLY|XOR)|\B(?:#CONST|#ELSE|#ELSEIF|#END|#IF))(?:\$|\b)/i,punctuation:/[,;:(){}]/})}DE.displayName="t4-vb";DE.aliases=[];function DE(e){e.register(cl),e.register(ad),e.languages["t4-vb"]=e.languages["t4-templating"].createT4("vbnet")}LE.displayName="tap";LE.aliases=[];function LE(e){e.register(Zc),e.languages.tap={fail:/not ok[^#{\n\r]*/,pass:/ok[^#{\n\r]*/,pragma:/pragma [+-][a-z]+/,bailout:/bail out!.*/i,version:/TAP version \d+/i,plan:/\b\d+\.\.\d+(?: +#.*)?/,subtest:{pattern:/# Subtest(?:: .*)?/,greedy:!0},punctuation:/[{}]/,directive:/#.*/,yamlish:{pattern:/(^[ \t]*)---[\s\S]*?[\r\n][ \t]*\.\.\.$/m,lookbehind:!0,inside:e.languages.yaml,alias:"language-yaml"}}}ME.displayName="tcl";ME.aliases=[];function ME(e){e.languages.tcl={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},string:{pattern:/"(?:[^"\\\r\n]|\\(?:\r\n|[\s\S]))*"/,greedy:!0},variable:[{pattern:/(\$)(?:::)?(?:[a-zA-Z0-9]+::)*\w+/,lookbehind:!0},{pattern:/(\$)\{[^}]+\}/,lookbehind:!0},{pattern:/(^[\t ]*set[ \t]+)(?:::)?(?:[a-zA-Z0-9]+::)*\w+/m,lookbehind:!0}],function:{pattern:/(^[\t ]*proc[ \t]+)\S+/m,lookbehind:!0},builtin:[{pattern:/(^[\t ]*)(?:break|class|continue|error|eval|exit|for|foreach|if|proc|return|switch|while)\b/m,lookbehind:!0},/\b(?:else|elseif)\b/],scope:{pattern:/(^[\t ]*)(?:global|upvar|variable)\b/m,lookbehind:!0,alias:"constant"},keyword:{pattern:/(^[\t ]*|\[)(?:Safe_Base|Tcl|after|append|apply|array|auto_(?:execok|import|load|mkindex|qualify|reset)|automkindex_old|bgerror|binary|catch|cd|chan|clock|close|concat|dde|dict|encoding|eof|exec|expr|fblocked|fconfigure|fcopy|file(?:event|name)?|flush|gets|glob|history|http|incr|info|interp|join|lappend|lassign|lindex|linsert|list|llength|load|lrange|lrepeat|lreplace|lreverse|lsearch|lset|lsort|math(?:func|op)|memory|msgcat|namespace|open|package|parray|pid|pkg_mkIndex|platform|puts|pwd|re_syntax|read|refchan|regexp|registry|regsub|rename|scan|seek|set|socket|source|split|string|subst|tcl(?:_endOfWord|_findLibrary|startOf(?:Next|Previous)Word|test|vars|wordBreak(?:After|Before))|tell|time|tm|trace|unknown|unload|unset|update|uplevel|vwait Line truncated
- a positive number
- less than the value passed to \`max\` (or ${yS} if no \`max\` prop is set)
- \`null\` or \`undefined\` if the progress is indeterminate.
Defaulting to \`null\`.`}var iq=vI,oq=SI;function sq({className:e,value:t,...n}){return p.jsx(iq,{"data-slot":"progress",className:be("bg-primary/20 relative h-2 w-full overflow-hidden rounded-full",e),...n,children:p.jsx(oq,{"data-slot":"progress-indicator",className:"bg-primary h-full w-full flex-1 transition-all",style:{transform:`translateX(-${100-(t||0)}%)`}})})}function dl(e){const t=v.useRef({value:e,previous:e});return v.useMemo(()=>(t.current.value!==e&&(t.current.previous=t.current.value,t.current.value=e),t.current.previous),[e])}var ud="Switch",[lq]=It(ud),[uq,cq]=lq(ud),wI=v.forwardRef((e,t)=>{const{__scopeSwitch:n,name:a,checked:o,defaultChecked:s,required:u,disabled:c,value:f="on",onCheckedChange:g,form:h,...m}=e,[E,S]=v.useState(null),x=ke(t,N=>S(N)),w=v.useRef(!1),T=E?h||!!E.closest("form"):!0,[A,_]=Zt({prop:o,defaultProp:s??!1,onChange:g,caller:ud});return p.jsxs(uq,{scope:n,checked:A,disabled:c,children:[p.jsx(ye.button,{type:"button",role:"switch","aria-checked":A,"aria-required":u,"data-state":_I(A),"data-disabled":c?"":void 0,disabled:c,value:f,...m,ref:x,onClick:ge(e.onClick,N=>{_(L=>!L),T&&(w.current=N.isPropagationStopped(),w.current||N.stopPropagation())})}),T&&p.jsx(kI,{control:E,bubbles:!w.current,name:a,value:f,checked:A,required:u,disabled:c,form:h,style:{transform:"translateX(-100%)"}})]})});wI.displayName=ud;var TI="SwitchThumb",AI=v.forwardRef((e,t)=>{const{__scopeSwitch:n,...a}=e,o=cq(TI,n);return p.jsx(ye.span,{"data-state":_I(o.checked),"data-disabled":o.disabled?"":void 0,...a,ref:t})});AI.displayName=TI;var dq="SwitchBubbleInput",kI=v.forwardRef(({__scopeSwitch:e,control:t,checked:n,bubbles:a=!0,...o},s)=>{const u=v.useRef(null),c=ke(u,s),f=dl(n),g=Xs(t);return v.useEffect(()=>{const h=u.current;if(!h)return;const m=window.HTMLInputElement.prototype,S=Object.getOwnPropertyDescriptor(m,"checked").set;if(f!==n&&S){const x=new Event("click",{bubbles:a});S.call(h,n),h.dispatchEvent(x)}},[f,n,a]),p.jsx("input",{type:"checkbox","aria-hidden":!0,defaultChecked:n,...o,tabIndex:-1,ref:c,style:{...o.style,...g,position:"absolute",pointerEvents:"none",opacity:0,margin:0}})});kI.displayName=dq;function _I(e){return e?"checked":"unchecked"}var pq=wI,fq=AI;function gq({className:e,size:t="default",...n}){return p.jsx(pq,{"data-slot":"switch","data-size":t,className:be("peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 group/switch inline-flex shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-[1.15rem] data-[size=default]:w-8 data-[size=sm]:h-3.5 data-[size=sm]:w-6",e),...n,children:p.jsx(fq,{"data-slot":"switch-thumb",className:be("bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block rounded-full ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0")})})}var cd="Checkbox",[mq]=It(cd),[hq,vS]=mq(cd);function bq(e){const{__scopeCheckbox:t,checked:n,children:a,defaultChecked:o,disabled:s,form:u,name:c,onCheckedChange:f,required:g,value:h="on",internal_do_not_use_render:m}=e,[E,S]=Zt({prop:n,defaultProp:o??!1,onChange:f,caller:cd}),[x,w]=v.useState(null),[T,A]=v.useState(null),_=v.useRef(!1),N=x?!!u||!!x.closest("form"):!0,L={checked:E,disabled:s,setChecked:S,control:x,setControl:w,name:c,form:u,value:h,hasConsumerStoppedPropagationRef:_,required:g,defaultChecked:fa(o)?!1:o,isFormControl:N,bubbleInput:T,setBubbleInput:A};return p.jsx(hq,{scope:t,...L,children:yq(m)?m(L):a})}var NI="CheckboxTrigger",CI=v.forwardRef(({__scopeCheckbox:e,onKeyDown:t,onClick:n,...a},o)=>{const{control:s,value:u,disabled:c,checked:f,required:g,setControl:h,setChecked:m,hasConsumerStoppedPropagationRef:E,isFormControl:S,bubbleInput:x}=vS(NI,e),w=ke(o,h),T=v.useRef(f);return v.useEffect(()=>{const A=s?.form;if(A){const _=()=>m(T.current);return A.addEventListener("reset",_),()=>A.removeEventListener("reset",_)}},[s,m]),p.jsx(ye.button,{type:"button",role:"checkbox","aria-checked":fa(f)?"mixed":f,"aria-required":g,"data-state":MI(f),"data-disabled":c?"":void 0,disabled:c,value:u,...a,ref:w,onKeyDown:ge(t,A=>{A.key==="Enter"&&A.preventDefault()}),onClick:ge(n,A=>{m(_=>fa(_)?!0:!_),x&&S&&(E.current=A.isPropagationStopped(),E.current||A.stopPropagation())})})});CI.displayName=NI;var RI=v.forwardRef((e,t)=>{const{__scopeCheckbox:n,name:a,checked:o,defaultChecked:s,required:u,disabled:c,value:f,onCheckedChange:g,form:h,...m}=e;return p.jsx(bq,{__scopeCheckbox:n,checked:o,defaultChecked:s,disabled:c,required:u,onCheckedChange:g,name:a,form:h,value:f,internal_do_not_use_render:({isFormControl:E})=>p.jsxs(p.Fragment,{children:[p.jsx(CI,{...m,ref:t,__scopeChecLine truncated
`);for(;t.length&&!t[0].trim();)t.shift();for(;t.length&&!t[t.length-1].trim();)t.pop();if(!t.length)return"";const n=Math.min(...t.filter(a=>a.trim().length>0).map(a=>a.match(/^ */)?.[0].length??0));return n===0?t.join(`
`):t.map(a=>a.slice(n)).join(`
`)}function TY({language:e,children:t}){const[n,a]=v.useState(!1),o=v.useCallback(async()=>{await navigator.clipboard.writeText(t),a(!0),setTimeout(()=>a(!1),2e3)},[t]);return p.jsxs("div",{className:"relative group/code my-3 rounded-lg overflow-hidden",children:[p.jsxs("div",{className:"flex items-center justify-between px-4 py-1.5 bg-[#1e1e2e] text-xs text-gray-400",children:[p.jsx("span",{children:e||"code"}),p.jsx("button",{onClick:o,className:"flex items-center gap-1 hover:text-white transition-colors",children:n?"✓ Copied":"Copy"})]}),p.jsx(F0,{style:K6,language:e||"text",PreTag:"div",customStyle:{margin:0,borderRadius:0,fontSize:"13px"},children:t})]})}function AY(e){const t=e.split(`
`);let n=!1,a=!1,o="",s=0;for(let u=0;u<t.length;u++){const c=t[u];if(/^[ \t]*```/.test(c)){n=!n;continue}if(n)continue;const f=c.match(/^([ \t]*)(\d+)\.[ \t]/);if(f){const g=f[1];!a||g!==o?(a=!0,o=g,s=1):s++,t[u]=c.replace(/^([ \t]*)\d+\./,`${g}${s}.`)}else c.trim()===""&&a||a&&/^[ \t]+\S/.test(c)||a&&(a=!1,s=0)}return t.join(`
`)}function u1({content:e}){const t=AY(e);return p.jsx("div",{className:"prose prose-sm dark:prose-invert max-w-none prose-p:leading-relaxed prose-pre:p-0 prose-pre:bg-transparent",children:p.jsx(XR,{remarkPlugins:[E0],components:{ul({children:n,ordered:a,start:o}){if(a){const s=o!=null?Number(o):1;return p.jsx("ol",{start:s,style:{listStyleType:"decimal",paddingLeft:"1.5rem",margin:"0.5rem 0"},children:n})}return p.jsx("ul",{style:{listStyleType:"disc",paddingLeft:"1.5rem",margin:"0.5rem 0"},children:n})},li({children:n}){return p.jsx("li",{style:{display:"list-item",marginBottom:"0.25rem"},children:n})},code({className:n,children:a,...o}){const s=/language-(\w+)/.exec(n||""),u=wY(String(a));return!s&&!u.includes(`
`)?p.jsx("code",{className:"px-1.5 py-0.5 rounded bg-muted text-sm font-mono",...o,children:a}):p.jsx(TY,{language:s?.[1],children:u})},a({href:n,children:a}){return p.jsx("a",{href:n,target:"_blank",rel:"noopener noreferrer",className:"text-primary hover:underline",children:a})},table({children:n}){return p.jsx("div",{className:"overflow-x-auto my-3",children:p.jsx("table",{className:"min-w-full text-sm",children:n})})}},children:t})})}function kY({message:e,sessionId:t}){return e.role==="user"?p.jsx("div",{className:"flex justify-end",children:p.jsxs("div",{className:"flex gap-3 max-w-[80%]",children:[p.jsx("div",{className:"rounded-2xl px-4 py-2.5 bg-primary text-primary-foreground",children:p.jsx("p",{className:"text-sm whitespace-pre-wrap",children:e.content})}),p.jsx(xc,{role:"user"})]})}):p.jsxs("div",{className:"flex gap-3 group",children:[p.jsx(xc,{role:"assistant"}),p.jsxs("div",{className:"flex-1 min-w-0",children:[e.toolCalls&&e.toolCalls.length>0&&p.jsx("div",{className:"mb-2 space-y-1",children:e.toolCalls.map((a,o)=>p.jsx(l1,{toolCall:a},o))}),p.jsx(u1,{content:e.content}),e.elements&&e.elements.length>0&&p.jsx("div",{className:"mt-3 space-y-3",children:e.elements.map((a,o)=>p.jsx(_S,{element:a,className:"w-full"},o))}),e.images&&e.images.length>0&&p.jsx("div",{className:"mt-2 flex flex-wrap gap-2",children:e.images.map((a,o)=>p.jsx("img",{src:a,alt:"",className:"max-w-full rounded-md max-h-64 object-contain"},o))}),e.actions&&e.actions.length>0&&p.jsx(hY,{actions:e.actions,messageId:e.id,sessionId:t}),p.jsxs("div",{className:"mt-1 flex items-center gap-1 relative",children:[p.jsx(SY,{text:e.content}),p.jsx(xY,{messageId:e.id})]})]})]})}function _Y({onSend:e,onCancel:t,isStreaming:n=!1,placeholder:a="Type a message...",enableFileUpload:o=!1}){const[s,u]=v.useState(""),[c,f]=v.useState([]),g=v.useRef(null),h=v.useRef(null),m=v.useCallback(()=>{const A=s.trim();(A||c.length>0)&&!n&&(e(A,c.length>0?c:void 0),u(""),f([]),g.current&&(g.current.style.height="auto"))},[s,c,n,e]),E=v.useCallback(A=>{const _=Array.from(A.target.files||[]);f(N=>[...N,..._]),h.current&&(h.current.value="")},[]),S=v.useCallback(()=>{h.current?.click()},[]),x=v.useCallback(A=>{f(_=>_.filter((N,L)=>L!==A))},[]),w=v.useCallback(A=>{A.key==="Enter"&&!A.shiftKey&&(A.preventDefault(),m())},[m]),T=v.useCallback(()=>{const A=g.current;A&&(A.style.height="auto",A.style.height=`${Math.min(A.scrollHeight,200)}px`)},[]);return p.jsx("div",{className:"p-4 pb-6",children:p.jsxs("div",{className:"max-w-3xl mx-auto",children:[p.jsxs("div",{className:"rounded-2xl border bg-background/80 backdrop-blur-sm shadow-lg",children:[c.length>0&&p.jsx("div",{className:"flex flex-wrap gap-1 px-4 pt-3",children:c.map((A,_)=>p.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-1 bg-muted rounded-lg text-xs",children:[p.jsx("span",{className:"truncate max-w-[100px]",children:A.name}),p.jsx("button",{type:"button",onClick:()=>x(_),className:"hover:text-destructive",children:"×"})]},`${A.name}-${_}`))}),p.jsxs("div",{className:"flex items-end gap-2 p-2",children:[o&&p.jsxs(p.Fragment,{children:[p.jsx("input",{ref:h,type:"file",multiple:!0,onChange:E,className:"hidden",accept:"image/*,audio/*,video/*,.pdf,.doc,.docx,.txt,.csv,.json"}),p.jsx("button",{type:"button",onClick:S,className:"p-2 rounded-xl hover:bg-accent text-muted-foreground transition-colors",title:"Attach file",children:p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:p.jsx("path",{d:"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"})})})]}),p.jsx("textarea",{ref:g,value:s,onChange:A=>u(A.target.value),onKeyDown:w,onInput:T,placeholder:a,disabled:n,rows:1,className:"flex-1 resize-none bg-transparent px-3 py-2.5 text-sm focus:outline-none disabled:opacity-50 placeholder:text-muted-foreground/60",style:{maxHeight:"200px"}}),n?p.jsx("button",{type:"button",onClick:t,className:"p-2 rounded-xl bg-destructive text-destructive-foreground hover:bg-destructive/90 transition-colors",title:"Stop",children:p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"18",height:"18",viewBox:"0 0 24 24",fill:"currentColor",children:p.jsx("rect",{x:"6",y:"6",width:"12",height:"12",rx:"2"})})}):p.jsx("button",{type:"button",onClick:m,disabled:!s.trim(),className:"p-2 rounded-xl bg-primary text-primary-foreground hover:bg-primary/90 disabled:opacity-30 disabled:cursor-not-allowed transition-colors",title:"Send",children:p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:p.jsx("path",{d:"M5 12h14M12 5l7 7-7 7"})})})]})]}),p.jsx("p",{className:"text-[10px] text-center text-muted-foreground/50 mt-2",children:"Press Enter to send, Shift+Enter for new line" Line truncated
`),m=v.useCallback(async()=>{!n.trim()||s||f(n)},[n,s,f]),E=v.useCallback(()=>{a("")},[]);return p.jsxs("div",{className:"min-h-screen bg-background text-foreground flex flex-col",children:[p.jsxs("header",{className:"border-b px-6 py-4 flex items-center justify-between",children:[p.jsx("h1",{className:"text-xl font-semibold",children:t||"Playground"}),p.jsx("div",{className:"flex items-center gap-2",children:p.jsx("button",{onClick:E,className:"px-3 py-1.5 text-sm rounded-md border hover:bg-accent",children:"Clear"})})]}),p.jsxs("div",{className:"flex-1 flex",children:[p.jsxs("div",{className:"flex-1 flex flex-col border-r",children:[p.jsx("div",{className:"px-4 py-2 border-b bg-muted/30",children:p.jsx("span",{className:"text-sm font-medium text-muted-foreground",children:"Input"})}),p.jsx("div",{className:"flex-1 p-4",children:p.jsx("textarea",{value:n,onChange:S=>a(S.target.value),placeholder:"Enter your prompt here...",className:"w-full h-full resize-none bg-transparent border rounded-md p-3 focus:outline-none focus:ring-2 focus:ring-primary"})}),p.jsx("div",{className:"px-4 py-3 border-t flex justify-end gap-2",children:s?p.jsx("button",{onClick:g,className:"px-4 py-2 bg-destructive text-destructive-foreground rounded-md hover:bg-destructive/90",children:"Stop"}):p.jsx("button",{onClick:m,disabled:!n.trim(),className:"px-4 py-2 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed",children:"Submit"})})]}),p.jsxs("div",{className:"flex-1 flex flex-col",children:[p.jsxs("div",{className:"px-4 py-2 border-b bg-muted/30 flex items-center justify-between",children:[p.jsx("span",{className:"text-sm font-medium text-muted-foreground",children:"Output"}),s&&p.jsx("span",{className:"text-xs text-muted-foreground animate-pulse",children:"Processing..."})]}),p.jsx("div",{className:"flex-1 p-4 overflow-auto",children:h?p.jsx("div",{className:"prose prose-sm dark:prose-invert max-w-none whitespace-pre-wrap",children:h}):p.jsx("div",{className:"h-full flex items-center justify-center text-muted-foreground text-sm",children:"Output will appear here"})})]})]}),e?.features&&p.jsxs("div",{className:"border-t px-6 py-3 bg-muted/20 flex items-center gap-4 text-sm text-muted-foreground",children:[e.features.streaming&&p.jsx("span",{children:"✓ Streaming"}),e.features.reasoning&&p.jsx("span",{children:"✓ Reasoning"}),e.features.tools&&p.jsx("span",{children:"✓ Tools"})]})]})}function fW(e,t){const n=e.replace(/^\/+|\/+$/g,""),o=t.replace(/^\/+|\/+$/g,"").replace(/\*\*/g,"{{GLOB}}").replace(/\*/g,"[^/]+").replace(/\{\{GLOB\}\}/g,".*");return new RegExp(`^${o}$`).test(n)}function gW(e,t,n){const o=[...t.routes??[]].sort((s,u)=>(u.priority??0)-(s.priority??0));for(const s of o){if(!fW(e,s.pattern))continue;const u=n[s.template];return u?{template:s.template,layout:u.layout??"ThreeColumnLayout",slots:u.slots??{},slotOverrides:s.slotOverrides}:(console.warn(`Template "${s.template}" not found`),null)}return null}function mW(e,t){if(t)return t.slotOverrides&&e in t.slotOverrides?t.slotOverrides[e]:t.slots[e]}function hW(e){return mW("right",e)!==null}function bW(e){return e.title.trim().toLowerCase()}function S1(e){const t=[];e.path&&t.push(e.path.toLowerCase());for(const n of e.children??[])t.push(...S1(n));return t}function yW(e,t){const n=t.replace(/^\/+/,"").toLowerCase(),a=e.replace(/\/+$/,"").toLowerCase();if(n==="index")return a.endsWith("/index")||a==="/docs";const o=`/${n}`;return a.endsWith(o)||a.endsWith(`${o}/index`)}function vW(e,t){if(!t.groups?.length)return!1;const n=bW(e),a=S1(e);for(const o of t.groups){const s=o.group.toLowerCase();if(n===s)return!0;if(o.prefix){const u=o.prefix.toLowerCase();if(n===u||n===u.replace(/-/g," "))return!0;const c=`/docs/${u}`;if(a.some(f=>f===c||f.startsWith(`${c}/`)))return!0}if(o.pages?.some(u=>a.some(c=>yW(c,u)))||!e.children?.length&&o.pages?.some(u=>{const c=u.split("/").pop()?.replace(/-/g," ")??"";return n===c||n===u.toLowerCase()}))return!0}return!1}function EW(e,t){const n=t.toLowerCase();let a=-1,o=0;for(let s=0;s<e.length;s++){const u=e[s];for(const c of u.groups??[]){if(!c.prefix)continue;const f=`/${c.prefix.toLowerCase()}/`;n.includes(f)&&f.length>o&&(a=s,o=f.length)}}return a>=0?a:0}function SW(e,t){return t?e.filter(n=>vW(n,t)):e}function Xu({enabled:e}){return e?p.jsx("a",{href:"#main-content",className:"sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 z-50 bg-primary text-primary-foreground px-4 py-2 rounded-md text-sm font-medium",children:"Skip to main content"}):null}function xW(){const[e,t]=v.useState({}),[n,a]=v.useState({}),[o,s]=v.useState({}),[u,c]=v.useState(!0),[f,g]=v.useState(null),[h,m]=v.useState(null),[E,S]=v.useState(""),[x,w]=v.useState(()=>Pt(window.location.pathname)),[T,A]=v.useState(!1),[_,N]=v.useState(0),L=e.navigation?.tabs??[],U=v.useMemo(()=>L.length?{items:SW(n.items??[],L[_])}:n,[n,L,_]);v.useEffect(()=>{L.length&&N(EW(L,x))},[x,L]);const D=(M,j)=>{con Line truncated
Loaded 100 of 800 files, more files were not shown because too many files have changed in this diff. Show more