chore(docs): remove non-e2e documentation
This commit is contained in:
parent
292e2b9454
commit
ecb0cd392e
47 changed files with 0 additions and 11844 deletions
|
|
@ -1,197 +0,0 @@
|
|||
# Agent Profile System
|
||||
|
||||
The Agent Profile system allows you to define and manage agent personalities, capabilities, and configurations. Each profile is a collection of markdown files and a JSON configuration file stored in a directory.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
~/.super-multica/agent-profiles/
|
||||
└── <profile-id>/
|
||||
├── soul.md # Personality constraints and behavior style
|
||||
├── identity.md # Agent's name and self-awareness
|
||||
├── tools.md # Custom tool usage instructions
|
||||
├── memory.md # Persistent knowledge base
|
||||
├── bootstrap.md # Guidance for each conversation start
|
||||
└── config.json # Profile configuration (tools, provider, model)
|
||||
```
|
||||
|
||||
## Profile Files
|
||||
|
||||
### soul.md
|
||||
Defines the agent's personality constraints and behavior boundaries.
|
||||
|
||||
```markdown
|
||||
# Soul
|
||||
|
||||
You are a helpful AI assistant. Follow these guidelines:
|
||||
|
||||
- Be concise and direct in your responses
|
||||
- Ask clarifying questions when requirements are ambiguous
|
||||
- Admit when you don't know something
|
||||
```
|
||||
|
||||
### identity.md
|
||||
Contains the agent's identity information.
|
||||
|
||||
```markdown
|
||||
# Identity
|
||||
|
||||
- Name: CodeBot
|
||||
- Role: Software development assistant
|
||||
```
|
||||
|
||||
### tools.md
|
||||
Custom instructions for tool usage (appended to the system prompt).
|
||||
|
||||
### memory.md
|
||||
Persistent knowledge base that survives across conversations.
|
||||
|
||||
### bootstrap.md
|
||||
Guidance information provided at the start of each conversation.
|
||||
|
||||
### config.json
|
||||
JSON configuration for the profile:
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"profile": "coding",
|
||||
"allow": ["web_fetch"],
|
||||
"deny": ["exec"]
|
||||
},
|
||||
"provider": "anthropic",
|
||||
"model": "claude-sonnet-4-20250514",
|
||||
"thinkingLevel": "medium"
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### tools
|
||||
Tool policy configuration. See [Tools README](../tools/README.md) for details.
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `profile` | string | Base profile: `minimal`, `coding`, `web`, `full` |
|
||||
| `allow` | string[] | Additional tools to allow (supports `group:*` syntax) |
|
||||
| `deny` | string[] | Tools to block (takes precedence over allow) |
|
||||
| `byProvider` | object | Provider-specific tool rules |
|
||||
|
||||
Example configurations:
|
||||
|
||||
```json
|
||||
// Minimal - only file operations
|
||||
{
|
||||
"tools": {
|
||||
"profile": "minimal",
|
||||
"allow": ["group:fs"]
|
||||
}
|
||||
}
|
||||
|
||||
// Coding without web access
|
||||
{
|
||||
"tools": {
|
||||
"profile": "coding",
|
||||
"deny": ["group:web"]
|
||||
}
|
||||
}
|
||||
|
||||
// Full access except shell execution
|
||||
{
|
||||
"tools": {
|
||||
"deny": ["exec", "process"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### provider
|
||||
Default LLM provider for this profile.
|
||||
|
||||
### model
|
||||
Default model ID for this profile.
|
||||
|
||||
### thinkingLevel
|
||||
Default thinking level: `none`, `low`, `medium`, `high`.
|
||||
|
||||
## Usage
|
||||
|
||||
### CLI
|
||||
|
||||
```bash
|
||||
# Use a specific profile
|
||||
pnpm agent:cli --profile my-agent "Hello"
|
||||
|
||||
# Profile with custom base directory
|
||||
pnpm agent:cli --profile my-agent --profile-dir /path/to/profiles "Hello"
|
||||
```
|
||||
|
||||
### Programmatic
|
||||
|
||||
```typescript
|
||||
import { ProfileManager } from "./profile/index.js";
|
||||
|
||||
// Load existing profile
|
||||
const manager = new ProfileManager({
|
||||
profileId: "my-agent",
|
||||
baseDir: "/custom/path", // optional
|
||||
});
|
||||
|
||||
// Get profile (returns undefined if not exists)
|
||||
const profile = manager.getProfile();
|
||||
|
||||
// Get or create with defaults
|
||||
const profile = manager.getOrCreateProfile(true); // useTemplates
|
||||
|
||||
// Build system prompt from profile
|
||||
const systemPrompt = manager.buildSystemPrompt();
|
||||
|
||||
// Get tools configuration
|
||||
const toolsConfig = manager.getToolsConfig();
|
||||
|
||||
// Get full profile config
|
||||
const config = manager.getProfileConfig();
|
||||
```
|
||||
|
||||
## Config Priority
|
||||
|
||||
When using a profile, configurations are merged with CLI options:
|
||||
|
||||
1. **Profile config.json** - Base configuration
|
||||
2. **CLI options** - Override profile settings
|
||||
|
||||
```bash
|
||||
# Profile has tools.profile = "coding"
|
||||
# CLI adds --tools-deny exec
|
||||
# Result: coding profile without exec tool
|
||||
pnpm agent:cli --profile my-agent --tools-deny exec "list files"
|
||||
```
|
||||
|
||||
The merge behavior:
|
||||
- `profile`: CLI wins if specified
|
||||
- `allow`: Union of both lists
|
||||
- `deny`: Union of both lists
|
||||
- `byProvider`: Deep merge with CLI taking precedence
|
||||
|
||||
## Creating a Profile
|
||||
|
||||
### Manual Creation
|
||||
|
||||
1. Create directory: `mkdir -p ~/.super-multica/agent-profiles/my-agent`
|
||||
2. Create markdown files (soul.md, identity.md, etc.)
|
||||
3. Create config.json with your settings
|
||||
|
||||
### Programmatic Creation
|
||||
|
||||
```typescript
|
||||
import { createAgentProfile } from "./profile/index.js";
|
||||
|
||||
// Create with default templates
|
||||
const profile = createAgentProfile("my-agent", {
|
||||
useTemplates: true, // Fill with default content
|
||||
});
|
||||
|
||||
// Create empty profile
|
||||
const profile = createAgentProfile("minimal-agent", {
|
||||
useTemplates: false,
|
||||
});
|
||||
```
|
||||
|
|
@ -1,438 +0,0 @@
|
|||
# Skills System
|
||||
|
||||
[English](./README.md) | [中文](./README.zh-CN.md)
|
||||
|
||||
Skills extend agent capabilities through `SKILL.md` definition files.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [SKILL.md Specification](#skillmd-specification)
|
||||
- [Skill Invocation](#skill-invocation)
|
||||
- [Loading & Precedence](#loading--precedence)
|
||||
- [CLI Commands](#cli-commands)
|
||||
|
||||
---
|
||||
|
||||
## SKILL.md Specification
|
||||
|
||||
Each skill is a directory containing a `SKILL.md` file with YAML frontmatter + Markdown content.
|
||||
|
||||
### Basic Structure
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: My Skill
|
||||
version: 1.0.0
|
||||
description: What this skill does
|
||||
metadata:
|
||||
emoji: "🔧"
|
||||
requires:
|
||||
bins: [git]
|
||||
---
|
||||
|
||||
# Instructions
|
||||
|
||||
Detailed instructions injected into the agent's system prompt...
|
||||
```
|
||||
|
||||
### Frontmatter Fields
|
||||
|
||||
| Field | Type | Required | Description |
|
||||
|-------|------|----------|-------------|
|
||||
| `name` | string | Yes | Display name |
|
||||
| `version` | string | No | Version number |
|
||||
| `description` | string | No | Short description |
|
||||
| `homepage` | string | No | Homepage URL |
|
||||
| `metadata` | object | No | See below |
|
||||
| `config` | object | No | See below |
|
||||
| `install` | array | No | See below |
|
||||
|
||||
### metadata.requires
|
||||
|
||||
Defines eligibility requirements:
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
emoji: "📝"
|
||||
requires:
|
||||
bins: [git, node] # All must exist
|
||||
anyBins: [npm, pnpm] # At least one must exist
|
||||
env: [API_KEY] # All must be set
|
||||
platforms: [darwin, linux] # Current OS must match
|
||||
```
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `bins` | Required binaries (all must exist in PATH) |
|
||||
| `anyBins` | Alternative binaries (at least one must exist) |
|
||||
| `env` | Required environment variables |
|
||||
| `platforms` | Supported platforms: `darwin`, `linux`, `win32` |
|
||||
|
||||
### config
|
||||
|
||||
Runtime configuration options:
|
||||
|
||||
```yaml
|
||||
config:
|
||||
enabled: true
|
||||
requiresConfig: ["skills.myskill.apiKey"]
|
||||
options:
|
||||
timeout: 30000
|
||||
```
|
||||
|
||||
### install
|
||||
|
||||
Dependency installation specifications:
|
||||
|
||||
```yaml
|
||||
install:
|
||||
- kind: brew
|
||||
package: jq
|
||||
|
||||
- kind: npm
|
||||
package: typescript
|
||||
global: true
|
||||
|
||||
- kind: uv
|
||||
package: requests
|
||||
|
||||
- kind: go
|
||||
package: github.com/example/tool@latest
|
||||
|
||||
- kind: download
|
||||
url: https://example.com/tool.tar.gz
|
||||
archiveType: tar.gz
|
||||
stripComponents: 1
|
||||
```
|
||||
|
||||
**Supported install kinds:**
|
||||
|
||||
| Kind | Description | Key Fields |
|
||||
|------|-------------|------------|
|
||||
| `brew` | Homebrew | `package`, `cask` |
|
||||
| `npm` | npm/pnpm/yarn | `package`, `global` |
|
||||
| `uv` | Python uv | `package` |
|
||||
| `go` | Go install | `package` |
|
||||
| `download` | Download & extract | `url`, `archiveType` |
|
||||
|
||||
**Common fields:** `id`, `label`, `platforms`, `when`
|
||||
|
||||
---
|
||||
|
||||
## Skill Invocation
|
||||
|
||||
Skills can be invoked by users via slash commands (`/skill-name`) or automatically by the AI model.
|
||||
|
||||
### User Invocation
|
||||
|
||||
In the interactive CLI, type `/` followed by a skill name to invoke it:
|
||||
|
||||
```
|
||||
You: /pdf analyze report.pdf
|
||||
```
|
||||
|
||||
**Tab completion**: Type `/p` then press Tab to see matching skills like `/pdf`.
|
||||
|
||||
**List available skills**: Type `/help` to see all available skill commands.
|
||||
|
||||
### Invocation Control
|
||||
|
||||
Control how skills can be invoked using frontmatter fields:
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: My Skill
|
||||
user-invocable: true # Can be invoked via /command (default: true)
|
||||
disable-model-invocation: false # Include in AI prompt (default: false)
|
||||
---
|
||||
```
|
||||
|
||||
| Field | Default | Description |
|
||||
|-------|---------|-------------|
|
||||
| `user-invocable` | `true` | Enable `/command` invocation in CLI |
|
||||
| `disable-model-invocation` | `false` | If `true`, skill is hidden from AI's system prompt |
|
||||
|
||||
**Use cases:**
|
||||
|
||||
- **User-only skill** (`disable-model-invocation: true`): User can invoke via `/command`, but AI won't use it automatically
|
||||
- **AI-only skill** (`user-invocable: false`): AI can use it, but no `/command` available
|
||||
- **Disabled skill** (both `false`): Hidden from both user and AI
|
||||
|
||||
### Command Dispatch
|
||||
|
||||
For advanced integrations, skills can dispatch directly to tools:
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: PDF Tool
|
||||
command-dispatch: tool
|
||||
command-tool: pdf-processor
|
||||
command-arg-mode: raw
|
||||
---
|
||||
```
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `command-dispatch` | Set to `tool` to enable tool dispatch |
|
||||
| `command-tool` | Name of the tool to invoke |
|
||||
| `command-arg-mode` | How arguments are passed (`raw` = as-is) |
|
||||
|
||||
### Command Name Normalization
|
||||
|
||||
Skill names are normalized for command use:
|
||||
|
||||
- Converted to lowercase
|
||||
- Special characters replaced with underscores
|
||||
- Truncated to 32 characters max
|
||||
- Duplicate names get numeric suffixes (e.g., `pdf_2`)
|
||||
|
||||
---
|
||||
|
||||
## Loading & Precedence
|
||||
|
||||
Skills load from two sources with precedence (lowest to highest):
|
||||
|
||||
| Priority | Source | Path | Description |
|
||||
|----------|--------|------|-------------|
|
||||
| 1 | managed | `~/.super-multica/skills/` | Global skills (CLI-installed + bundled) |
|
||||
| 2 | profile | `~/.super-multica/agent-profiles/<id>/skills/` | Profile-specific skills |
|
||||
|
||||
Higher priority sources override skills with the same ID.
|
||||
|
||||
### Initialization
|
||||
|
||||
On first run, bundled skills are automatically copied to the managed directory (`~/.super-multica/skills/`). This makes them editable and allows users to customize or remove them.
|
||||
|
||||
### Adding Profile-Specific Skills
|
||||
|
||||
You can install skills directly to a profile using the `--profile` option:
|
||||
|
||||
```bash
|
||||
# Install skill to a specific profile
|
||||
multica skills add owner/repo --profile my-agent
|
||||
|
||||
# Install with force overwrite
|
||||
multica skills add owner/repo/skill-name --profile my-agent --force
|
||||
```
|
||||
|
||||
Alternatively, create them manually:
|
||||
|
||||
```bash
|
||||
# Create profile skills directory
|
||||
mkdir -p ~/.super-multica/agent-profiles/<profile-id>/skills/<skill-name>
|
||||
|
||||
# Create the SKILL.md file
|
||||
cat > ~/.super-multica/agent-profiles/<profile-id>/skills/<skill-name>/SKILL.md << 'EOF'
|
||||
---
|
||||
name: My Profile Skill
|
||||
version: 1.0.0
|
||||
description: A skill specific to this profile
|
||||
---
|
||||
|
||||
# Instructions
|
||||
|
||||
Your skill instructions here...
|
||||
EOF
|
||||
```
|
||||
|
||||
Profile skills automatically override managed skills with the same ID, allowing per-profile customization.
|
||||
|
||||
### Eligibility Filtering
|
||||
|
||||
After loading, skills are filtered by:
|
||||
|
||||
1. Platform check (`platforms`)
|
||||
2. Binary check (`bins`, `anyBins`)
|
||||
3. Environment check (`env`)
|
||||
4. Config check (`requiresConfig`)
|
||||
5. Enabled check (`config.enabled`)
|
||||
|
||||
Only skills passing all checks are marked as eligible.
|
||||
|
||||
---
|
||||
|
||||
## CLI Commands
|
||||
|
||||
All commands use the unified `multica` CLI (or `pnpm multica` during development).
|
||||
|
||||
### List Skills
|
||||
|
||||
```bash
|
||||
multica skills list # List all skills
|
||||
multica skills list -v # Verbose mode
|
||||
multica skills status # Summary status
|
||||
multica skills status <id> # Specific skill status
|
||||
```
|
||||
|
||||
### Install from GitHub
|
||||
|
||||
**Example: Installing from [anthropics/skills](https://github.com/anthropics/skills)**
|
||||
|
||||
The repository structure:
|
||||
```
|
||||
anthropics/skills/
|
||||
├── skills/
|
||||
│ ├── algorithmic-art/
|
||||
│ │ └── SKILL.md
|
||||
│ ├── brand-guidelines/
|
||||
│ │ └── SKILL.md
|
||||
│ ├── pdf/
|
||||
│ │ └── SKILL.md
|
||||
│ └── ... (16 skills total)
|
||||
```
|
||||
|
||||
Install the entire repository (all 16 skills):
|
||||
```bash
|
||||
multica skills add anthropics/skills
|
||||
# Installs to: ~/.super-multica/skills/skills/
|
||||
# All skills available: algorithmic-art, brand-guidelines, pdf, etc.
|
||||
```
|
||||
|
||||
Install a single skill only:
|
||||
```bash
|
||||
multica skills add anthropics/skills/skills/pdf
|
||||
# Installs to: ~/.super-multica/skills/pdf/
|
||||
# Only the pdf skill is installed
|
||||
```
|
||||
|
||||
Install from a specific branch or tag:
|
||||
```bash
|
||||
multica skills add anthropics/skills@main
|
||||
```
|
||||
|
||||
Using full URL:
|
||||
```bash
|
||||
multica skills add https://github.com/anthropics/skills
|
||||
multica skills add https://github.com/anthropics/skills/tree/main/skills/pdf
|
||||
```
|
||||
|
||||
Force overwrite existing:
|
||||
```bash
|
||||
multica skills add anthropics/skills --force
|
||||
```
|
||||
|
||||
**Supported formats:**
|
||||
|
||||
| Format | Example | Description |
|
||||
|--------|---------|-------------|
|
||||
| `owner/repo` | `anthropics/skills` | Clone entire repository |
|
||||
| `owner/repo/path` | `anthropics/skills/skills/pdf` | Single directory (sparse checkout) |
|
||||
| `owner/repo@ref` | `anthropics/skills@v1.0.0` | Specific branch or tag |
|
||||
| Full URL | `https://github.com/anthropics/skills` | GitHub URL |
|
||||
| Full URL + path | `https://github.com/.../tree/main/skills/pdf` | URL with specific path |
|
||||
|
||||
### Remove Skills
|
||||
|
||||
```bash
|
||||
multica skills remove <name> # Remove installed skill
|
||||
multica skills remove # List installed skills
|
||||
```
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
```bash
|
||||
multica skills install <id> # Install skill dependencies
|
||||
multica skills install <id> <install-id> # Specific install option
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Status Diagnostics
|
||||
|
||||
The `status` command provides detailed diagnostics for understanding why skills are or aren't eligible.
|
||||
|
||||
### Summary Status
|
||||
|
||||
```bash
|
||||
multica skills status # Show summary with grouping by issue type
|
||||
multica skills status -v # Verbose mode with hints
|
||||
```
|
||||
|
||||
Output shows:
|
||||
- Total/eligible/ineligible counts
|
||||
- Ineligible skills grouped by issue type (binary, env, platform, etc.)
|
||||
|
||||
### Detailed Skill Status
|
||||
|
||||
```bash
|
||||
multica skills status <skill-id>
|
||||
```
|
||||
|
||||
Output includes:
|
||||
- Basic skill info (name, version, source, path)
|
||||
- **Eligibility status** with detailed diagnostics
|
||||
- **Requirements checklist** showing which binaries/env vars are present
|
||||
- **Install options** with availability status
|
||||
- **Quick actions** with actionable hints to resolve issues
|
||||
|
||||
### Diagnostic Types
|
||||
|
||||
| Type | Description | Example Hint |
|
||||
|------|-------------|--------------|
|
||||
| `disabled` | Skill disabled in config | Enable via `skills.<id>.enabled: true` |
|
||||
| `not_in_allowlist` | Bundled skill not allowed | Add to `config.allowBundled` array |
|
||||
| `platform` | Platform mismatch | "Only works on: darwin, linux" |
|
||||
| `binary` | Missing required binary | "brew install git" |
|
||||
| `any_binary` | No alternative binary found | "Install any of: npm, pnpm, yarn" |
|
||||
| `env` | Missing environment variable | "export OPENAI_API_KEY=..." |
|
||||
| `config` | Missing config value | "Set config path: browser.enabled" |
|
||||
|
||||
---
|
||||
|
||||
## Async Serialization
|
||||
|
||||
The skills system uses async serialization to prevent concurrent operations from corrupting files or causing race conditions.
|
||||
|
||||
### How It Works
|
||||
|
||||
Operations with the same key are executed sequentially:
|
||||
|
||||
```typescript
|
||||
import { serialize, SerializeKeys } from "./skills/index.js";
|
||||
|
||||
// These will execute sequentially, not in parallel
|
||||
const p1 = serialize(SerializeKeys.skillAdd("my-skill"), () => addSkill(...));
|
||||
const p2 = serialize(SerializeKeys.skillAdd("my-skill"), () => addSkill(...));
|
||||
|
||||
// This runs in parallel (different key)
|
||||
const p3 = serialize(SerializeKeys.skillAdd("other-skill"), () => addSkill(...));
|
||||
```
|
||||
|
||||
### Built-in Serialization
|
||||
|
||||
The following operations are automatically serialized:
|
||||
- `addSkill()` - by skill name
|
||||
- `removeSkill()` - by skill name
|
||||
- `installSkill()` - by skill ID
|
||||
|
||||
### Utility Functions
|
||||
|
||||
```typescript
|
||||
import {
|
||||
isProcessing, // Check if key is being processed
|
||||
getQueueLength, // Get pending operations count
|
||||
getActiveKeys, // Get all active operation keys
|
||||
waitForKey, // Wait for key operations to complete
|
||||
waitForAll, // Wait for all operations
|
||||
} from "./skills/index.js";
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Skill not showing as eligible?**
|
||||
|
||||
Run `pnpm skills:cli status <skill-id>` to see detailed diagnostics with actionable hints.
|
||||
|
||||
**Override a bundled skill?**
|
||||
|
||||
Create a skill with the same ID in `~/.super-multica/skills/` or profile skills directory.
|
||||
|
||||
**Hot reload not working?**
|
||||
|
||||
Ensure `chokidar` is installed: `pnpm add chokidar`
|
||||
|
||||
**Concurrent operations causing issues?**
|
||||
|
||||
All add/remove/install operations are automatically serialized. If you're building custom integrations, use the `serialize()` function with appropriate keys.
|
||||
|
|
@ -1,438 +0,0 @@
|
|||
# Skills 系统
|
||||
|
||||
[English](./README.md) | [中文](./README.zh-CN.md)
|
||||
|
||||
Skills 通过 `SKILL.md` 定义文件扩展 Agent 的能力。
|
||||
|
||||
## 目录
|
||||
|
||||
- [SKILL.md 规范](#skillmd-规范)
|
||||
- [Skill 调用](#skill-调用)
|
||||
- [加载与优先级](#加载与优先级)
|
||||
- [CLI 命令](#cli-命令)
|
||||
|
||||
---
|
||||
|
||||
## SKILL.md 规范
|
||||
|
||||
每个 skill 是一个包含 `SKILL.md` 文件的目录,文件包含 YAML frontmatter 和 Markdown 内容。
|
||||
|
||||
### 基本结构
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: My Skill
|
||||
version: 1.0.0
|
||||
description: 这个 skill 的功能描述
|
||||
metadata:
|
||||
emoji: "🔧"
|
||||
requires:
|
||||
bins: [git]
|
||||
---
|
||||
|
||||
# 说明
|
||||
|
||||
注入到 agent 系统提示词中的详细说明...
|
||||
```
|
||||
|
||||
### Frontmatter 字段
|
||||
|
||||
| 字段 | 类型 | 必需 | 描述 |
|
||||
|------|------|------|------|
|
||||
| `name` | string | 是 | 显示名称 |
|
||||
| `version` | string | 否 | 版本号 |
|
||||
| `description` | string | 否 | 简短描述 |
|
||||
| `homepage` | string | 否 | 主页 URL |
|
||||
| `metadata` | object | 否 | 见下文 |
|
||||
| `config` | object | 否 | 见下文 |
|
||||
| `install` | array | 否 | 见下文 |
|
||||
|
||||
### metadata.requires
|
||||
|
||||
定义资格要求:
|
||||
|
||||
```yaml
|
||||
metadata:
|
||||
emoji: "📝"
|
||||
requires:
|
||||
bins: [git, node] # 全部必须存在
|
||||
anyBins: [npm, pnpm] # 至少一个必须存在
|
||||
env: [API_KEY] # 全部必须设置
|
||||
platforms: [darwin, linux] # 当前操作系统必须匹配
|
||||
```
|
||||
|
||||
| 字段 | 描述 |
|
||||
|------|------|
|
||||
| `bins` | 必需的二进制文件(全部必须存在于 PATH 中) |
|
||||
| `anyBins` | 备选二进制文件(至少一个必须存在) |
|
||||
| `env` | 必需的环境变量 |
|
||||
| `platforms` | 支持的平台:`darwin`、`linux`、`win32` |
|
||||
|
||||
### config
|
||||
|
||||
运行时配置选项:
|
||||
|
||||
```yaml
|
||||
config:
|
||||
enabled: true
|
||||
requiresConfig: ["skills.myskill.apiKey"]
|
||||
options:
|
||||
timeout: 30000
|
||||
```
|
||||
|
||||
### install
|
||||
|
||||
依赖安装规范:
|
||||
|
||||
```yaml
|
||||
install:
|
||||
- kind: brew
|
||||
package: jq
|
||||
|
||||
- kind: npm
|
||||
package: typescript
|
||||
global: true
|
||||
|
||||
- kind: uv
|
||||
package: requests
|
||||
|
||||
- kind: go
|
||||
package: github.com/example/tool@latest
|
||||
|
||||
- kind: download
|
||||
url: https://example.com/tool.tar.gz
|
||||
archiveType: tar.gz
|
||||
stripComponents: 1
|
||||
```
|
||||
|
||||
**支持的安装类型:**
|
||||
|
||||
| 类型 | 描述 | 关键字段 |
|
||||
|------|------|----------|
|
||||
| `brew` | Homebrew | `package`、`cask` |
|
||||
| `npm` | npm/pnpm/yarn | `package`、`global` |
|
||||
| `uv` | Python uv | `package` |
|
||||
| `go` | Go install | `package` |
|
||||
| `download` | 下载并解压 | `url`、`archiveType` |
|
||||
|
||||
**通用字段:** `id`、`label`、`platforms`、`when`
|
||||
|
||||
---
|
||||
|
||||
## Skill 调用
|
||||
|
||||
用户可以通过斜杠命令(`/skill-name`)调用 skills,AI 模型也可以自动调用。
|
||||
|
||||
### 用户调用
|
||||
|
||||
在交互式 CLI 中,输入 `/` 加上 skill 名称来调用:
|
||||
|
||||
```
|
||||
You: /pdf analyze report.pdf
|
||||
```
|
||||
|
||||
**Tab 补全**:输入 `/p` 然后按 Tab 键查看匹配的 skills,如 `/pdf`。
|
||||
|
||||
**列出可用 skills**:输入 `/help` 查看所有可用的 skill 命令。
|
||||
|
||||
### 调用控制
|
||||
|
||||
使用 frontmatter 字段控制 skill 的调用方式:
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: My Skill
|
||||
user-invocable: true # 可通过 /command 调用(默认:true)
|
||||
disable-model-invocation: false # 包含在 AI 提示词中(默认:false)
|
||||
---
|
||||
```
|
||||
|
||||
| 字段 | 默认值 | 描述 |
|
||||
|------|--------|------|
|
||||
| `user-invocable` | `true` | 在 CLI 中启用 `/command` 调用 |
|
||||
| `disable-model-invocation` | `false` | 如果为 `true`,skill 对 AI 的系统提示词隐藏 |
|
||||
|
||||
**使用场景:**
|
||||
|
||||
- **仅用户 skill**(`disable-model-invocation: true`):用户可通过 `/command` 调用,但 AI 不会自动使用
|
||||
- **仅 AI skill**(`user-invocable: false`):AI 可使用,但没有 `/command` 可用
|
||||
- **禁用 skill**(两者都为 `false`):对用户和 AI 都隐藏
|
||||
|
||||
### 命令分发
|
||||
|
||||
对于高级集成,skills 可以直接分发到工具:
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: PDF Tool
|
||||
command-dispatch: tool
|
||||
command-tool: pdf-processor
|
||||
command-arg-mode: raw
|
||||
---
|
||||
```
|
||||
|
||||
| 字段 | 描述 |
|
||||
|------|------|
|
||||
| `command-dispatch` | 设置为 `tool` 启用工具分发 |
|
||||
| `command-tool` | 要调用的工具名称 |
|
||||
| `command-arg-mode` | 参数传递方式(`raw` = 原样传递) |
|
||||
|
||||
### 命令名称规范化
|
||||
|
||||
Skill 名称会被规范化以用作命令:
|
||||
|
||||
- 转换为小写
|
||||
- 特殊字符替换为下划线
|
||||
- 截断至最多 32 个字符
|
||||
- 重复名称添加数字后缀(如 `pdf_2`)
|
||||
|
||||
---
|
||||
|
||||
## 加载与优先级
|
||||
|
||||
Skills 从两个来源加载,优先级从低到高:
|
||||
|
||||
| 优先级 | 来源 | 路径 | 描述 |
|
||||
|--------|------|------|------|
|
||||
| 1 | managed | `~/.super-multica/skills/` | 全局 skills(CLI 安装 + 内置) |
|
||||
| 2 | profile | `~/.super-multica/agent-profiles/<id>/skills/` | Profile 专属 skills |
|
||||
|
||||
高优先级来源会覆盖具有相同 ID 的 skills。
|
||||
|
||||
### 初始化
|
||||
|
||||
首次运行时,内置 skills 会自动复制到 managed 目录(`~/.super-multica/skills/`)。这使得用户可以编辑或删除它们。
|
||||
|
||||
### 添加 Profile 专属 Skills
|
||||
|
||||
可以使用 `--profile` 选项直接安装 skills 到特定 profile:
|
||||
|
||||
```bash
|
||||
# 安装 skill 到特定 profile
|
||||
multica skills add owner/repo --profile my-agent
|
||||
|
||||
# 强制覆盖安装
|
||||
multica skills add owner/repo/skill-name --profile my-agent --force
|
||||
```
|
||||
|
||||
也可以手动创建:
|
||||
|
||||
```bash
|
||||
# 创建 profile skills 目录
|
||||
mkdir -p ~/.super-multica/agent-profiles/<profile-id>/skills/<skill-name>
|
||||
|
||||
# 创建 SKILL.md 文件
|
||||
cat > ~/.super-multica/agent-profiles/<profile-id>/skills/<skill-name>/SKILL.md << 'EOF'
|
||||
---
|
||||
name: My Profile Skill
|
||||
version: 1.0.0
|
||||
description: 此 profile 专属的 skill
|
||||
---
|
||||
|
||||
# 说明
|
||||
|
||||
你的 skill 说明内容...
|
||||
EOF
|
||||
```
|
||||
|
||||
Profile skills 会自动覆盖同 ID 的 managed skills,允许按 profile 自定义。
|
||||
|
||||
### 资格过滤
|
||||
|
||||
加载后,skills 会按以下条件过滤:
|
||||
|
||||
1. 平台检查(`platforms`)
|
||||
2. 二进制文件检查(`bins`、`anyBins`)
|
||||
3. 环境变量检查(`env`)
|
||||
4. 配置检查(`requiresConfig`)
|
||||
5. 启用检查(`config.enabled`)
|
||||
|
||||
只有通过所有检查的 skills 才会被标记为符合条件。
|
||||
|
||||
---
|
||||
|
||||
## CLI 命令
|
||||
|
||||
所有命令使用统一的 `multica` CLI(开发时使用 `pnpm multica`)。
|
||||
|
||||
### 列出 Skills
|
||||
|
||||
```bash
|
||||
multica skills list # 列出所有 skills
|
||||
multica skills list -v # 详细模式
|
||||
multica skills status # 汇总状态
|
||||
multica skills status <id> # 特定 skill 状态
|
||||
```
|
||||
|
||||
### 从 GitHub 安装
|
||||
|
||||
**示例:从 [anthropics/skills](https://github.com/anthropics/skills) 安装**
|
||||
|
||||
仓库结构:
|
||||
```
|
||||
anthropics/skills/
|
||||
├── skills/
|
||||
│ ├── algorithmic-art/
|
||||
│ │ └── SKILL.md
|
||||
│ ├── brand-guidelines/
|
||||
│ │ └── SKILL.md
|
||||
│ ├── pdf/
|
||||
│ │ └── SKILL.md
|
||||
│ └── ... (共 16 个 skills)
|
||||
```
|
||||
|
||||
安装整个仓库(所有 16 个 skills):
|
||||
```bash
|
||||
multica skills add anthropics/skills
|
||||
# 安装到:~/.super-multica/skills/skills/
|
||||
# 所有 skills 可用:algorithmic-art、brand-guidelines、pdf 等
|
||||
```
|
||||
|
||||
只安装单个 skill:
|
||||
```bash
|
||||
multica skills add anthropics/skills/skills/pdf
|
||||
# 安装到:~/.super-multica/skills/pdf/
|
||||
# 只安装 pdf skill
|
||||
```
|
||||
|
||||
从特定分支或标签安装:
|
||||
```bash
|
||||
multica skills add anthropics/skills@main
|
||||
```
|
||||
|
||||
使用完整 URL:
|
||||
```bash
|
||||
multica skills add https://github.com/anthropics/skills
|
||||
multica skills add https://github.com/anthropics/skills/tree/main/skills/pdf
|
||||
```
|
||||
|
||||
强制覆盖现有:
|
||||
```bash
|
||||
multica skills add anthropics/skills --force
|
||||
```
|
||||
|
||||
**支持的格式:**
|
||||
|
||||
| 格式 | 示例 | 描述 |
|
||||
|------|------|------|
|
||||
| `owner/repo` | `anthropics/skills` | 克隆整个仓库 |
|
||||
| `owner/repo/path` | `anthropics/skills/skills/pdf` | 单个目录(稀疏检出) |
|
||||
| `owner/repo@ref` | `anthropics/skills@v1.0.0` | 特定分支或标签 |
|
||||
| 完整 URL | `https://github.com/anthropics/skills` | GitHub URL |
|
||||
| 完整 URL + 路径 | `https://github.com/.../tree/main/skills/pdf` | 带特定路径的 URL |
|
||||
|
||||
### 移除 Skills
|
||||
|
||||
```bash
|
||||
multica skills remove <name> # 移除已安装的 skill
|
||||
multica skills remove # 列出已安装的 skills
|
||||
```
|
||||
|
||||
### 安装依赖
|
||||
|
||||
```bash
|
||||
multica skills install <id> # 安装 skill 依赖
|
||||
multica skills install <id> <install-id> # 特定安装选项
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 状态诊断
|
||||
|
||||
`status` 命令提供详细的诊断信息,帮助了解 skills 为何符合或不符合条件。
|
||||
|
||||
### 汇总状态
|
||||
|
||||
```bash
|
||||
multica skills status # 显示按问题类型分组的汇总
|
||||
multica skills status -v # 详细模式带提示
|
||||
```
|
||||
|
||||
输出显示:
|
||||
- 总计/符合条件/不符合条件计数
|
||||
- 按问题类型分组的不符合条件 skills(binary、env、platform 等)
|
||||
|
||||
### 详细 Skill 状态
|
||||
|
||||
```bash
|
||||
multica skills status <skill-id>
|
||||
```
|
||||
|
||||
输出包括:
|
||||
- 基本 skill 信息(名称、版本、来源、路径)
|
||||
- **资格状态**及详细诊断
|
||||
- **要求检查表**显示哪些二进制文件/环境变量存在
|
||||
- **安装选项**及可用性状态
|
||||
- **快速操作**及可操作的提示
|
||||
|
||||
### 诊断类型
|
||||
|
||||
| 类型 | 描述 | 示例提示 |
|
||||
|------|------|----------|
|
||||
| `disabled` | Skill 在配置中禁用 | 通过 `skills.<id>.enabled: true` 启用 |
|
||||
| `not_in_allowlist` | 内置 skill 不在允许列表中 | 添加到 `config.allowBundled` 数组 |
|
||||
| `platform` | 平台不匹配 | "仅支持:darwin、linux" |
|
||||
| `binary` | 缺少必需的二进制文件 | "brew install git" |
|
||||
| `any_binary` | 未找到备选二进制文件 | "安装任一:npm、pnpm、yarn" |
|
||||
| `env` | 缺少环境变量 | "export OPENAI_API_KEY=..." |
|
||||
| `config` | 缺少配置值 | "设置配置路径:browser.enabled" |
|
||||
|
||||
---
|
||||
|
||||
## 异步序列化
|
||||
|
||||
Skills 系统使用异步序列化来防止并发操作损坏文件或导致竞态条件。
|
||||
|
||||
### 工作原理
|
||||
|
||||
具有相同键的操作按顺序执行:
|
||||
|
||||
```typescript
|
||||
import { serialize, SerializeKeys } from "./skills/index.js";
|
||||
|
||||
// 这些将按顺序执行,而非并行
|
||||
const p1 = serialize(SerializeKeys.skillAdd("my-skill"), () => addSkill(...));
|
||||
const p2 = serialize(SerializeKeys.skillAdd("my-skill"), () => addSkill(...));
|
||||
|
||||
// 这个并行运行(不同的键)
|
||||
const p3 = serialize(SerializeKeys.skillAdd("other-skill"), () => addSkill(...));
|
||||
```
|
||||
|
||||
### 内置序列化
|
||||
|
||||
以下操作自动序列化:
|
||||
- `addSkill()` - 按 skill 名称
|
||||
- `removeSkill()` - 按 skill 名称
|
||||
- `installSkill()` - 按 skill ID
|
||||
|
||||
### 工具函数
|
||||
|
||||
```typescript
|
||||
import {
|
||||
isProcessing, // 检查键是否正在处理
|
||||
getQueueLength, // 获取待处理操作数量
|
||||
getActiveKeys, // 获取所有活动操作键
|
||||
waitForKey, // 等待键操作完成
|
||||
waitForAll, // 等待所有操作
|
||||
} from "./skills/index.js";
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 故障排除
|
||||
|
||||
**Skill 未显示为符合条件?**
|
||||
|
||||
运行 `multica skills status <skill-id>` 查看详细诊断及可操作的提示。
|
||||
|
||||
**覆盖内置 skill?**
|
||||
|
||||
在 `~/.super-multica/skills/` 或配置文件 skills 目录中创建具有相同 ID 的 skill。
|
||||
|
||||
**热重载不工作?**
|
||||
|
||||
确保安装了 `chokidar`:`pnpm add chokidar`
|
||||
|
||||
**并发操作导致问题?**
|
||||
|
||||
所有 add/remove/install 操作都会自动序列化。如果你在构建自定义集成,请使用 `serialize()` 函数并使用适当的键。
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
# Subagent System
|
||||
|
||||
The subagent system allows a parent agent to spawn isolated child agents that run tasks in parallel and report results back automatically.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Parent Agent (runner.ts) │
|
||||
│ │
|
||||
│ tools: sessions_spawn, sessions_list │
|
||||
│ state: resolvedProvider, toolsOptions │
|
||||
└──────────┬──────────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ sessions_spawn(task, label, timeoutSeconds)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Spawn Flow (sessions-spawn.ts) │
|
||||
│ │
|
||||
│ 1. Build subagent system prompt (announce.ts) │
|
||||
│ 2. hub.createSubagent(childSessionId, { provider, model }) │
|
||||
│ 3. registerSubagentRun({ start: () => childAgent.write(task) }) │
|
||||
│ 4. Return { status: "accepted", runId, childSessionId } │
|
||||
└──────────┬──────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Concurrency Queue (command-queue.ts) │
|
||||
│ │
|
||||
│ Lane: "subagent" — max 10 concurrent (configurable) │
|
||||
│ Queued runs wait for a slot before start() is called │
|
||||
└──────────┬──────────────────────────────────────────────────────────┘
|
||||
│ slot acquired
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Child Agent Execution │
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────────────┐ │
|
||||
│ │ AsyncAgent (async-agent.ts) │ │
|
||||
│ │ - Isolated session with restricted tools (isSubagent=true) │ │
|
||||
│ │ - Inherits parent's LLM provider │ │
|
||||
│ │ - System prompt: task focus + error reporting rules │ │
|
||||
│ │ - Tracks lastRunError for error propagation │ │
|
||||
│ └───────────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌───────────────────────────────────────────────────────────────┐ │
|
||||
│ │ watchChildAgent (registry.ts) │ │
|
||||
│ │ - Sets startedAt, starts timeout timer │ │
|
||||
│ │ - waitForIdle() — waits for child's task queue to drain │ │
|
||||
│ │ - onClose() — handles explicit close (timeout kill, etc.) │ │
|
||||
│ └───────────────────────────────────────────────────────────────┘ │
|
||||
└──────────┬──────────────────────────────────────────────────────────┘
|
||||
│
|
||||
│ child completes / errors / times out
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Completion Handling (registry.ts) │
|
||||
│ │
|
||||
│ handleRunCompletion(record) │
|
||||
│ │ │
|
||||
│ ├─ Phase 1: captureFindings() │
|
||||
│ │ - Read last assistant reply from child session JSONL │
|
||||
│ │ - Falls back to last toolResult if no assistant text │
|
||||
│ │ - Persists findings to record before session deletion │
|
||||
│ │ │
|
||||
│ ├─ Session Cleanup │
|
||||
│ │ - cleanup="delete": rm child session dir + hub.closeAgent() │
|
||||
│ │ - cleanup="keep": preserve for audit │
|
||||
│ │ │
|
||||
│ └─ Phase 2: checkAndAnnounce(requesterSessionId) │
|
||||
│ - Finds all unannounced, completed runs with findings │
|
||||
│ - Calls runCoalescedAnnounceFlow() │
|
||||
│ - Marks records: announced=true, archiveAtMs=now+60min │
|
||||
└──────────┬──────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Announcement Delivery (announce.ts) │
|
||||
│ │
|
||||
│ runCoalescedAnnounceFlow(requesterSessionId, records) │
|
||||
│ │ │
|
||||
│ ├─ Format message: formatCoalescedAnnouncementMessage() │
|
||||
│ │ - Single record: task name, status, findings, stats │
|
||||
│ │ - Multiple records: combined report with all findings │
|
||||
│ │ │
|
||||
│ ├─ Two-tier delivery: │
|
||||
│ │ │
|
||||
│ │ Tier 1: BUSY (parent running or has pending writes) │
|
||||
│ │ └─ enqueueAnnounce() → announce-queue.ts │
|
||||
│ │ - Debounce 1s to batch nearby completions │
|
||||
│ │ - Drain via writeInternal() when parent finishes │
|
||||
│ │ │
|
||||
│ │ Tier 2: IDLE (parent not running) │
|
||||
│ │ └─ sendAnnounceDirect() │
|
||||
│ │ - writeInternal(msg, { forwardAssistant, persistResponse })│
|
||||
│ │ │
|
||||
│ └─ All delivery uses writeInternal() (marks as internal: true) │
|
||||
│ → Prevents announcement from showing as user bubble in UI │
|
||||
│ → LLM processes findings and responds naturally to user │
|
||||
└──────────┬──────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Record Lifecycle (registry.ts) │
|
||||
│ │
|
||||
│ created → startedAt → endedAt → findingsCaptured → announced │
|
||||
│ │
|
||||
│ After announcement: │
|
||||
│ - Record kept with archiveAtMs = now + 60 min │
|
||||
│ - sessions_list can still query records during this window │
|
||||
│ - Sweeper runs every 60s, removes expired records │
|
||||
│ - When all records removed, sweeper stops │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Key Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `sessions-spawn.ts` | Tool: spawns a child agent with task, label, timeout, provider |
|
||||
| `sessions-list.ts` | Tool: lists subagent runs and their status |
|
||||
| `registry.ts` | Lifecycle management: register, watch, capture, announce, archive |
|
||||
| `announce.ts` | System prompt builder, findings reader, message formatter, delivery |
|
||||
| `announce-queue.ts` | Debounced queue for batching announcements when parent is busy |
|
||||
| `command-queue.ts` | Concurrency limiter for subagent lane slots |
|
||||
| `lanes.ts` | Lane config: max concurrency (10), default timeout (1800s) |
|
||||
| `types.ts` | Shared types: SubagentRunRecord, SubagentRunOutcome, etc. |
|
||||
| `registry-store.ts` | Persistence: save/load runs to disk for crash recovery |
|
||||
|
||||
## Provider Inheritance
|
||||
|
||||
Subagents inherit the parent's resolved LLM provider:
|
||||
|
||||
```
|
||||
runner.ts (resolvedProvider)
|
||||
→ toolsOptions.provider
|
||||
→ tools.ts (CreateToolsOptions.provider)
|
||||
→ sessions-spawn.ts (options.provider)
|
||||
→ hub.createSubagent({ provider })
|
||||
```
|
||||
|
||||
When the user switches providers via UI (`setProvider()`), `toolsOptions.provider` is updated in sync so future spawns use the new provider.
|
||||
|
||||
## Error Propagation
|
||||
|
||||
```
|
||||
Child tool error (e.g., API 401)
|
||||
→ Subagent LLM sees error, includes in final message (system prompt rule)
|
||||
→ captureFindings() reads final message
|
||||
→ Announcement includes error in findings
|
||||
→ Parent LLM sees error and can inform user
|
||||
|
||||
Child run error (e.g., missing API key for provider)
|
||||
→ AsyncAgent._lastRunError set
|
||||
→ registry.ts checks childAgent.lastRunError after waitForIdle()
|
||||
→ outcome = { status: "error", error: "No API key configured..." }
|
||||
→ Announcement: "task failed: No API key configured..."
|
||||
```
|
||||
|
||||
## Timeout Behavior
|
||||
|
||||
Default: 1800s (30 min). System prompt guides the parent LLM:
|
||||
- Simple tasks: 1800s (default)
|
||||
- Moderate tasks: 1800-2400s (30-40 min)
|
||||
- Complex tasks: 2400-3600s (40-60 min)
|
||||
|
||||
On timeout:
|
||||
1. Timeout timer fires in `watchChildAgent()`
|
||||
2. `cleanup({ status: "timeout" })` is called
|
||||
3. Child agent is closed via `hub.closeAgent()`
|
||||
4. Findings are captured from whatever the child wrote so far
|
||||
5. Announcement reports "timed out" with partial findings
|
||||
|
|
@ -1,266 +0,0 @@
|
|||
# Tools System
|
||||
|
||||
[中文文档](./README.zh-CN.md)
|
||||
|
||||
The tools system provides LLM agents with capabilities to interact with the external world. Tools are the "hands and feet" of an agent - without tools, an LLM can only generate text responses.
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Tool Definition │
|
||||
│ (AgentTool from @mariozechner/pi-agent-core) │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ name │ │ description │ │ parameters │ │
|
||||
│ │ label │ │ execute │ │ (TypeBox) │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 3-Layer Policy Filter │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||
│ │ Layer 1: Global Allow/Deny │ │
|
||||
│ │ User customization via CLI or config │ │
|
||||
│ └──────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||
│ │ Layer 2: Provider-Specific │ │
|
||||
│ │ Different rules for different LLM providers │ │
|
||||
│ └──────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||
│ │ Layer 3: Subagent Restrictions │ │
|
||||
│ │ Limited tools for spawned child agents │ │
|
||||
│ └──────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Filtered Tools │
|
||||
│ (passed to pi-agent-core) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Available Tools
|
||||
|
||||
| Tool | Name | Description |
|
||||
| -------------- | ---------------- | ----------------------------------- |
|
||||
| Read | `read` | Read file contents |
|
||||
| Write | `write` | Write content to files |
|
||||
| Edit | `edit` | Edit existing files |
|
||||
| Glob | `glob` | Find files by pattern |
|
||||
| Exec | `exec` | Execute shell commands |
|
||||
| Process | `process` | Manage long-running processes |
|
||||
| Web Fetch | `web_fetch` | Fetch and extract content from URLs |
|
||||
| Web Search | `web_search` | Search the web via Devv Search |
|
||||
| Sessions Spawn | `sessions_spawn` | Spawn a sub-agent session |
|
||||
|
||||
> **Note**: Agents use file-based memory (`memory.md`, `memory/*.md`) via `read` and `edit` tools instead of dedicated memory tools.
|
||||
|
||||
## Tool Groups
|
||||
|
||||
Groups provide shortcuts for allowing/denying multiple tools at once:
|
||||
|
||||
| Group | Tools |
|
||||
| ---------------- | ------------------------------------ |
|
||||
| `group:fs` | read, write, edit, glob |
|
||||
| `group:runtime` | exec, process |
|
||||
| `group:web` | web_search, web_fetch |
|
||||
| `group:subagent` | sessions_spawn |
|
||||
| `group:core` | All fs, runtime, and web tools |
|
||||
|
||||
## Usage
|
||||
|
||||
### CLI Usage
|
||||
|
||||
All commands use the unified `multica` CLI (or `pnpm multica` during development).
|
||||
|
||||
```bash
|
||||
# Allow only specific tools
|
||||
multica run --tools-allow group:fs,group:runtime "list files"
|
||||
|
||||
# Deny specific tools
|
||||
multica run --tools-deny exec,process "read file.txt"
|
||||
|
||||
# Use tool groups
|
||||
multica run --tools-allow group:fs "read config.json"
|
||||
```
|
||||
|
||||
### Programmatic Usage
|
||||
|
||||
```typescript
|
||||
import { Agent } from './runner.js';
|
||||
|
||||
const agent = new Agent({
|
||||
tools: {
|
||||
// Layer 1: Global allow/deny
|
||||
allow: ['group:fs', 'group:runtime', 'web_fetch'],
|
||||
deny: ['exec'],
|
||||
|
||||
// Layer 2: Provider-specific rules
|
||||
byProvider: {
|
||||
google: {
|
||||
deny: ['exec', 'process'], // Google models can't use runtime tools
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Layer 3: Subagent mode
|
||||
isSubagent: false,
|
||||
});
|
||||
```
|
||||
|
||||
### Inspecting Tool Configuration
|
||||
|
||||
Use the tools CLI to inspect and test configurations:
|
||||
|
||||
```bash
|
||||
# List all available tools
|
||||
multica tools list
|
||||
|
||||
# List tools with allow rules
|
||||
multica tools list --allow group:fs,group:runtime
|
||||
|
||||
# List tools with deny rules
|
||||
multica tools list --deny exec
|
||||
|
||||
# Show all tool groups
|
||||
multica tools groups
|
||||
```
|
||||
|
||||
## Policy System Details
|
||||
|
||||
### Layer 1: Global Allow/Deny
|
||||
|
||||
User-specified allow/deny lists:
|
||||
|
||||
- `allow`: Only these tools are available (supports group:\* syntax)
|
||||
- `deny`: These tools are blocked (takes precedence over allow)
|
||||
|
||||
If no `allow` list is specified, all tools are available by default.
|
||||
|
||||
### Layer 2: Provider-Specific
|
||||
|
||||
Different LLM providers may have different capabilities or restrictions:
|
||||
|
||||
```typescript
|
||||
{
|
||||
byProvider: {
|
||||
google: { deny: ["exec"] }, // Gemini can't execute commands
|
||||
anthropic: { allow: ["*"] }, // Claude has full access
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Layer 3: Subagent Restrictions
|
||||
|
||||
When `isSubagent: true`, additional restrictions are applied to prevent spawned agents from accessing sensitive tools like session management.
|
||||
|
||||
## Adding New Tools
|
||||
|
||||
1. Create a new file in `src/agent/tools/` (e.g., `my-tool.ts`)
|
||||
|
||||
2. Define the tool using TypeBox for the schema:
|
||||
|
||||
```typescript
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import type { AgentTool } from '@mariozechner/pi-agent-core';
|
||||
|
||||
const MyToolSchema = Type.Object({
|
||||
param1: Type.String({ description: 'Parameter description' }),
|
||||
param2: Type.Optional(Type.Number()),
|
||||
});
|
||||
|
||||
export function createMyTool(): AgentTool<typeof MyToolSchema> {
|
||||
return {
|
||||
name: 'my_tool',
|
||||
label: 'My Tool',
|
||||
description: 'What this tool does',
|
||||
parameters: MyToolSchema,
|
||||
execute: async (toolCallId, args) => {
|
||||
// Implementation
|
||||
return { result: 'success' };
|
||||
},
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
3. Register the tool in `src/agent/tools.ts`:
|
||||
|
||||
```typescript
|
||||
import { createMyTool } from './tools/my-tool.js';
|
||||
|
||||
export function createAllTools(cwd: string): AgentTool<any>[] {
|
||||
// ... existing tools
|
||||
const myTool = createMyTool();
|
||||
|
||||
return [
|
||||
...baseTools,
|
||||
myTool as AgentTool<any>,
|
||||
// ...
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
4. Add the tool to appropriate groups in `groups.ts`:
|
||||
|
||||
```typescript
|
||||
export const TOOL_GROUPS: Record<string, string[]> = {
|
||||
'group:my_category': ['my_tool', 'other_tool'],
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Run the policy system tests:
|
||||
|
||||
```bash
|
||||
pnpm test src/agent/tools/policy.test.ts
|
||||
```
|
||||
|
||||
## Agent Profile Integration
|
||||
|
||||
Tools configuration can be defined in Agent Profile's `config.json`, allowing different agents to have different tool capabilities:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Super Multica Hub │
|
||||
│ │
|
||||
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
|
||||
│ │ Agent A │ │ Agent B │ │ Agent C │ │
|
||||
│ │ Profile: │ │ Profile: │ │ Profile: │ │
|
||||
│ │ coder │ │ reviewer │ │ devops │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ tools: │ │ tools: │ │ tools: │ │
|
||||
│ │ allow:fs │ │ deny:* │ │ allow:* │ │
|
||||
│ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │
|
||||
│ │ │ │ │
|
||||
└─────────┼────────────────┼────────────────┼─────────────────────┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ Client │ │ Client │ │ Client │
|
||||
└──────────┘ └──────────┘ └──────────┘
|
||||
```
|
||||
|
||||
Each Agent's Profile can define its own tools configuration in `config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"allow": ["group:fs", "group:runtime"],
|
||||
"deny": ["exec"]
|
||||
},
|
||||
"provider": "anthropic",
|
||||
"model": "claude-sonnet-4-20250514"
|
||||
}
|
||||
```
|
||||
|
||||
See [Profile README](../profile/README.md) for full documentation.
|
||||
|
|
@ -1,268 +0,0 @@
|
|||
# 工具系统
|
||||
|
||||
[English](./README.md)
|
||||
|
||||
工具系统为 LLM Agent 提供与外部世界交互的能力。工具是 Agent 的"手和脚"——没有工具,LLM 只能生成文本响应。
|
||||
|
||||
## 架构概览
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 工具定义 │
|
||||
│ (AgentTool from @mariozechner/pi-agent-core) │
|
||||
│ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ name │ │ description │ │ parameters │ │
|
||||
│ │ label │ │ execute │ │ (TypeBox) │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 3 层策略过滤器 │
|
||||
│ │
|
||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||
│ │ 第 1 层: 全局 Allow/Deny │ │
|
||||
│ │ 通过 CLI 或配置文件进行用户自定义 │ │
|
||||
│ └──────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||
│ │ 第 2 层: Provider 特定规则 │ │
|
||||
│ │ 不同 LLM Provider 有不同的规则 │ │
|
||||
│ └──────────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────────────────────────────────────────────────┐ │
|
||||
│ │ 第 3 层: Subagent 限制 │ │
|
||||
│ │ 子 Agent 的工具访问受限 │ │
|
||||
│ └──────────────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 过滤后的工具 │
|
||||
│ (传递给 pi-agent-core) │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 可用工具
|
||||
|
||||
| 工具 | 名称 | 描述 |
|
||||
| -------------- | ---------------- | ------------------------------ |
|
||||
| Read | `read` | 读取文件内容 |
|
||||
| Write | `write` | 写入文件内容 |
|
||||
| Edit | `edit` | 编辑现有文件 |
|
||||
| Glob | `glob` | 按模式查找文件 |
|
||||
| Exec | `exec` | 执行 Shell 命令 |
|
||||
| Process | `process` | 管理长时间运行的进程 |
|
||||
| Web Fetch | `web_fetch` | 从 URL 获取并提取内容 |
|
||||
| Web Search | `web_search` | 搜索网络(需要 API Key) |
|
||||
| Memory Search | `memory_search` | 搜索 memory 文件(需要 Profile)|
|
||||
| Sessions Spawn | `sessions_spawn` | 创建子 Agent 会话 |
|
||||
|
||||
> **注意**: `memory_search` 工具通过关键词搜索 `memory.md` 和 `memory/*.md` 文件。Agent 通过 `read` 和 `edit` 工具操作 memory 文件内容。
|
||||
|
||||
## 工具组
|
||||
|
||||
工具组提供了一次性允许/禁止多个工具的快捷方式:
|
||||
|
||||
| 组 | 工具 |
|
||||
| ---------------- | ------------------------------ |
|
||||
| `group:fs` | read, write, edit, glob |
|
||||
| `group:runtime` | exec, process |
|
||||
| `group:web` | web_search, web_fetch |
|
||||
| `group:memory` | memory_search |
|
||||
| `group:subagent` | sessions_spawn |
|
||||
| `group:core` | 所有 fs、runtime 和 web 工具 |
|
||||
|
||||
## 使用方法
|
||||
|
||||
### CLI 使用
|
||||
|
||||
所有命令使用统一的 `multica` CLI(开发时使用 `pnpm multica`)。
|
||||
|
||||
```bash
|
||||
# 只允许特定工具
|
||||
multica run --tools-allow group:fs,group:runtime "list files"
|
||||
|
||||
# 禁止特定工具
|
||||
multica run --tools-deny exec,process "read file.txt"
|
||||
|
||||
# 使用工具组
|
||||
multica run --tools-allow group:fs "read config.json"
|
||||
```
|
||||
|
||||
### 编程使用
|
||||
|
||||
```typescript
|
||||
import { Agent } from './runner.js';
|
||||
|
||||
const agent = new Agent({
|
||||
tools: {
|
||||
// 第 1 层: 全局 allow/deny
|
||||
allow: ['group:fs', 'group:runtime', 'web_fetch'],
|
||||
deny: ['exec'],
|
||||
|
||||
// 第 2 层: Provider 特定规则
|
||||
byProvider: {
|
||||
google: {
|
||||
deny: ['exec', 'process'], // Google 模型不能使用运行时工具
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// 第 3 层: Subagent 模式
|
||||
isSubagent: false,
|
||||
});
|
||||
```
|
||||
|
||||
### 检查工具配置
|
||||
|
||||
使用 tools CLI 检查和测试配置:
|
||||
|
||||
```bash
|
||||
# 列出所有可用工具
|
||||
multica tools list
|
||||
|
||||
# 列出带有允许规则的工具
|
||||
multica tools list --allow group:fs,group:runtime
|
||||
|
||||
# 列出带有禁止规则的工具
|
||||
multica tools list --deny exec
|
||||
|
||||
# 显示所有工具组
|
||||
multica tools groups
|
||||
```
|
||||
|
||||
## 策略系统详情
|
||||
|
||||
### 第 1 层: 全局 Allow/Deny
|
||||
|
||||
用户指定的 allow/deny 列表:
|
||||
|
||||
- `allow`: 只有这些工具可用(支持 group:\* 语法)
|
||||
- `deny`: 这些工具被阻止(优先于 allow)
|
||||
|
||||
如果未指定 `allow` 列表,默认所有工具都可用。
|
||||
|
||||
### 第 2 层: Provider 特定规则
|
||||
|
||||
不同的 LLM Provider 可能有不同的能力或限制:
|
||||
|
||||
```typescript
|
||||
{
|
||||
byProvider: {
|
||||
google: { deny: ["exec"] }, // Gemini 不能执行命令
|
||||
anthropic: { allow: ["*"] }, // Claude 有完全访问权限
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 第 3 层: Subagent 限制
|
||||
|
||||
当 `isSubagent: true` 时,会应用额外的限制,防止子 Agent 访问敏感工具(如会话管理)。
|
||||
|
||||
## 添加新工具
|
||||
|
||||
1. 在 `src/agent/tools/` 中创建新文件(例如 `my-tool.ts`)
|
||||
|
||||
2. 使用 TypeBox 定义工具的 Schema:
|
||||
|
||||
```typescript
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import type { AgentTool } from '@mariozechner/pi-agent-core';
|
||||
|
||||
const MyToolSchema = Type.Object({
|
||||
param1: Type.String({ description: '参数描述' }),
|
||||
param2: Type.Optional(Type.Number()),
|
||||
});
|
||||
|
||||
export function createMyTool(): AgentTool<typeof MyToolSchema> {
|
||||
return {
|
||||
name: 'my_tool',
|
||||
label: 'My Tool',
|
||||
description: '这个工具做什么',
|
||||
parameters: MyToolSchema,
|
||||
execute: async (toolCallId, args) => {
|
||||
// 实现
|
||||
return { result: 'success' };
|
||||
},
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
3. 在 `src/agent/tools.ts` 中注册工具:
|
||||
|
||||
```typescript
|
||||
import { createMyTool } from './tools/my-tool.js';
|
||||
|
||||
export function createAllTools(cwd: string): AgentTool<any>[] {
|
||||
// ... 现有工具
|
||||
const myTool = createMyTool();
|
||||
|
||||
return [
|
||||
...baseTools,
|
||||
myTool as AgentTool<any>,
|
||||
// ...
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
4. 在 `groups.ts` 中将工具添加到适当的组:
|
||||
|
||||
```typescript
|
||||
export const TOOL_GROUPS: Record<string, string[]> = {
|
||||
'group:my_category': ['my_tool', 'other_tool'],
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
## 测试
|
||||
|
||||
运行策略系统测试:
|
||||
|
||||
```bash
|
||||
pnpm test src/agent/tools/policy.test.ts
|
||||
```
|
||||
|
||||
## Agent Profile 集成
|
||||
|
||||
工具配置可以在 Agent Profile 的 `config.json` 中定义,允许不同的 Agent 拥有不同的工具能力:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Super Multica Hub │
|
||||
│ │
|
||||
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
|
||||
│ │ Agent A │ │ Agent B │ │ Agent C │ │
|
||||
│ │ Profile: │ │ Profile: │ │ Profile: │ │
|
||||
│ │ coder │ │ reviewer │ │ devops │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ tools: │ │ tools: │ │ tools: │ │
|
||||
│ │ allow:fs │ │ deny:* │ │ allow:* │ │
|
||||
│ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │
|
||||
│ │ │ │ │
|
||||
└─────────┼────────────────┼────────────────┼─────────────────────┘
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ Client │ │ Client │ │ Client │
|
||||
└──────────┘ └──────────┘ └──────────┘
|
||||
```
|
||||
|
||||
每个 Agent 的 Profile 可以在 `config.json` 中定义自己的工具配置:
|
||||
|
||||
```json
|
||||
{
|
||||
"tools": {
|
||||
"allow": ["group:fs", "group:runtime"],
|
||||
"deny": ["exec"]
|
||||
},
|
||||
"provider": "anthropic",
|
||||
"model": "claude-sonnet-4-20250514"
|
||||
}
|
||||
```
|
||||
|
||||
详见 [Profile README](../profile/README.md)。
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
# @multica/store
|
||||
|
||||
Zustand state management for Multica apps.
|
||||
|
||||
## Usage
|
||||
|
||||
```tsx
|
||||
// From barrel
|
||||
import { useHubStore, useMessagesStore, useGatewayStore } from '@multica/store'
|
||||
|
||||
// Per-file subpath import
|
||||
import { useGatewayStore } from '@multica/store/gateway'
|
||||
import { useHubStore } from '@multica/store/hub'
|
||||
import { useMessagesStore } from '@multica/store/messages'
|
||||
import { useHubInit } from '@multica/store/hub-init'
|
||||
import { useDeviceId } from '@multica/store/device-id'
|
||||
```
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# @multica/ui
|
||||
|
||||
Shared UI component library. Shadcn + Tailwind CSS v4.
|
||||
|
||||
## Usage
|
||||
|
||||
```tsx
|
||||
// UI components — subpath imports, no barrel
|
||||
import { Button } from '@multica/ui/components/ui/button'
|
||||
import { Card, CardContent } from '@multica/ui/components/ui/card'
|
||||
|
||||
// Feature components
|
||||
import { ThemeProvider } from '@multica/ui/components/theme-provider'
|
||||
import { Chat } from '@multica/ui/components/chat'
|
||||
import { Markdown } from '@multica/ui/components/markdown'
|
||||
|
||||
// Hooks
|
||||
import { useIsMobile } from '@multica/ui/hooks/use-mobile'
|
||||
import { useAutoScroll } from '@multica/ui/hooks/use-auto-scroll'
|
||||
|
||||
// Utilities
|
||||
import { cn } from '@multica/ui/lib/utils'
|
||||
|
||||
// Styles (app entry point)
|
||||
import '@multica/ui/globals.css'
|
||||
```
|
||||
|
||||
## Adding Components
|
||||
|
||||
```bash
|
||||
pnpm --filter @multica/ui dlx shadcn@latest add <component>
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue