diff --git a/.gitignore b/.gitignore index b9ae2c37..3dd98fb2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ node_modules # Computer Use runtime (auto-generated) .runtime/ extracted-natives/ + +# VitePress +docs/.vitepress/dist +docs/.vitepress/cache diff --git a/README.en.md b/README.en.md index ac643bcc..e0f383ab 100644 --- a/README.en.md +++ b/README.en.md @@ -13,6 +13,7 @@ [![License](https://img.shields.io/github/license/NanmiCoder/cc-haha)](https://github.com/NanmiCoder/cc-haha/blob/main/LICENSE) [![中文](https://img.shields.io/badge/🇨🇳_中文-Available-green)](README.md) [![English](https://img.shields.io/badge/🇺🇸_English-当前-blue)](README.en.md) +[![Docs](https://img.shields.io/badge/📖_Documentation-Visit-D97757)](https://claudecodehaha.relakkesyang.org) @@ -21,7 +22,7 @@ A **locally runnable version** repaired from the leaked Claude Code source, with > The original leaked source does not run as-is. This repository fixes multiple blocking issues in the startup path so the full Ink TUI can work locally.

- Features · Architecture · Quick Start · Env Vars · FAQ · Global Usage · More Docs + Features · Architecture · Quick Start · Env Vars · FAQ · Global Usage · More Docs

--- @@ -31,8 +32,8 @@ A **locally runnable version** repaired from the leaked Claude Code source, with - Full Ink TUI experience (matching the official Claude Code interface) - `--print` headless mode for scripts and CI - MCP server, plugin, and Skills support -- Custom API endpoint and model support ([Third-Party Models Guide](docs/guide/third-party-models.en.md)) -- **Computer Use desktop control** — [Guide](docs/features/computer-use.en.md) +- Custom API endpoint and model support ([Third-Party Models Guide](docs/en/guide/third-party-models.md)) +- **Computer Use desktop control** — [Guide](docs/en/features/computer-use.md) - **Memory System** (cross-session persistent memory) — [Usage Guide](docs/memory/01-usage-guide.md) - **Multi-Agent System** (agent orchestration, parallel tasks, Teams collaboration) — [Usage Guide](docs/agent/01-usage-guide.md) | [Implementation](docs/agent/02-implementation.md) - **Skills System** (extensible capability plugins, custom workflows) — [Usage Guide](docs/skills/01-usage-guide.md) | [Implementation](docs/skills/02-implementation.md) @@ -81,7 +82,7 @@ powershell -c "irm bun.sh/install.ps1 | iex" ```bash bun install cp .env.example .env -# Edit .env with your API key — see docs/guide/env-vars.en.md for details +# Edit .env with your API key — see docs/en/guide/env-vars.md for details ``` ### 3. Start @@ -108,7 +109,7 @@ bun --env-file=.env ./src/entrypoints/cli.tsx ### 4. Global Usage (Optional) -Add `bin/` to your PATH to run from any directory. See [Global Usage Guide](docs/guide/global-usage.en.md): +Add `bin/` to your PATH to run from any directory. See [Global Usage Guide](docs/en/guide/global-usage.md): ```bash export PATH="$HOME/path/to/claude-code-haha/bin:$PATH" @@ -133,16 +134,16 @@ export PATH="$HOME/path/to/claude-code-haha/bin:$PATH" | Document | Description | |------|------| -| [Environment Variables](docs/guide/env-vars.en.md) | Full env var reference and configuration methods | -| [Third-Party Models](docs/guide/third-party-models.en.md) | Using OpenAI / DeepSeek / Ollama and other non-Anthropic models | -| [Computer Use](docs/features/computer-use.en.md) | Desktop control (screenshots, mouse, keyboard) | +| [Environment Variables](docs/en/guide/env-vars.md) | Full env var reference and configuration methods | +| [Third-Party Models](docs/en/guide/third-party-models.md) | Using OpenAI / DeepSeek / Ollama and other non-Anthropic models | +| [Computer Use](docs/en/features/computer-use.md) | Desktop control (screenshots, mouse, keyboard) | | [Memory System](docs/memory/01-usage-guide.md) | Cross-session persistent memory usage and implementation | | [Multi-Agent System](docs/agent/01-usage-guide.md) | Agent orchestration, parallel tasks and Teams collaboration | | [Skills System](docs/skills/01-usage-guide.md) | Extensible capability plugins, custom workflows and conditional activation | -| [Global Usage](docs/guide/global-usage.en.md) | Run claude-haha from any directory | -| [FAQ](docs/guide/faq.en.md) | Common error troubleshooting | -| [Source Fixes](docs/reference/fixes.en.md) | Fixes compared with the original leaked source | -| [Project Structure](docs/reference/project-structure.en.md) | Code directory structure | +| [Global Usage](docs/en/guide/global-usage.md) | Run claude-haha from any directory | +| [FAQ](docs/en/guide/faq.md) | Common error troubleshooting | +| [Source Fixes](docs/en/reference/fixes.md) | Fixes compared with the original leaked source | +| [Project Structure](docs/en/reference/project-structure.md) | Code directory structure | --- diff --git a/README.md b/README.md index cece10cb..607f703e 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ [![License](https://img.shields.io/github/license/NanmiCoder/cc-haha)](https://github.com/NanmiCoder/cc-haha/blob/main/LICENSE) [![中文](https://img.shields.io/badge/🇨🇳_中文-当前-blue)](README.md) [![English](https://img.shields.io/badge/🇺🇸_English-Available-green)](README.en.md) +[![Docs](https://img.shields.io/badge/📖_文档站点-Visit-D97757)](https://claudecodehaha.relakkesyang.org) diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts new file mode 100644 index 00000000..9cf718ac --- /dev/null +++ b/docs/.vitepress/config.mts @@ -0,0 +1,175 @@ +import { defineConfig } from 'vitepress' + +const zhSidebar = [ + { + text: '快速开始', + items: [ + { text: '安装与启动', link: '/guide/quick-start' }, + { text: '环境变量', link: '/guide/env-vars' }, + { text: '第三方模型', link: '/guide/third-party-models' }, + { text: '全局使用', link: '/guide/global-usage' }, + { text: '常见问题', link: '/guide/faq' }, + ], + }, + { + text: '功能', + items: [ + { text: 'Computer Use', link: '/features/computer-use' }, + ], + }, + { + text: '记忆系统', + collapsed: false, + items: [ + { text: '概览', link: '/memory/' }, + { text: '使用指南', link: '/memory/01-usage-guide' }, + { text: '实现原理', link: '/memory/02-implementation' }, + { text: 'AutoDream 记忆整合', link: '/memory/03-autodream' }, + ], + }, + { + text: '多 Agent 系统', + collapsed: false, + items: [ + { text: '概览', link: '/agent/' }, + { text: '使用指南', link: '/agent/01-usage-guide' }, + { text: '实现原理', link: '/agent/02-implementation' }, + ], + }, + { + text: 'Skills 系统', + collapsed: false, + items: [ + { text: '使用指南', link: '/skills/01-usage-guide' }, + { text: '实现原理', link: '/skills/02-implementation' }, + ], + }, + { + text: '参考', + collapsed: true, + items: [ + { text: '源码修复记录', link: '/reference/fixes' }, + { text: '项目结构', link: '/reference/project-structure' }, + ], + }, +] + +const enSidebar = [ + { + text: 'Getting Started', + items: [ + { text: 'Quick Start', link: '/en/guide/quick-start' }, + { text: 'Environment Variables', link: '/en/guide/env-vars' }, + { text: 'Third-Party Models', link: '/en/guide/third-party-models' }, + { text: 'Global Usage', link: '/en/guide/global-usage' }, + { text: 'FAQ', link: '/en/guide/faq' }, + ], + }, + { + text: 'Features', + items: [ + { text: 'Computer Use', link: '/en/features/computer-use' }, + ], + }, + { + text: 'Memory System', + collapsed: false, + items: [ + { text: 'Overview', link: '/en/memory/' }, + { text: 'Usage Guide', link: '/en/memory/01-usage-guide' }, + { text: 'Implementation', link: '/en/memory/02-implementation' }, + { text: 'AutoDream', link: '/en/memory/03-autodream' }, + ], + }, + { + text: 'Multi-Agent System', + collapsed: false, + items: [ + { text: 'Overview', link: '/en/agent/' }, + { text: 'Usage Guide', link: '/en/agent/01-usage-guide' }, + { text: 'Implementation', link: '/en/agent/02-implementation' }, + ], + }, + { + text: 'Skills System', + collapsed: false, + items: [ + { text: 'Usage Guide', link: '/en/skills/01-usage-guide' }, + { text: 'Implementation', link: '/en/skills/02-implementation' }, + ], + }, + { + text: 'Reference', + collapsed: true, + items: [ + { text: 'Source Fixes', link: '/en/reference/fixes' }, + { text: 'Project Structure', link: '/en/reference/project-structure' }, + ], + }, +] + +export default defineConfig({ + title: 'Claude Code Haha', + description: '基于 Claude Code 泄露源码修复的本地可运行版本,支持接入任意 Anthropic 兼容 API', + lastUpdated: true, + base: '/', + + head: [ + // Google Analytics - 获取 GA ID 后取消注释 + // ['script', { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX' }], + // ['script', {}, `window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', 'G-XXXXXXXXXX');`], + ], + + locales: { + root: { + label: '中文', + lang: 'zh-CN', + themeConfig: { + nav: [ + { text: '首页', link: '/' }, + { text: '快速开始', link: '/guide/quick-start' }, + ], + sidebar: zhSidebar, + outline: { label: '页面导航' }, + returnToTopLabel: '返回顶部', + sidebarMenuLabel: '菜单', + darkModeSwitchLabel: '主题', + lastUpdated: { text: '最后更新于' }, + docFooter: { prev: '上一页', next: '下一页' }, + }, + }, + en: { + label: 'English', + lang: 'en-US', + description: 'A locally runnable version repaired from the leaked Claude Code source, with support for any Anthropic-compatible API endpoint.', + themeConfig: { + editLink: { + pattern: 'https://github.com/NanmiCoder/cc-haha/edit/main/docs/:path', + text: 'Edit this page on GitHub', + }, + nav: [ + { text: 'Home', link: '/en/' }, + { text: 'Quick Start', link: '/en/guide/quick-start' }, + ], + sidebar: enSidebar, + }, + }, + }, + + themeConfig: { + editLink: { + pattern: 'https://github.com/NanmiCoder/cc-haha/edit/main/docs/:path', + text: '在 GitHub 上编辑此页', + }, + search: { + provider: 'local', + }, + socialLinks: [ + { icon: 'github', link: 'https://github.com/NanmiCoder/cc-haha' }, + ], + footer: { + message: 'Released under the MIT License.', + copyright: 'Copyright 2026 Claude Code Haha Contributors', + }, + }, +}) diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css new file mode 100644 index 00000000..cda033fc --- /dev/null +++ b/docs/.vitepress/theme/custom.css @@ -0,0 +1,14 @@ +:root { + --vp-c-brand-1: #D97757; + --vp-c-brand-2: #c5684a; + --vp-c-brand-3: #b15a3e; + --vp-c-brand-soft: rgba(217, 119, 87, 0.14); + --vp-sidebar-width: 280px; +} + +.dark { + --vp-c-brand-1: #D97757; + --vp-c-brand-2: #e08868; + --vp-c-brand-3: #ea9a7a; + --vp-c-brand-soft: rgba(217, 119, 87, 0.16); +} diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts new file mode 100644 index 00000000..15492a8c --- /dev/null +++ b/docs/.vitepress/theme/index.ts @@ -0,0 +1,6 @@ +import DefaultTheme from 'vitepress/theme' +import './custom.css' + +export default { + extends: DefaultTheme, +} diff --git a/docs/agent/README.md b/docs/agent/index.md similarity index 91% rename from docs/agent/README.md rename to docs/agent/index.md index b74f8439..3e350721 100644 --- a/docs/agent/README.md +++ b/docs/agent/index.md @@ -99,9 +99,9 @@ ## 🔗 相关资源 -- [Claude Code 主文档](../) -- [记忆系统文档](../memory/) -- [Agent Tool 源码](../../src/tools/AgentTool/) -- [Swarm 基础设施](../../src/utils/swarm/) -- [任务管理系统](../../src/tasks/) -- [GitHub Issues](https://github.com/anthropics/claude-code/issues) +- [Claude Code Haha 主页](/) +- [记忆系统文档](/memory/01-usage-guide) +- [Agent Tool 源码](https://github.com/NanmiCoder/cc-haha/tree/main/src/tools/AgentTool/) +- [Swarm 基础设施](https://github.com/NanmiCoder/cc-haha/tree/main/src/utils/swarm/) +- [任务管理系统](https://github.com/NanmiCoder/cc-haha/tree/main/src/tasks/) +- [GitHub Issues](https://github.com/NanmiCoder/cc-haha/issues) diff --git a/docs/en/agent/01-usage-guide.md b/docs/en/agent/01-usage-guide.md new file mode 100644 index 00000000..48ff198f --- /dev/null +++ b/docs/en/agent/01-usage-guide.md @@ -0,0 +1,443 @@ +# Claude Code Multi-Agent System — Usage Guide + +> Let Claude Code orchestrate multiple specialized agents to handle complex tasks in parallel. + +

+Multi-Agent System · Six Built-in Agents · Spawning Agents · Background Tasks · Agent Teams · Custom Agents · Permission Modes · Quick Reference +

+ +![Multi-Agent System Overview](./images/01-agent-overview.png) + +--- + +## 1. What Is the Multi-Agent System? + +Claude Code's multi-agent system is an **intelligent task orchestration framework** that enables the primary agent to spawn multiple specialized subagents, each executing different tasks independently, then aggregating results for the user. + +Core philosophy: **Break large tasks into specialized subtasks, execute them in parallel, and boost efficiency.** + +| Scenario | Traditional Approach | Multi-Agent Approach | +|----------|---------------------|---------------------| +| Research 5 module architectures | Explore them one by one | 5 Explore agents scan in parallel | +| Implement + Test + Document | Complete sequentially | Team members each handle one part | +| Code review | Single-threaded, file by file | Multiple reviewers in parallel | +| Debug a complex bug | Try one hypothesis at a time | Multiple debuggers verify in parallel | + +--- + +## 2. Six Built-in Agents + +![Six Built-in Agents](./images/02-agent-types.png) + +Claude Code ships with 6 specialized agent types, each with a specific tool pool and intended use case: + +### 2.1 general-purpose (General Agent) + +**Use case**: Complex multi-step research, code search, tasks requiring full tool access. + +``` +Agent({ + description: "Research auth module", + prompt: "Analyze all files under src/auth/ for the authentication flow...", + subagent_type: "general-purpose" +}) +``` + +- **Tool pool**: All tools (`*`) +- **Model**: Inherited from parent +- **Characteristics**: The all-rounder — choose this when you are unsure which agent type to use + +### 2.2 Explore (Exploration Agent) + +**Use case**: Quickly search files, find code patterns, answer questions about codebase structure. + +``` +Agent({ + description: "Search API endpoints", + prompt: "Find all REST API endpoint definitions...", + subagent_type: "Explore" +}) +``` + +- **Tool pool**: Read-only tools (Glob, Grep, Read, Bash) +- **Model**: Haiku (fast, low cost) +- **Characteristics**: Cannot modify files; fast; ideal for research + +### 2.3 Plan (Planning Agent) + +**Use case**: Design implementation plans, analyze architectural trade-offs, generate step-by-step plans. + +``` +Agent({ + description: "Plan refactoring", + prompt: "Design a plan to split the monolith into microservices...", + subagent_type: "Plan" +}) +``` + +- **Tool pool**: Read-only tools (same as Explore) +- **Model**: Inherited from parent (requires strong reasoning) +- **Characteristics**: Outputs structured plans including key files and dependency analysis + +### 2.4 verification (Verification Agent) + +**Use case**: Independently verify that an implementation is correct, run tests, perform boundary checks. + +``` +Agent({ + description: "Verify login feature", + prompt: "Verify the newly implemented login feature works correctly...", + subagent_type: "verification" +}) +``` + +- **Tool pool**: Read-only tools +- **Model**: Inherited from parent +- **Characteristics**: Always runs in the background; outputs PASS/FAIL/PARTIAL verdicts; displayed with a red badge + +### 2.5 claude-code-guide (Guide Agent) + +**Use case**: Answer questions about Claude Code, Agent SDK, or the Claude API. + +``` +Agent({ + description: "Query Claude API usage", + prompt: "How do I use the tool_use feature...", + subagent_type: "claude-code-guide" +}) +``` + +- **Tool pool**: Bash, Read, WebFetch, WebSearch +- **Model**: Haiku +- **Characteristics**: Focused on documentation queries; uses the dontAsk permission mode + +### 2.6 statusline-setup (Status Bar Configuration Agent) + +**Use case**: Configure the Claude Code status bar display. + +- **Tool pool**: Read + Edit only +- **Model**: Sonnet +- **Characteristics**: Highly specialized with an extremely narrow scope + +### Agent Type Comparison + +| Agent | Access | Tool Pool | Model | Purpose | +|-------|--------|-----------|-------|---------| +| general-purpose | Read/Write | All | Inherited | General tasks | +| Explore | Read-only | Search + Read | Haiku | Quick exploration | +| Plan | Read-only | Search + Read | Inherited | Architecture planning | +| verification | Read-only | Search + Read | Inherited | Independent verification | +| claude-code-guide | Read-only | Search + Web | Haiku | Documentation guide | +| statusline-setup | Read/Write | Read + Edit | Sonnet | Status bar config | + +--- + +## 3. How to Spawn Agents + +### Parameters + +The Agent tool accepts the following parameters: + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `description` | string | Yes | 3-5 word task summary | +| `prompt` | string | Yes | Full task description | +| `subagent_type` | string | No | Agent type (see table above) | +| `model` | string | No | Model override: sonnet/opus/haiku | +| `run_in_background` | boolean | No | Whether to run in background | +| `name` | string | No | Name the agent so it can be addressed via SendMessage | +| `team_name` | string | No | Join a specified team | +| `mode` | string | No | Permission mode | +| `isolation` | string | No | Isolation mode: worktree | + +### Foreground Synchronous Execution (Default) + +The simplest usage — the agent completes and returns its result: + +``` +Agent({ + description: "Analyze error logs", + prompt: "Read the latest error logs under logs/ and summarize common error patterns" +}) +``` + +The primary agent waits for the subagent to finish, then receives the result and continues working. + +### Background Asynchronous Execution + +Suitable for time-consuming tasks where the primary agent can continue with other work: + +``` +Agent({ + description: "Full code review", + prompt: "Review all TypeScript files under src/ for code quality...", + run_in_background: true +}) +``` + +- The agent immediately returns an `async_launched` status with a taskId +- The primary agent continues working without waiting +- When the agent completes, a `` is delivered automatically +- The notification includes task status, output file path, and a result summary + +### Spawning Multiple Agents in Parallel + +Spawn multiple independent agents in a single message for true parallelism: + +``` +// Launch 3 explore agents simultaneously +Agent({ description: "Explore frontend", prompt: "...", subagent_type: "Explore", run_in_background: true }) +Agent({ description: "Explore backend", prompt: "...", subagent_type: "Explore", run_in_background: true }) +Agent({ description: "Explore database", prompt: "...", subagent_type: "Explore", run_in_background: true }) +``` + +### Worktree Isolation + +Let an agent work in an isolated git worktree without affecting the main workspace: + +``` +Agent({ + description: "Experimental refactor", + prompt: "Try refactoring module X into...", + isolation: "worktree" +}) +``` + +- Automatically creates a git worktree (on an independent branch) +- The agent can freely modify files in the isolated environment +- If changes were made, returns the worktree path and branch name on completion +- If no changes were made, cleans up automatically + +--- + +## 4. Background Task Management + +![Agent Spawn Flow](./images/03-spawn-flow.png) + +### Task States + +Background agents have four possible states: + +| State | Description | +|-------|-------------| +| `running` | Currently executing | +| `completed` | Finished successfully | +| `failed` | Execution failed | +| `killed` | Manually terminated | + +### Progress Tracking + +Background agent progress updates in real time: + +- **Token usage**: Input/output token counts +- **Tool usage**: Number of tools invoked +- **Recent activity**: Descriptions of the last 5 tool calls (circular buffer) +- **Last activity time**: Used to detect stuck tasks + +### Completion Notifications + +When a background agent finishes, the primary agent receives an XML-formatted notification: + +```xml + + abc123 + completed + Agent "Explore frontend" completed + ~/.claude/temp/.../tasks/abc123.output + +``` + +### Automatic Backgrounding + +When the `tengu_auto_background_agents` feature flag is enabled, foreground agents that run for more than **120 seconds** are automatically moved to background execution, freeing the primary agent to continue working. + +--- + +## 5. Agent Teams — Multi-Agent Collaboration + +![Agent Teams Collaboration](./images/04-agent-teams.png) + +Agent Teams is an advanced multi-agent collaboration mode where multiple agents work as a team, coordinating tasks through message-based communication. + +### Creating a Team + +``` +TeamCreate({ + team_name: "feature-team", + description: "Develop user authentication feature" +}) +``` + +After team creation: +- A team configuration file is generated: `~/.claude/teams/{team_name}/config.json` +- A shared task directory is created: `~/.claude/tasks/{team_name}/` +- The current agent automatically becomes the **Team Lead** + +### Adding Team Members + +Spawn teammates by specifying `name` and `team_name` in the Agent tool: + +``` +Agent({ + description: "Frontend development", + prompt: "Implement the login page React components...", + name: "frontend-dev", + team_name: "feature-team" +}) + +Agent({ + description: "Backend development", + prompt: "Implement the authentication API endpoints...", + name: "backend-dev", + team_name: "feature-team" +}) +``` + +### Teammate Communication + +Send messages using the SendMessage tool: + +``` +// Send to a specific teammate +SendMessage({ + to: "frontend-dev", + message: "API interface is ready, the format is...", + summary: "Notify API interface format" +}) + +// Broadcast to all teammates +SendMessage({ + to: "*", + message: "Everyone pause, requirements have changed...", + summary: "Broadcast requirements change" +}) +``` + +### Shutdown Coordination + +When the task is complete, the Team Lead requests teammates to shut down: + +``` +// 1. Send shutdown request +SendMessage({ + to: "frontend-dev", + message: { type: "shutdown_request", reason: "Task completed" } +}) + +// 2. Teammate responds with approval +SendMessage({ + to: "team-lead", + message: { type: "shutdown_response", request_id: "...", approve: true } +}) + +// 3. After all teammates shut down, clean up the team +TeamDelete() +``` + +### Execution Backends + +Agent Teams supports two execution backends: + +| Backend | Description | Use Case | +|---------|-------------|----------| +| **in-process** | Runs in the same process, isolated via AsyncLocalStorage | Default mode; lightweight and efficient | +| **tmux** | Runs in a separate tmux pane | When an independent terminal view is needed | +| **iTerm2** | Runs in a separate iTerm2 window | For macOS iTerm2 users | + +--- + +## 6. Custom Agents + +In addition to built-in agents, you can create your own specialized agents. + +### Definition Format + +Create a `.md` file in the `.claude/agents/` directory: + +```markdown +--- +name: code-reviewer +description: Professional code review agent +tools: + - Read + - Grep + - Glob + - Bash +model: sonnet +permissionMode: dontAsk +maxTurns: 10 +--- + +You are a professional code reviewer. Check the following aspects: + +1. Code quality and readability +2. Potential security vulnerabilities +3. Performance issues +4. Adherence to best practices +``` + +### Configurable Fields + +| Field | Type | Description | +|-------|------|-------------| +| `name` | string | Agent type name | +| `description` | string | Description of when to use this agent | +| `tools` | string[] | Allowed tool list (`['*']` for all) | +| `disallowedTools` | string[] | Disallowed tool list | +| `model` | string | Model to use (sonnet/opus/haiku/inherit) | +| `permissionMode` | string | Permission mode | +| `maxTurns` | number | Maximum conversation turns | +| `mcpServers` | object[] | Required MCP servers | +| `hooks` | object | Agent-specific hooks | +| `skills` | string[] | Available skills | +| `memory` | string | Memory scope (user/project/local) | +| `isolation` | string | Isolation mode (worktree/remote) | +| `background` | boolean | Whether to run in background by default | + +### Loading Priority + +Custom agents are loaded according to the following priority: + +1. **Built-in agents** (built-in) — System predefined +2. **Plugin agents** (plugin) — Registered via plugins +3. **User agents** (user) — `~/.claude/agents/` +4. **Project agents** (project) — `.claude/agents/` (project-level) +5. **Flag agents** (flag) — Registered via API +6. **Policy agents** (policy) — Organization policies + +Agents with the same name are overridden according to priority. + +--- + +## 7. Permission Modes + +Each agent can be configured with a different permission mode: + +| Mode | Description | +|------|-------------| +| `default` | Normal permission requests requiring user confirmation | +| `plan` | All operations require explicit approval | +| `acceptEdits` | File edits are auto-approved; other operations require confirmation | +| `bypassPermissions` | Skip all permission checks | +| `dontAsk` | Reject all operations not pre-approved | +| `auto` | AI-driven permission classification (Anthropic internal only) | +| `bubble` | Permission prompts bubble up to the parent agent's terminal | + +--- + +## 8. Quick Reference + +| Action | Method | +|--------|--------| +| Spawn a subagent | `Agent({ prompt: "...", subagent_type: "Explore" })` | +| Run in background | `Agent({ ..., run_in_background: true })` | +| Spawn in parallel | Send multiple Agent calls in a single message | +| Worktree isolation | `Agent({ ..., isolation: "worktree" })` | +| Create a team | `TeamCreate({ team_name: "..." })` | +| Send a message | `SendMessage({ to: "name", message: "..." })` | +| Broadcast a message | `SendMessage({ to: "*", message: "..." })` | +| Request shutdown | `SendMessage({ to: "name", message: { type: "shutdown_request" } })` | +| Delete a team | `TeamDelete()` | +| Custom agent | Create a definition file in `.claude/agents/*.md` | +| Specify a model | `Agent({ ..., model: "haiku" })` | +| Name an agent | `Agent({ ..., name: "researcher" })` | diff --git a/docs/en/agent/02-implementation.md b/docs/en/agent/02-implementation.md new file mode 100644 index 00000000..b1b94ec5 --- /dev/null +++ b/docs/en/agent/02-implementation.md @@ -0,0 +1,856 @@ +# Claude Code Multi-Agent System — Implementation Details + +> A deep dive into the architecture, spawn flow, context passing, and collaboration mechanisms of multi-agent orchestration. + +

+Architecture · Spawn Flow · Tool Pool · Context Passing · Teams Internals · Task Engine · DreamTask · Worktree Isolation · Permission Sync · Lifecycle Data Flow · Source Index · Feature Flags +

+ +![Implementation Architecture Overview](./images/05-architecture.png) + +--- + +## 1. Architecture Overview + +Claude Code's multi-agent system consists of the following core modules: + +### 5 Core Modules + +| Module | Responsibility | Key Files | +|--------|---------------|-----------| +| **Agent Tool** | Primary entry point, routing & dispatch, parameter parsing | `src/tools/AgentTool/AgentTool.tsx` | +| **Execution Engine** | Agent lifecycle management, query loop | `src/tools/AgentTool/runAgent.ts` | +| **Context Manager** | System prompt construction, cache-safe parameters | `src/utils/forkedAgent.ts` | +| **Task System** | State tracking, progress updates, notification queue | `src/tasks/LocalAgentTask/` | +| **Swarm Infrastructure** | Team management, mailbox communication, permission sync | `src/utils/swarm/` | + +### 5 Agent Categories + +``` +┌─────────────────────────────────────────────────┐ +│ Agent Tool │ +│ (Entry & Route Dispatch) │ +├───────────┬───────────┬───────────┬─────────────┤ +│ Subagent │ Fork │ Teammate │ Remote │ +│ │ │ │ │ +│ Standalone│ Inherited │ Team │ CCR │ +│ context │ context │ collab │ environment │ +│ Type-based│ Cache │ Mailbox │ Remote │ +│ tool pool │ sharing │ comms │ execution │ +│ │ Byte-level│ Permission│ Poll for │ +│ │ consistent│ sync │ results │ +└───────────┴───────────┴───────────┴─────────────┘ + │ + ┌─────┴─────┐ + │ DreamTask │ + │ (Memory │ + │ Consolidation) │ + │ Scheduled │ + │ background│ + └───────────┘ +``` + +--- + +## 2. Agent Spawn Flow — Four Paths + +### Entry Point: `AgentTool.call()` + +The `call()` function in `src/tools/AgentTool/AgentTool.tsx` is the entry point for all agent spawning. Based on input parameters, it routes to one of four spawn paths: + +``` +AgentTool.call(input) + │ + ├─ team_name + name? ──────→ Path 1: spawnTeammate() + │ + ├─ run_in_background? ────→ Path 2: registerAsyncAgent() + │ └─ agent.background? + │ + ├─ subagent_type omitted? ─→ Path 3: Fork (buildForkedMessages()) + │ └─ fork experiment on? + │ + └─ default ────────────────→ Path 4: runAgent() synchronous execution +``` + +### Path 1: Teammate Spawn + +**Trigger**: Both `team_name` and `name` are present + +**Entry function**: `spawnTeammate()` — `src/tools/shared/spawnMultiAgent.ts` + +**Flow**: + +1. Detect execution backend (tmux / iTerm2 / in-process) +2. Generate a unique `agentId` for the teammate: `formatAgentId(name, teamName)` +3. Assign a color (from a predefined palette) +4. Create the execution environment: + - **in-process**: Start in the same process via `spawnInProcessTeammate()` + - **tmux**: Create a new pane via `TmuxBackend` + - **iTerm2**: Create a new window via `ITerm2Backend` +5. Write to the TeamFile member list +6. Return `TeammateSpawnedOutput` (including pane ID, agent ID, etc.) + +**In-Process Teammate Isolation**: + +```typescript +// src/utils/swarm/spawnInProcess.ts +export async function spawnInProcessTeammate(config, context) { + // 1. Independent AbortController (not tied to leader's cancellation) + const abortController = new AbortController() + + // 2. AsyncLocalStorage context isolation + runWithTeammateContext(teammateContext, async () => { + // 3. Independent task state + // 4. Independent message loop + // 5. Shared permission pipeline (via mailbox) + }) +} +``` + +### Path 2: Async Subagent + +**Trigger**: `run_in_background=true` or `background: true` in the agent definition + +**Flow**: + +``` +registerAsyncAgent() + │ + ├─ Create LocalAgentTask (status: 'running') + ├─ Register in agentNameRegistry (if named) + ├─ Create output file symlink + ├─ Create AbortController (linked to parent) + ├─ Emit SDK event: task_started + │ + └─ void runAsyncAgentLifecycle() ← fire-and-forget async + │ + ├─ Create ProgressTracker + ├─ Iterate makeStream() generator + │ ├─ Append messages to agentMessages[] + │ ├─ Update progress (tokens, tools, activities) + │ └─ Emit SDK progress events + │ + └─ On completion: + ├─ finalizeAgentTool() (extract result) + ├─ completeAgentTask() (mark complete) + ├─ Clean up worktree (if isolated) + └─ enqueuePendingNotification() (notify primary agent) +``` + +**Key implementation**: `src/tools/AgentTool/agentToolUtils.ts` — `runAsyncAgentLifecycle()` + +### Path 3: Fork Subagent + +**Trigger**: `subagent_type` is omitted and the fork experiment is enabled + +**Core optimization**: Achieves **prompt cache hits** through byte-level consistent API request prefixes. + +![Fork Cache Optimization](./images/10-fork-cache.png) + +**Flow**: + +``` +buildForkedMessages(directive, assistantMessage) + │ + ├─ Preserve parent agent's complete assistant message (all tool_use blocks) + ├─ Build user message: + │ ├─ Create placeholder tool_result for each tool_use (byte-consistent) + │ └─ Append per-child directive (the only divergent part) + │ + └─ Result: byte-level consistent API prefix → prompt cache hit! +``` + +**Fork child behavioral constraints** (injected via `FORK_BOILERPLATE_TAG`): + +``` +1. You are a forked worker process, not the primary agent +2. Do not converse, ask questions, or suggest next steps +3. Use tools directly (Bash, Read, Write, etc.) +4. If you modify files, commit changes before reporting +5. Do not output text between tool calls +6. Stay strictly within the scope of your directive +7. Keep your report under 500 words +8. Your response must begin with "Scope:" +``` + +**Anti-recursion protection**: `isInForkChild()` detects whether execution is inside a fork child, preventing nested forks. + +### Path 4: Synchronous Subagent + +**Trigger**: Default path (no team_name, no background, not a fork) + +**Flow**: + +``` +runAgent(promptMessages, toolUseContext, options) + │ + ├─ Resolve agent definition (getSystemPrompt, tools, permissions) + ├─ Build system prompt (buildEffectiveSystemPrompt) + ├─ Create isolated ToolUseContext (createSubagentContext) + ├─ Start query loop (query() async generator) + │ ├─ Send API request + │ ├─ Process streaming events + │ ├─ Execute tool calls + │ └─ Accumulate messages and usage + │ + └─ Return AgentToolResult + ├─ content: text from the last assistant message + ├─ totalToolUseCount + ├─ totalDurationMs + └─ totalTokens +``` + +--- + +## 3. Tool Pool System — Three-Layer Filtering + +![Tool Pool System](./images/07-tool-pool.png) + +### Layer 1: Global Disallow List + +`ALL_AGENT_DISALLOWED_TOOLS` — tools disallowed for all agents: + +| Tool | Reason for Disallowing | +|------|----------------------| +| TaskOutput | Only the primary agent may read task output | +| ExitPlanMode | Only the primary agent may exit plan mode | +| EnterPlanMode | Only the primary agent may enter plan mode | +| AskUserQuestion | Subagents should not directly ask the user | +| TaskStop | Only the primary agent may terminate tasks | +| Agent | Prevent recursive spawning (Anthropic internal exception) | + +### Layer 2: Agent Type Filtering + +`filterToolsForAgent()` — tool filtering based on agent type: + +```typescript +// src/tools/AgentTool/agentToolUtils.ts +function filterToolsForAgent(tools, agentDef) { + // 1. Remove ALL_AGENT_DISALLOWED_TOOLS + // 2. If not a built-in agent, also remove CUSTOM_AGENT_DISALLOWED_TOOLS + // 3. If async agent, restrict to ASYNC_AGENT_ALLOWED_TOOLS + // 4. MCP tools are always allowed +} +``` + +**ASYNC_AGENT_ALLOWED_TOOLS** (15 tools): + +``` +Read, WebSearch, TodoWrite, Grep, WebFetch, Glob, +Bash/PowerShell, FileEdit, FileWrite, NotebookEdit, +Skill, SyntheticOutput, ToolSearch, EnterWorktree, ExitWorktree +``` + +### Layer 3: Agent Definition Filtering + +`resolveAgentTools()` — tool resolution based on agent definition: + +```typescript +function resolveAgentTools(agentDef, availableTools) { + if (tools === ['*'] || undefined) → wildcard, allow all + if (tools === ['Read', 'Grep']) → allow only listed tools + if (disallowedTools === ['Agent']) → subtract from available tools +} +``` + +**Filtering Pipeline**: + +``` +All available tools + │ + ├─ Subtract ALL_AGENT_DISALLOWED_TOOLS ──→ Global disallow + │ + ├─ Not built-in? Subtract CUSTOM_AGENT_DISALLOWED_TOOLS ──→ Custom restrictions + │ + ├─ Async? Restrict to ASYNC_AGENT_ALLOWED_TOOLS ──→ Async allowlist + │ + ├─ Has tools list? Intersect ──→ Agent allowlist + │ + ├─ Has disallowedTools? Subtract ──→ Agent denylist + │ + └─ Final tool pool +``` + +--- + +## 4. Context Passing Mechanism + +![Context Passing](./images/06-context-passing.png) + +### CacheSafeParams — Cache-Safe Parameters + +```typescript +// src/utils/forkedAgent.ts +export type CacheSafeParams = { + systemPrompt: SystemPrompt // System prompt + userContext: { [k: string]: string } // Directory structure, CLAUDE.md, etc. + systemContext: { [k: string]: string } // Git status, environment info + toolUseContext: ToolUseContext // Tool configuration, model, options + forkContextMessages: Message[] // Fork context messages (for cache sharing) +} +``` + +**Cache Sharing Principle**: + +Fork agents reuse prompt cache by keeping API request prefixes byte-level consistent: + +``` +┌─────────────────────────────────────────┐ +│ Shared Prefix (byte-consistent) │ +│ ┌──────────────────────────────────┐ │ +│ │ System Prompt │ │ +│ │ User Context │ │ +│ │ System Context │ │ +│ │ Tool Use Context │ │ +│ │ Conversation History Messages │ │ +│ │ Assistant Message (all tool_use) │ │ +│ │ User Message (placeholder results│) │ +│ └──────────────────────────────────┘ │ +├─────────────────────────────────────────┤ +│ Only divergence: per-child directive │ +└─────────────────────────────────────────┘ +``` + +### System Prompt Construction + +`buildEffectiveSystemPrompt()` — `src/utils/systemPrompt.ts` + +**Priority chain** (highest to lowest): + +``` +Override System Prompt ← Highest priority, full replacement + ↓ +Coordinator System Prompt ← Coordinator mode only + ↓ +Agent System Prompt ← agentDefinition.getSystemPrompt() + ↓ - proactive mode: appended to default + ↓ - otherwise: replaces default +Custom System Prompt ← --system-prompt argument + ↓ +Default System Prompt ← Standard Claude Code prompt + ↓ +Append System Prompt ← Appended to the end +``` + +**Agent-specific system prompt enhancement**: + +```typescript +// src/tools/AgentTool/runAgent.ts +function getAgentSystemPrompt(agentDef, toolUseContext) { + let prompt = agentDef.getSystemPrompt({ toolUseContext }) + prompt = enhanceSystemPromptWithEnvDetails(prompt) + // Adds: working directory, enabled tools list, model info, environment variables + return prompt +} +``` + +### SubagentContext — Subagent Context Isolation + +```typescript +// src/utils/forkedAgent.ts +export type SubagentContextOverrides = { + options?: ToolUseContext['options'] // Custom tools, model + agentId?: AgentId // Subagent ID + agentType?: string // Agent type + messages?: Message[] // Custom message history + readFileState?: ToolUseContext['readFileState'] // File read cache + abortController?: AbortController // Abort controller + + // Explicit opt-in sharing (isolated by default) + shareSetAppState?: boolean // Share AppState writes + shareSetResponseLength?: boolean // Share response length metrics + shareAbortController?: boolean // Share abort controller + + // Experimental injection + criticalSystemReminder_EXPERIMENTAL?: string // Re-injected each turn + contentReplacementState?: ContentReplacementState +} +``` + +**Isolation vs. Sharing**: + +| Resource | Default | Description | +|----------|---------|-------------| +| readFileState | Cloned | File read cache is independent | +| messages | New | Message history is independent | +| abortController | New (linked to parent) | Child is cancelled when parent cancels | +| setAppState | No-op | Does not affect parent state by default | +| contentReplacementState | Cloned | Content replacement state is independent | + +### Model Resolution + +`getAgentModel()` — `src/utils/model/agent.ts` + +**Priority chain**: + +``` +CLAUDE_CODE_SUBAGENT_MODEL env var ← Highest + ↓ +Agent({ model: 'opus' }) parameter ← Specified via tool + ↓ +agentDefinition.model ← Agent definition + ↓ +'inherit' ← Inherit parent model +``` + +--- + +## 5. Agent Teams Internals + +### TeamFile Structure + +```typescript +// Storage path: ~/.claude/teams/{team_name}/config.json +{ + name: string // Team name + description?: string // Team description + createdAt: number // Creation timestamp + leadAgentId: string // Team Lead's Agent ID + leadSessionId?: string // Lead's session UUID + hiddenPaneIds?: string[] // Panes hidden in UI + teamAllowedPaths?: TeamAllowedPath[] // Team-level shared permissions + members: Array<{ + agentId: string // Member Agent ID + name: string // Display name + agentType?: string // Role type + model?: string // Model used + prompt?: string // Initial task + color?: string // UI color + planModeRequired?: boolean // Whether plan approval is required + joinedAt: number // Join timestamp + tmuxPaneId: string // Terminal pane ID + cwd: string // Working directory + worktreePath?: string // Worktree path + sessionId?: string // Session ID + subscriptions: string[] // Message subscriptions + backendType?: 'tmux'|'iterm2'|'in-process' + isActive?: boolean // false=idle, true/undefined=active + mode?: PermissionMode // Current permission mode + }> +} +``` + +### Mailbox System + +![Teams Mailbox System](./images/09-teams-mailbox.png) + +**Storage path**: `~/.claude/teams/{team_name}/inboxes/{agent_name}.json` + +```typescript +// src/utils/teammateMailbox.ts +type TeammateMessage = { + from: string // Sender name + text: string // Message content (plain text or JSON) + timestamp: string // ISO timestamp + read: boolean // Whether the message has been read + color?: string // Sender's color + summary?: string // 5-10 word summary +} +``` + +**Concurrency safety**: Uses `proper-lockfile` file locks with 10 retries and 5-100ms exponential backoff. + +**Message Types**: + +| Message | Format | Purpose | +|---------|--------|---------| +| Plain text | `string` | Regular conversation messages | +| shutdown_request | `{ type, reason }` | Request a teammate to shut down | +| shutdown_response | `{ type, request_id, approve }` | Approve/reject shutdown | +| plan_approval_response | `{ type, request_id, approve }` | Approve a plan | +| permission_request | `{ type, toolName, path }` | Permission request | +| idle_notification | Special format | Idle notification | + +### Inbox Polling + +```typescript +// src/hooks/useInboxPoller.ts +// Poll interval: 1000ms + +useEffect(() => { + const interval = setInterval(async () => { + const messages = await readUnreadMessages(agentName, teamName) + + for (const msg of messages) { + if (isShutdownRequest(msg.text)) { + // Handle shutdown request + } else if (isPlanApprovalResponse(msg.text)) { + // Handle plan approval + } else if (isPermissionRequest(msg.text)) { + // Route to permission system + } else { + // Plain text message → submit as new conversation turn + onSubmitMessage(formatted) + } + } + }, INBOX_POLL_INTERVAL_MS) +}, []) +``` + +**Message Processing States**: + +| State | Description | +|-------|-------------| +| `pending` | Newly received, awaiting processing | +| `processing` | Currently being processed (e.g., permission requests) | +| `processed` | Processing complete | + +### Message Routing + +``` +SendMessage({ to, message }) + │ + ├─ to === "*" → Broadcast + │ └─ Iterate all teammates, write to each mailbox + │ + ├─ agentNameRegistry.has(to) → In-process subagent + │ └─ Route via AppState pending messages queue + │ + ├─ teamFile.members.find(to) → Process-level teammate + │ └─ writeToMailbox(to, message, teamName) + │ + ├─ to.startsWith("bridge:") → Remote session + │ └─ postInterClaudeMessage(sessionId, message) + │ + └─ to.startsWith("uds:") → Unix Domain Socket + └─ sendToUdsSocket(socketPath, message) +``` + +--- + +## 6. Background Task Engine + +![Background Task Engine](./images/08-background-task.png) + +### LocalAgentTask State Machine + +```typescript +// src/tasks/LocalAgentTask/LocalAgentTask.tsx +type LocalAgentTaskState = { + type: 'local_agent' + agentId: AgentId // Unique identifier + status: 'running' | 'completed' | 'failed' | 'killed' + isBackgrounded: boolean // Foreground vs. background + + progress: { + latestInputTokens: number // Latest input tokens + cumulativeOutputTokens: number // Cumulative output tokens + toolUseCount: number // Tool invocation count + recentActivities: ToolActivity[] // Last 5 activities + lastActivity: number // Last activity timestamp + } + + result?: AgentToolResult // Final result + abortController: AbortController // Abort controller + retain: boolean // UI retention flag + evictAfter?: number // Delayed eviction timestamp +} +``` + +**State Transitions**: + +``` + ┌──────────────────────────┐ + │ │ + register │ ┌──── killed ←── abort() + │ │ │ + ▼ │ │ + running ─────┼────┼──── completed ← finalizeAgentTool() + │ │ + │ └──── failed ← error / timeout + │ + └──── evict ← notified && endTime > grace +``` + +### Progress Tracking + +```typescript +// ProgressTracker +function updateProgressFromMessage(tracker, message) { + // 1. Track input tokens (take latest value) + tracker.latestInputTokens = message.usage?.input_tokens + + // 2. Accumulate output tokens + tracker.cumulativeOutputTokens += message.usage?.output_tokens + + // 3. Count tool invocations + tracker.toolUseCount += countToolUses(message) + + // 4. Maintain recent activities (circular buffer, max 5) + tracker.recentActivities = [...activities].slice(-5) +} +``` + +### Notification System + +```typescript +// src/utils/messageQueueManager.ts +function enqueuePendingNotification(taskId, result) { + // 1. Atomically set notified flag (prevent duplicates) + if (task.notified) return + task.notified = true + + // 2. Format XML notification + const notification = ` + + ${taskId} + ${status} + ${summary} + ${outputPath} + + ` + + // 3. Enqueue for primary agent consumption + pendingNotifications.push(notification) +} +``` + +### Output Management + +**Storage path**: `~/.claude/temp/{sessionId}/tasks/{taskId}.output` + +| Parameter | Value | +|-----------|-------| +| Max capacity | 5GB / file | +| Circular buffer | 1000 lines | +| Poll interval | 1 second | +| Terminal state retention | 3 seconds (30 seconds for task panel) | +| Write method | Asynchronous queue writes to prevent memory buildup | +| Safety measure | O_NOFOLLOW to prevent symlink attacks | + +--- + +## 7. DreamTask — Automatic Memory Consolidation + +DreamTask is a special background agent used for cross-session memory consolidation. + +### Trigger Conditions + +```typescript +// src/services/autoDream/autoDream.ts +function executeAutoDream() { + // Four gates: + if (hoursSinceLastConsolidation < minHours) return // Time gate: default 24h + if (sessionsSinceLastConsolidation < minSessions) return // Session gate: default 5 + if (otherProcessConsolidating) return // Lock gate: mutual exclusion + if (timeSinceLastScan < 10min) return // Scan throttle: 10 minutes +} +``` + +### DreamTask State + +```typescript +type DreamTaskState = { + type: 'dream' + phase: 'starting' | 'updating' // updating = has started editing files + sessionsReviewing: number // Number of sessions being reviewed + filesTouched: string[] // File paths that have been edited + turns: DreamTurn[] // Conversation turn records +} +``` + +--- + +## 8. Worktree Isolation Implementation + +### Creation Flow + +```typescript +// src/utils/worktree.ts +async function createAgentWorktree(slug) { + // 1. Validate slug (prevent directory traversal attacks) + validateWorktreeSlug(slug) + + // 2. Create git worktree + git worktree add {path} -b {branch} + + // 3. Symlink large directories (save disk space) + symlink(node_modules, worktree/node_modules) + + // 4. Apply sparse-checkout (if configured) + if (sparseCheckoutPaths) { + git sparse-checkout set {paths} + } + + // 5. Return WorktreeSession + return { worktreePath, worktreeBranch, headCommit } +} +``` + +### Cleanup Mechanism + +- After agent completion, automatically checks for changes (`hasWorktreeChanges()`) +- If changes exist: returns the worktree path and branch name to the user +- If no changes: automatically deletes the worktree (`removeAgentWorktree()`) +- On abnormal exit: cleanup is ensured via `registerTeamForSessionCleanup()` + +--- + +## 9. Permission Synchronization + +### Team-Level Permissions + +```typescript +type TeamAllowedPath = { + path: string // Absolute directory path + toolName: string // Applicable tool (e.g., "Edit", "Write") + addedBy: string // Who added it + addedAt: number // When it was added +} +``` + +Teammates automatically inherit team-level permission rules on startup. + +### Bubble Mode + +Fork agents use the `bubble` permission mode — permission prompts bubble up to the parent agent's terminal: + +``` +Fork Agent needs permission + │ + └─ bubble mode → Permission request sent to parent agent + │ + └─ Parent agent's ToolUseConfirm dialog is displayed + │ + ├─ User approves → Result relayed back to Fork Agent + └─ User denies → Fork Agent receives denial +``` + +### In-Process Teammate Permissions + +``` +Teammate needs permission + │ + ├─ Has UI bridge → Displayed directly in Leader's confirmation dialog + │ └─ With worker badge indicating source + │ + └─ No UI bridge → Queued via mailbox + └─ Handled by Leader's useSwarmPermissionPoller +``` + +--- + +## 10. Agent Lifecycle End-to-End Data Flow + +``` +1. User triggers Agent Tool + │ +2. AgentTool.call() routes and dispatches + │ +3. Resolve agent definition + ├─ Look up agent type (built-in > plugin > user > project) + ├─ Load system prompt + ├─ Resolve tool pool (three-layer filtering) + └─ Determine permission mode and model + │ +4. Create isolated context + ├─ createSubagentContext() (clone readFileState) + ├─ Generate agentId + ├─ Create AbortController + └─ Optional: create worktree + │ +5. Register task state + ├─ registerAsyncAgent() or registerAgentForeground() + ├─ Emit SDK event: task_started + └─ Register Perfetto trace + │ +6. Execute query loop + ├─ query() async generator + │ ├─ Build API request (with CacheSafeParams) + │ ├─ Process streaming response + │ ├─ Execute tool calls + │ └─ Accumulate usage metrics + ├─ Update progress (ProgressTracker) + └─ Record transcript + │ +7. Completion handling + ├─ finalizeAgentTool() (extract result text) + ├─ completeAgentTask() (mark complete) + ├─ Clean up resources + │ ├─ Release file state cache + │ ├─ Close MCP connections + │ └─ Delete worktree (if applicable) + ├─ enqueuePendingNotification() (notify primary agent) + └─ Emit SDK event: task_completed + │ +8. Primary agent consumes result + ├─ Synchronous: directly receives AgentToolResult + └─ Asynchronous: processes after receiving +``` + +--- + +## 11. Key Source File Index + +### Agent Tool Core + +| File | Responsibility | +|------|---------------| +| `src/tools/AgentTool/AgentTool.tsx` | Main tool implementation, routing & dispatch | +| `src/tools/AgentTool/runAgent.ts` | Execution engine, query loop | +| `src/tools/AgentTool/agentToolUtils.ts` | Tool pool resolution, result finalization | +| `src/tools/AgentTool/forkSubagent.ts` | Fork semantics, message inheritance | +| `src/tools/AgentTool/loadAgentsDir.ts` | Agent definition types, parsing & loading | +| `src/tools/AgentTool/builtInAgents.ts` | Built-in agent registry | +| `src/tools/AgentTool/prompt.ts` | Agent tool schema and documentation | +| `src/tools/AgentTool/agentMemory.ts` | Agent persistent memory | + +### Swarm Infrastructure + +| File | Responsibility | +|------|---------------| +| `src/tools/TeamCreateTool/TeamCreateTool.ts` | Team creation | +| `src/tools/TeamDeleteTool/TeamDeleteTool.ts` | Team cleanup | +| `src/tools/SendMessageTool/SendMessageTool.ts` | Inter-agent communication | +| `src/tools/shared/spawnMultiAgent.ts` | Teammate spawn entry point | +| `src/utils/swarm/spawnInProcess.ts` | In-process teammate spawning | +| `src/utils/swarm/teamHelpers.ts` | Team file read/write | +| `src/utils/swarm/constants.ts` | Constant definitions | +| `src/utils/swarm/teammateInit.ts` | Teammate initialization | +| `src/utils/swarm/permissionSync.ts` | Permission synchronization | +| `src/utils/teammate.ts` | Teammate identity resolution | +| `src/utils/teammateMailbox.ts` | Mailbox message queue | +| `src/utils/teamDiscovery.ts` | Team discovery | +| `src/hooks/useInboxPoller.ts` | Inbox polling | + +### Context Management + +| File | Responsibility | +|------|---------------| +| `src/utils/forkedAgent.ts` | Cache-safe parameters, subagent context | +| `src/utils/systemPrompt.ts` | System prompt priority construction | +| `src/utils/model/agent.ts` | Agent model resolution | +| `src/utils/worktree.ts` | Git worktree isolation | + +### Task System + +| File | Responsibility | +|------|---------------| +| `src/tasks/LocalAgentTask/LocalAgentTask.tsx` | Local agent task | +| `src/tasks/RemoteAgentTask/RemoteAgentTask.tsx` | Remote agent task | +| `src/tasks/InProcessTeammateTask/` | In-process teammate task | +| `src/tasks/DreamTask/DreamTask.ts` | Memory consolidation task | +| `src/utils/task/framework.ts` | Task registration, state updates | +| `src/utils/task/diskOutput.ts` | Task output file management | +| `src/utils/messageQueueManager.ts` | Notification queue | + +### Coordinator + +| File | Responsibility | +|------|---------------| +| `src/coordinator/coordinatorMode.ts` | Coordinator mode configuration | + +--- + +## 12. Feature Flags + +| Flag | Controls | +|------|----------| +| `FORK_SUBAGENT` | Enable fork path (when subagent_type is omitted) | +| `BUILTIN_EXPLORE_PLAN_AGENTS` | Enable Explore/Plan agents | +| `VERIFICATION_AGENT` | Enable verification agent | +| `COORDINATOR_MODE` | Enable coordinator mode | +| `KAIROS` | Enable cwd parameter | +| `tengu_auto_background_agents` | Auto-background after 120 seconds | +| `tengu_slim_subagent_claudemd` | Omit CLAUDE.md for read-only agents | +| `tengu_agent_list_attach` | Inject agent list via attachment | diff --git a/docs/en/agent/images/01-agent-overview.png b/docs/en/agent/images/01-agent-overview.png new file mode 100644 index 00000000..d2bf87d3 Binary files /dev/null and b/docs/en/agent/images/01-agent-overview.png differ diff --git a/docs/en/agent/images/02-agent-types.png b/docs/en/agent/images/02-agent-types.png new file mode 100644 index 00000000..ff9bd2bf Binary files /dev/null and b/docs/en/agent/images/02-agent-types.png differ diff --git a/docs/en/agent/images/03-spawn-flow.png b/docs/en/agent/images/03-spawn-flow.png new file mode 100644 index 00000000..d6c3f3d2 Binary files /dev/null and b/docs/en/agent/images/03-spawn-flow.png differ diff --git a/docs/en/agent/images/04-agent-teams.png b/docs/en/agent/images/04-agent-teams.png new file mode 100644 index 00000000..9d0b92ba Binary files /dev/null and b/docs/en/agent/images/04-agent-teams.png differ diff --git a/docs/en/agent/images/05-architecture.png b/docs/en/agent/images/05-architecture.png new file mode 100644 index 00000000..4478c0a7 Binary files /dev/null and b/docs/en/agent/images/05-architecture.png differ diff --git a/docs/en/agent/images/06-context-passing.png b/docs/en/agent/images/06-context-passing.png new file mode 100644 index 00000000..26d4d45d Binary files /dev/null and b/docs/en/agent/images/06-context-passing.png differ diff --git a/docs/en/agent/images/07-tool-pool.png b/docs/en/agent/images/07-tool-pool.png new file mode 100644 index 00000000..7fdc9cc9 Binary files /dev/null and b/docs/en/agent/images/07-tool-pool.png differ diff --git a/docs/en/agent/images/08-background-task.png b/docs/en/agent/images/08-background-task.png new file mode 100644 index 00000000..cadad907 Binary files /dev/null and b/docs/en/agent/images/08-background-task.png differ diff --git a/docs/en/agent/images/09-teams-mailbox.png b/docs/en/agent/images/09-teams-mailbox.png new file mode 100644 index 00000000..df0e8678 Binary files /dev/null and b/docs/en/agent/images/09-teams-mailbox.png differ diff --git a/docs/en/agent/images/10-fork-cache.png b/docs/en/agent/images/10-fork-cache.png new file mode 100644 index 00000000..3b1b42e4 Binary files /dev/null and b/docs/en/agent/images/10-fork-cache.png differ diff --git a/docs/en/agent/index.md b/docs/en/agent/index.md new file mode 100644 index 00000000..920f1bf6 --- /dev/null +++ b/docs/en/agent/index.md @@ -0,0 +1,107 @@ +# Claude Code Multi-Agent System Documentation + +> Complete guide and technical reference for multi-agent orchestration + +--- + +## Documentation Index + +### [01-usage-guide.md](./01-usage-guide.md) — Usage Guide + +A comprehensive user-facing manual covering: + +- **Agent Tool**: Parameter reference, spawn methods, background execution +- **Six Built-in Agents**: general-purpose, Explore, Plan, verification, claude-code-guide, statusline-setup +- **Background Tasks**: Asynchronous execution, progress tracking, completion notifications +- **Agent Teams**: Team creation, member collaboration, message communication +- **Worktree Isolation**: Independent environments, branch management, secure contexts +- **Custom Agents**: Definition format, tool pool configuration, system prompts + +**Target Audience**: All Claude Code users + +--- + +### [02-implementation.md](./02-implementation.md) — Implementation Details + +A deep technical reference for developers covering: + +- **Architecture Overview**: 5 agent categories, 4 spawn paths +- **Agent Spawn Flow**: Detailed walkthrough of Sync / Async / Fork / Teammate paths +- **Tool Pool System**: Three-layer filtering, constant definitions, permission mapping +- **Context Passing**: CacheSafeParams, system prompt construction, fork cache optimization +- **Teams Internals**: TeamFile structure, mailbox system, inbox polling, message routing +- **Background Task Engine**: LocalAgentTask lifecycle, progress tracking, notification queue +- **Permission Synchronization**: Team-level permissions, mode propagation, bubble mode +- **End-to-End Data Flow**: From Agent Tool invocation to result delivery + +**Target Audience**: Contributors, architects, and developers seeking deep implementation understanding + +--- + +## Illustration Notes + +All diagrams use a dark background (#1a1a2e) with Anthropic brand copper-orange (#D97757), consistent with Claude Code's official documentation style. + +| Image | Description | Document | +|-------|-------------|----------| +| `01-agent-overview.png` | Multi-Agent System Overview — Architecture panorama | Usage Guide | +| `02-agent-types.png` | Six Built-in Agents — Type comparison matrix | Usage Guide | +| `03-spawn-flow.png` | Agent Spawn Flow — Four-path decision tree | Usage Guide | +| `04-agent-teams.png` | Agent Teams Collaboration — Team communication topology | Usage Guide | +| `05-architecture.png` | Implementation Architecture — Core module relationships | Implementation | +| `06-context-passing.png` | Context Passing — CacheSafeParams data flow | Implementation | +| `07-tool-pool.png` | Tool Pool System — Three-layer filtering pipeline | Implementation | +| `08-background-task.png` | Background Task Engine — Lifecycle state machine | Implementation | +| `09-teams-mailbox.png` | Teams Mailbox System — Message routing topology | Implementation | +| `10-fork-cache.png` | Fork Cache Optimization — Byte-level consistent sharing | Implementation | + +--- + +## Quick Start + +### For Users + +1. Read the [Usage Guide](./01-usage-guide.md) +2. Learn about the six built-in agents and their use cases +3. Try spawning subagents using the Agent tool in a conversation +4. Explore multi-agent collaboration with Agent Teams + +### For Developers + +1. Read the [Implementation Details](./02-implementation.md) +2. Browse the source code: + - `src/tools/AgentTool/` — Agent tool implementation + - `src/tools/TeamCreateTool/` — Team creation + - `src/tools/SendMessageTool/` — Inter-agent communication + - `src/utils/swarm/` — Swarm collaboration infrastructure + - `src/utils/forkedAgent.ts` — Fork agent context + - `src/tasks/` — Task management system +3. Understand the four spawn paths and context passing mechanisms + +--- + +## Core Concepts Quick Reference + +| Concept | Description | +|---------|-------------| +| **Agent Tool** | Primary entry point — accepts a prompt + subagent_type to spawn a subagent | +| **Subagent** | An independent child agent that executes tasks with its own tool pool and permissions | +| **Fork Agent** | A forked agent that inherits the parent's full context and shares prompt cache | +| **Teammate** | A collaborative member within an Agent Team, communicating via mailbox | +| **Worktree** | Git worktree isolation mode providing an independent file environment | +| **LocalAgentTask** | Local agent task state, tracking running/completed/failed status | +| **DreamTask** | Automatic memory consolidation task that runs periodically in the background | +| **CacheSafeParams** | Cache-safe parameters ensuring byte-level consistency of API request prefixes | +| **TeamFile** | Team configuration file storing the member list and permissions | +| **Mailbox** | File-based message queue supporting asynchronous communication between teammates | + +--- + +## Related Resources + +- [Claude Code Haha Home](/) +- [Memory System Documentation](/en/memory/01-usage-guide) +- [Agent Tool Source Code](https://github.com/NanmiCoder/cc-haha/tree/main/src/tools/AgentTool/) +- [Swarm Infrastructure](https://github.com/NanmiCoder/cc-haha/tree/main/src/utils/swarm/) +- [Task Management System](https://github.com/NanmiCoder/cc-haha/tree/main/src/tasks/) +- [GitHub Issues](https://github.com/NanmiCoder/cc-haha/issues) diff --git a/docs/features/computer-use.en.md b/docs/en/features/computer-use.md similarity index 99% rename from docs/features/computer-use.en.md rename to docs/en/features/computer-use.md index 031a0930..30a51933 100644 --- a/docs/features/computer-use.en.md +++ b/docs/en/features/computer-use.md @@ -1,6 +1,5 @@ # Computer Use Guide -

中文 | English

> **Modified Version**: This feature is a **heavily modified version** of the Computer Use (internal codename "Chicago") found in the leaked Claude Code source. The official implementation relies on Anthropic's private native modules (`@ant/computer-use-swift`, `@ant/computer-use-input`) that are not publicly available. We **replaced the entire underlying operation layer** with a Python bridge (`pyautogui` + `mss` + `pyobjc`), enabling anyone to run Computer Use on macOS. diff --git a/docs/guide/env-vars.en.md b/docs/en/guide/env-vars.md similarity index 95% rename from docs/guide/env-vars.en.md rename to docs/en/guide/env-vars.md index 91a8b576..e7fdda5d 100644 --- a/docs/guide/env-vars.en.md +++ b/docs/en/guide/env-vars.md @@ -1,6 +1,5 @@ # Environment Variables -

中文 | Back to README

| Variable | Required | Description | |------|------|------| diff --git a/docs/guide/faq.en.md b/docs/en/guide/faq.md similarity index 85% rename from docs/guide/faq.en.md rename to docs/en/guide/faq.md index a02452ba..46be2889 100644 --- a/docs/guide/faq.en.md +++ b/docs/en/guide/faq.md @@ -1,6 +1,5 @@ # FAQ -

中文 | Back to README

## Q: `undefined is not an object (evaluating 'usage.input_tokens')` @@ -12,7 +11,7 @@ This project uses the **Anthropic Messages API protocol**. `ANTHROPIC_BASE_URL` - OpenRouter: `ANTHROPIC_BASE_URL=https://openrouter.ai/api` ✅ - OpenRouter (wrong): `ANTHROPIC_BASE_URL=https://openrouter.ai/anthropic` ❌ (returns HTML) -If your model provider only supports the OpenAI protocol, you need a proxy like LiteLLM for protocol translation. See the [Third-Party Models Guide](./third-party-models.en.md). +If your model provider only supports the OpenAI protocol, you need a proxy like LiteLLM for protocol translation. See the [Third-Party Models Guide](./third-party-models.md). ## Q: `Cannot find package 'bundle'` @@ -32,4 +31,4 @@ bun upgrade This project only supports the Anthropic protocol. If your model provider doesn't natively support the Anthropic protocol, you need a proxy like [LiteLLM](https://github.com/BerriAI/litellm) for protocol translation (OpenAI → Anthropic). -See the [Third-Party Models Guide](./third-party-models.en.md) for detailed setup instructions. +See the [Third-Party Models Guide](./third-party-models.md) for detailed setup instructions. diff --git a/docs/guide/global-usage.en.md b/docs/en/guide/global-usage.md similarity index 88% rename from docs/guide/global-usage.en.md rename to docs/en/guide/global-usage.md index 1577f17b..828b0fba 100644 --- a/docs/guide/global-usage.en.md +++ b/docs/en/guide/global-usage.md @@ -1,6 +1,5 @@ # Global Usage (Run from Any Directory) -

中文 | Back to README

If you want to run `claude-haha` directly from any project directory, set up one of the following. Once configured, `claude-haha` will automatically recognize your current working directory. diff --git a/docs/en/guide/quick-start.md b/docs/en/guide/quick-start.md new file mode 100644 index 00000000..109e24fb --- /dev/null +++ b/docs/en/guide/quick-start.md @@ -0,0 +1,64 @@ +# Quick Start + +## 1. Install Bun + +```bash +# macOS / Linux +curl -fsSL https://bun.sh/install | bash + +# macOS (Homebrew) +brew install bun + +# Windows (PowerShell) +powershell -c "irm bun.sh/install.ps1 | iex" +``` + +> On minimal Linux images, if you see `unzip is required`, run `apt update && apt install -y unzip` first. + +## 2. Install Dependencies and Configure + +```bash +bun install +cp .env.example .env +# Edit .env with your API key +``` + +See [Environment Variables](./env-vars.md) for the full reference. + +## 3. Start + +### macOS / Linux + +```bash +./bin/claude-haha # Interactive TUI mode +./bin/claude-haha -p "your prompt here" # Headless mode +./bin/claude-haha --help # Show all options +``` + +### Windows + +> **Prerequisite**: [Git for Windows](https://git-scm.com/download/win) must be installed. + +```powershell +# PowerShell / cmd — call Bun directly +bun --env-file=.env ./src/entrypoints/cli.tsx + +# Or run inside Git Bash +./bin/claude-haha +``` + +## 4. Global Usage (Optional) + +Add `bin/` to your PATH to run from any directory. See [Global Usage Guide](./global-usage.md): + +```bash +export PATH="$HOME/path/to/claude-code-haha/bin:$PATH" +``` + +## 5. Recovery Mode + +If the Ink TUI has issues, use the fallback Recovery CLI mode: + +```bash +CLAUDE_CODE_FORCE_RECOVERY_CLI=1 ./bin/claude-haha +``` diff --git a/docs/guide/third-party-models.en.md b/docs/en/guide/third-party-models.md similarity index 100% rename from docs/guide/third-party-models.en.md rename to docs/en/guide/third-party-models.md diff --git a/docs/en/index.md b/docs/en/index.md new file mode 100644 index 00000000..155fd246 --- /dev/null +++ b/docs/en/index.md @@ -0,0 +1,40 @@ +--- +layout: home + +hero: + name: Claude Code Haha + text: Locally Runnable Claude Code + tagline: Repaired from leaked source, supports any Anthropic-compatible API endpoint (MiniMax, OpenRouter, etc.) + image: + src: /images/banner.jpg + alt: Claude Code Haha + actions: + - theme: brand + text: Quick Start + link: /en/guide/quick-start + - theme: alt + text: GitHub + link: https://github.com/NanmiCoder/cc-haha + +features: + - icon: "\U0001F5A5" + title: Full TUI Experience + details: Ink terminal UI matching the official Claude Code interface, with --print headless mode + - icon: "\U0001F9E0" + title: Memory System + details: Cross-session persistent memory with auto-extraction, smart retrieval, and AutoDream consolidation + - icon: "\U0001F916" + title: Multi-Agent System + details: Agent orchestration, parallel tasks, Teams collaboration, Worktree isolation + - icon: "\U0001F9E9" + title: Skills System + details: Extensible capability plugins, custom workflows, conditional activation + - icon: "\U0001F4BB" + title: Computer Use + details: Desktop control — screenshots, mouse, and keyboard automation + link: /en/features/computer-use + - icon: "\U0001F310" + title: Third-Party Models + details: Support for OpenAI, DeepSeek, Ollama, and any compatible model + link: /en/guide/third-party-models +--- diff --git a/docs/en/memory/01-usage-guide.md b/docs/en/memory/01-usage-guide.md new file mode 100644 index 00000000..46ab5ac8 --- /dev/null +++ b/docs/en/memory/01-usage-guide.md @@ -0,0 +1,277 @@ +# Claude Code Memory System — Usage Guide + +> Let Claude Code remember who you are, what you prefer, and what's happening in your project across sessions. + +

+Memory System · Four Memory Types · Trigger Saving · Storage Location · Manage Memories · Lifecycle · Quick Reference +

+ +![Memory System Overview](./images/01-memory-overview.png) + +--- + +## 1. What Is the Memory System? + +Claude Code's memory system is a **file-based persistent knowledge store** that allows Claude to continuously build understanding of you and your project across multiple conversations. + +Core principle: **Only remember things that cannot be inferred from the code itself.** + +| Remembered | Not Remembered | +|------------|----------------| +| You're a data scientist focused on logging systems | Code architecture, file structure | +| "Don't mock the database" | Git history, who changed what | +| Non-critical merges frozen after Thursday | Existing CLAUDE.md content | +| Bug tracking is in Linear's INGEST project | Debugging solutions (fixes are already in the code) | + +--- + +## 2. Four Memory Types + +![Four Memory Types](./images/02-memory-types.png) + +Claude Code strictly categorizes memories into four types: + +### 2.1 User (User Profile) + +Records your role, goals, skill level, and preferences to help Claude tailor its collaboration approach. + +``` +User says: I've written Go for ten years, but this is my first time touching the React part of this repo +Claude saves: Deep Go experience, React newcomer — explain frontend concepts using backend analogies +``` + +### 2.2 Feedback (Behavioral Feedback) + +Your corrections or affirmations about how Claude works. These memories prevent Claude from repeating the same mistakes. + +``` +User says: Don't summarize what you did at the end of your reply, I can see the diff +Claude saves: User prefers concise replies, no trailing summaries +``` + +**Important**: Not only corrections are recorded -- affirmations are too. If Claude makes a non-obvious choice and you approve, that gets remembered as well. + +### 2.3 Project (Project Context) + +Project context that cannot be derived from the code or Git history: who's doing what, why, and deadlines. + +``` +User says: We're freezing all non-critical merges after Thursday, the mobile team needs to cut a release branch +Claude saves: Merge freeze starting 2026-03-05, flag non-critical PR work after this date +``` + +**Note**: Claude converts relative dates ("Thursday") to absolute dates ("2026-03-05") to ensure memories don't become ambiguous over time. + +### 2.4 Reference (External References) + +Pointers to information in external systems: dashboards, issue trackers, Slack channels. + +``` +User says: On-call monitors the grafana.internal/d/api-latency dashboard +Claude saves: grafana.internal/d/api-latency is the on-call latency dashboard — check when editing request path code +``` + +--- + +## 3. How to Trigger Memory Saving + +![Memory Trigger Flow](./images/03-memory-trigger.png) + +### Method 1: Automatic Extraction (Most Common) + +This is the primary method. **You don't need to do anything** -- Claude automatically analyzes conversation content at the end of each conversation turn and extracts information worth remembering. + +Workflow: +1. You have a normal conversation with Claude +2. Claude finishes its response (no tool calls pending) +3. A **memory extraction sub-agent** starts in the background +4. The sub-agent analyzes the recent conversation content +5. It identifies memories worth saving +6. Writes memory files + updates the MEMORY.md index + +The terminal will display a notification: +``` +Memory updated in ~/.claude/projects/.../memory/feedback_testing.md · /memory to edit +``` + +### Method 2: Explicit Request + +Directly tell Claude to "remember this": + +``` +User: Remember, this project must run bun test before deploying +Claude: [Immediately saves as a feedback-type memory] +``` + +### Method 3: /memory Command + +Type `/memory` in the terminal to open a file picker that lets you edit memory files directly in your editor. + +``` +> /memory +``` + +This lists all editable memory files (CLAUDE.md, CLAUDE.local.md, auto-memory, etc.) and opens the selected file with your `$EDITOR` or `$VISUAL`. + +### Method 4: /remember Command + +Type `/remember` to trigger the memory review skill, which will: +- Review all automatic memory entries +- Propose promoting suitable entries to CLAUDE.md or CLAUDE.local.md +- Detect duplicate, outdated, and conflicting memories +- **Does not modify anything directly** -- all changes require your approval + +--- + +## 4. Where Are Memories Stored? + +### Directory Structure + +``` +~/.claude/ +└── projects/ + └── {project-path-hash}/ + └── memory/ <- Auto-memory directory + ├── MEMORY.md <- Index file (always loaded into context) + ├── user_role.md <- User profile memory + ├── feedback_testing.md <- Behavioral feedback memory + ├── project_freeze.md <- Project context memory + ├── reference_linear.md <- External reference memory + └── team/ <- Team shared memory (if enabled) + ├── MEMORY.md + └── ... +``` + +### Memory File Format + +Each memory file uses YAML frontmatter + Markdown content: + +```markdown +--- +name: Testing strategy preference +description: Integration tests must use a real database, no mocking +type: feedback +--- + +Integration tests must use a real database, no mocking. + +**Why:** Last quarter, mocked tests passed but production migrations failed — mock/production divergence masked the issues. + +**How to apply:** When writing or reviewing tests, ensure database operations use real connections. +``` + +### MEMORY.md Index File + +MEMORY.md is an index, not content. It is **always loaded into context**, with one entry per line: + +```markdown +- [User role](user_role.md) — Data scientist, focused on observability/logging +- [Testing strategy](feedback_testing.md) — Integration tests use real DB, no mocking +- [Merge freeze](project_freeze.md) — Non-critical merges frozen starting 2026-03-05 +- [Bug tracking](reference_linear.md) — Pipeline bugs tracked in Linear INGEST project +``` + +**Limit**: Maximum 200 lines or 25KB; content beyond this is truncated. + +--- + +## 5. How to Manage Memories + +### Ask Claude to Forget + +``` +User: Forget the memory about the merge freeze +Claude: [Finds and deletes the relevant memory file and index entry] +``` + +### Ask Claude to Ignore Memories + +``` +User: Ignore memories, start from scratch +Claude: [Does not use any memory content in this conversation] +``` + +### Manual Editing + +Directly edit files under `~/.claude/projects/{hash}/memory/`, or use the `/memory` command. + +### Disable Automatic Memory + +| Method | How | +|--------|-----| +| Environment variable | `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` | +| Settings file | Set `"autoMemoryEnabled": false` in `settings.json` | +| Bare mode | Start with `--bare` / `CLAUDE_CODE_SIMPLE=1` | + +### Custom Memory Directory + +Set in `~/.claude/settings.json`: + +```json +{ + "autoMemoryDirectory": "~/my-claude-memories" +} +``` + +Supports `~/` expansion. For security reasons, the project-level `.claude/settings.json` is **not allowed** to set this option. + +--- + +## 6. Memory Lifecycle + +![Memory Lifecycle](./images/04-memory-lifecycle.png) + +``` +New information learned during conversation + | + Auto-extraction / Explicit save + | + Write memory file + index + | + Next conversation loads MEMORY.md + | + Intelligent selection of relevant memories (Sonnet) + | + Inject into conversation context + | + Memory getting old? Verify before using + | + Outdated? Update or delete + | + (After 24h + 5 sessions) + | + AutoDream consolidates memories in background +``` + +### AutoDream -- "Dreaming" to Organize Memories + +Claude Code has a hidden **AutoDream** feature, analogous to how the human brain organizes memories during sleep. When the following conditions are met, Claude silently launches a "dreaming" sub-agent in the background: + +- At least **>= 24 hours** since the last consolidation +- At least **>= 5 sessions** accumulated in the interim + +The dreaming process has four phases: Orient -> Gather -> Consolidate -> Prune. The bottom status bar shows **"dreaming"**, and you can press `Shift+Down` to view progress or `x` to terminate. + +For a detailed technical analysis, see [AutoDream Memory Consolidation](./03-autodream.md). + +### Freshness Management + +- **Today's/yesterday's memories**: Used directly +- **Memories older than 1 day**: Accompanied by a stale warning, reminding Claude to verify before citing +- **Memories referencing file paths/function names**: Confirmed via grep before use to ensure they still exist + +--- + +## 7. Quick Reference + +| Action | Method | +|--------|--------| +| Ask Claude to remember | "Remember: this project uses bun, not npm" | +| Ask Claude to forget | "Forget the memory about XXX" | +| Edit memories | `/memory` command | +| Review and organize | `/remember` command | +| Ignore memories | "Ignore memories" / "Don't use memories" | +| Disable auto-memory | `CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` | +| Disable AutoDream | Set `"autoDreamEnabled": false` in `settings.json` | +| Manually consolidate memories | `/dream` command | +| View memory directory | `~/.claude/projects/{hash}/memory/` | diff --git a/docs/en/memory/02-implementation.md b/docs/en/memory/02-implementation.md new file mode 100644 index 00000000..ddf2da7c --- /dev/null +++ b/docs/en/memory/02-implementation.md @@ -0,0 +1,480 @@ +# Claude Code Memory System — Implementation Details + +> From system prompt injection to background auto-extraction, dissecting every technical detail of the memory system. + +

+Architecture · Path Resolution · Prompt Injection · Auto-Extraction · Intelligent Retrieval · Memory Scanning · Agent Memory · Team Sync · Constants · Data Flow +

+ +![Implementation Architecture Overview](./images/05-architecture-overview.png) + +--- + +## 1. Overall Architecture + +The memory system is powered by 5 core modules working in concert: + +| Module | Source Location | Responsibility | +|--------|----------------|----------------| +| **Path Resolution** | `src/memdir/paths.ts` | Computes memory storage directory, handles overrides and security validation | +| **Prompt Construction** | `src/memdir/memdir.ts` | Injects memory instructions into the system prompt | +| **Memory Scanning** | `src/memdir/memoryScan.ts` | Scans directories, parses frontmatter, sorts entries | +| **Intelligent Retrieval** | `src/memdir/findRelevantMemories.ts` | Uses Sonnet to select memories relevant to the current query | +| **Auto-Extraction** | `src/services/extractMemories/` | Background forked agent that extracts memories from conversations | + +Auxiliary modules: + +| Module | Source Location | Responsibility | +|--------|----------------|----------------| +| **AutoDream** | `src/services/autoDream/` | Background memory consolidation ("dreaming"); see [03-autodream.md](./03-autodream.md) | +| **Type Definitions** | `src/memdir/memoryTypes.ts` | Taxonomy and prompt templates for the four memory types | +| **Freshness** | `src/memdir/memoryAge.ts` | Calculates memory age, generates stale warnings | +| **File Detection** | `src/utils/memoryFileDetection.ts` | Determines whether a path belongs to the memory system | +| **Agent Memory** | `src/tools/AgentTool/agentMemory.ts` | Three-level memory directories exclusive to sub-agents | +| **Team Sync** | `src/services/teamMemorySync/` | Remote upload/download of memories | + +--- + +## 2. Path Resolution System + +![Path Resolution Flow](./images/06-path-resolution.png) + +### Core Function: `getAutoMemPath()` + +``` +Path resolution priority (highest to lowest): + +1. CLAUDE_COWORK_MEMORY_PATH_OVERRIDE <- Cowork environment variable (full path) +2. settings.json -> autoMemoryDirectory <- User setting (supports ~/ expansion) +3. {memoryBase}/projects/{sanitized-git-root}/memory/ <- Default computed path +``` + +**Key source** `src/memdir/paths.ts:223`: + +```typescript +export const getAutoMemPath = memoize( + (): string => { + const override = getAutoMemPathOverride() ?? getAutoMemPathSetting() + if (override) return override + const projectsDir = join(getMemoryBaseDir(), 'projects') + return join(projectsDir, sanitizePath(getAutoMemBase()), AUTO_MEM_DIRNAME) + sep + }, + () => getProjectRoot(), // Cache key = project root +) +``` + +### Path Security Validation + +`validateMemoryPath()` rejects dangerous paths: + +| Rejected Path | Reason | +|---------------|--------| +| `../foo` | Relative path, CWD-dependent | +| `/` or `/a` | Root path or too-short path | +| `C:\` | Windows drive root | +| `\\server\share` | UNC network path | +| Contains `\0` | Null byte, can truncate in system calls | + +**Security restriction**: Project-level `.claude/settings.json` is **not allowed** to set `autoMemoryDirectory`, preventing malicious repositories from gaining write access to sensitive directories like `~/.ssh`. + +### Enable Conditions + +The `isAutoMemoryEnabled()` check chain: + +``` +CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 -> Disabled +CLAUDE_CODE_SIMPLE (--bare) -> Disabled +Remote mode without REMOTE_MEMORY_DIR -> Disabled +settings.json autoMemoryEnabled -> Follows setting +Default -> Enabled +``` + +--- + +## 3. System Prompt Injection + +![Prompt Injection Flow](./images/07-prompt-injection.png) + +### Entry Point: `loadMemoryPrompt()` + +This is the interface between the memory system and the system prompt. It is called once at startup (cached via `systemPromptSection`). + +``` +loadMemoryPrompt() + |-- KAIROS mode? -> buildAssistantDailyLogPrompt() [log append mode] + |-- TEAMMEM enabled? -> buildCombinedMemoryPrompt() [personal + team dual directory] + |-- Normal mode -> buildMemoryLines() [single directory] + |-- Disabled -> return null +``` + +### Prompt Structure Built by `buildMemoryLines()` + +``` +# auto memory + +You have a persistent file-based memory system located at `{memoryDir}`... + +## Types of memory <- Definitions and examples for all four types +## What NOT to save <- Exclusion rules +## How to save memories <- Two-step saving process +## When to access memories <- When to consult +## Before recommending <- Verify before citing +## Memory and other forms <- Distinction from Plan/Task + +## MEMORY.md <- Index content (or "currently empty") +``` + +### MEMORY.md Truncation Strategy + +`truncateEntrypointContent()` applies dual limits: + +```typescript +// First truncate by line count +if (lineCount > 200) -> Truncate to 200 lines + +// Then truncate by byte size (handles extra-long lines) +if (bytes > 25,000) -> Truncate at last newline character + +// Append warning +"WARNING: MEMORY.md is {reason}. Only part of it was loaded." +``` + +### Automatic Directory Creation + +`ensureMemoryDirExists()` ensures the directory exists when loading the prompt: +- Recursively creates with `mkdir` (handles the entire parent chain) +- Swallows `EEXIST` (idempotent) +- Genuine permission errors are only logged, not thrown (the Write tool will surface the real error) + +The prompt explicitly tells the model the directory already exists, avoiding wasted turns on `ls` or `mkdir`. + +--- + +## 4. Automatic Memory Extraction + +![Auto-Extraction Flow](./images/08-auto-extraction.png) + +### Trigger Timing + +Triggered in `handleStopHooks` when the model produces a final response (no tool calls). + +**Key source**: `src/services/extractMemories/extractMemories.ts` + +### Complete Extraction Flow + +``` +1. Model finishes response (no tool_use) + | +2. executeExtractMemories() is called + | +3. Guard checks: + - Is this the main agent? (sub-agents don't extract) + - Feature gate enabled? + - Auto-memory enabled? + - Not in remote mode? + - No parallel extraction in progress? + | +4. Frequency control: + turnsSinceLastExtraction++ + if < tengu_bramble_lintel -> skip + | +5. Mutual exclusion check: + Main agent wrote memory itself? -> skip, advance cursor + | +6. Scan existing memory directory (scanMemoryFiles) + Generate manifest (formatMemoryManifest) + | +7. Build extraction prompt (buildExtractAutoOnlyPrompt) + | +8. Run forked agent (runForkedAgent) + - Shares parent session's prompt cache + - Max 5 turns + - Restricted tool permissions + | +9. Extract written file paths + Advance cursor to latest message + | +10. Notify user: "Memory updated in ..." +``` + +### Forked Agent + +Auto-extraction uses `runForkedAgent` -- a perfect fork of the main session: + +- **Shared prompt cache**: Avoids duplicate API cache creation costs +- **Isolated execution**: Does not affect the main session's message history +- **Restricted tools**: Only allows Read, Grep, Glob, read-only Bash, and Edit/Write within the memory directory +- **No transcript recording**: Prevents race conditions with the main thread + +### Tool Permissions (`createAutoMemCanUseTool`) + +``` +Allowed: Read, Grep, Glob (unrestricted) +Allowed: Bash (read-only commands only: ls, find, grep, cat, stat...) +Allowed: Edit/Write (only within auto-memory directory) +Denied: MCP, Agent, non-read-only Bash, other write operations +``` + +### Mutual Exclusion Mechanism + +The main agent and the extraction agent are **mutually exclusive**: + +```typescript +function hasMemoryWritesSince(messages, sinceUuid): boolean { + // Scan all assistant messages after sinceUuid + // If any Edit/Write tool_use targets the auto-memory directory + // -> return true (skip extraction, advance cursor) +} +``` + +This prevents duplicate saves: when the main agent has already written a memory, the background extraction is skipped. + +### Merge Mechanism + +If a previous extraction is still running: +1. The new context is queued (`pendingContext`) +2. After the old extraction completes, a **tail extraction** is immediately launched +3. The tail extraction only processes messages added between the two calls + +--- + +## 5. Intelligent Memory Retrieval + +![Memory Retrieval Flow](./images/09-memory-retrieval.png) + +### How It Works + +Each time the user sends a query, `findRelevantMemories()` is triggered: + +``` +1. scanMemoryFiles(memoryDir) + - Recursively reads all .md files (excludes MEMORY.md) + - Parses frontmatter (first 30 lines) + - Sorts by modification time in descending order + - Max 200 files + | +2. Filter out previously surfaced memories (alreadySurfaced) + | +3. Format manifest (formatMemoryManifest) + - [type] filename (ISO timestamp): description + | +4. Sonnet model selection (sideQuery) + - System prompt: You are a memory selector... + - User message: Query + Available memories + Recently used tools + - Output: JSON { selected_memories: string[] } + - Max 5 selections + | +5. Return selected memories as { path, mtimeMs } +``` + +### Sonnet Selector Prompt + +``` +You are selecting memories useful for Claude Code to handle the user's query. +You'll receive the user's query and a list of available memory files (with filenames and descriptions). + +Return at most 5 memory filenames that are clearly useful. +- If uncertain whether something is useful, don't select it +- If nothing is clearly useful, return an empty list +- If a list of recently used tools is provided, don't select usage docs for those tools + (but DO select warnings/gotchas/known issues about those tools) +``` + +### Freshness Warning + +Selected memories are injected into the context with freshness information: + +```typescript +function memoryFreshnessText(mtimeMs: number): string { + const d = memoryAgeDays(mtimeMs) + if (d <= 1) return '' // Today/yesterday: no warning + return `This memory is ${d} days old. Memories are point-in-time observations... + Verify against current code before asserting as fact.` +} +``` + +--- + +## 6. Memory Scanning in Detail + +### `scanMemoryFiles()` + +**Key design**: Single-pass (read-then-sort) to avoid double stat system calls. + +```typescript +async function scanMemoryFiles(memoryDir, signal): Promise { + const entries = await readdir(memoryDir, { recursive: true }) + const mdFiles = entries.filter(f => f.endsWith('.md') && basename(f) !== 'MEMORY.md') + + // Read all files' frontmatter in parallel (first 30 lines) + const headerResults = await Promise.allSettled( + mdFiles.map(async (relativePath) => { + const { content, mtimeMs } = await readFileInRange(filePath, 0, 30) + const { frontmatter } = parseFrontmatter(content) + return { filename, filePath, mtimeMs, description, type } + }) + ) + + // Filter successful results, sort by time descending, take first 200 + return fulfilled.sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, 200) +} +``` + +### `formatMemoryManifest()` + +Generates a manifest consumed by Sonnet or the extraction agent: + +``` +- [feedback] testing_policy.md (2026-03-15T10:30:00.000Z): Integration tests use real DB +- [user] role.md (2026-03-14T08:00:00.000Z): Data scientist, focused on logging +- [project] freeze.md (2026-03-10T15:00:00.000Z): Merge freeze starting 3/5 +``` + +--- + +## 7. Agent Memory + +![Agent Memory Three-Level Scoping](./images/10-agent-memory.png) + +Sub-agents (launched via the Agent tool) have an independent three-level memory system: + +| Scope | Path | Description | +|-------|------|-------------| +| **user** | `~/.claude/agent-memory/{agentType}/` | Global user-level | +| **project** | `.claude/agent-memory/{agentType}/` | Project-level (committed to VCS) | +| **local** | `.claude/agent-memory-local/{agentType}/` | Local-level (not committed) | + +Differences from main memory: +- No MEMORY.md index step (`skipIndex = true`) +- Files can be written directly without the two-step process +- Each agent type is isolated (explorer, planner, etc. each have their own directory) + +--- + +## 8. Team Memory Sync + +When the `TEAMMEM` feature flag is enabled: + +### Directory Structure + +``` +~/.claude/projects/{hash}/memory/ +├── MEMORY.md <- Personal memory index +├── user_*.md <- Personal memories +└── team/ <- Team shared directory + ├── MEMORY.md <- Team memory index + └── *.md <- Team memories +``` + +### Sync API + +``` +GET /api/claude_code/team_memory?repo={owner/repo} <- Pull +PUT /api/claude_code/team_memory?repo={owner/repo} <- Push +``` + +### Sync Semantics + +- **Pull**: Server content overwrites local files +- **Push**: Only uploads keys with different content hashes (delta upload) +- **Deletes don't propagate**: Local deletions do not delete remote entries +- **Limits**: Single file max 250KB, upload body max 200KB (batched) + +### Team vs. Personal Routing Rules + +In `memoryTypes.ts`, each type has a `` directive: + +| Type | Default Scope | +|------|---------------| +| user | Always personal | +| feedback | Personal by default; project-level conventions go to team | +| project | Leans toward team | +| reference | Usually team | + +--- + +## 9. Key Constants Quick Reference + +```typescript +// Index file +ENTRYPOINT_NAME = 'MEMORY.md' +MAX_ENTRYPOINT_LINES = 200 +MAX_ENTRYPOINT_BYTES = 25_000 + +// Scanning +MAX_MEMORY_FILES = 200 +FRONTMATTER_MAX_LINES = 30 + +// Path +AUTO_MEM_DIRNAME = 'memory' + +// Extraction +maxTurns = 5 // Forked agent max 5 turns + +// Retrieval +Max 5 relevant memories returned +``` + +--- + +## 10. Data Flow Overview + +``` +┌─────────────────────────────────────────────────────┐ +│ Session Startup │ +│ │ +│ loadMemoryPrompt() │ +│ -> ensureMemoryDirExists() │ +│ -> buildMemoryLines() + MEMORY.md content │ +│ -> Inject into system prompt │ +└────────────────────────┬────────────────────────────┘ + | +┌─────────────────────────────────────────────────────┐ +│ User Query │ +│ │ +│ findRelevantMemories() │ +│ -> scanMemoryFiles() [scan + frontmatter] │ +│ -> Sonnet selects up to 5 relevant memories │ +│ -> Inject into conversation context │ +│ + freshness warnings │ +└────────────────────────┬────────────────────────────┘ + | +┌─────────────────────────────────────────────────────┐ +│ Claude's Response │ +│ │ +│ Model may write memories directly │ +│ (following system prompt guidance) │ +│ Or not -> triggers background extraction │ +└────────────────────────┬────────────────────────────┘ + | +┌─────────────────────────────────────────────────────┐ +│ Background Auto-Extraction │ +│ │ +│ executeExtractMemories() │ +│ -> Mutual exclusion check │ +│ (main agent already wrote? skip) │ +│ -> Build extraction prompt + memory manifest │ +│ -> runForkedAgent() │ +│ [shared cache, restricted tools, 5 turns] │ +│ -> Write new memory files + update MEMORY.md │ +│ -> Notify user │ +└────────────────────────┬────────────────────────────┘ + | +┌─────────────────────────────────────────────────────┐ +│ Background Memory Consolidation (AutoDream) │ +│ │ +│ executeAutoDream() │ +│ [triggers every 24h + 5 sessions] │ +│ -> Five-gate check │ +│ (toggle/time/throttle/session/lock) │ +│ -> buildConsolidationPrompt() │ +│ -> runForkedAgent() │ +│ [read-only Bash, memory-dir writes only] │ +│ -> Four phases: │ +│ Orient -> Gather -> Consolidate -> Prune │ +│ -> Merge duplicates / fix stale / compress index │ +│ -> Notify user: "Improved N memories" │ +│ │ +│ See 03-autodream.md for details │ +└─────────────────────────────────────────────────────┘ +``` diff --git a/docs/en/memory/03-autodream.md b/docs/en/memory/03-autodream.md new file mode 100644 index 00000000..fb983eb4 --- /dev/null +++ b/docs/en/memory/03-autodream.md @@ -0,0 +1,316 @@ +# Claude Code Memory System — AutoDream Memory Consolidation + +> Claude "dreams" -- silently reviewing recent sessions in the background to consolidate, update, and prune memories, much like the human brain organizes memories during sleep. + +

+AutoDream · Trigger Conditions · Consolidation Process · Security · UI · Configuration · Comparison · Source Code +

+ +![AutoDream Overview](./images/11-autodream-overview.png) + +--- + +## 1. What Is AutoDream? + +AutoDream is Claude Code's **background memory consolidation mechanism**, internally codenamed **"Dream: Memory Consolidation"**. + +Core metaphor: + +| Human | Claude Code | +|-------|-------------| +| Jotting down notes throughout the day | `extractMemories` -- extracts new memories after each conversation | +| Organizing the notebook while sleeping | `autoDream` -- periodically reviews multiple sessions to consolidate all memories | + +When you're inactive (default interval: 24 hours with 5 accumulated sessions), Claude silently launches a **"dreaming" sub-agent** (forked subagent) in the background. It reviews all recent session transcripts and consolidates scattered memories into structured, deduplicated, up-to-date persistent knowledge. + +**Key source**: `src/services/autoDream/autoDream.ts` + +```typescript +// Background memory consolidation. Fires the /dream prompt as a forked +// subagent when time-gate passes AND enough sessions have accumulated. +``` + +--- + +## 2. Trigger Conditions + +![AutoDream Trigger Flow](./images/12-autodream-trigger.png) + +AutoDream uses a **five-gate** mechanism, checking in order of increasing cost: + +### Gate Chain + +| # | Gate | Description | Cost | +|---|------|-------------|------| +| 1 | **Feature toggle** | `isAutoDreamEnabled()` + not KAIROS + not remote mode + autoMemory enabled | Memory read | +| 2 | **Time gate** | At least `minHours` since last consolidation (default 24h) | 1 stat call | +| 3 | **Scan throttle** | At least 10 minutes since last scan before rescanning | Timestamp comparison | +| 4 | **Session gate** | At least `minSessions` new sessions since last consolidation (default 5, excluding current) | Directory scan | +| 5 | **Lock gate** | No other process currently dreaming (PID lock file) | stat + read | + +**Key source** `src/services/autoDream/autoDream.ts:63-66`: + +```typescript +const DEFAULTS: AutoDreamConfig = { + minHours: 24, // At least 24 hours since last consolidation + minSessions: 5, // At least 5 sessions accumulated in the interim +} +``` + +### Scan Throttle + +When the time gate passes but the session gate doesn't, the lock file's mtime remains unchanged, causing the time gate to pass on every subsequent turn. To avoid frequent directory scans, a **10-minute scan throttle** is in place: + +```typescript +const SESSION_SCAN_INTERVAL_MS = 10 * 60 * 1000 +``` + +### Execution Entry Point + +AutoDream is triggered during the stop hook phase after each AI response (fire-and-forget, does not block the main thread): + +**Key source** `src/query/stopHooks.ts:154-156`: + +```typescript +if (!toolUseContext.agentId) { + void executeAutoDream(stopHookContext, toolUseContext.appendSystemMessage) +} +``` + +### Blocking Conditions + +AutoDream will not trigger in the following situations: + +- **KAIROS mode**: Uses a separate disk-skill dream +- **Remote mode**: `getIsRemoteMode() === true` +- **autoMemory not enabled** +- **`--bare` / SIMPLE mode** +- **Inside a sub-agent**: Only the main agent triggers it + +--- + +## 3. Four-Phase Consolidation Process + +![AutoDream Four Phases](./images/13-autodream-phases.png) + +Once all gates pass, AutoDream launches a **forked sub-agent** that operates according to the 4-phase prompt defined in `consolidationPrompt.ts`: + +### Phase 1 -- Orient + +``` +- ls the memory directory, see existing files +- Read MEMORY.md index, understand the current knowledge structure +- Browse existing topic files to avoid creating duplicates +- If logs/ or sessions/ subdirectories exist, check recent entries +``` + +### Phase 2 -- Gather Recent Signal + +Collects information in order of priority (highest first): + +1. **Daily logs** -- `logs/YYYY/MM/YYYY-MM-DD.md` (append-stream logs) +2. **Drifted memories** -- Old facts that contradict the current codebase state +3. **Session transcript search** -- Narrow-scope `grep` searches in JSONL transcript files + +``` +Don't exhaustively read transcript files. Only look for content you already suspect is important. +``` + +### Phase 3 -- Consolidate + +- **Merge** new signals into existing topic files (rather than creating new near-duplicate files) +- **Convert** relative dates to absolute dates ("yesterday" -> "2026-04-03") +- **Delete** old facts that have been superseded + +### Phase 4 -- Prune and Index + +- Update `MEMORY.md`, keeping it within the line limit and <= 25KB +- Remove pointers to outdated memories +- Compress verbose entries (index lines >200 characters have their content moved into topic files) +- Add pointers to important memories +- Resolve conflicts (when two files disagree, fix the incorrect one) + +**Key source**: `src/services/autoDream/consolidationPrompt.ts:10-64` + +--- + +## 4. Security Restrictions + +The AutoDream sub-agent operates under strict tool permission constraints: + +### Bash: Read-Only Only + +``` +Allowed: ls, find, grep, cat, stat, wc, head, tail +Denied: All write, redirect, or state-modifying commands +``` + +### File Operations: Memory Directory Only + +`createAutoMemCanUseTool()` is the permission function shared by both `extractMemories` and `autoDream`: + +``` +Allowed: Read / Grep / Glob -- unrestricted +Allowed: Edit / Write -- only within the auto-memory directory +Denied: MCP / Agent / non-read-only Bash / other write operations +``` + +**Key source**: `src/services/extractMemories/extractMemories.ts:167-171` + +### Lock File Mechanism + +Uses a `.consolidate-lock` file for process-level mutual exclusion: + +| Mechanism | Description | +|-----------|-------------| +| **Lock content** | PID of the holder | +| **Timestamp** | Lock file mtime = time of last consolidation | +| **Expiry** | Held for more than 1 hour is considered expired (prevents PID reuse issues) | +| **Contention** | Two processes write simultaneously -> last writer wins, loser exits on re-read | +| **Rollback** | On failure, mtime is rolled back to the pre-acquisition value so the next attempt is unaffected | +| **Crash recovery** | Stale mtime + dead PID -> next process reclaims the lock | + +**Key source**: `src/services/autoDream/consolidationLock.ts` + +--- + +## 5. UI Presentation + +### Bottom Status Bar + +When AutoDream is running, the bottom status bar displays a **"dreaming"** label: + +```typescript +// src/tasks/pillLabel.ts:61-62 +case 'dream': + return 'dreaming' +``` + +### Task Detail Dialog + +Users can press `Shift+Down` to open the background task dialog and view real-time dream progress: + +- **DreamDetailDialog** component displays: + - Number of sessions being reviewed + - Current phase: `starting` (analyzing) -> `updating` (modifying memory files) + - Latest assistant text response and tool call count + - List of file paths touched + +- **Users can press `x` to terminate** an ongoing dream (triggers abort + lock rollback) + +### Completion Notification + +After the dream completes, if files were modified, an inline notification appears in the main session: + +```typescript +appendSystemMessage({ + ...createMemorySavedMessage(dreamState.filesTouched), + verb: 'Improved', +}) +``` + +**Key source**: +- `src/tasks/DreamTask/DreamTask.ts` -- Task state management +- `src/components/tasks/DreamDetailDialog.tsx` -- UI component + +--- + +## 6. Configuration and Toggles + +### settings.json + +```json +{ + "autoDreamEnabled": true +} +``` + +- **When explicitly set**: Uses the user's value directly +- **When not set**: Controlled by the remote GrowthBook feature flag `tengu_onyx_plover` + +**Key source** `src/services/autoDream/config.ts:13-21`: + +```typescript +export function isAutoDreamEnabled(): boolean { + const setting = getInitialSettings().autoDreamEnabled + if (setting !== undefined) return setting + const gb = getFeatureValue_CACHED_MAY_BE_STALE<{ enabled?: unknown } | null>( + 'tengu_onyx_plover', null, + ) + return gb?.enabled === true +} +``` + +### Remote Configuration Parameters + +The `tengu_onyx_plover` feature flag can configure: + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `enabled` | boolean | -- | Master feature toggle | +| `minHours` | number | 24 | Minimum interval (hours) | +| `minSessions` | number | 5 | Minimum session count | + +### Manual Trigger: `/dream` + +In addition to automatic triggering, users can manually trigger memory consolidation via the `/dream` command. Manual triggers call `recordConsolidation()` to update the lock file timestamp. + +--- + +## 7. Relationship with extractMemories + +| Dimension | extractMemories | autoDream | +|-----------|----------------|-----------| +| **Trigger frequency** | After each conversation turn | Every 24h + 5 sessions | +| **Trigger location** | `stopHooks.ts` L149 | `stopHooks.ts` L155 | +| **Processing scope** | Recent messages from the current conversation | Historical transcripts from multiple sessions | +| **Goal** | Extract new memories | Consolidate/deduplicate/prune existing memories | +| **Human analogy** | Jotting down notes during the day | Organizing the notebook while sleeping | +| **Shared component** | `createAutoMemCanUseTool` | `createAutoMemCanUseTool` | +| **Forked agent** | Max 5 turns | No turn limit | +| **Transcript** | Not recorded (`skipTranscript`) | Not recorded (`skipTranscript`) | + +### Collaboration Flow + +``` +After each conversation turn + | +extractMemories -> Extract new memory fragments -> Write *.md + MEMORY.md + | +(After accumulating 24h + 5 sessions) + | +autoDream -> Review all memories + session transcripts + | +Merge duplicates / Fix stale data / Delete conflicts / Compress index + | +MEMORY.md and topic files refreshed +``` + +--- + +## 8. Source Code Navigation + +| File | Responsibility | +|------|----------------| +| `src/services/autoDream/autoDream.ts` | Main logic: gate checks, launch forked agent, progress monitoring | +| `src/services/autoDream/config.ts` | Toggle control: settings.json or GrowthBook | +| `src/services/autoDream/consolidationPrompt.ts` | Dream prompt: 4-phase consolidation workflow | +| `src/services/autoDream/consolidationLock.ts` | Lock file mechanism: concurrency prevention, timestamps, rollback | +| `src/tasks/DreamTask/DreamTask.ts` | UI task registration: state management, termination, rollback | +| `src/tasks/pillLabel.ts` | Bottom status bar label: "dreaming" | +| `src/components/tasks/DreamDetailDialog.tsx` | Dream detail dialog UI | +| `src/query/stopHooks.ts` | Execution entry point: triggers after each response | +| `src/utils/backgroundHousekeeping.ts` | Initialization entry point: `initAutoDream()` | +| `src/services/extractMemories/extractMemories.ts` | Shared `createAutoMemCanUseTool` | + +--- + +## 9. Analytics Events + +AutoDream records its operational state through the following events: + +| Event | Timing | Attached Data | +|-------|--------|---------------| +| `tengu_auto_dream_fired` | Dream started | `hours_since`, `sessions_since` | +| `tengu_auto_dream_completed` | Dream completed | `cache_read`, `cache_created`, `output`, `sessions_reviewed` | +| `tengu_auto_dream_failed` | Dream failed | -- | diff --git a/docs/en/memory/images/01-memory-overview.png b/docs/en/memory/images/01-memory-overview.png new file mode 100644 index 00000000..306018f6 Binary files /dev/null and b/docs/en/memory/images/01-memory-overview.png differ diff --git a/docs/en/memory/images/02-memory-types.png b/docs/en/memory/images/02-memory-types.png new file mode 100644 index 00000000..3d013250 Binary files /dev/null and b/docs/en/memory/images/02-memory-types.png differ diff --git a/docs/en/memory/images/03-memory-trigger.png b/docs/en/memory/images/03-memory-trigger.png new file mode 100644 index 00000000..27497247 Binary files /dev/null and b/docs/en/memory/images/03-memory-trigger.png differ diff --git a/docs/en/memory/images/04-memory-lifecycle.png b/docs/en/memory/images/04-memory-lifecycle.png new file mode 100644 index 00000000..3f55e393 Binary files /dev/null and b/docs/en/memory/images/04-memory-lifecycle.png differ diff --git a/docs/en/memory/images/05-architecture-overview.png b/docs/en/memory/images/05-architecture-overview.png new file mode 100644 index 00000000..a4dca2bc Binary files /dev/null and b/docs/en/memory/images/05-architecture-overview.png differ diff --git a/docs/en/memory/images/06-path-resolution.png b/docs/en/memory/images/06-path-resolution.png new file mode 100644 index 00000000..5a3c9c49 Binary files /dev/null and b/docs/en/memory/images/06-path-resolution.png differ diff --git a/docs/en/memory/images/07-prompt-injection.png b/docs/en/memory/images/07-prompt-injection.png new file mode 100644 index 00000000..b52d3832 Binary files /dev/null and b/docs/en/memory/images/07-prompt-injection.png differ diff --git a/docs/en/memory/images/08-auto-extraction.png b/docs/en/memory/images/08-auto-extraction.png new file mode 100644 index 00000000..24bf9ae4 Binary files /dev/null and b/docs/en/memory/images/08-auto-extraction.png differ diff --git a/docs/en/memory/images/09-memory-retrieval.png b/docs/en/memory/images/09-memory-retrieval.png new file mode 100644 index 00000000..086934d5 Binary files /dev/null and b/docs/en/memory/images/09-memory-retrieval.png differ diff --git a/docs/en/memory/images/10-agent-memory.png b/docs/en/memory/images/10-agent-memory.png new file mode 100644 index 00000000..a63f30c8 Binary files /dev/null and b/docs/en/memory/images/10-agent-memory.png differ diff --git a/docs/en/memory/images/11-autodream-overview.png b/docs/en/memory/images/11-autodream-overview.png new file mode 100644 index 00000000..bfb8fad1 Binary files /dev/null and b/docs/en/memory/images/11-autodream-overview.png differ diff --git a/docs/en/memory/images/12-autodream-trigger.png b/docs/en/memory/images/12-autodream-trigger.png new file mode 100644 index 00000000..0239e9a9 Binary files /dev/null and b/docs/en/memory/images/12-autodream-trigger.png differ diff --git a/docs/en/memory/images/13-autodream-phases.png b/docs/en/memory/images/13-autodream-phases.png new file mode 100644 index 00000000..543e7a58 Binary files /dev/null and b/docs/en/memory/images/13-autodream-phases.png differ diff --git a/docs/en/memory/index.md b/docs/en/memory/index.md new file mode 100644 index 00000000..a6ac4daf --- /dev/null +++ b/docs/en/memory/index.md @@ -0,0 +1,121 @@ +# Claude Code Memory System Documentation + +> Complete usage guide and technical implementation documentation for the memory system + +--- + +## Documentation Index + +### [01-usage-guide.md](./01-usage-guide.md) — Usage Guide + +A comprehensive user-facing manual covering: + +- **Four memory types**: User (user profile), Feedback (behavioral feedback), Project (project context), Reference (external references) +- **Four trigger methods**: Automatic extraction, explicit requests, `/memory` command, `/remember` command +- **Storage format**: YAML frontmatter + Markdown content +- **Management operations**: Forgetting, ignoring, manual editing, disabling, custom directories +- **Lifecycle**: From learning to injection, freshness management + +**Target audience**: All Claude Code users + +--- + +### [02-implementation.md](./02-implementation.md) — Implementation Details + +A deep technical analysis for developers, covering: + +- **5 core modules**: Path resolution, prompt construction, memory scanning, intelligent retrieval, automatic extraction +- **Path resolution system**: Priority chain, security validation, enable conditions +- **System prompt injection**: `loadMemoryPrompt()` -> `buildMemoryLines()`, MEMORY.md truncation strategy +- **Automatic memory extraction**: Forked agent, mutual exclusion mechanism, tool permissions, merge mechanism +- **Intelligent retrieval**: `scanMemoryFiles()` -> Sonnet selection -> freshness warnings +- **Agent memory**: Three-level scoping (user/project/local) +- **Team memory sync**: Pull/Push API, merge semantics +- **Complete data flow**: From session startup to context injection + +**Target audience**: Contributors, architects, developers who want a deep understanding of the implementation + +--- + +### [03-autodream.md](./03-autodream.md) — AutoDream Memory Consolidation + +Claude's "dreaming" mechanism -- a deep dive into background silent memory consolidation, covering: + +- **Core concept**: Like how the human brain organizes memories during sleep, periodically reviewing multiple sessions to consolidate knowledge +- **Five-gate check**: Feature toggle -> Time gate (24h) -> Scan throttle (10min) -> Session gate (5 sessions) -> Lock gate +- **Four-phase process**: Orient -> Gather -> Consolidate -> Prune +- **Security restrictions**: Read-only Bash, write operations limited to memory directory, PID lock file mutual exclusion +- **UI presentation**: Bottom "dreaming" label, Shift+Down detail dialog, completion notification +- **Configuration control**: settings.json local toggle + GrowthBook remote feature flag +- **Comparison with extractMemories**: Taking notes during the day vs. organizing the notebook while sleeping + +**Target audience**: Contributors, architects, developers interested in Claude's automated memory management + +--- + +## Illustrations + +All illustrations use a dark background (#1a1a2e) + Anthropic brand copper-orange (#D97757) style, consistent with the official Claude Code documentation. + +| Image | Description | Size | +|-------|-------------|------| +| `01-memory-overview.png` | Memory system overview -- four-layer architecture (trigger/type/storage/retrieval) | 632 KB | +| `02-memory-types.png` | Four memory types -- 2x2 grid showing User/Feedback/Project/Reference | 507 KB | +| `03-memory-trigger.png` | Memory trigger flow -- four paths from conversation to storage | 474 KB | +| `04-memory-lifecycle.png` | Memory lifecycle -- complete cycle flow + freshness checks | 1.0 MB | +| `05-architecture-overview.png` | Implementation architecture overview -- 5 core modules + auxiliary modules | 3.5 MB | +| `06-path-resolution.png` | Path resolution flow -- three-level priority + security validation | 1.0 MB | +| `07-prompt-injection.png` | Prompt injection flow -- loadMemoryPrompt dispatch logic | 1.1 MB | +| `08-auto-extraction.png` | Auto-extraction flow -- forked agent complete process | 1.2 MB | +| `09-memory-retrieval.png` | Intelligent retrieval flow -- Sonnet selection + freshness management | 816 KB | +| `10-agent-memory.png` | Agent memory scoping -- three-level nested structure | 523 KB | +| `11-autodream-overview.png` | AutoDream overview -- dreaming mechanism core architecture and human sleep analogy | 777 KB | +| `12-autodream-trigger.png` | AutoDream trigger flow -- five-gate check chain | 493 KB | +| `13-autodream-phases.png` | AutoDream four phases -- Orient/Gather/Consolidate/Prune | 602 KB | + +--- + +## Quick Start + +### For Users + +1. Read the [Usage Guide](./01-usage-guide.md) +2. Learn about the four memory types and trigger methods +3. Try the `/memory` and `/remember` commands + +### For Developers + +1. Read the [Implementation Details](./02-implementation.md) +2. Explore the source code: + - `src/memdir/paths.ts` -- Path resolution + - `src/memdir/memdir.ts` -- Prompt construction + - `src/memdir/memoryScan.ts` -- Memory scanning + - `src/memdir/findRelevantMemories.ts` -- Intelligent retrieval + - `src/services/extractMemories/` -- Automatic extraction +3. Understand the data flow and module interactions + +--- + +## Core Concepts Quick Reference + +| Concept | Description | +|---------|-------------| +| **MEMORY.md** | Index file, always loaded into context (max 200 lines / 25KB) | +| **Topic files** | `*.md` files containing frontmatter + content | +| **Auto-extraction** | Runs in the background after each response; a forked agent analyzes the conversation | +| **AutoDream** | Triggers after 24h + 5 sessions; consolidates/deduplicates/prunes all memories in the background | +| **Intelligent retrieval** | Sonnet model selects up to 5 relevant memories from the entire collection | +| **Freshness** | <=1 day: no warning; >1 day: stale warning attached | +| **Forked agent** | Shares prompt cache, restricted tool permissions, max 5 turns | +| **Three-level scoping** | Agent memory: user (global) > project (project-level) > local (local-level) | + +--- + +## Related Resources + +- [Claude Code Haha Home](/en/) +- [Memory system source code](https://github.com/NanmiCoder/cc-haha/tree/main/src/memdir/) +- [Auto-extraction service](https://github.com/NanmiCoder/cc-haha/tree/main/src/services/extractMemories/) +- [AutoDream service](https://github.com/NanmiCoder/cc-haha/tree/main/src/services/autoDream/) +- [DreamTask](https://github.com/NanmiCoder/cc-haha/tree/main/src/tasks/DreamTask/) +- [GitHub Issues](https://github.com/NanmiCoder/cc-haha/issues) diff --git a/docs/reference/fixes.en.md b/docs/en/reference/fixes.md similarity index 90% rename from docs/reference/fixes.en.md rename to docs/en/reference/fixes.md index 8116c27f..092f66c3 100644 --- a/docs/reference/fixes.en.md +++ b/docs/en/reference/fixes.md @@ -1,6 +1,5 @@ # Fixes Compared with the Original Leaked Source -

中文 | Back to README

The leaked source could not run directly. This repository mainly fixes the following issues: diff --git a/docs/reference/project-structure.en.md b/docs/en/reference/project-structure.md similarity index 89% rename from docs/reference/project-structure.en.md rename to docs/en/reference/project-structure.md index 2aeff8b0..d0f071e8 100644 --- a/docs/reference/project-structure.en.md +++ b/docs/en/reference/project-structure.md @@ -1,6 +1,5 @@ # Project Structure -

中文 | Back to README

```text bin/claude-haha # Entry script diff --git a/docs/en/skills/01-usage-guide.md b/docs/en/skills/01-usage-guide.md new file mode 100644 index 00000000..f29cc6ca --- /dev/null +++ b/docs/en/skills/01-usage-guide.md @@ -0,0 +1,393 @@ +# Claude Code Skills System -- Usage Guide + +> Skills are the extensible capability engine of Claude Code, allowing you to define custom automated workflows using Markdown files. + +

+What Are Skills · Six Sources · Definition Format · Invocation · Execution Context · Conditional Activation · Permissions · Quick Reference +

+ +![Skills System Overview](./images/01-skills-overview.png) + +--- + +## 1. What Are Skills? + +Skills are Claude Code's **extensible capability plugin system**. Each Skill is a Markdown file (with YAML frontmatter) that defines a specialized prompt and behavioral configuration, enabling Claude to execute professional workflows in specific scenarios. + +Core capabilities: + +| Capability | Description | +|------------|-------------| +| Specialized Workflows | Define standard processes for code review, TDD, debugging, etc. | +| Tool Permission Control | Restrict a Skill to only use specified tools | +| Model Switching | Assign different models to different Skills | +| Execution Isolation | Fork mode runs in an isolated sub-agent | +| Conditional Activation | Activate only when specific files are being operated on | +| Hook Injection | Automatically register lifecycle hooks when a Skill is invoked | + +--- + +## 2. Six Skill Sources + +![Skill Source Types](./images/02-skill-sources.png) + +Claude Code loads Skills from 6 different sources, ordered by priority from highest to lowest: + +### 1. Bundled (Built-in Skills) + +Compiled into the CLI binary and available to all users. Defined in TypeScript and registered via `registerBundledSkill()`. + +**Current Built-in Skills:** + +| Skill | Description | Special Conditions | +|-------|-------------|--------------------| +| `/verify` | Verify code changes | -- | +| `/debug` | Debugging assistant | -- | +| `/simplify` | Code simplification review | -- | +| `/remember` | Memory management | Requires auto-memory enabled | +| `/batch` | Batch processing | -- | +| `/stuck` | Help when stuck | -- | +| `/skillify` | Create a new Skill | -- | +| `/keybindings` | Custom keyboard shortcuts | -- | +| `/loop` | Timed loop tasks | AGENT_TRIGGERS feature gate | +| `/schedule` | Remote agent scheduling | AGENT_TRIGGERS_REMOTE feature gate | +| `/claude-api` | Claude API integration | BUILDING_CLAUDE_APPS feature gate | +| `/dream` | Automatic memory organization | KAIROS feature gate | + +### 2. Managed (Policy-Managed Skills) + +Controlled by organizational policies, stored in `/.claude/skills/`. Suitable for enterprise deployments. + +### 3. User (User Skills) + +Defined by individual users, stored in `~/.claude/skills/`. + +``` +~/.claude/skills/ +├── my-review/ +│ └── SKILL.md ← Main Skill file +├── deploy-check/ +│ └── SKILL.md +└── ... +``` + +### 4. Project (Project Skills) + +Defined at the project level, stored in `.claude/skills/`. Can be committed to version control. + +``` +your-project/ +└── .claude/ + └── skills/ + ├── lint-fix/ + │ └── SKILL.md + └── test-runner/ + └── SKILL.md +``` + +### 5. Plugin (Plugin Skills) + +Provided by installed plugins. Plugins declare Skills directories via `skillsPath` / `skillsPaths` in their manifest. + +Naming format: `{pluginName}:{skillName}` + +``` +Examples: superpowers:code-reviewer + superpowers:brainstorming +``` + +### 6. MCP (MCP Server Skills) + +Provided by connected MCP servers, naming format: `mcp__server-name__prompt-name`. + +**Security restriction**: MCP Skills are from remote untrusted sources and are **prohibited from executing** `!`...`` inline shell commands. + +--- + +## 3. Skill Definition Format + +### Directory Structure + +Each Skill is a directory containing a `SKILL.md` file: + +``` +skill-name/ +└── SKILL.md ← Filename must be SKILL.md (case-insensitive) +``` + +### Complete Frontmatter Fields + +```yaml +--- +name: My Skill # Display name (optional, defaults to directory name) +description: What this skill does # Description (required; auto-extracted from content if missing) +when_to_use: When to use this skill # Usage scenario description (optional) +version: 1.0.0 # Version number (optional) + +# ── Invocation Control ── +user-invocable: true # Whether user can invoke via /skill-name (default: true) +disable-model-invocation: false # Prevent model from invoking via Skill tool (optional) +argument-hint: "" # Argument hint (optional) + +# ── Execution Configuration ── +context: inline # Execution context: inline (default) or fork (sub-agent) +agent: general-purpose # Agent type when forked (optional) +model: sonnet # Model override: haiku / sonnet / opus / inherit (optional) +effort: high # Thinking effort: low / medium / high / max (optional) +allowed-tools: "Bash, Read" # Allowed tools (comma-separated or YAML list) +shell: bash # Shell type: bash (default) or powershell + +# ── Conditional Activation ── +paths: "src/**/*.ts, test/**/*.ts" # Glob patterns; activate only when matching files are operated on + +# ── Lifecycle Hooks ── +hooks: + PreToolUse: + - matcher: "Bash" + hooks: + - command: "echo 'Before bash'" + once: true # Execute only once +--- + +# Skill Body Content + +This is the Markdown-formatted prompt that Claude sees when this Skill is invoked. + +Supported special syntax: +- `${CLAUDE_SKILL_DIR}` — Expands to the Skill's directory +- `${CLAUDE_SESSION_ID}` — Expands to the current session ID +- `$ARGUMENTS` / `${ARG1}` — Argument substitution +- !`shell command` — Inline shell command execution +``` + +### Frontmatter Field Reference + +| Field | Type | Default | Description | +|-------|------|---------|-------------| +| `name` | string | Directory name | Display name override | +| `description` | string | Auto-extracted | Brief Skill description | +| `when_to_use` | string | -- | Usage scenario description | +| `user-invocable` | boolean | true | Whether user can invoke via /name | +| `disable-model-invocation` | boolean | false | Prevent model invocation | +| `context` | `inline` \| `fork` | inline | Execution context | +| `agent` | string | general-purpose | Agent type when forked | +| `model` | string | Inherited | Model override (haiku/sonnet/opus) | +| `effort` | string \| int | -- | Thinking effort level | +| `allowed-tools` | string \| list | All | Allowed tools whitelist | +| `paths` | string \| list | -- | Conditional activation glob patterns | +| `shell` | `bash` \| `powershell` | bash | Shell command type | +| `hooks` | object | -- | Lifecycle hook configuration | +| `argument-hint` | string | -- | Argument hint text | +| `version` | string | -- | Version number | + +--- + +## 4. Invocation Methods + +![Skill Invocation Flow](./images/03-skill-invocation.png) + +### Method 1: User Slash Commands + +Type `/skill-name` directly in the terminal: + +``` +> /commit +> /review-pr 123 +> /verify +``` + +**Prerequisite**: The Skill's `user-invocable` must be `true`. + +### Method 2: Automatic Model Invocation + +When Claude identifies a suitable Skill during conversation, it automatically invokes it via SkillTool: + +``` +User: Please review this code for me +Claude: [Invokes superpowers:code-reviewer via SkillTool] +``` + +**Prerequisite**: The Skill's `disable-model-invocation` must not be `true`. + +### Method 3: Nested Invocation + +One Skill can trigger another during execution: + +``` +/verify → internally invokes → /simplify +``` + +Tracked in telemetry via `invocation_trigger: 'nested-skill'`. + +### Invocation Priority + +When Skills with the same name exist in multiple sources, they are resolved in the following order (first match wins): + +``` +1. Bundled (built-in) ← Highest priority +2. Built-in Plugin +3. Skill Dirs (user/project directories) +4. Workflow Commands +5. Plugin Commands +6. Plugin Skills +7. Built-in Commands ← Lowest priority +``` + +--- + +## 5. Execution Context + +### Inline Mode (Default) + +Skill content is **expanded into the current conversation**. Claude directly sees the prompt and executes within the same context. + +```yaml +context: inline # Default value, can be omitted +``` + +**Characteristics:** +- Shares the parent conversation's token budget +- Can access conversation history context +- `allowedTools` restricts available tools for the current turn +- `model` overrides the model used for the current turn + +### Fork Mode (Sub-Agent) + +The Skill runs in an **isolated sub-agent** with its own independent token budget and context. + +```yaml +context: fork +agent: general-purpose # Optional, specifies agent type +``` + +**Characteristics:** +- Independent token budget; does not consume the parent conversation's quota +- Isolated conversation context +- Can specify a different agent type (e.g., `Bash`, `general-purpose`) +- Results are extracted and returned to the parent conversation upon completion +- Supports progress reporting (`onProgress` callback) + +### Comparison of Both Modes + +| Feature | Inline | Fork | +|---------|--------|------| +| Token Budget | Shared with parent | Independent budget | +| Context Access | Full conversation history | Skill prompt only | +| Result Return | Directly in conversation | Text extracted into tool_result | +| Use Cases | Brief guidance, extended context | Long tasks, independent computation | +| Tool Restrictions | contextModifier modification | modifiedGetAppState | + +--- + +## 6. Conditional Activation + +Skills can use the `paths` frontmatter to implement **on-demand activation**, becoming visible to the model only when matching files are operated on. + +### Configuration + +```yaml +--- +name: TypeScript Fix +description: Fix TypeScript type errors +paths: "src/**/*.ts, test/**/*.ts" +--- +``` + +### How It Works + +``` +1. All Skills are loaded at startup +2. Skills with paths are stored in the conditionalSkills Map (not exposed to the model) +3. When the user operates on a file (Read/Write/Edit) +4. activateConditionalSkillsForPaths() matches using the ignore library +5. On match → moved to the dynamicSkills Map → visible to model +6. Once activated, remains active for the entire session +``` + +### Dynamic Discovery + +In addition to conditional activation, Skills also support **runtime discovery**: + +``` +1. User operates on a file in a deeply nested directory +2. discoverSkillDirsForPaths() traverses upward from the file path +3. Looks for .claude/skills/ directories (not beyond cwd) +4. Skips directories ignored by .gitignore +5. New directory found → addSkillDirectories() → load and register +``` + +--- + +## 7. Permission Control + +### Auto-Allow + +If a Skill contains only "safe properties" (no `allowedTools`, no `hooks`, no `fork`), it is **automatically approved** for execution without user confirmation. + +### Manual Confirmation + +Skills with tool restrictions, hooks, or fork execution will prompt the user on first invocation: + +``` +Execute skill: my-custom-skill +Allow? (y)es / (n)o / (a)lways allow / (d)eny +``` + +### Permission Rules + +| Rule Type | Format | Description | +|-----------|--------|-------------| +| Exact Allow | `Skill:commit` | Allow execution of the commit Skill | +| Prefix Allow | `Skill:review:*` | Allow all Skills with the review: prefix | +| Exact Deny | `Skill:dangerous` set to deny | Deny execution | +| Prefix Deny | `Skill:untrusted:*` set to deny | Deny all Skills with the untrusted: prefix | + +**Processing order:** Deny rules → Allow rules → Safe property check → Ask user + +--- + +## 8. Quick Reference + +### Creating a Skill + +```bash +# 1. Create directory +mkdir -p ~/.claude/skills/my-skill + +# 2. Create SKILL.md +cat > ~/.claude/skills/my-skill/SKILL.md << 'EOF' +--- +name: My Skill +description: An example Skill +user-invocable: true +--- + +# Skill Content + +Hello, this is my custom Skill. +EOF +``` + +### Common Operations + +| Operation | Method | +|-----------|--------| +| Create a Skill | `~/.claude/skills//SKILL.md` | +| Project-level Skill | `.claude/skills//SKILL.md` | +| Invoke a Skill | Type `/skill-name` in terminal | +| View available Skills | Type `/skills` in terminal | +| Create Skill with AI | `/skillify` | +| Restrict tools | Add `allowed-tools` in frontmatter | +| Fork execution | Add `context: fork` in frontmatter | +| Conditional activation | Add `paths: "src/**"` in frontmatter | + +### Skill Availability Matrix + +| Source | User Invocable | Model Invocable | Supports Fork | Supports Hooks | +|--------|---------------|-----------------|---------------|----------------| +| Bundled | Per definition | Per definition | Yes | Yes | +| Managed | Yes | Yes | Yes | Yes | +| User | Yes (default) | Yes | Yes | Yes | +| Project | Yes (default) | Yes | Yes | Yes | +| Plugin | Per config | Per config | Yes | Yes | +| MCP | Per config | Per config | Yes | No (security restriction) | diff --git a/docs/en/skills/02-implementation.md b/docs/en/skills/02-implementation.md new file mode 100644 index 00000000..78ecd02d --- /dev/null +++ b/docs/en/skills/02-implementation.md @@ -0,0 +1,897 @@ +# Claude Code Skills System -- Implementation Details + +> A deep dive into how Skills are discovered, loaded, injected, executed, and managed. + +

+Architecture · Discovery & Loading · Frontmatter Parsing · Injection · Execution Engine · Fork Execution · Conditional Activation · Hook Integration · Permission System · Complete Lifecycle · Source Index +

+ +![Skills Architecture Overview](./images/04-skills-architecture.png) + +--- + +## 1. Overall Architecture + +The Skills system consists of 5 core modules working together: + +``` +┌─────────────────────────────────────────────────────┐ +│ Skills System │ +│ │ +│ ┌─────────────┐ ┌──────────────┐ ┌────────────┐ │ +│ │ Discovery │ │ Prompt │ │ SkillTool │ │ +│ │ & Loading │→│ Injection │→│ Execution │ │ +│ └─────────────┘ └──────────────┘ └────────────┘ │ +│ ↑ ↓ │ +│ ┌─────────────┐ ┌────────────┐ │ +│ │ Activation │ │ Context │ │ +│ │ Conditional │←────────────────────│ Modifier │ │ +│ └─────────────┘ └────────────┘ │ +└─────────────────────────────────────────────────────┘ +``` + +### Module Responsibilities + +| Module | Core File | Responsibility | +|--------|-----------|----------------| +| Discovery | `loadSkillsDir.ts` | Discover and load Skills from 6 sources | +| Prompt | `prompt.ts` + `attachments.ts` | Inject Skill listing into system-reminder | +| SkillTool | `SkillTool.ts` | Validation, permission checks, Skill execution | +| Activation | `loadSkillsDir.ts` (second half) | Conditional activation and dynamic discovery | +| Context | `forkedAgent.ts` | Context preparation and modification | + +--- + +## 2. Skill Discovery and Loading + +### Loading Entry Point + +Skills loading begins with the `getSkills()` function in `commands.ts`: + +```typescript +// src/commands.ts:351-396 +async function getSkills(cwd: string) { + const [skillDirCommands, pluginSkills] = await Promise.all([ + getSkillDirCommands(cwd), // Directory Skills (managed/user/project) + getPluginSkills(), // Plugin Skills + ]) + const bundledSkills = getBundledSkills() // Built-in Skills + const builtinPluginSkills = getBuiltinPluginSkillCommands() // Built-in plugin Skills + return { skillDirCommands, pluginSkills, bundledSkills, builtinPluginSkills } +} +``` + +### Aggregation and Ordering + +All Skills from all sources are aggregated in `loadAllCommands()`, ordered by priority: + +```typescript +// src/commands.ts:447-467 +const loadAllCommands = memoize(async (cwd: string): Promise => { + return [ + ...bundledSkills, // 1. Built-in Skills (highest priority) + ...builtinPluginSkills, // 2. Built-in plugin Skills + ...skillDirCommands, // 3. Directory Skills (managed → user → project) + ...workflowCommands, // 4. Workflow commands + ...pluginCommands, // 5. Plugin commands + ...pluginSkills, // 6. Plugin Skills + ...COMMANDS(), // 7. Built-in commands (lowest priority) + ] +}) +``` + +**Key feature:** Uses `memoize` for caching to avoid redundant disk I/O. + +### Directory Skill Loading Flow + +![Skill Loading Flow](./images/05-skill-loading.png) + +`getSkillDirCommands()` is the core loading function for directory Skills: + +``` +getSkillDirCommands(cwd) +├─ Determine loading paths +│ ├─ managed: ${MANAGED_PATH}/.claude/skills/ +│ ├─ user: ~/.claude/skills/ +│ ├─ project: .claude/skills/ (traverse upward to HOME) +│ └─ additional: paths specified via --add-dir +│ +├─ Parallel loading (Promise.all) +│ ├─ loadSkillsFromSkillsDir(managedDir, 'policySettings') +│ ├─ loadSkillsFromSkillsDir(userDir, 'userSettings') +│ ├─ loadSkillsFromSkillsDir(projectDirs, 'projectSettings') +│ ├─ loadSkillsFromSkillsDir(additionalDirs, 'projectSettings') +│ └─ loadSkillsFromCommandsDir(cwd) ← Legacy /commands/ format compatibility +│ +├─ Deduplication (by realpath) +│ └─ getFileIdentity(filePath) → realpath resolves symlinks +│ └─ seenFileIds Map, first occurrence wins +│ +└─ Separate conditional Skills + ├─ No paths → unconditionalSkills (immediately available) + └─ Has paths → conditionalSkills Map (awaiting activation) +``` + +### Deduplication Mechanism + +```typescript +// src/skills/loadSkillsDir.ts:725-763 +const fileIds = await Promise.all( + allSkillsWithPaths.map(({ skill, filePath }) => + skill.type === 'prompt' + ? getFileIdentity(filePath) // realpath() resolves symlinks + : Promise.resolve(null), + ), +) + +const seenFileIds = new Map() +for (const entry of allSkillsWithPaths) { + const fileId = fileIds[i] + const existingSource = seenFileIds.get(fileId) + if (existingSource !== undefined) continue // Skip duplicates + seenFileIds.set(fileId, skill.source) + deduplicatedSkills.push(skill) +} +``` + +### Bundled Skill Registration + +Built-in Skills use an entirely different registration path: + +```typescript +// src/skills/bundledSkills.ts:53-100 +export function registerBundledSkill(definition: BundledSkillDefinition): void { + // If files are present, create extraction directory and lazy extraction logic + if (files && Object.keys(files).length > 0) { + skillRoot = getBundledSkillExtractDir(definition.name) + // Extract files to disk on first invocation + getPromptForCommand = async (args, ctx) => { + extractionPromise ??= extractBundledSkillFiles(name, files) + const extractedDir = await extractionPromise + const blocks = await inner(args, ctx) + return prependBaseDir(blocks, extractedDir) + } + } + + const command: Command = { + type: 'prompt', + source: 'bundled', + loadedFrom: 'bundled', + // ...other fields + } + bundledSkills.push(command) +} +``` + +**File extraction:** Bundled Skills can include a `files: Record` field. On first invocation, these files are extracted to disk (`getBundledSkillExtractDir()`), allowing the model to access them via Read/Grep. + +### Startup Registration + +```typescript +// src/skills/bundled/index.ts:13-58 +export function initBundledSkills(): void { + require('./verify.js').registerVerifySkill() + require('./debug.js').registerDebugSkill() + require('./remember.js').registerRememberSkill() + // ... + if (feature('AGENT_TRIGGERS')) { + require('./loop.js').registerLoopSkill() // Feature-gated + } + if (feature('KAIROS')) { + require('./dream.js').registerDreamSkill() // Feature-gated + } +} +``` + +### Plugin Skill Loading + +``` +Plugin System +├─ loadAllPluginsCacheOnly() +│ └─ Get all enabled plugins +│ +├─ For each plugin: +│ ├─ Read manifest.skillsPath → default Skills directory +│ ├─ Read manifest.skillsPaths[] → additional Skills directories +│ └─ loadSkillsFromDirectory() to load SKILL.md +│ +├─ Namespacing: +│ └─ {pluginName}:{namespace}:{skillName} +│ e.g.: superpowers:code-reviewer +│ +└─ Variable substitution: + ├─ ${CLAUDE_PLUGIN_ROOT} → plugin root directory + ├─ ${CLAUDE_PLUGIN_DATA} → plugin data directory + ├─ ${CLAUDE_SKILL_DIR} → skill directory + └─ ${user_config.X} → user configuration values +``` + +### MCP Skill Loading + +```typescript +// src/services/mcp/client.ts:2030-2102 +// MCP prompts are converted to Command objects +async function fetchCommandsForClient(client) { + const prompts = await client.listPrompts() + return prompts.map(prompt => ({ + type: 'prompt', + name: `mcp__${normalizeNameForMCP(serverName)}__${prompt.name}`, + source: 'mcp', + loadedFrom: 'mcp', + // getPromptForCommand calls the MCP server to fetch content + })) +} +``` + +**Feature gate:** `feature('MCP_SKILLS')` controls whether MCP Skills are available. + +--- + +## 3. Frontmatter Parsing + +### Parsing Flow + +``` +SKILL.md file + ↓ +parseFrontmatter() ← frontmatterParser.ts + ├─ Separate YAML frontmatter from Markdown content + ├─ quoteProblematicValues() ← Handle special characters (glob patterns, etc.) + └─ parseYaml() ← Parse YAML + ↓ +parseSkillFrontmatterFields() ← loadSkillsDir.ts:185-265 + ├─ description extraction priority: + │ 1. frontmatter.description field + │ 2. First # heading in Markdown + │ 3. Skill name as fallback + ├─ parseUserSpecifiedModel() ← Model alias resolution + ├─ parseEffortValue() ← Effort level parsing + ├─ parseHooksFromFrontmatter() ← Hook configuration validation + ├─ parseBooleanFrontmatter() ← Boolean field parsing + └─ parseSlashCommandToolsFromFrontmatter() ← Tool list parsing + ↓ +createSkillCommand() ← loadSkillsDir.ts:270-401 + └─ Generate Command object (with getPromptForCommand closure) +``` + +### FrontmatterData Type Definition + +```typescript +// src/utils/frontmatterParser.ts:10-59 +export type FrontmatterData = { + 'allowed-tools'?: string | string[] | null + description?: string | null + 'argument-hint'?: string | null + when_to_use?: string | null + version?: string | null + model?: string | null // haiku, sonnet, opus, inherit + 'user-invocable'?: string | null + 'disable-model-invocation'?: string | null + hooks?: HooksSettings | null + effort?: string | null // low, medium, high, max, or numeric + context?: 'inline' | 'fork' | null + agent?: string | null + paths?: string | string[] | null + shell?: string | null // bash, powershell + [key: string]: unknown +} +``` + +### The getPromptForCommand Closure + +Each Command object contains a `getPromptForCommand` closure that executes upon invocation: + +```typescript +// src/skills/loadSkillsDir.ts:344-399 +async getPromptForCommand(args, toolUseContext) { + // 1. Add base directory header + let finalContent = baseDir + ? `Base directory for this skill: ${baseDir}\n\n${markdownContent}` + : markdownContent + + // 2. Argument substitution + finalContent = substituteArguments(finalContent, args, true, argumentNames) + + // 3. Skill directory variable substitution + if (baseDir) { + finalContent = finalContent.replace(/\$\{CLAUDE_SKILL_DIR\}/g, skillDir) + } + + // 4. Session ID substitution + finalContent = finalContent.replace(/\$\{CLAUDE_SESSION_ID\}/g, getSessionId()) + + // 5. Execute inline shell commands (skipped for MCP Skills — security restriction) + if (loadedFrom !== 'mcp') { + finalContent = await executeShellCommandsInPrompt(finalContent, context) + } + + return [{ type: 'text', text: finalContent }] +} +``` + +--- + +## 4. Skill Injection into Conversations + +### Injection Flow + +![Skill Listing Injection](./images/06-skill-injection.png) + +Skills are injected into conversations via `system-reminder` messages: + +``` +Start of each conversation turn + ↓ +getSkillListingAttachments() ← attachments.ts:2600-2747 + ├─ getSkillToolCommands(cwd) ← Get all model-invocable Skills + ├─ getMcpSkillCommands() ← Get MCP Skills + ├─ sentSkillNames Map tracking ← Avoid duplicate sends (per-agent) + └─ formatCommandsWithinBudget() ← Truncate to context budget + ↓ +Returns Attachment: + { type: 'skill_listing', content, skillCount, isInitial } + ↓ +normalizeAttachmentForAPI() ← messages.ts:3732-3737 + ↓ +Wrapped as user message: + "The following skills are available for use with the Skill tool: + - commit: Create a git commit... + - review-pr: Review a pull request... + - superpowers:code-reviewer: Expert code review..." +``` + +### Context Budget Control + +```typescript +// src/tools/SkillTool/prompt.ts:21-29 +export const SKILL_BUDGET_CONTEXT_PERCENT = 0.01 // 1% of context window +export const CHARS_PER_TOKEN = 4 +export const DEFAULT_CHAR_BUDGET = 8_000 // 200k × 4 × 1% fallback +export const MAX_LISTING_DESC_CHARS = 250 // Max characters per description +``` + +**Truncation strategy:** + +``` +formatCommandsWithinBudget(commands, contextWindowTokens) + ├─ Calculate total budget = contextWindowTokens × 4 × 1% + ├─ Try full descriptions + │ └─ Total chars ≤ budget → output all + │ + ├─ Partition: Bundled (never truncated) + rest + │ ├─ Bundled Skills always retain full descriptions + │ └─ Remaining Skills split the leftover budget evenly + │ + ├─ Truncate descriptions → maxDescLen characters + │ └─ maxDescLen < 20 → extreme case: non-Bundled show name only + │ + └─ Output format: "- skill-name: description..." +``` + +### SkillTool Prompt + +The tool prompt definition seen by the model: + +```typescript +// src/tools/SkillTool/prompt.ts:173-196 +export const getPrompt = memoize(async (_cwd: string): Promise => { + return `Execute a skill within the main conversation + +When users ask you to perform tasks, check if any of the available skills match. + +How to invoke: +- Use this tool with the skill name and optional arguments +- Examples: + - skill: "pdf" + - skill: "commit", args: "-m 'Fix bug'" + +Important: +- Available skills are listed in system-reminder messages +- When a skill matches, invoke BEFORE generating any other response +- NEVER mention a skill without calling this tool +- Do not invoke a skill that is already running +` +}) +``` + +--- + +## 5. SkillTool Execution Engine + +### Tool Definition + +```typescript +// src/tools/SkillTool/SkillTool.ts:331-340 +export const SkillTool = buildTool({ + name: 'Skill', + inputSchema: z.object({ + skill: z.string(), // Skill name + args: z.string().optional(), // Optional arguments + }), + outputSchema: z.union([inlineOutputSchema, forkedOutputSchema]), +}) +``` + +### Execution Flow + +![SkillTool Execution Flow](./images/07-skill-execution.png) + +``` +SkillTool.call({ skill, args }) + │ + ├─ 1. Normalize input + │ └─ Strip leading /, trim whitespace + │ + ├─ 2. Remote Skill check (experimental) + │ └─ _canonical_ prefix → executeRemoteSkill() + │ + ├─ 3. Find Command object + │ └─ getAllCommands(context) → findCommand(name, commands) + │ + ├─ 4. Record usage frequency + │ └─ recordSkillUsage(commandName) → influences sorting recommendations + │ + ├─ 5. Determine execution path + │ ├─ command.context === 'fork' + │ │ └─ → executeForkedSkill() [see Section 6] + │ │ + │ └─ Default: inline + │ ├─ processPromptSlashCommand() + │ │ └─ getMessagesForPromptSlashCommand() + │ │ ├─ command.getPromptForCommand(args, context) + │ │ ├─ registerSkillHooks() ← Register hooks + │ │ ├─ addInvokedSkill() ← Record (restored after compression) + │ │ ├─ formatCommandLoadingMetadata() + │ │ │ └─ /skillName + │ │ └─ Extract attachments → create messages + │ │ + │ ├─ Extract metadata: allowedTools, model, effort + │ ├─ tagMessagesWithToolUseID() ← Associate with tool_use + │ └─ Return { newMessages, contextModifier } + │ + └─ 6. contextModifier() closure + ├─ Update allowedTools + │ └─ appState.toolPermissionContext.alwaysAllowRules.command + ├─ Update model + │ └─ resolveSkillModelOverride() preserves [1m] suffix + └─ Update effort + └─ appState.effortValue +``` + +### Validation Logic + +```typescript +// src/tools/SkillTool/SkillTool.ts:354-430 +async validateInput({ skill }, context) { + // 1. Format check — non-empty + // 2. Normalize — strip leading / + // 3. Remote Skill check — _canonical_ prefix + // 4. Lookup — findCommand() within getAllCommands() + // 5. Disabled check — disableModelInvocation + // 6. Type check — must be 'prompt' type +} +``` + +**Error code definitions:** + +| errorCode | Meaning | +|-----------|---------| +| 1 | Invalid format (empty skill name) | +| 2 | Unknown skill | +| 4 | Model invocation disabled | +| 5 | Not a prompt type | +| 6 | Remote skill not found | + +### getAllCommands -- MCP Skill Merging + +```typescript +// src/tools/SkillTool/SkillTool.ts:81-94 +async function getAllCommands(context: ToolUseContext): Promise { + // Get MCP Skills from AppState (loadedFrom === 'mcp') + const mcpSkills = context.getAppState() + .mcp.commands.filter( + cmd => cmd.type === 'prompt' && cmd.loadedFrom === 'mcp', + ) + if (mcpSkills.length === 0) return getCommands(getProjectRoot()) + const localCommands = await getCommands(getProjectRoot()) + return uniqBy([...localCommands, ...mcpSkills], 'name') +} +``` + +--- + +## 6. Fork Sub-Agent Execution + +### Execution Flow + +``` +executeForkedSkill(command, commandName, args, context, ...) + │ + ├─ 1. Create sub-agent ID + │ └─ agentId = createAgentId() + │ + ├─ 2. Telemetry recording + │ └─ logEvent('tengu_skill_tool_invocation', { execution_context: 'fork' }) + │ + ├─ 3. Prepare fork context + │ └─ prepareForkedCommandContext(command, args, context) + │ ├─ command.getPromptForCommand(args, context) ← Get skill content + │ ├─ parseToolListFromCLI(allowedTools) ← Parse tool whitelist + │ ├─ createGetAppStateWithAllowedTools() ← Modify AppState + │ ├─ Select agent: command.agent ?? 'general-purpose' + │ └─ promptMessages = [createUserMessage(skillContent)] + │ + ├─ 4. Merge effort + │ └─ command.effort → inject into agentDefinition + │ + ├─ 5. Run sub-agent + │ └─ for await (message of runAgent({ + │ agentDefinition, + │ promptMessages, + │ toolUseContext: { ...context, getAppState: modifiedGetAppState }, + │ model: command.model, + │ override: { agentId }, + │ })) + │ └─ Collect messages + report progress (onProgress) + │ + ├─ 6. Extract results + │ └─ extractResultText(agentMessages) + │ └─ Get text from the last assistant message + │ + └─ 7. Cleanup + └─ clearInvokedSkillsForAgent(agentId) +``` + +### prepareForkedCommandContext + +```typescript +// src/utils/forkedAgent.ts:191-232 +export async function prepareForkedCommandContext( + command: PromptCommand, + args: string, + context: ToolUseContext, +): Promise { + // Get skill content (with argument substitution and shell execution) + const skillPrompt = await command.getPromptForCommand(args, context) + const skillContent = skillPrompt.map(b => b.type === 'text' ? b.text : '').join('\n') + + // Build tool whitelist + const allowedTools = parseToolListFromCLI(command.allowedTools ?? []) + const modifiedGetAppState = createGetAppStateWithAllowedTools( + context.getAppState, allowedTools, + ) + + // Select agent type + const agentTypeName = command.agent ?? 'general-purpose' + const baseAgent = agents.find(a => a.agentType === agentTypeName) + + // Build prompt messages + const promptMessages = [createUserMessage({ content: skillContent })] + + return { skillContent, modifiedGetAppState, baseAgent, promptMessages } +} +``` + +### Inline vs Fork Return Differences + +**Inline return:** +```typescript +{ + data: { + success: true, + commandName: 'commit', + allowedTools: ['Bash', 'Read'], + model: 'sonnet', + status: 'inline', + }, + newMessages: [...], // Injected into conversation + contextModifier: (ctx) => { ... }, // Modifies context +} +``` + +**Fork return:** +```typescript +{ + data: { + success: true, + commandName: 'verify', + status: 'forked', + agentId: 'agent_abc123', + result: 'Verification passed, all tests have run...', + }, + // No newMessages — result is embedded in the tool_result block +} +``` + +--- + +## 7. Conditional Activation and Dynamic Discovery + +### Conditional Skills + +![Conditional Activation Mechanism](./images/08-conditional-activation.png) + +Skills with `paths` frontmatter are not immediately exposed to the model: + +``` +At startup +├─ Load all Skills +├─ Those with paths → conditionalSkills Map +└─ Those without paths → immediately available + +At runtime (triggered by file operations) +├─ activateConditionalSkillsForPaths(filePaths, cwd) +│ ├─ Iterate over conditionalSkills Map +│ ├─ Match paths patterns using the ignore library +│ │ └─ filePath converted to cwd-relative path before matching +│ ├─ On match: +│ │ ├─ Move to dynamicSkills Map +│ │ ├─ Remove from conditionalSkills +│ │ ├─ Add to activatedConditionalSkillNames Set +│ │ └─ Log telemetry: tengu_dynamic_skills_changed +│ └─ Once activated, remains active for the session +└─ Notify cache invalidation → skillsLoaded.emit() +``` + +### Dynamic Discovery + +When operating on files in deeply nested directories, the system automatically discovers new Skills: + +```typescript +// src/skills/loadSkillsDir.ts:861-915 +export async function discoverSkillDirsForPaths( + filePaths: string[], + cwd: string, +): Promise { + for (const filePath of filePaths) { + let currentDir = dirname(filePath) + // Traverse upward from the file's directory to cwd (excluding cwd itself) + while (currentDir.startsWith(resolvedCwd + pathSep)) { + const skillDir = join(currentDir, '.claude', 'skills') + if (!dynamicSkillDirs.has(skillDir)) { + dynamicSkillDirs.add(skillDir) + await fs.stat(skillDir) // Check if it exists + // Check if ignored by .gitignore + if (await isPathGitignored(currentDir, resolvedCwd)) continue + newDirs.push(skillDir) + } + currentDir = dirname(currentDir) + } + } + // Sort by depth (deepest first), ensuring nearest Skills have higher priority + return newDirs.sort((a, b) => b.split(pathSep).length - a.split(pathSep).length) +} +``` + +### Cache Invalidation Chain + +``` +Dynamic Skill change + ↓ +skillsLoaded.emit() + ↓ +clearCommandMemoizationCaches() + ├─ loadAllCommands.cache.clear() + ├─ getSkillToolCommands.cache.clear() + ├─ getSlashCommandToolSkills.cache.clear() + └─ clearSkillIndexCache() + ↓ +Next conversation turn loads the updated Skill list +``` + +--- + +## 8. Hook Integration + +### Hook Registration + +Skills can declare hooks via frontmatter, which are automatically registered as session-level hooks upon invocation: + +```typescript +// src/utils/hooks/registerSkillHooks.ts:20-64 +export function registerSkillHooks( + setAppState, sessionId, hooks, skillName, skillRoot?, +): void { + for (const eventName of HOOK_EVENTS) { + const matchers = hooks[eventName] + if (!matchers) continue + for (const matcher of matchers) { + for (const hook of matcher.hooks) { + // once: true → automatically removed after one execution + const onHookSuccess = hook.once + ? () => removeSessionHook(setAppState, sessionId, eventName, hook) + : undefined + + addSessionHook( + setAppState, sessionId, eventName, + matcher.matcher || '', + hook, onHookSuccess, skillRoot, + ) + } + } + } +} +``` + +### Hook Lifecycle + +``` +Skill invocation + ↓ +processPromptSlashCommand() + ├─ Check command.hooks + └─ registerSkillHooks(setAppState, sessionId, hooks, skillName, skillRoot) + ├─ Iterate over HOOK_EVENTS (PreToolUse, PostToolUse, Stop, ...) + ├─ Register addSessionHook() for each matcher + ├─ skillRoot → CLAUDE_PLUGIN_ROOT environment variable + └─ once: true → removeSessionHook() after first execution + ↓ +During session + ├─ Tool calls trigger PreToolUse/PostToolUse + ├─ Matcher matches → execute hook command + └─ Hooks with once: true are automatically removed after first execution +``` + +--- + +## 9. Permission System + +### Check Flow + +``` +checkPermissions({ skill, args }, context) + │ + ├─ 1. Deny rule check (highest priority) + │ └─ getRuleByContentsForTool(context, SkillTool, 'deny') + │ ├─ Exact match: "commit" === commandName + │ └─ Prefix match: "review:*" → commandName.startsWith("review") + │ + ├─ 2. Remote Skill auto-allow + │ └─ _canonical_ → auto-allow (Ant-specific experimental) + │ + ├─ 3. Allow rule check + │ └─ getRuleByContentsForTool(context, SkillTool, 'allow') + │ + ├─ 4. Safe property auto-allow + │ └─ skillHasOnlySafeProperties(command) + │ └─ SAFE_SKILL_PROPERTIES whitelist check + │ + └─ 5. Default: ask user + └─ Provide suggestions: exact allow + prefix allow +``` + +### Safe Property Whitelist + +If a Skill contains only the following properties (no hooks, no allowedTools, no fork), it is automatically allowed: + +``` +SAFE_SKILL_PROPERTIES = { + type, name, description, contentLength, source, + loadedFrom, progressMessage, userInvocable, + disableModelInvocation, hasUserSpecifiedDescription, + getPromptForCommand, userFacingName, ... +} +``` + +**Core principle:** Newly added frontmatter fields require permission by default, unless explicitly added to the whitelist. + +--- + +## 10. Complete Lifecycle + +### Data Flow Overview + +![Complete Lifecycle](./images/09-skill-lifecycle.png) + +``` +Phase 1: Discovery and Registration +────────────────────────────────── +CLI startup + ├─ initBundledSkills() → bundledSkills[] + ├─ getPluginSkills() → pluginSkills[] + ├─ getSkillDirCommands(cwd) → skillDirCommands[] + │ └─ Conditional Skills → conditionalSkills Map + └─ loadAllCommands() → aggregate & memoize + +Phase 2: Injection into Conversation +──────────────────────────────────── +Each conversation turn + ├─ getSkillListingAttachments() + │ ├─ getSkillToolCommands() → filter model-invocable Skills + │ ├─ getMcpSkillCommands() → MCP Skills + │ └─ formatCommandsWithinBudget() → truncate to budget + └─ Wrap as message and inject + +Phase 3: Invocation and Execution +───────────────────────────────── +Model/user trigger + ├─ SkillTool.validateInput() → validation + ├─ SkillTool.checkPermissions() → permissions + └─ SkillTool.call() + ├─ Inline → processPromptSlashCommand() + │ ├─ getPromptForCommand() → content expansion + │ ├─ registerSkillHooks() → hook registration + │ ├─ addInvokedSkill() → record (restored after compression) + │ └─ contextModifier() → update tools/model/effort + └─ Fork → executeForkedSkill() + ├─ prepareForkedCommandContext() + ├─ runAgent() → sub-agent execution + └─ extractResultText() → extract results + +Phase 4: Runtime Discovery +───────────────────────── +File operation trigger + ├─ discoverSkillDirsForPaths() → new Skills directories + ├─ addSkillDirectories() → load & register + ├─ activateConditionalSkillsForPaths() → conditional activation + └─ clearCommandMemoizationCaches() → cache invalidation +``` + +### Skill Content Persistence + +Inline Skill content is recorded to session state via `addInvokedSkill()`, ensuring it can be restored after context compression: + +``` +addInvokedSkill(name, path, content, agentId) + ↓ +Stored in session state + ↓ +On compression → buildPostCompactMessages() + ↓ +Restored scoped by agentId (prevents cross-agent leakage) +``` + +--- + +## 11. Source Code Index + +### Core Files + +| File | Responsibility | +|------|----------------| +| `src/tools/SkillTool/SkillTool.ts` | SkillTool definition, validation, permissions, execution | +| `src/tools/SkillTool/prompt.ts` | Tool prompt, Skill listing formatting, budget control | +| `src/skills/loadSkillsDir.ts` | Directory Skill discovery, loading, deduplication, conditional activation | +| `src/skills/bundledSkills.ts` | Built-in Skill registration system | +| `src/skills/bundled/index.ts` | Built-in Skills initialization entry point | +| `src/commands.ts` | Command aggregation, ordering, filtering, cache management | + +### Type Definitions + +| File | Key Types | +|------|-----------| +| `src/types/command.ts` | `PromptCommand`, `Command`, `LocalCommandResult` | +| `src/utils/frontmatterParser.ts` | `FrontmatterData`, `ParsedMarkdown` | +| `src/skills/bundledSkills.ts` | `BundledSkillDefinition` | + +### Utility Modules + +| File | Responsibility | +|------|----------------| +| `src/utils/forkedAgent.ts` | Fork context preparation, result extraction | +| `src/utils/hooks/registerSkillHooks.ts` | Skill hook registration | +| `src/utils/argumentSubstitution.ts` | Argument substitution ($ARGUMENTS, ${ARG1}) | +| `src/utils/promptShellExecution.ts` | Inline shell command execution | +| `src/utils/attachments.ts` | Skill listing attachment generation | +| `src/utils/messages.ts` | system-reminder wrapping | +| `src/utils/plugins/loadPluginCommands.ts` | Plugin Skill loading | +| `src/services/mcp/client.ts` | MCP Skill conversion | +| `src/skills/mcpSkillBuilders.ts` | MCP Skill builder registration | + +### Key Constants + +| Constant | Value | Location | +|----------|-------|----------| +| `SKILL_BUDGET_CONTEXT_PERCENT` | 0.01 | prompt.ts:21 | +| `DEFAULT_CHAR_BUDGET` | 8,000 | prompt.ts:23 | +| `MAX_LISTING_DESC_CHARS` | 250 | prompt.ts:29 | +| `SKILL_TOOL_NAME` | `'Skill'` | constants.ts | + +### Telemetry Events + +| Event | Description | +|-------|-------------| +| `tengu_skill_tool_invocation` | Skill invocation (includes execution_context, invocation_trigger) | +| `tengu_skill_tool_slash_prefix` | Model used the / prefix | +| `tengu_dynamic_skills_changed` | Dynamic Skills changed (conditional activation/directory discovery) | +| `tengu_skill_descriptions_truncated` | Skill descriptions were truncated | diff --git a/docs/en/skills/images/01-skills-overview.png b/docs/en/skills/images/01-skills-overview.png new file mode 100644 index 00000000..343c687f Binary files /dev/null and b/docs/en/skills/images/01-skills-overview.png differ diff --git a/docs/en/skills/images/02-skill-sources.png b/docs/en/skills/images/02-skill-sources.png new file mode 100644 index 00000000..65dc606f Binary files /dev/null and b/docs/en/skills/images/02-skill-sources.png differ diff --git a/docs/en/skills/images/03-skill-invocation.png b/docs/en/skills/images/03-skill-invocation.png new file mode 100644 index 00000000..53596187 Binary files /dev/null and b/docs/en/skills/images/03-skill-invocation.png differ diff --git a/docs/en/skills/images/04-skills-architecture.png b/docs/en/skills/images/04-skills-architecture.png new file mode 100644 index 00000000..a32b18df Binary files /dev/null and b/docs/en/skills/images/04-skills-architecture.png differ diff --git a/docs/en/skills/images/05-skill-loading.png b/docs/en/skills/images/05-skill-loading.png new file mode 100644 index 00000000..e2571fbb Binary files /dev/null and b/docs/en/skills/images/05-skill-loading.png differ diff --git a/docs/en/skills/images/06-skill-injection.png b/docs/en/skills/images/06-skill-injection.png new file mode 100644 index 00000000..34170451 Binary files /dev/null and b/docs/en/skills/images/06-skill-injection.png differ diff --git a/docs/en/skills/images/07-skill-execution.png b/docs/en/skills/images/07-skill-execution.png new file mode 100644 index 00000000..fb8f29fe Binary files /dev/null and b/docs/en/skills/images/07-skill-execution.png differ diff --git a/docs/en/skills/images/08-conditional-activation.png b/docs/en/skills/images/08-conditional-activation.png new file mode 100644 index 00000000..8e63ee3d Binary files /dev/null and b/docs/en/skills/images/08-conditional-activation.png differ diff --git a/docs/en/skills/images/09-skill-lifecycle.png b/docs/en/skills/images/09-skill-lifecycle.png new file mode 100644 index 00000000..a41e547b Binary files /dev/null and b/docs/en/skills/images/09-skill-lifecycle.png differ diff --git a/docs/features/computer-use.md b/docs/features/computer-use.md index ee43ef90..7b40c285 100644 --- a/docs/features/computer-use.md +++ b/docs/features/computer-use.md @@ -1,6 +1,5 @@ # Computer Use 功能指南 -

中文 | English

> **魔改说明**:本功能是基于 Claude Code 泄露源码中的 Computer Use(内部代号 "Chicago")进行的**深度改造版本**。官方实现依赖 Anthropic 内部私有原生模块(`@ant/computer-use-swift`、`@ant/computer-use-input`),无法公开获取。我们**替换了整个底层操作层**,使用 Python bridge(`pyautogui` + `mss` + `pyobjc`)实现所有系统交互,使得任何人都可以在 macOS 上运行 Computer Use 功能。 diff --git a/docs/guide/env-vars.md b/docs/guide/env-vars.md index 44dddca0..fa2d76d9 100644 --- a/docs/guide/env-vars.md +++ b/docs/guide/env-vars.md @@ -1,6 +1,5 @@ # 环境变量说明 -

English | 返回 README

| 变量 | 必填 | 说明 | |------|------|------| diff --git a/docs/guide/faq.md b/docs/guide/faq.md index 1e5f3358..77c11870 100644 --- a/docs/guide/faq.md +++ b/docs/guide/faq.md @@ -1,6 +1,5 @@ # 常见问题 -

English | 返回 README

## Q: `undefined is not an object (evaluating 'usage.input_tokens')` diff --git a/docs/guide/global-usage.md b/docs/guide/global-usage.md index f4ffee92..4a5f87f3 100644 --- a/docs/guide/global-usage.md +++ b/docs/guide/global-usage.md @@ -1,6 +1,5 @@ # 全局使用(任意目录启动) -

English | 返回 README

如果你希望在任意项目目录直接运行 `claude-haha`,可以通过以下方式配置。配置完成后,`claude-haha` 会自动识别你当前所在的工作目录。 diff --git a/docs/guide/quick-start.md b/docs/guide/quick-start.md new file mode 100644 index 00000000..fb262d61 --- /dev/null +++ b/docs/guide/quick-start.md @@ -0,0 +1,64 @@ +# 快速开始 + +## 1. 安装 Bun + +```bash +# macOS / Linux +curl -fsSL https://bun.sh/install | bash + +# macOS (Homebrew) +brew install bun + +# Windows (PowerShell) +powershell -c "irm bun.sh/install.ps1 | iex" +``` + +> 精简版 Linux 如提示 `unzip is required`,先运行 `apt update && apt install -y unzip` + +## 2. 安装依赖并配置 + +```bash +bun install +cp .env.example .env +# 编辑 .env 填入你的 API Key,详见「环境变量」文档 +``` + +环境变量的完整说明请参考 [环境变量配置](./env-vars.md)。 + +## 3. 启动 + +### macOS / Linux + +```bash +./bin/claude-haha # 交互 TUI 模式 +./bin/claude-haha -p "your prompt here" # 无头模式 +./bin/claude-haha --help # 查看所有选项 +``` + +### Windows + +> **前置要求**:必须安装 [Git for Windows](https://git-scm.com/download/win) + +```powershell +# PowerShell / cmd 直接调用 Bun +bun --env-file=.env ./src/entrypoints/cli.tsx + +# 或在 Git Bash 中运行 +./bin/claude-haha +``` + +## 4. 全局使用(可选) + +将 `bin/` 加入 PATH 后可在任意目录启动,详见 [全局使用指南](./global-usage.md): + +```bash +export PATH="$HOME/path/to/claude-code-haha/bin:$PATH" +``` + +## 5. 降级模式 + +如果 Ink TUI 出现问题,可以使用降级 Recovery CLI 模式: + +```bash +CLAUDE_CODE_FORCE_RECOVERY_CLI=1 ./bin/claude-haha +``` diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..c44b53d3 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,43 @@ +--- +layout: home + +hero: + name: Claude Code Haha + text: 本地可运行的 Claude Code + tagline: 基于泄露源码修复,支持接入任意 Anthropic 兼容 API(MiniMax、OpenRouter 等) + image: + src: /images/banner.jpg + alt: Claude Code Haha + actions: + - theme: brand + text: 快速开始 + link: /guide/quick-start + - theme: alt + text: GitHub + link: https://github.com/NanmiCoder/cc-haha + +features: + - icon: "\U0001F5A5" + title: 完整 TUI 交互 + details: 与官方 Claude Code 一致的 Ink 终端界面,支持 --print 无头模式 + - icon: "\U0001F9E0" + title: 记忆系统 + details: 跨会话持久化记忆,自动提取、智能检索、AutoDream 做梦整合 + link: /memory/ + - icon: "\U0001F916" + title: 多 Agent 系统 + details: 多代理编排、并行任务执行、Teams 协作、Worktree 隔离 + link: /agent/ + - icon: "\U0001F9E9" + title: Skills 系统 + details: 可扩展能力插件、自定义工作流、条件激活 + link: /skills/01-usage-guide + - icon: "\U0001F4BB" + title: Computer Use + details: 桌面控制功能 — 截屏、鼠标、键盘操作 + link: /features/computer-use + - icon: "\U0001F310" + title: 第三方模型支持 + details: 接入 OpenAI、DeepSeek、Ollama 等任意兼容模型 + link: /guide/third-party-models +--- diff --git a/docs/memory/README.md b/docs/memory/index.md similarity index 91% rename from docs/memory/README.md rename to docs/memory/index.md index 4bf9b812..3c77e193 100644 --- a/docs/memory/README.md +++ b/docs/memory/index.md @@ -113,9 +113,9 @@ Claude 的"做梦"机制——后台静默整合记忆的深度解析,涵盖 ## 🔗 相关资源 -- [Claude Code 主文档](../) -- [记忆系统源码](../../src/memdir/) -- [自动提取服务](../../src/services/extractMemories/) -- [AutoDream 服务](../../src/services/autoDream/) -- [DreamTask 任务](../../src/tasks/DreamTask/) -- [GitHub Issues](https://github.com/anthropics/claude-code/issues) +- [Claude Code Haha 主页](/) +- [记忆系统源码](https://github.com/NanmiCoder/cc-haha/tree/main/src/memdir/) +- [自动提取服务](https://github.com/NanmiCoder/cc-haha/tree/main/src/services/extractMemories/) +- [AutoDream 服务](https://github.com/NanmiCoder/cc-haha/tree/main/src/services/autoDream/) +- [DreamTask 任务](https://github.com/NanmiCoder/cc-haha/tree/main/src/tasks/DreamTask/) +- [GitHub Issues](https://github.com/NanmiCoder/cc-haha/issues) diff --git a/docs/public/CNAME b/docs/public/CNAME new file mode 100644 index 00000000..f6c41488 --- /dev/null +++ b/docs/public/CNAME @@ -0,0 +1 @@ +claudecodehaha.relakkesyang.org diff --git a/docs/public/images/banner.jpg b/docs/public/images/banner.jpg new file mode 100644 index 00000000..f2bc6f6e Binary files /dev/null and b/docs/public/images/banner.jpg differ diff --git a/docs/reference/fixes.md b/docs/reference/fixes.md index 97424b32..1c7acc55 100644 --- a/docs/reference/fixes.md +++ b/docs/reference/fixes.md @@ -1,6 +1,5 @@ # 相对于原始泄露源码的修复 -

English | 返回 README

泄露的源码无法直接运行,主要修复了以下问题: diff --git a/docs/reference/project-structure.md b/docs/reference/project-structure.md index 5403d5fe..8e6c0918 100644 --- a/docs/reference/project-structure.md +++ b/docs/reference/project-structure.md @@ -1,6 +1,5 @@ # 项目结构 -

English | 返回 README

``` bin/claude-haha # 入口脚本 diff --git a/package-lock.json b/package-lock.json index 0db4033b..b1790c04 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "claude-code-local", - "version": "0.0.0-local", + "version": "999.0.0-local", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "claude-code-local", - "version": "0.0.0-local", + "version": "999.0.0-local", "dependencies": { "@anthropic-ai/sandbox-runtime": "^0.0.44", "@anthropic-ai/sdk": "^0.80.0", @@ -73,6 +73,10 @@ }, "bin": { "claude-haha": "bin/claude-haha" + }, + "devDependencies": { + "vitepress": "^1.6.3", + "vue": "^3.5.13" } }, "node_modules/@alcalzone/ansi-tokenize": { @@ -88,6 +92,264 @@ "node": ">=18" } }, + "node_modules/@algolia/abtesting": { + "version": "1.16.1", + "resolved": "https://registry.npmmirror.com/@algolia/abtesting/-/abtesting-1.16.1.tgz", + "integrity": "sha512-Xxk4l00pYI+jE0PNw8y0MvsQWh5278WRtZQav8/BMMi3HKi2xmeuqe11WJ3y8/6nuBHdv39w76OpJb09TMfAVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.17.7", + "resolved": "https://registry.npmmirror.com/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz", + "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", + "@algolia/autocomplete-shared": "1.17.7" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.17.7", + "resolved": "https://registry.npmmirror.com/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz", + "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.17.7", + "resolved": "https://registry.npmmirror.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz", + "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.17.7", + "resolved": "https://registry.npmmirror.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz", + "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/client-abtesting": { + "version": "5.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/client-abtesting/-/client-abtesting-5.50.1.tgz", + "integrity": "sha512-4peZlPXMwTOey9q1rQKMdCnwZb/E95/1e+7KujXpLLSh0FawJzg//U2NM+r4AiJy4+naT2MTBhj0K30yshnVTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "5.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/client-analytics/-/client-analytics-5.50.1.tgz", + "integrity": "sha512-i+aWHHG8NZvGFHtPeMZkxL2Loc6Fm7iaRo15lYSMx8gFL+at9vgdWxhka7mD1fqxkrxXsQstUBCIsSY8FvkEOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "5.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/client-common/-/client-common-5.50.1.tgz", + "integrity": "sha512-Hw52Fwapyk/7hMSV/fI4+s3H9MGZEUcRh4VphyXLAk2oLYdndVUkc6KBi0zwHSzwPAr+ZBwFPe2x6naUt9mZGw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights": { + "version": "5.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/client-insights/-/client-insights-5.50.1.tgz", + "integrity": "sha512-Bn/wtwhJ7p1OD/6pY+Zzn+zlu2N/SJnH46md/PAbvqIzmjVuwjNwD4y0vV5Ov8naeukXdd7UU9v550+v8+mtlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "5.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/client-personalization/-/client-personalization-5.50.1.tgz", + "integrity": "sha512-0V4Tu0RWR8YxkgI9EPVOZHGE4K5pEIhkLNN0CTkP/rnPsqaaSQpNMYW3/mGWdiKOWbX0iVmwLB9QESk3H0jS5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions": { + "version": "5.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/client-query-suggestions/-/client-query-suggestions-5.50.1.tgz", + "integrity": "sha512-jofcWNYMXJDDr87Z2eivlWY6o71Zn7F7aOvQCXSDAo9QTlyf7BhXEsZymLUvF0O1yU9Q9wvrjAWn8uVHYnAvgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "5.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/client-search/-/client-search-5.50.1.tgz", + "integrity": "sha512-OteRb8WubcmEvU0YlMJwCXs3Q6xrdkb0v50/qZBJP1TF0CvujFZQM++9BjEkTER/Jr9wbPHvjSFKnbMta0b4dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion": { + "version": "1.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/ingestion/-/ingestion-1.50.1.tgz", + "integrity": "sha512-0GmfSgDQK6oiIVXnJvGxtNFOfosBspRTR7csCOYCTL1P8QtxX2vDCIKwTM7xdSAEbJaZ43QlWg25q0Qdsndz8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring": { + "version": "1.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/monitoring/-/monitoring-1.50.1.tgz", + "integrity": "sha512-ySuigKEe4YjYV3si8NVk9BHQpFj/1B+ON7DhhvTvbrZJseHQQloxzq0yHwKmznSdlO6C956fx4pcfOKkZClsyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "5.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/recommend/-/recommend-5.50.1.tgz", + "integrity": "sha512-Cp8T/B0gVmjFlzzp6eP47hwKh5FGyeqQp1N48/ANDdvdiQkPqLyFHQVDwLBH0LddfIPQE+yqmZIgmKc82haF4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "5.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.50.1.tgz", + "integrity": "sha512-XKdGGLikfrlK66ZSXh/vWcXZZ8Vg3byDFbJD8pwEvN1FoBRGxhxya476IY2ohoTymLa4qB5LBRlIa+2TLHx3Uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/requester-fetch/-/requester-fetch-5.50.1.tgz", + "integrity": "sha512-mBAU6WyVsDwhHyGM+nodt1/oebHxgvuLlOAoMGbj/1i6LygDHZWDgL1t5JEs37x9Aywv7ZGhqbM1GsfZ54sU6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "5.50.1", + "resolved": "https://registry.npmmirror.com/@algolia/requester-node-http/-/requester-node-http-5.50.1.tgz", + "integrity": "sha512-qmo1LXrNKLHvJE6mdQbLnsZAoZvj7VyF2ft4xmbSGWI2WWm87fx/CjUX4kEExt4y0a6T6nEts6ofpUfH5TEE1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/@anthropic-ai/sandbox-runtime": { "version": "0.0.44", "resolved": "https://registry.npmmirror.com/@anthropic-ai/sandbox-runtime/-/sandbox-runtime-0.0.44.tgz", @@ -841,6 +1103,42 @@ "node": ">=18.0.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/@babel/runtime": { "version": "7.29.2", "resolved": "https://registry.npmmirror.com/@babel/runtime/-/runtime-7.29.2.tgz", @@ -850,6 +1148,20 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@commander-js/extra-typings": { "version": "14.0.0", "resolved": "https://registry.npmmirror.com/@commander-js/extra-typings/-/extra-typings-14.0.0.tgz", @@ -859,6 +1171,463 @@ "commander": "~14.0.0" } }, + "node_modules/@docsearch/css": { + "version": "3.8.2", + "resolved": "https://registry.npmmirror.com/@docsearch/css/-/css-3.8.2.tgz", + "integrity": "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@docsearch/js": { + "version": "3.8.2", + "resolved": "https://registry.npmmirror.com/@docsearch/js/-/js-3.8.2.tgz", + "integrity": "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/react": "3.8.2", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/js/node_modules/@docsearch/react": { + "version": "3.8.2", + "resolved": "https://registry.npmmirror.com/@docsearch/react/-/react-3.8.2.tgz", + "integrity": "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.17.7", + "@algolia/autocomplete-preset-algolia": "1.17.7", + "@docsearch/css": "3.8.2", + "algoliasearch": "^5.14.2" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@docsearch/js/node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmmirror.com/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@growthbook/growthbook": { "version": "1.6.5", "resolved": "https://registry.npmmirror.com/@growthbook/growthbook/-/growthbook-1.6.5.tgz", @@ -883,6 +1652,30 @@ "hono": "^4" } }, + "node_modules/@iconify-json/simple-icons": { + "version": "1.2.76", + "resolved": "https://registry.npmmirror.com/@iconify-json/simple-icons/-/simple-icons-1.2.76.tgz", + "integrity": "sha512-lLRlA8yaf+1L5VCPRvR9lynoSklsddKHEylchmZJKdj/q2xVQ1ZAEJ8SCQlv9cbgtMefnlyM98U+8Si2aoFZPA==", + "dev": true, + "license": "CC0-1.0", + "dependencies": { + "@iconify/types": "*" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, "node_modules/@modelcontextprotocol/sdk": { "version": "1.29.0", "resolved": "https://registry.npmmirror.com/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", @@ -1041,12 +1834,449 @@ "integrity": "sha512-bQY06wzzR8D2+vVCUoBsr5QS2U6UgPUQRmErNwtsuI6vLcyRKkafjkr3KxbtGFf9aBBIV2mcvlsKD1UYaIV+sg==", "license": "MIT" }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@sec-ant/readable-stream": { "version": "0.4.1", "resolved": "https://registry.npmmirror.com/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", "license": "MIT" }, + "node_modules/@shikijs/core": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/@shikijs/core/-/core-2.5.0.tgz", + "integrity": "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.4" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz", + "integrity": "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^3.1.0" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz", + "integrity": "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/@shikijs/langs/-/langs-2.5.0.tgz", + "integrity": "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/@shikijs/themes/-/themes-2.5.0.tgz", + "integrity": "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/transformers": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/@shikijs/transformers/-/transformers-2.5.0.tgz", + "integrity": "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/types": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/@shikijs/types/-/types-2.5.0.tgz", + "integrity": "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmmirror.com/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "dev": true, + "license": "MIT" + }, "node_modules/@sindresorhus/merge-streams": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", @@ -1696,6 +2926,30 @@ "node": ">=18.0.0" } }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmmirror.com/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/lodash": { "version": "4.17.24", "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.24.tgz", @@ -1711,6 +2965,320 @@ "@types/lodash": "*" } }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmmirror.com/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.32", + "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.32.tgz", + "integrity": "sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.2", + "@vue/shared": "3.5.32", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.32", + "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.32.tgz", + "integrity": "sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.32", + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.32", + "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz", + "integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.2", + "@vue/compiler-core": "3.5.32", + "@vue/compiler-dom": "3.5.32", + "@vue/compiler-ssr": "3.5.32", + "@vue/shared": "3.5.32", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.8", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.32", + "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.32.tgz", + "integrity": "sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.32", + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmmirror.com/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmmirror.com/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.32", + "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.32.tgz", + "integrity": "sha512-/ORasxSGvZ6MN5gc+uE364SxFdJ0+WqVG0CENXaGW58TOCdrAW76WWaplDtECeS1qphvtBZtR+3/o1g1zL4xPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.32", + "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.32.tgz", + "integrity": "sha512-pDrXCejn4UpFDFmMd27AcJEbHaLemaE5o4pbb7sLk79SRIhc6/t34BQA7SGNgYtbMnvbF/HHOftYBgFJtUoJUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.32", + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.32", + "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.32.tgz", + "integrity": "sha512-1CDVv7tv/IV13V8Nip1k/aaObVbWqRlVCVezTwx3K07p7Vxossp5JU1dcPNhJk3w347gonIUT9jQOGutyJrSVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.32", + "@vue/runtime-core": "3.5.32", + "@vue/shared": "3.5.32", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.32", + "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.32.tgz", + "integrity": "sha512-IOjm2+JQwRFS7W28HNuJeXQle9KdZbODFY7hFGVtnnghF51ta20EWAZJHX+zLGtsHhaU6uC9BGPV52KVpYryMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.32", + "@vue/shared": "3.5.32" + }, + "peerDependencies": { + "vue": "3.5.32" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.32", + "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.32.tgz", + "integrity": "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "12.8.2", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-12.8.2.tgz", + "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/integrations": { + "version": "12.8.2", + "resolved": "https://registry.npmmirror.com/@vueuse/integrations/-/integrations-12.8.2.tgz", + "integrity": "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vueuse/core": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "^4", + "axios": "^1", + "change-case": "^5", + "drauu": "^0.4", + "focus-trap": "^7", + "fuse.js": "^7", + "idb-keyval": "^6", + "jwt-decode": "^4", + "nprogress": "^0.2", + "qrcode": "^1.5", + "sortablejs": "^1", + "universal-cookie": "^7" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "12.8.2", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-12.8.2.tgz", + "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "12.8.2", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-12.8.2.tgz", + "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/accepts/-/accepts-2.0.0.tgz", @@ -1766,6 +3334,32 @@ } } }, + "node_modules/algoliasearch": { + "version": "5.50.1", + "resolved": "https://registry.npmmirror.com/algoliasearch/-/algoliasearch-5.50.1.tgz", + "integrity": "sha512-/bwdue1/8LWELn/DBalGRfuLsXBLXULJo/yOeavJtDu8rBwxIzC6/Rz9Jg19S21VkJvRuZO1k8CZXBMS73mYbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/abtesting": "1.16.1", + "@algolia/client-abtesting": "5.50.1", + "@algolia/client-analytics": "5.50.1", + "@algolia/client-common": "5.50.1", + "@algolia/client-insights": "5.50.1", + "@algolia/client-personalization": "5.50.1", + "@algolia/client-query-suggestions": "5.50.1", + "@algolia/client-search": "5.50.1", + "@algolia/ingestion": "1.50.1", + "@algolia/monitoring": "1.50.1", + "@algolia/recommend": "5.50.1", + "@algolia/requester-browser-xhr": "5.50.1", + "@algolia/requester-fetch": "5.50.1", + "@algolia/requester-node-http": "5.50.1" + }, + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ansi-escapes": { "version": "7.3.0", "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-7.3.0.tgz", @@ -1878,6 +3472,16 @@ "node": "*" } }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmmirror.com/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/body-parser": { "version": "2.2.2", "resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-2.2.2.tgz", @@ -1961,6 +3565,17 @@ "node": ">=6" } }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chalk": { "version": "5.6.2", "resolved": "https://registry.npmmirror.com/chalk/-/chalk-5.6.2.tgz", @@ -1973,6 +3588,28 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chokidar": { "version": "5.0.0", "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-5.0.0.tgz", @@ -2163,6 +3800,17 @@ "node": ">= 0.8" } }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/commander": { "version": "14.0.3", "resolved": "https://registry.npmmirror.com/commander/-/commander-14.0.3.tgz", @@ -2222,6 +3870,22 @@ "node": ">=6.6.0" } }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/cors": { "version": "2.8.6", "resolved": "https://registry.npmmirror.com/cors/-/cors-2.8.6.tgz", @@ -2259,6 +3923,13 @@ "integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==", "license": "MIT" }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/data-uri-to-buffer": { "version": "4.0.1", "resolved": "https://registry.npmmirror.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", @@ -2312,6 +3983,30 @@ "node": ">= 0.8" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/diff": { "version": "8.0.4", "resolved": "https://registry.npmmirror.com/diff/-/diff-8.0.4.tgz", @@ -2371,6 +4066,13 @@ "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", "license": "MIT" }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "dev": true, + "license": "MIT" + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-2.0.0.tgz", @@ -2380,6 +4082,19 @@ "node": ">= 0.8" } }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-paths": { "version": "4.0.0", "resolved": "https://registry.npmmirror.com/env-paths/-/env-paths-4.0.0.tgz", @@ -2462,6 +4177,45 @@ "benchmarks" ] }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz", @@ -2477,6 +4231,13 @@ "node": ">=8" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz", @@ -2729,6 +4490,16 @@ "node": ">=8" } }, + "node_modules/focus-trap": { + "version": "7.8.0", + "resolved": "https://registry.npmmirror.com/focus-trap/-/focus-trap-7.8.0.tgz", + "integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tabbable": "^6.4.0" + } + }, "node_modules/follow-redirects": { "version": "1.15.11", "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.11.tgz", @@ -2816,6 +4587,21 @@ "node": ">= 0.8" } }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", @@ -3053,6 +4839,44 @@ "node": ">= 0.4" } }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmmirror.com/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/highlight.js": { "version": "11.11.1", "resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-11.11.1.tgz", @@ -3071,6 +4895,24 @@ "node": ">=16.9.0" } }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmmirror.com/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/http-errors": { "version": "2.0.1", "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.1.tgz", @@ -3359,6 +5201,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmmirror.com/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", @@ -3374,6 +5229,15 @@ "url": "https://github.com/sponsors/panva" } }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/json-bigint": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/json-bigint/-/json-bigint-1.0.0.tgz", @@ -3459,6 +5323,21 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "license": "MIT" }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmmirror.com/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "11.2.7", "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.2.7.tgz", @@ -3468,6 +5347,23 @@ "node": "20 || >=22" } }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmmirror.com/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/marked": { "version": "17.0.5", "resolved": "https://registry.npmmirror.com/marked/-/marked-17.0.5.tgz", @@ -3489,6 +5385,28 @@ "node": ">= 0.4" } }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmmirror.com/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/media-typer": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-1.1.0.tgz", @@ -3510,6 +5428,100 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, "node_modules/mime-db": { "version": "1.54.0", "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.54.0.tgz", @@ -3544,12 +5556,45 @@ "node": ">=6" } }, + "node_modules/minisearch": { + "version": "7.2.0", + "resolved": "https://registry.npmmirror.com/minisearch/-/minisearch-7.2.0.tgz", + "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", + "dev": true, + "license": "MIT" + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/negotiator": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-1.0.0.tgz", @@ -3682,6 +5727,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/oniguruma-to-es": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz", + "integrity": "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex-xs": "^1.0.0", + "regex": "^6.0.1", + "regex-recursion": "^6.0.2" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz", @@ -3803,6 +5860,20 @@ "url": "https://opencollective.com/express" } }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, "node_modules/picomatch": { "version": "4.0.4", "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz", @@ -3833,6 +5904,46 @@ "node": ">=10.13.0" } }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/preact": { + "version": "10.29.1", + "resolved": "https://registry.npmmirror.com/preact/-/preact-10.29.1.tgz", + "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, "node_modules/pretty-ms": { "version": "9.3.0", "resolved": "https://registry.npmmirror.com/pretty-ms/-/pretty-ms-9.3.0.tgz", @@ -3865,6 +5976,17 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmmirror.com/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -3980,6 +6102,33 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmmirror.com/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmmirror.com/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "dev": true, + "license": "MIT" + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", @@ -4035,6 +6184,58 @@ "node": ">= 4" } }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.60.1", + "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.60.1.tgz", + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.1", + "@rollup/rollup-android-arm64": "4.60.1", + "@rollup/rollup-darwin-arm64": "4.60.1", + "@rollup/rollup-darwin-x64": "4.60.1", + "@rollup/rollup-freebsd-arm64": "4.60.1", + "@rollup/rollup-freebsd-x64": "4.60.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", + "@rollup/rollup-linux-arm-musleabihf": "4.60.1", + "@rollup/rollup-linux-arm64-gnu": "4.60.1", + "@rollup/rollup-linux-arm64-musl": "4.60.1", + "@rollup/rollup-linux-loong64-gnu": "4.60.1", + "@rollup/rollup-linux-loong64-musl": "4.60.1", + "@rollup/rollup-linux-ppc64-gnu": "4.60.1", + "@rollup/rollup-linux-ppc64-musl": "4.60.1", + "@rollup/rollup-linux-riscv64-gnu": "4.60.1", + "@rollup/rollup-linux-riscv64-musl": "4.60.1", + "@rollup/rollup-linux-s390x-gnu": "4.60.1", + "@rollup/rollup-linux-x64-gnu": "4.60.1", + "@rollup/rollup-linux-x64-musl": "4.60.1", + "@rollup/rollup-openbsd-x64": "4.60.1", + "@rollup/rollup-openharmony-arm64": "4.60.1", + "@rollup/rollup-win32-arm64-msvc": "4.60.1", + "@rollup/rollup-win32-ia32-msvc": "4.60.1", + "@rollup/rollup-win32-x64-gnu": "4.60.1", + "@rollup/rollup-win32-x64-msvc": "4.60.1", + "fsevents": "~2.3.2" + } + }, "node_modules/router": { "version": "2.2.0", "resolved": "https://registry.npmmirror.com/router/-/router-2.2.0.tgz", @@ -4083,6 +6284,14 @@ "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", "license": "MIT" }, + "node_modules/search-insights": { + "version": "2.17.3", + "resolved": "https://registry.npmmirror.com/search-insights/-/search-insights-2.17.3.tgz", + "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/semver": { "version": "7.7.4", "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.4.tgz", @@ -4185,6 +6394,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/shiki": { + "version": "2.5.0", + "resolved": "https://registry.npmmirror.com/shiki/-/shiki-2.5.0.tgz", + "integrity": "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/langs": "2.5.0", + "@shikijs/themes": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, "node_modules/side-channel": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.0.tgz", @@ -4285,6 +6511,37 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmmirror.com/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmmirror.com/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/stack-utils": { "version": "2.0.6", "resolved": "https://registry.npmmirror.com/stack-utils/-/stack-utils-2.0.6.tgz", @@ -4322,6 +6579,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmmirror.com/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/strip-ansi": { "version": "7.2.0", "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", @@ -4361,6 +6633,19 @@ ], "license": "MIT" }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmmirror.com/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/supports-color": { "version": "10.2.2", "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-10.2.2.tgz", @@ -4389,6 +6674,13 @@ "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" } }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmmirror.com/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "dev": true, + "license": "MIT" + }, "node_modules/tagged-tag": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/tagged-tag/-/tagged-tag-1.0.0.tgz", @@ -4431,6 +6723,17 @@ "tree-kill": "cli.js" } }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/ts-algebra": { "version": "2.0.0", "resolved": "https://registry.npmmirror.com/ts-algebra/-/ts-algebra-2.0.0.tgz", @@ -4493,6 +6796,79 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmmirror.com/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmmirror.com/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.1.0", + "resolved": "https://registry.npmmirror.com/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmmirror.com/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz", @@ -4526,6 +6902,138 @@ "node": ">= 0.8" } }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmmirror.com/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmmirror.com/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vitepress": { + "version": "1.6.4", + "resolved": "https://registry.npmmirror.com/vitepress/-/vitepress-1.6.4.tgz", + "integrity": "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/css": "3.8.2", + "@docsearch/js": "3.8.2", + "@iconify-json/simple-icons": "^1.2.21", + "@shikijs/core": "^2.1.0", + "@shikijs/transformers": "^2.1.0", + "@shikijs/types": "^2.1.0", + "@types/markdown-it": "^14.1.2", + "@vitejs/plugin-vue": "^5.2.1", + "@vue/devtools-api": "^7.7.0", + "@vue/shared": "^3.5.13", + "@vueuse/core": "^12.4.0", + "@vueuse/integrations": "^12.4.0", + "focus-trap": "^7.6.4", + "mark.js": "8.11.1", + "minisearch": "^7.1.1", + "shiki": "^2.1.0", + "vite": "^5.4.14", + "vue": "^3.5.13" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4", + "postcss": "^8" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, "node_modules/vscode-jsonrpc": { "version": "8.2.1", "resolved": "https://registry.npmmirror.com/vscode-jsonrpc/-/vscode-jsonrpc-8.2.1.tgz", @@ -4541,6 +7049,28 @@ "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", "license": "MIT" }, + "node_modules/vue": { + "version": "3.5.32", + "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.32.tgz", + "integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.32", + "@vue/compiler-sfc": "3.5.32", + "@vue/runtime-dom": "3.5.32", + "@vue/server-renderer": "3.5.32", + "@vue/shared": "3.5.32" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/web-streams-polyfill": { "version": "3.3.3", "resolved": "https://registry.npmmirror.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", @@ -4793,6 +7323,17 @@ "peerDependencies": { "zod": "^3.25.28 || ^4" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmmirror.com/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/package.json b/package.json index b048d49a..6520e771 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,10 @@ }, "scripts": { "claude-haha": "bun run ./bin/claude-haha", - "start": "bun run ./bin/claude-haha" + "start": "bun run ./bin/claude-haha", + "docs:dev": "vitepress dev docs", + "docs:build": "vitepress build docs", + "docs:preview": "vitepress preview docs" }, "dependencies": { "@anthropic-ai/sandbox-runtime": "^0.0.44", @@ -73,5 +76,9 @@ "xss": "^1.0.15", "yaml": "^2.8.3", "zod": "^4.3.6" + }, + "devDependencies": { + "vitepress": "^1.6.3", + "vue": "^3.5.13" } }