diff --git a/mateclaw-server/src/main/resources/docs/en/agents.md b/mateclaw-server/src/main/resources/docs/en/agents.md index fa2e74f9..93f847e4 100644 --- a/mateclaw-server/src/main/resources/docs/en/agents.md +++ b/mateclaw-server/src/main/resources/docs/en/agents.md @@ -116,6 +116,55 @@ An agent doesn't work alone. One agent can delegate to another — or to **three Example: coding agent takes the Jira ticket, research agent pulls competitor data, writing agent drafts the Slack reply. Three in parallel, results flow back to the orchestrator. +### Multi-level subagent delegation tree + +::: tip New in 1.4.0 +Delegation is no longer flat. A parent employee can delegate to children, and those children can delegate further — **recursively, up to 3 levels deep**. A temporary team can grow its own hierarchy for a specific task. +::: + +Three delegation tools, one per cadence: + +- **`delegateToAgent`** — synchronous. Hand a sub-task to a specific employee, wait for it to finish, and return only after the child's final result. Optional `inheritParentContext` carries the parent conversation's recent context to the child, so you don't have to re-explain the background. +- **`delegateParallel`** — fan out. Delegate to several children at once; each runs in its own isolated session and the results are collected together. +- **`delegateAsync`** — background. Returns a `task_id` immediately while the child runs in the background; fetch the result later with **`taskOutput`**. `taskOutput` has an **attribution gate** — only the **same conversation + the same user** that spawned the task can read its result, preventing cross-conversation / cross-user leakage. + +Children deny a default set of tools so the tree can't run away: + +- `delegateToAgent` / `delegateParallel` (recursion guard — children can't launch their own synchronous/parallel delegations, avoiding a delegation storm) +- the `setGoal` family + the `remember` family (goal and memory ownership stays with the parent) +- `create_employee` (children can't conjure new employees) + +This default deny list is tunable via `mateclaw.delegation.child-denied-tools`. + +Delegation pairs with the [Goals](./goals) system — the parent sets goals, breaks the work down, and delegates sub-tasks; children focus on execution. + +### UI — nested subagent timeline + always-on plan panel + +The ChatConsole draws the whole delegation tree, not a flat log: + +- **Delegation start** is marked clearly +- Each child shows its **name / depth / task excerpt** +- **Completion badges**: success / timeout / error, plus duration and content length +- Every subagent has a stable **id + parentId + depth**, so the nesting is legible in the timeline — you can see exactly who delegated to whom +- **The plan panel is always on** — no longer Plan-and-Execute only; delegation-tree progress folds into the same panel + +--- + +## Build a team from one sentence: the digital-employee builder skill + +::: tip New in 1.4.0 +Don't want to create employees one at a time? Give it a sentence and let the "digital-employee builder" skill assemble the whole team for you. +::: + +The skill starts from your one sentence and runs the full chain: + +1. **Clarify the requirement** — it pins down the vague sentence first, confirming the problem you're actually trying to solve +2. **Design the roles** — breaks it into **2 to 6** complementary roles +3. **Create each one** — calls `create_employee` per role to produce real, usable employees +4. **Chain them into a workflow draft** — links the employees into a [workflow](./workflow) draft you can tweak right away + +The companion tool **`list_capability_catalog`** lets the skill survey which tools / skills / knowledge bases the deployment has available before assigning capabilities to roles. Created employees are **enabled on creation** — no extra toggle to flip. + --- ## Deep thinking @@ -233,6 +282,7 @@ Why the turn ended: These are things the runtime does so agents don't fail in ways you'd have to debug: - **Context pruning** — when the context window gets too full, earlier turns get summarized by the LLM and the summary replaces them. Cached for 30 minutes. Injected as a user message, not a system message, to prevent prompt injection from historical content. +- **Structured compaction (on prompt-too-long)** — when the model returns "prompt too long," the runtime walks a four-stage escalation: **soft trim → hard clear → pre-prune → LLM structured summary**. At every stage it **always preserves the prefix** — the system prompt + the goal anchor stay intact — and injects the final summary as a UserMessage. Delegation tool results are **never compacted** (they're a child's hard-won output; lose them and they're gone). After a failed summary there's a **10-minute cooldown**, so the runtime won't keep hammering the LLM inside the same over-budget turn. - **Thinking recovery** — if a stream breaks mid-response, the partial thinking and content persist and show up when the conversation reloads. - **Iteration limit handler** — instead of crashing when `max_iterations` is hit, the runtime forces a best-effort summary answer. - **Stale stream cleanup** — every open SSE stream is tracked, abandoned ones are reaped automatically. diff --git a/mateclaw-server/src/main/resources/docs/en/api.md b/mateclaw-server/src/main/resources/docs/en/api.md index 54c22ba8..8bd22fad 100644 --- a/mateclaw-server/src/main/resources/docs/en/api.md +++ b/mateclaw-server/src/main/resources/docs/en/api.md @@ -16,7 +16,7 @@ Every endpoint except `/api/v1/auth/login` requires a JWT in the `Authorization` Authorization: Bearer ``` -For deep behavior, read the feature page — [Chat & Messaging](./chat), [Agents](./agents), [Tools](./tools), [Security & Approval](./security), [LLM Wiki](./wiki), [Multimodal](./multimodal), [Memory](./memory), [Channels](./channels), [Models](./models), [Workspaces](./workspaces), [Doctor](./doctor). +For deep behavior, read the feature page — [Chat & Messaging](./chat), [Agents](./agents), [Tools](./tools), [Security & Approval](./security), [LLM Wiki](./wiki), [Multimodal](./multimodal), [Memory](./memory), [Channels](./channels), [Models](./models), [Workspaces](./workspaces), [Goals](./goals), [Doctor](./doctor). --- @@ -83,7 +83,9 @@ Event types and schema are documented in [Chat & Messaging](./chat). ``` GET /api/v1/conversations # List (?page&size&agentId) +GET /api/v1/conversations/page?page=&size=&keyword= # Paginated sessions (with keyword search) GET /api/v1/conversations/{id}/messages # Get messages +PUT /api/v1/conversations/{id}/model # Set the model used by this conversation DELETE /api/v1/conversations/{id} # Delete DELETE /api/v1/conversations/{id}/messages # Clear messages GET /api/v1/conversations/{id}/status # Conversation status @@ -109,6 +111,10 @@ DELETE /api/v1/agents/{id}/workspace/files/{filename} # Delete GET /api/v1/agents/{id}/workspace/prompt-files # Which files are injected PUT /api/v1/agents/{id}/workspace/prompt-files # Set prompt file list +GET /api/v1/agents/{agentId}/workspace/memory/export # Export memory snapshot +POST /api/v1/agents/{agentId}/workspace/memory/import/preview # Preview import (no writes) +POST /api/v1/agents/{agentId}/workspace/memory/import # Import memory snapshot + GET /api/v1/agents/templates # List templates POST /api/v1/agents/templates/{id} # Create from template ``` @@ -121,6 +127,7 @@ POST /api/v1/agents/templates/{id} # Create from template GET /api/v1/tools # List PUT /api/v1/tools/{id} # Update PUT /api/v1/tools/{id}/toggle?enabled={bool} # Toggle +PUT /api/v1/tools/{id}/disclosure-tier # Set disclosure tier (core / extension) POST /api/v1/tools/{name}/test # Test directly ``` @@ -323,6 +330,9 @@ GET /api/v1/channels/health # Aggregate hea GET /api/v1/channels/webhook/weixin/qrcode # WeChat iLink QR code GET /api/v1/channels/webhook/weixin/qrcode/status # QR scan status + +POST /api/v1/channels/qrcode/qq/begin # Begin QQ scan-to-bind +GET /api/v1/channels/qrcode/qq/status # QQ scan-to-bind status ``` ### Channel webhook callbacks @@ -396,6 +406,19 @@ GET /api/v1/triggers/{id}/events # Event history for this --- +## Goals (1.4.0+) + +Goal-completion scoring and auto-followup behavior in [Goals](./goals). + +``` +POST /api/v1/goals # Create goal +GET /api/v1/goals/{id} # Get goal +PATCH /api/v1/goals/{id} # Update goal (partial) +GET /api/v1/goals/{id}/events # Evaluation event history for this goal +``` + +--- + ## Token usage ``` @@ -435,10 +458,27 @@ GET /api/v1/workspaces/{id} # Get POST /api/v1/workspaces # Create PUT /api/v1/workspaces/{id} # Update DELETE /api/v1/workspaces/{id} # Delete (owner only) -GET /api/v1/workspaces/{id}/members # List members -POST /api/v1/workspaces/{id}/members # Add member -DELETE /api/v1/workspaces/{id}/members/{userId} # Remove member -PUT /api/v1/workspaces/{id}/members/{userId}/role # Change role +GET /api/v1/workspaces/{id}/access # Caller's access info (see below) +``` + +### Members & RBAC (1.4.0+) + +`/access` returns the caller's effective permissions in the workspace; the frontend uses it to render routes and menus: + +```json +{ + "memberRole": "editor", + "isGlobalAdmin": false, + "effectiveRole": "editor", + "capabilities": ["workspace.read", "conversation.write", "..."] +} +``` + +``` +GET /api/v1/workspaces/{id}/members # List members +POST /api/v1/workspaces/{id}/members # Add member +PUT /api/v1/workspaces/{id}/members/{memberId} # Update member (role, etc.) +DELETE /api/v1/workspaces/{id}/members/{memberId} # Remove member ``` --- diff --git a/mateclaw-server/src/main/resources/docs/en/architecture.md b/mateclaw-server/src/main/resources/docs/en/architecture.md index 05ae1483..126fbcae 100644 --- a/mateclaw-server/src/main/resources/docs/en/architecture.md +++ b/mateclaw-server/src/main/resources/docs/en/architecture.md @@ -134,7 +134,7 @@ This is the most important thing to know if you're contributing to the backend. - `agent/graph/StateGraphReActAgent.java` — assembles the ReAct loop - `agent/graph/plan/StateGraphPlanExecuteAgent.java` — assembles the Plan-and-Execute graph -- `agent/graph/node/` — `ReasoningNode`, `ActionNode`, `ObservationNode`, `FinalAnswerNode`, `SummarizingNode`, `LimitExceededNode` +- `agent/graph/node/` — `ReasoningNode`, `ActionNode`, `ObservationNode`, `FinalAnswerNode`, `SummarizingNode`, `LimitExceededNode`, `GoalEvaluationNode` - `agent/graph/plan/node/` — `PlanGenerationNode`, `StepExecutionNode`, `PlanSummaryNode`, `DirectAnswerNode` - `agent/graph/edge/` + `plan/edge/` — dispatcher functions that decide the next node based on state - `agent/graph/state/MateClawStateKeys.java` — the keys for the shared state object @@ -149,6 +149,17 @@ This is the most important thing to know if you're contributing to the backend. **Don't** create a new `XxxAgent` class. You'll be reimplementing what the graph already does. +### Goal-evaluation node (1.4.0+) + +The graph (both ReAct and Plan-Execute) now runs a `GoalEvaluationNode` after `FinalAnswerNode` has streamed the final answer: it scores how completely the goal was met and can optionally inject an auto-followup message to keep pushing any unmet goals forward. + +### Other 1.4.0 runtime changes + +- **Progressive tool/skill disclosure** — a tool-disclosure layer splits tools into core and extension tiers; `enable_tool` / `load_skill` let an employee activate extension tools / load skills on demand, keeping the system prompt small. +- **Multi-level subagent delegation** — parent-to-child delegation is recursive and depth-capped, forming a tree; child-graph events are relayed back to the root conversation in real time. +- **ChannelToolProvider SPI** — channels (e.g. Feishu) can expose platform capabilities directly as agent tools without a separate MCP server. +- **Workspace RBAC** — capabilities are resolved from a backend role→capability mapping that gates both REST endpoints and frontend routes/menus. + ### Shared state keys | Key | Purpose | diff --git a/mateclaw-server/src/main/resources/docs/en/backstage.md b/mateclaw-server/src/main/resources/docs/en/backstage.md index 6859eaf6..097fefdb 100644 --- a/mateclaw-server/src/main/resources/docs/en/backstage.md +++ b/mateclaw-server/src/main/resources/docs/en/backstage.md @@ -19,8 +19,12 @@ It is **admin-only** (`ROLE_ADMIN`), live (auto-refresh every 5 s, pausable), an ## Where it lives -- **Route:** `/backstage` -- **Sidebar:** top-level entry under *Operate* +::: tip 1.4.0: the live view folded into the Employees page +As of v1.4.0, this live runtime view is folded into the **Employees page**. `/backstage` now **redirects to** `/agents?view=live`, and the Employees page has a segmented **Roster / Live** toggle — "Live" is the runtime console described here. The `/backstage` route below still works; it just lands on the Employees page's live view. +::: + +- **Route:** `/backstage` (redirects to `/agents?view=live`) +- **Sidebar:** the **Live** segment of the Employees page; when an employee is stuck, the sidebar surfaces an **orange "stuck employee" dot** that links straight to this live view - **Authorization:** the JWT must carry `ROLE_ADMIN`. Non-admins get a 403 from every `/api/v1/admin/agent-runtime/*` endpoint, and the route guard hides the link from the sidebar entirely. --- diff --git a/mateclaw-server/src/main/resources/docs/en/channels.md b/mateclaw-server/src/main/resources/docs/en/channels.md index 49d2bc95..41cebae6 100644 --- a/mateclaw-server/src/main/resources/docs/en/channels.md +++ b/mateclaw-server/src/main/resources/docs/en/channels.md @@ -20,6 +20,21 @@ v1.3.0 lands a wave of long-run stability and group-collaboration work in the ch WeCom-specific tuning lives in [WeCom deep tuning](./wecom-tuning). ::: +::: tip 1.4.0 channel-layer hardening +v1.4.0 makes Feishu a first-class channel — interactive cards, streaming cards, approval cards, native tools, media in/out — plus QR binding for QQ: + +- **Feishu interactive cards (Schema 2.0)** — structured replies auto-render as Feishu interactive cards; short plain text stays text +- **Feishu approval cards** — tool-guard approval flows arrive as an Approve / Deny button card; one tap runs the tool to completion +- **Feishu streaming cards (CardKit)** — replies stream char-by-char into a single card +- **Feishu inbound voice transcription** — voice messages go through STT and reach the agent as text +- **Feishu inbound file / audio / video download** — no longer images only; `media_download_enabled` **now defaults to true in 1.4.0** +- **Feishu channel-native tools** — calendar lookup and doc read / write, no MCP server required +- **QQ QR binding** — QQ gets the same scan-to-bind onboarding as DingTalk / Feishu +- **Per-conversation model selection across all IM channels** — IM conversations remember a per-conversation model, just like web + +Feishu specifics are spelled out in the [Feishu](#feishu-lark) section below. +::: + --- ## The nine channels @@ -247,6 +262,97 @@ curl -X POST http://localhost:18088/api/v1/channels \ Webhook URL: `https://your-domain/api/v1/channels/webhook/feishu` +### Feishu 1.4.0 enhancements + +v1.4.0 upgrades Feishu from "can send and receive text" into a full rich-interaction channel. Most of these work with zero config — they're listed here so you know where the switches live and what the defaults are. + +#### Interactive cards (Schema 2.0) + +Structured replies — JSON, Markdown with headers / tables / lists, long text — auto-render as Feishu **interactive cards**; short plain text still goes out as a normal text message. + +| Config | Default | What it does | +|--------|---------|--------------| +| `card_format` | `auto` | `auto` decides by content; `always` forces cards (for debugging); `never` forces plain text | +| `card_header` | `AI 助手` | Card title text; set to an empty string to suppress the header | + +The JSON card payload is capped at ~32 KB; anything larger degrades to plain text. + +#### Approval cards + +Tool-guard approval flows arrive as a card with **Approve / Deny** buttons. Tapping **Approve** injects a synthetic `/approve`, tapping **Deny** injects `/deny`, and the agent then runs the approved tool end-to-end — approval and execution close the loop in the same conversation, no detour back to the web console. + +#### Streaming cards (CardKit) + +Replies stream char-by-char into a **single card** instead of waiting for the whole answer before sending. + +- `card_streaming_enabled` (default `true`) +- The first token appears immediately; subsequent updates are throttled at 500ms +- On CardKit failure it falls back to accumulate-then-send + +#### Inbound voice transcription + +Feishu voice messages go through speech-to-text (STT) and are fed to the agent as text — the agent sees real words, not an `[audio]` placeholder. **Auto-enabled once STT is configured**, no extra switch. + +#### Inbound file / audio / video download + +Before 1.4.0 only images were downloaded; now files, audio, and video are downloaded too, cached locally, and surfaced to the agent via `/api/v1/files/generated/{id}`. + +::: warning Default change +`media_download_enabled` **now defaults to `true`** in 1.4.0. If disk usage or privacy matters to you, set it explicitly to `false` to opt out. +::: + +Size and format limits: images cap at 10 MB (auto-compressed beyond that); files / audio / video cap at 30 MB; audio is opus-only and video is mp4-only, with everything else degrading to plain file handling. + +#### Outbound generated files → native attachments + +File URLs the agent generates are turned back into native Feishu **attachments** sent directly. On a cache miss, the reply carries a retry hint instead of a dead link. + +#### Channel-native tools (no MCP server) + +Bind a Feishu channel and the agent immediately gains three native Feishu tools, **no separate MCP server required**: + +| Tool | Type | Default | +|------|------|---------| +| `feishu_calendar_list_events` | read | on | +| `feishu_doc_read` | read | on | +| `feishu_doc_create` | write | off, approval-gated | + +DB-seeded guard rules automatically apply `NEEDS_APPROVAL` to mutating tools (e.g. `feishu_doc_create`), triggering the approval-card flow above. + +#### Sender context injection + +In group chats the agent needs to know who's talking. When a Feishu message comes in, the agent prompt automatically carries Channel / Sender / (in groups) Chat context lines. **No config.** + +#### DONE reaction + +After a successful reply, the bot adds a ✅ reaction to the inbound message as a lightweight "handled" receipt. `enable_done_reaction` (default `true`). + +#### Mention filtering + +By default the bot responds to anyone in a group chat. Set `require_mention` to `true` (default `false`) and only an @mention triggers it — the check uses the Feishu SDK's mentions field. The bot's own open_id is prefetched on startup with a 60s negative cache (if it can't be resolved, the gate falls open rather than locking the whole group on a single failure). + +```bash +curl -X POST http://localhost:18088/api/v1/channels \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "name": "Feishu Bot", + "type": "feishu", + "agentId": 1, + "config": { + "appId": "cli_your_app_id", + "appSecret": "your-app-secret", + "card_format": "auto", + "card_header": "AI 助手", + "card_streaming_enabled": true, + "media_download_enabled": true, + "enable_done_reaction": true, + "require_mention": false + }, + "enabled": true + }' +``` + --- ## WeCom (WeChat Work) @@ -377,6 +483,25 @@ curl -X POST http://localhost:18088/api/v1/channels \ ## QQ +WebSocket / callback modes, on the official bot platform. + +### One-click QR binding (recommended, v1.4.0+) + +Like DingTalk / Feishu, QQ now supports scan-to-bind — no manual copying of AppID / AppSecret from the open platform. + +1. `Channels → New → choose type: QQ` +2. In the form, click **Bind QQ App via QR** — a QR code unfolds +3. Scan it with QQ and **confirm authorization** +4. Back in the form, **AppID and AppSecret are auto-filled** + +::: tip What's happening under the hood +This goes through the QQ Open Platform Lite portal: MateClaw mints a temporary session and the credentials land in the form via an AES-256-GCM encrypted exchange. The session is valid for 12 minutes and auto-invalidates on expiry. **No hand-copied credentials anywhere in the flow.** +::: + +### Manual app creation (fallback) + +If the QR flow can't reach QQ on your network: + 1. [QQ Open Platform](https://q.qq.com/) → create a bot application ![QQ Open Platform](/images/channels/qq/01-open-platform.png) ![Create Bot](/images/channels/qq/02-create-bot.png) @@ -510,6 +635,12 @@ IM channels (WeCom, WeChat, DingTalk) support voice input. Transcription via Das --- +## Per-conversation model selection (all IM channels) + +As of 1.4.0, IM channel conversations **remember a per-conversation model**, just like web. Each IM conversation seeds a conversation-level model when it's created, and later replies respect that choice rather than always falling back to the agent's default model. See [Chat & Messaging](./chat) for the web-side switching detail. + +--- + ## Things worth knowing - **Webhook mode needs HTTPS.** Production deployments should front MateClaw with Nginx + SSL. diff --git a/mateclaw-server/src/main/resources/docs/en/chat.md b/mateclaw-server/src/main/resources/docs/en/chat.md index ebe8811b..0bd0b343 100644 --- a/mateclaw-server/src/main/resources/docs/en/chat.md +++ b/mateclaw-server/src/main/resources/docs/en/chat.md @@ -171,6 +171,62 @@ A conversation is a sequence of messages scoped to a single agent and a single u The segment representation is what powers the progressive display. It also makes the database the source of truth — the UI can reconstruct any past response exactly as it looked while streaming. +### Per-conversation model selection + +::: tip Added in 1.4.0 +The model selector in the chat header now binds a model **to the conversation**, not as a global switch. See [issue #150](https://github.com/matevip/mateclaw/issues/150). +::: + +Switching the model in the header affects **only this conversation**: the choice is stored on the conversation and takes effect starting with the **next message**. A conversation you never set explicitly falls back to the workspace default model. The runtime model indicator stays in sync with whatever is pinned on the conversation — what you see is what the next turn actually uses. + +This isolation also makes model config more robust: **a single bad model id no longer takes its whole provider offline**. The broken conversation only affects itself; everything else keeps running. + +### Conversation list management + +::: tip Added in 1.4.0 +The conversation sidebar grew from a plain history list into an actionable operations panel. See [issue #144](https://github.com/matevip/mateclaw/issues/144). +::: + +- **Pin / unpin** — from each row's `⋮` overflow menu. Important threads stay at the top in a "Pinned" group. +- **Multi-select batch delete** — enter multi-select mode and a checkbox appears on each row; tick several and delete them in one go. +- **Filter by employee** — when the workspace has **2 or more employees**, a dropdown appears at the top of the sidebar to filter the list by employee (hidden with a single employee, so there's no pointless control). +- **Status dots** — read each conversation's state at a glance: currently generating (blue pulse), an active goal in progress, or unread content. + +### Global keyboard shortcuts + +::: tip Added in 1.4.0 +Two global shortcuts let you jump between conversations without touching the mouse. The hint lives in the sidebar footer. +::: + +| Shortcut | Action | +|----------|--------| +| `Ctrl/Cmd + K` | Open the employee picker to jump to any chat | +| `Ctrl/Cmd + N` | Start a new conversation | + +`Ctrl+N` does not fire while you're typing in an input or textarea — its native behavior is left alone. + +### Session Admin page + +::: tip Added in 1.4.0 +When conversations outgrow the sidebar, reach a dedicated admin page from the chat header overflow menu ("Session Admin"), at `/sessions`. +::: + +This page exists for the "lots of conversations" case: + +- **Server-side pagination** — no more cramming thousands of conversations into the sidebar. +- **Search by title or ID** — filter as you type to locate a specific conversation. +- **Depth-styled card layout** — one card per conversation, denser than the sidebar. +- **Inline editable model chip** — each row shows and switches that conversation's model directly, without entering it first. +- **Back button** — one click returns you to the chat console. + +### Shared employee picker + +::: tip Added in 1.4.0 +A single shared picker dialog is reused in three places: the sidebar, the `Ctrl+K` shortcut, and the new-conversation modal. +::: + +All three entry points open the **same dialog** with identical behavior. Agent icons inside it are **color-coded per employee**, so in a multi-employee workspace you can tell who's who at a glance. + --- ## Context window management diff --git a/mateclaw-server/src/main/resources/docs/en/console.md b/mateclaw-server/src/main/resources/docs/en/console.md index 3a56acde..5bb80269 100644 --- a/mateclaw-server/src/main/resources/docs/en/console.md +++ b/mateclaw-server/src/main/resources/docs/en/console.md @@ -38,6 +38,13 @@ Six groups matching the intent-based information architecture: Pages you don't have permission to see (based on workspace role) are hidden. +### Sidebar notification badges (new in 1.4.0) + +The sidebar surfaces live badges in two spots to flag things needing your attention: + +- **Pending approvals** — a red count badge; clicking jumps to [Security & Approval](./security) +- **Stuck employees** — an orange dot; clicking jumps to the **Live** runtime view on the Employees page (see [Backstage](./backstage)) + ### Auth guard Every route except `/login` is protected by a `beforeEach` route guard checking for a valid JWT in `localStorage`. Set `VITE_SKIP_AUTH=true` in development to bypass. @@ -68,7 +75,7 @@ Username/password form with password visibility toggle. Shown automatically on first login. Four-step wizard: 1. **Welcome** — short product overview -2. **Configure a model** — pick a provider and paste an API key (or OAuth into ChatGPT Plus, or auto-detect Ollama) +2. **Configure a model** — pick a provider and paste an API key (or OAuth into ChatGPT Plus, or auto-detect Ollama); as of 1.4.0 this step does **provider enablement** directly — tick the providers you want and they're live 3. **Pick an agent template** — seeds a default agent based on your choice 4. **Send the first message** — a test prompt so you can see streaming work @@ -162,10 +169,15 @@ Generate media interactively without going through an agent. **Route:** `/sessions` +::: tip 1.4.0: a real Sessions admin page +As of v1.4.0 `/sessions` is a standalone Sessions admin page, reached from the **chat header overflow menu**. It has **server-side pagination** + search by **title / ID**, a depth-styled **card layout**, and an **inline editable model chip** per row — change a session's default model right from the list. +::: + Browse conversations across every agent and channel. -- Search by keyword +- Search by keyword (title / ID, server-side pagination) - Session title, ID, agent, message count, status, last active +- **Inline editable model chip** per row - Channel source icon - Jump to chat console with session open - Delete historical sessions @@ -222,9 +234,13 @@ Card grid for eight IM channels plus web. --- -### 12. Cron Jobs +### 12. Cron Jobs (Scheduler) -**Route:** `/cron-jobs` +**Route:** `/settings/scheduler` (old `/cron-jobs` redirects here) + +::: tip 1.4.0: merged into the unified Scheduler +As of v1.4.0, **Scheduled Jobs** and **Triggers** are merged into a single **Scheduler** page (`Settings → Scheduler`) with three tabs: **Scheduled Jobs / Event Triggers / Run History**, each showing an item count, with a context-aware top-right action button. Scheduled Jobs gain the `wiki_process` type (off-peak KB processing) and a **visual cron editor**. See [Triggers](./triggers). +::: Scheduled tasks that trigger agent conversations. @@ -262,6 +278,7 @@ External database connections agents can query through the SQL query skill. **Route:** `/dashboard` - Summary cards — active agents, conversations today, tool calls today, pending approvals +- **Model-config card** (new in 1.4.0) — lists enabled LLM providers, each with a **liveness status** and its **active model**, plus a link to model settings - **Trend chart** — messages / tool calls / token usage over 7 / 30 / 90 days - **Top agents / top tools** — ranked by usage - Recent approval activity @@ -278,7 +295,7 @@ System health checks. Backend reachability, database, model providers, channels, ### 17. Settings -Sub-route layout with four child pages. +Sub-route layout with four child pages. A floating button pinned to the bottom of the settings sub-nav **collapses/expands** it (new in 1.4.0). #### 17.1 Models @@ -508,7 +525,7 @@ Response is read incrementally via `ReadableStream` and parsed segment by segmen /mcp-servers — MCP Servers /channels — Channels -/cron-jobs — Cron Jobs +/settings/scheduler — Scheduler (Scheduled Jobs / Event Triggers / Run History; old /cron-jobs redirects here) /datasources — Datasources /token-usage — Token Usage /dashboard — Dashboard diff --git a/mateclaw-server/src/main/resources/docs/en/memory.md b/mateclaw-server/src/main/resources/docs/en/memory.md index dc6f3f57..3c9ed46b 100644 --- a/mateclaw-server/src/main/resources/docs/en/memory.md +++ b/mateclaw-server/src/main/resources/docs/en/memory.md @@ -303,6 +303,21 @@ Memory isn't just something that *happens to* an agent. The agent itself can act | `write_workspace_memory_file` | Create or overwrite a file (full replace) | | `edit_workspace_memory_file` | Find-and-replace edit (incremental, `replaceAll` supported) | +### Keyword search over its own memory + +::: tip New in 1.4.0 +An employee can do more than read whole files — during a conversation it can **search all of its workspace memory files by keyword** and jump straight to the line. +::: + +This is an agent runtime capability: the employee supplies a keyword and the system searches across its own workspace memory files: + +- **Tokenization** — CJK is split into 2-character sliding windows, Latin text on whitespace, so both languages match +- **Per-file weighted scoring** — hits in core files like `AGENTS.md` / `MEMORY.md` / `PROFILE.md` rank above hits in the daily ledger +- **What comes back** — each hit gives a filename + line number + an 80-char context snippet (matched term highlighted) + a relevance score +- **Scan scope** — up to ~50 candidate files, sorted by score, highest first + +Use it when the employee wants to confirm "did I note this before?" or recover a specific decision spread across many days of notes — without pulling whole files into context. + ### Examples **List:** @@ -344,6 +359,41 @@ Memory isn't just something that *happens to* an agent. The agent itself can act --- +## Memory snapshot export / import + +::: tip New in 1.4.0 +An employee's entire accumulated memory can be packaged into a ZIP and taken with you — for backup, migration to another deployment, or cloning a coworker who "already knows you." +::: + +A snapshot packages an employee's core memory into a single ZIP: + +- `AGENTS.md` / `MEMORY.md` / `PROFILE.md` / `SOUL.md` / `KNOWLEDGE.md` +- daily ledger files (`memory/YYYY-MM-DD.md`) +- a `manifest.json` (what's in the package, and which employee it came from) + +### Three endpoints + +| Method | Path | Role | What it does | +|--------|------|------|--------------| +| GET | `/api/v1/agents/{agentId}/workspace/memory/export` | Viewer | Export the ZIP — even read-only access can take a backup | +| POST | `.../workspace/memory/import/preview` | Member | **Dry run**: parse the ZIP, classify each file as create / update / skip, write nothing | +| POST | `.../workspace/memory/import` | Member | Apply the import, written **atomically** | + +Preview to see the diff, confirm, then import — you always know what will change before it does. + +### Safety guards + +- **Whitelist** — only the file types listed above are accepted; everything else is ignored +- **Zip-bomb guards** — ≤ 500 entries, ≤ 1 MB each (uncompressed), ≤ 16 MB total; anything over is rejected +- **UI toggle state is not serialized** — `enabled` / `sortOrder` are kept out of the snapshot; on import into a new employee the target decides them by seed rules, rather than forcing the source's toggle state + +### UI + +- The **Agent Context page right panel** has **Export / Import** buttons +- Import shows a **diff** first (what's created, overwritten, skipped) and only writes after you confirm + +--- + ## Configuration reference ### Memory extraction & consolidation diff --git a/mateclaw-server/src/main/resources/docs/en/models.md b/mateclaw-server/src/main/resources/docs/en/models.md index 1bd4116b..2d036e52 100644 --- a/mateclaw-server/src/main/resources/docs/en/models.md +++ b/mateclaw-server/src/main/resources/docs/en/models.md @@ -19,7 +19,8 @@ MateClaw doesn't care which LLM you use. It talks to every mainstream provider t | **OpenAI OAuth (ChatGPT Plus/Pro)** | GPT-4o, o3, o4-mini via subscription | openai | Browser-based OAuth — no API key | | **Anthropic** | Claude 4.7, Claude 4.6 Sonnet, Claude 4.5 Haiku | anthropic | Native Messages API | | **Anthropic Claude Code OAuth** | Claude 4.7 / 4.6 via Claude Pro/Max/Team subscription | anthropic | Browser OAuth + manual-paste flow — no API key | -| **Google Gemini** | Gemini 2 Pro, Gemini 2 Flash | gemini | Google Generative AI API | +| **Google Gemini** _(native)_ | gemini-2.5-flash, gemini-3-pro-image-preview, gemini-2.5-flash-image | gemini | Native `generateContent` API (not OpenAI-compatible) — see "Native Gemini" below | +| **xAI / Grok** | Grok 3, Grok 4 | openai | OpenAI-compatible (base URL + API key); xAI brand icon in the UI | | **DeepSeek** | deepseek-chat, deepseek-coder, **DeepSeek V4 flash + pro** (thinking-mode) | openai | OpenAI-compatible | | **Kimi (Moonshot)** | moonshot-v1-8k/32k/128k | openai | OpenAI-compatible | | **Zhipu AI** | GLM-5-Turbo, GLM-5V-Turbo, GLM-5, GLM-5.1 | openai | OpenAI-compatible | @@ -74,6 +75,23 @@ Same `sk-` API key, **two endpoints** that ship different model families: --- +## Native Gemini + +::: tip New in 1.4.0 +Gemini no longer rides on an OpenAI-compatibility shim — MateClaw talks to Google's **native `generateContent` API** directly. +::: + +Plenty of products bolt Gemini on as "just another OpenAI-compatible endpoint" and then hit walls around system instructions, function calling, and inline images. MateClaw speaks Gemini's own protocol instead: + +- **Native chat builder** — maps `systemInstruction`, `functionCall` / `functionResponse` (tool-call turns), and inline image parts (multimodal input) correctly +- **Streaming SSE parsing** — parses Gemini's streaming response format chunk by chunk +- **JSON Schema sanitizing** — automatically strips JSON Schema keywords Gemini rejects, so tool definitions aren't refused +- **Startup liveness probe** — sends a lightweight request at startup to confirm the credentials and model are reachable + +Configure it under `Settings → Models → Add Provider`, pick the **Gemini** provider, paste your API key. Example models: `gemini-2.5-flash`, `gemini-3-pro-image-preview`, `gemini-2.5-flash-image`. Image generation runs through the same native path — see [Multimodal → Image generation](./multimodal#image-generation-six-providers). + +--- + ## Adding a provider **A fresh MateClaw install has an empty provider list. That's deliberate.** @@ -254,6 +272,10 @@ Restart MateClaw. Auto-discovered, added, enabled. No `EMBEDDING_API_KEY` env vars. Embedding models are regular rows in `mate_model_config` with `model_type='embedding'`. They show up alongside chat models in `Settings → Models`. Knowledge bases pick their embedding model from a dropdown. +::: tip New in 1.4.0 ([issue #79](https://github.com/matevip/mateclaw/issues/79)) +**Embedding models from any provider.** In the embedding section of `Settings → Models`, configure an embedding model from any provider — it **reuses that provider's API key**, so there's no separate `EMBEDDING_API_KEY`. Each knowledge base picks its embedding model from a dropdown. Keyless local proxies use a no-op placeholder key; the protocol is resolved from the provider's chat-model / protocol setting, so you never hand-enter it. +::: + ### Anthropic prompt caching System prompts, agent personas, tool definitions — automatically marked with `cache_control: ephemeral` on Anthropic-compatible endpoints. First request warms the cache, every follow-up gets a cache hit. The Dashboard tracks `cache_read_tokens` / `cache_write_tokens` daily. @@ -275,7 +297,9 @@ System prompts, agent personas, tool definitions — automatically marked with ` **Kimi K2.5 thinking**: the model activates thinking natively; don't set `reasoning_effort`. -**Multi-round tool calls + thinking**: thinking-capable models (DeepSeek-Reasoner / GPT-5 / Kimi K2.5) correctly round-trip historical `reasoning_content` during ReAct multi-round tool calls. Cross-user-turn history is cleared at the boundary, in-turn history is preserved — matching DeepSeek's "pass back within a turn, reset across turns" contract. +**Multi-round tool calls + thinking**: thinking-capable models (DeepSeek-Reasoner / GPT-5 / Kimi K2.5 / Xiaomi MiMo) correctly round-trip historical `reasoning_content` during ReAct multi-round tool calls. Cross-user-turn history is cleared at the boundary, in-turn history is preserved — matching DeepSeek's "pass back within a turn, reset across turns" contract. + +**Xiaomi MiMo thinking-mode multi-turn fix** ([issue #189](https://github.com/matevip/mateclaw/issues/189)): MiMo's `reasoning_content` is now kept correctly across turns in thinking mode, instead of being lost on subsequent turns. --- @@ -298,6 +322,11 @@ Takes effect **immediately** — no restart. Next message uses the new model. In Per-agent override supported: bind a specific agent to a specific model config. +::: tip New in 1.4.0 +- **Per-conversation model selection** ([issue #150](https://github.com/matevip/mateclaw/issues/150)): in the chat UI you can switch the model for **just the current conversation**, without touching the global active model or any other conversation. See [Chat & Messaging](./chat). +- **A single bad model id no longer evicts the whole provider**: when discovery / probing hits one invalid model identifier, only that model is skipped — the rest of the provider's models stay available. +::: + --- ## Per-model testing diff --git a/mateclaw-server/src/main/resources/docs/en/multimodal.md b/mateclaw-server/src/main/resources/docs/en/multimodal.md index 17b048e0..63ec19b2 100644 --- a/mateclaw-server/src/main/resources/docs/en/multimodal.md +++ b/mateclaw-server/src/main/resources/docs/en/multimodal.md @@ -17,7 +17,7 @@ Configure once. Use everywhere. | **DashScope** | Wanxiang | Alibaba's image model, default cloud option | | **OpenAI** | DALL-E 3 | Standard DALL-E endpoint | | **fal.ai** | Flux | Fast Flux inference via fal.ai | -| **Google Imagen** | Imagen 3 | Google Cloud credentials required | +| **Google (Nano Banana)** | gemini-3-pro-image-preview, gemini-2.5-flash-image | Via the native Gemini path; **supports image editing** — see [Nano Banana](#nano-banana) below | | **Zhipu** | CogView | Native Chinese prompt support | | **MiniMax** | — | Sync and async both supported | @@ -61,6 +61,17 @@ Agent: image_generate(prompt="replace background with forest", A fuller model catalog lives in [Models](./models#two-dashscope-variants). +#### Nano Banana + +::: tip New in 1.4.0 +Google image generation runs through **Nano Banana Pro** (`gemini-3-pro-image-preview`) via the [native Gemini path](./models#native-gemini), not an OpenAI-compatibility shim. +::: + +Because it uses the native `generateContent` endpoint, the image tool passes input images as **inline parts** straight to the model — so Nano Banana isn't just text-to-image, it **supports image editing** (image-to-image) too. It works exactly like [Image edit](#image-edit) above: pass the `image` / `images` parameter to reference one or more source images. + +- **Nano Banana Pro** — `gemini-3-pro-image-preview` (default) +- **Nano Banana** — `gemini-2.5-flash-image` (another Google image model) + ### Video generation — six providers - **DashScope** — Tongyi Wanxiang video diff --git a/mateclaw-server/src/main/resources/docs/en/releases.md b/mateclaw-server/src/main/resources/docs/en/releases.md index 42b117ff..d29afa68 100644 --- a/mateclaw-server/src/main/resources/docs/en/releases.md +++ b/mateclaw-server/src/main/resources/docs/en/releases.md @@ -10,6 +10,7 @@ For historical diffs, check the corresponding git tag. For the "why" behind a fe | Version | Date | Highlights | |---------|------|------------| +| [v1.4.0](./releases/1.4.0) | 2026-05-23 | Persistent Goals — an employee locks a goal and follows it to done on its own · Subagent delegation became a tree (recursive 3 levels + async + digital-employee builder) · Progressive tool/skill disclosure (`enable_tool` + `load_skill`) · Workspace RBAC (4 roles + capability gating) · Feishu as a first-class citizen (interactive / approval / streaming cards + voice / file / audio / video + channel-native tools) | | [v1.3.0](./releases/1.3.0) | 2026-05-13 | Year one of workflow — 7 step modes assemble employees into business processes · 6 trigger patterns make events drive workflows · Wiki promoted from search index to processing pipeline (user templates + cross-material aggregator + reverse citations) · Per-agent MCP tool binding + multimodal sidecar routing · 4 JVM-native document generation tools + image edit | | [v1.2.0](./releases/1.2.0) | 2026-05-05 | Agents renamed "digital employees" (role / goal / backstory + 5 career templates) · Skills became the skeleton (manifest + template wizard + LESSONS self-evolution) · ACP integration: Claude Code / Codex now show up as your employees · Admin Runtime Console lets you see every employee working in real time | | [v1.1.137](./releases/1.1.137) | 2026-04-29 | It learns from yesterday now · One bad model doesn't take the whole thing down · The "almost good" parts are good now · The knowledge base became a library you can open | diff --git a/mateclaw-server/src/main/resources/docs/en/security.md b/mateclaw-server/src/main/resources/docs/en/security.md index 86124e4e..4404f97c 100644 --- a/mateclaw-server/src/main/resources/docs/en/security.md +++ b/mateclaw-server/src/main/resources/docs/en/security.md @@ -202,6 +202,10 @@ curl -X POST http://localhost:18088/api/v1/security/guard/rules \ }' ``` +### Credential-rule toggles (1.4.0) + +Credential rules now support **per-rule control** — each rule can be enabled/disabled individually, each rule carries its own decision (allow / deny / require_approval), and the entire guard rule set can be **exported and imported as JSON** for migrating between deployments or version-controlling your policy. + ### Dangerous pattern detection In addition to user-defined rules, MateClaw's shell tool has built-in detection for patterns that are dangerous no matter what. `find -delete`, `rm -rf /`, piped downloads through `bash`, and similar patterns trigger elevated approval even if a rule would otherwise allow them. @@ -370,14 +374,20 @@ Workspaces are how MateClaw keeps multiple teams' data separate. Every agent, sk - **Memory files** — every agent's memory is under its workspace's directory - **Channels** — each channel belongs to a workspace -### Roles +### Roles (four-tier RBAC) -| Role | Can do | -|------|--------| -| **Owner** | Everything, including deleting the workspace | -| **Admin** | Everything except deleting/changing owner | -| **Member** | Use agents, read/write wiki, create conversations | -| **Viewer** | Read-only — see agents and KBs, can't create or modify | +Capabilities are **additive** — a higher role inherits everything below it. + +| Role | Capabilities (added on top of the tier below) | +|------|-----------------------------------------------| +| **Viewer** | `chat`, `view:wiki`. Read-only. So that chat works, a Viewer can also read the active model and read an employee's workspace files. | +| **Member** | Viewer + `view:memory`, `view:dashboard`, `manage:wiki`, `manage:agents` | +| **Admin** | Member + `manage:skills`, `manage:channels`, `manage:models`, `manage:security`, `manage:settings` | +| **Owner** | Same as Admin, plus owner-only: delete the workspace, transfer ownership | + +**The backend is the single source of truth for capabilities** — it holds a `RoleCapabilities` mapping, and the frontend never derives them locally. After a workspace switch, or on a capability-related 403, the frontend calls `GET /api/v1/workspaces/{id}/access`, which returns `memberRole`, `isGlobalAdmin`, `effectiveRole`, and `capabilities`. + +**Global admin vs workspace role**: `mate_user.role='admin'` is the system-wide global admin — it manages users, creates workspaces, and spans **all** workspaces with owner-equivalent power even where it isn't a member; `mate_workspace_member.role` is per-workspace. System-level endpoints (models / providers / OAuth / datasources, user management, workspace creation) require a global admin (`@RequireGlobalAdmin`); workspace-scoped endpoints (skills / tools / plugins) require a workspace role — reads need Member, writes need Admin. Full details in [Workspaces](./workspaces). diff --git a/mateclaw-server/src/main/resources/docs/en/skills.md b/mateclaw-server/src/main/resources/docs/en/skills.md index 33b9c752..6820b64b 100644 --- a/mateclaw-server/src/main/resources/docs/en/skills.md +++ b/mateclaw-server/src/main/resources/docs/en/skills.md @@ -95,6 +95,32 @@ Two things to notice. First, the body is a prompt — not a description of one. | `default` | — | Fallback value if caller omits | | `description` | ✅ | What the parameter controls | +### Typed wrapper tools for scripts (new in v1.4) + +A SKILL.md can declare a `scripts:` block that turns each script entrypoint into its **own named tool** with a typed JSON Schema. Instead of one generic `runSkillScript`, the model sees `skill__` tools and fills in schema-described parameters directly. + +```yaml +scripts: + - id: summarize + path: scripts/dispatch.py + fixedArgs: ["summarize"] # prepended verbatim to every call + parameters: + - name: url + type: string + required: true + - id: translate + path: scripts/dispatch.py + fixedArgs: ["translate"] + parameters: + - name: lang + type: string + required: true +``` + +- **One typed tool per entrypoint** — the model gets typed params, not a free-form arg string. +- **`fixedArgs` lets one dispatcher script back several entrypoints** — both entries above call `dispatch.py`, distinguished by the fixed leading arg, so you don't need a separate file per command. +- **Wrappers register/deregister with the skill lifecycle** — they appear when the skill goes live and disappear when it's disabled or archived. Path traversal is blocked: only scripts under the skill's own `scripts/` directory are reachable. A database-only skill (no directory) exposes no wrappers. + --- ## The runtime pipeline @@ -317,7 +343,7 @@ Generate a standup update by analyzing recent git activity. ## Workspace isolation -Each workspace gets its own copy of skills. When you enable a skill for a workspace, its files are staged under that workspace's directory, the skill's tools are scoped to that workspace, and any file the skill writes stays inside the workspace boundary. See [Workspaces](./workspaces). +Each workspace gets its own copy of skills. When you enable a skill for a workspace, its files are staged under that workspace's directory, the skill's tools are scoped to that workspace, and any file the skill writes stays inside the workspace boundary. As of v1.4 the skill **catalog and runtime are scoped per workspace** too, so each workspace sees and runs only its own skills. See [Workspaces](./workspaces). --- @@ -352,6 +378,18 @@ Don't know how to write a SKILL.md? Open the wizard. You don't get just a SKILL.md. You get a **multi-file bundle** — SKILL.md, references/, scripts/, secret references — packaged together. +### The `skill-authoring` meta-skill (new in v1.4) + +There's now a built-in `skill-authoring` skill, auto-seeded on startup, that teaches an agent (or you) how to author a SKILL.md correctly. It covers: + +- **Required frontmatter** and what each field means +- **Validator limits** — name must match `^[a-z0-9][a-z0-9._-]{0,63}$`, content ≤ 100k characters +- **Built-in vs custom** authoring workflows +- **Directory placement** for scripts/ and references/ +- **Common pitfalls** that fail validation or silently misbehave + +Bind it to an agent and "write me a skill that…" produces a valid bundle on the first try, not after three validation round-trips. + --- ## Pre-flight check before installation @@ -472,6 +510,68 @@ As of v1.3, when `ToolExecutionExecutor` sees this case AND `readSkillFile` is b --- +## Progressive skill disclosure (new in v1.4) + +Dumping every skill's full SKILL.md into the system prompt doesn't scale — it blows the token budget and churns the prompt cache on every turn. v1.4 flips the model: the prompt carries only a compact catalog, and the agent **pulls a skill's instructions on demand**. + +**`load_skill(skillName, filePath?)`** loads a skill's SKILL.md (or any bundle file via the optional `filePath`) right when the agent decides to use it: + +- **Injected via message history, not the system prompt** — the loaded content arrives as a conversation turn, so the system prompt (and its cache) stays byte-stable across the session. +- **Loaded skills get pinned** to the top of the runtime catalog on later turns, so the agent keeps seeing what it just pulled in. +- The catalog guidance tells the model to `load_skill(skillName=)` before using a skill, and to call it directly when the user names a specific skill. + +```yaml +mateclaw: + skill: + disclosure: + load-skill-tool: + enabled: true # default; set false to fall back to the older readSkillFile flow +``` + +When disabled, the catalog guidance points at `readSkillFile` instead and `load_skill` is not registered. + +--- + +## Skill lifecycle curator (new in v1.4) + +Agents that synthesize skills accumulate cruft — a one-off skill from three weeks ago is still in the catalog, eating a slot. The **curator** is a daily sweep that ages idle, **agent-created** skills through `active → stale → archived` and gets them out of the way without deleting anything. + +- Idle past `staleAfterDays` (default 30) → **stale**; idle past `archiveAfterDays` (default 90) → **archived** (workspace moved to a `.archived/` subdir). `restore` brings an archived skill back. +- **Never touched**: built-ins, pinned skills, MCP/ACP/virtual skills, and any name starting with a protected prefix (default `sys-`, `ops-`). + +### Settings → Skill Curator panel + +- **Preview (dry-run)** — see exactly which skills the next sweep would move, before it runs. +- **Pause / resume** the whole sweep; **activate / deactivate** an individual skill. +- **Last run / next run** timestamps and **per-state counts** (active / stale / archived). + +### Configuration + +```yaml +mateclaw: + skill: + curator: + enabled: true + cron: "0 0 2 * * *" # daily at 02:00 + staleAfterDays: 30 + archiveAfterDays: 90 + scope: AGENT_CREATED # AGENT_CREATED | ALL_DYNAMIC | OFF + protectPrefixes: ["sys-", "ops-"] +``` + +`scope: AGENT_CREATED` touches only skills with a source conversation; `ALL_DYNAMIC` also sweeps manually-created dynamic skills; `OFF` disables the sweep regardless of `enabled`. + +### Lifecycle in the Skill Market + +The Skills page picks up the lifecycle: + +- **Lifecycle tabs** — Enabled / Stale / Archived. +- Cards show a **"last used"** badge. +- The detail drawer adds **manual archive / restore / pin**. +- Manually archiving a still-bound skill triggers a **confirm handshake** — you don't silently pull a skill out from under a digital employee that's still using it. + +--- + ## ACP bridge: plug in external coding agents ACP (Agent Client Protocol) is a protocol that lets external agent clients (Claude Code, Codex, other compatible clients) plug into MateClaw as skills. @@ -488,6 +588,10 @@ Templates: `claude-code-helper`, `codex-helper` — install and go. A digital employee calls an ACP skill the same way it calls a built-in tool. +### Virtual SKILL.md for MCP/ACP skills (new in v1.4) + +MCP- and ACP-derived skills used to be opaque tool bundles with no readable instructions. v1.4 **synthesizes a read-only virtual SKILL.md** from each MCP/ACP server's metadata (transport, command, args, env, exposed tools), so those integrations show up as **navigable skill catalogs** in the Skills page. Because they're synthesized, virtual SKILL.md rebuilds on every list call — no stale persisted copy to maintain — and `load_skill` can read it just like a real skill, giving the agent a description of what the integration can do before it calls a single tool. + --- ## Detail drawer: everything in one place diff --git a/mateclaw-server/src/main/resources/docs/en/tools.md b/mateclaw-server/src/main/resources/docs/en/tools.md index 7c72b181..7e3a8c43 100644 --- a/mateclaw-server/src/main/resources/docs/en/tools.md +++ b/mateclaw-server/src/main/resources/docs/en/tools.md @@ -54,12 +54,33 @@ None of this shows up in the agent's prompt. The agent just asks for a tool. The **2. MCP servers.** External processes speaking the Model Context Protocol expose tools dynamically. MateClaw discovers them via `tools/list` and they appear in the registry alongside built-in ones. See [MCP](./mcp). +> **Per-agent MCP tool scoping (1.4.0+, #117)**: when an agent has **ticked no specific MCP tool rows**, enabled MCP tools **auto-join** its tool set; once it ticks specific MCP tools, it's **restricted to that set**. Agents bound to skills / built-in tools only keep full access to all MCP tools. + **3. Skill scripts.** Skill packages can ship executable scripts that get wrapped as tools at runtime. See [Skills](./skills). Tool discovery is **blacklist-style** — every discoverable tool is registered by default. Exclude specific tools explicitly. Newly added tools don't get silently missed. --- +## Progressive tool disclosure (1.4.0+) + +As the tool count grows, the system prompt balloons with dozens of full tool schemas — even when a task needs only one or two of them. **Progressive disclosure** splits tools into two tiers so the prompt scales with the **task**, not with the **total tool count**. + +| Tier | How it appears in the system prompt | Callable out of the box? | +|------|-------------------------------------|--------------------------| +| **CORE** | Always advertised in full, with the complete schema | Yes | +| **EXTENSION** | Only a compressed directory — name + source + one-line description; the full schema stays hidden | No — activate with `enable_tool` first | + +**Default tiering**: the generative tools (`image_generate`, `music_generate`, `video_generate`, `model3d_generate`) and `browser_use` default to **EXTENSION**; everything else is **CORE**. + +- **Page control** — the Tools page has Core and Extension sections with a per-row tier toggle for built-in and channel tools; MCP / ACP tools are locked. +- **Persistence** — the tier is stored in `mate_tool.disclosure_tier` and `mate_mcp_server.disclosure_tier`. +- **Config** — `mateclaw.tools.disclosure.mode`, default `progressive`; set it to `legacy` to restore the old "advertise everything" behavior. + +**Why** — to stop context bloat. The system prompt should scale with what the current task needs, not with how many tools you've installed. + +--- + ## The twenty built-in tools | Tool | What it does | Dangerous | @@ -88,6 +109,9 @@ Tool discovery is **blacklist-style** — every discoverable tool is registered | `CronJobTool` | Create and manage scheduled tasks | ⚠️ | | `DatasourceTool` | Manage external datasource connections | ⚠️ | | `SqlQueryTool` | Execute SQL queries on connected datasources | ⚠️ | +| `send_file` | **1.4.0+** Deliver an existing server file as a native IM attachment (#199) | — | +| `enable_tool` | **1.4.0+** Activate an extension-tier tool for this conversation | — | +| `load_skill` | **1.4.0+** Load a skill's `SKILL.md` on demand | — | Plus the `MusicGenerateTool` from [Multimodal](./multimodal). And the 14 Wiki tools from [LLM Wiki](./wiki): `wiki_read_page`, `wiki_read_many`, `wiki_list_pages`, `wiki_search_pages`, `wiki_semantic_search`, `wiki_compile_page`, `wiki_trace_source`, `wiki_create_page`, `wiki_delete_page`, `wiki_archive_page`, `wiki_unarchive_page`, `wiki_related_pages`, `wiki_explain_relation`, `wiki_enrich_page`. @@ -196,6 +220,41 @@ Safety: Reads the built-in MateClaw project documentation. Lets an agent answer "how does X work in MateClaw" questions by consulting actual docs rather than guessing. +### enable_tool — activate an extension-tier tool (1.4.0+) + +`enable_tool(toolName)` activates an **EXTENSION**-tier tool so it becomes fully callable for the **rest of the conversation**. + +- **Validated** — only tools in the agent's effective set can be activated. +- **Takes effect next turn** — activation lands on the **next reasoning turn** of the same ReAct loop (the agent sees the full schema, then emits the real call). +- **Conversation-scoped, not persisted** — activation lasts only for the current conversation; nothing is written to the database, and a new conversation reverts to the default tiering. + +### load_skill — load a skill on demand (1.4.0+) + +`load_skill(skillName, filePath?)` pulls a skill's `SKILL.md` in only when it's needed — omit `filePath` for the main file, or pass one to read a sub-file inside the skill package. + +- **Injected via message history** — the loaded content goes into **message history**, not the system prompt, so the **prompt cache stays stable** (the system prompt is unchanged, so the cache isn't invalidated). +- **Pinned in later turns** — a loaded skill stays **pinned** for the rest of the conversation, so it doesn't have to be reloaded. +- **Config** — `mateclaw.skill.disclosure.load-skill-tool.enabled`, default true. + +See [Skills](./skills). + +### send_file — deliver an existing file as a native attachment (1.4.0+, #199) + +`send_file(filePath, fileName?)` reads an **existing file** on the server and delivers it as a **native IM attachment** — not a text download link. + +- **Stored in the generated-file cache** — the file is placed in the generated-file cache, and channel adapters (Feishu / DingTalk / Telegram) **auto-detect and deliver** it. +- **Any common file type**, up to a **20 MB** limit. +- **Contrast with `ReadFileTool`** — `ReadFileTool` **extracts text** from a file to feed the agent's reasoning; `send_file` ships the file **as-is** to the user. + +### ReadFileTool — oversized-line paging (1.4.0+, #190) + +For files with a very long single line, `ReadFileTool` adds an optional `startColumn` (a 1-based character offset within `startLine`) to **resume the tail** of that line from where you left off. + +- On truncation it **always returns** `nextStartLine`; +- it **additionally returns** `nextStartColumn` when more of that line remains. + +Feed both back into the next call to page through a giant single-line file in segments. + --- ## Tool Guard — the permission layer diff --git a/mateclaw-server/src/main/resources/docs/en/triggers.md b/mateclaw-server/src/main/resources/docs/en/triggers.md index 597db022..208dbd97 100644 --- a/mateclaw-server/src/main/resources/docs/en/triggers.md +++ b/mateclaw-server/src/main/resources/docs/en/triggers.md @@ -102,15 +102,21 @@ The HTTP entry (`POST /api/v1/triggers/events`) → envelope wrap → dedup chec ## Managing triggers from the UI +::: tip 1.4.0 change: merged into the Scheduler +As of v1.4.0, **Scheduled Jobs** and **Triggers** are merged into a single **Scheduler** page (`Settings → Scheduler`, route `/settings/scheduler`) with three tabs: **Scheduled Jobs** / **Event Triggers** / **Run History**. Each tab shows an item count next to its title; the top-right action button is context-aware (it's "New" on the Scheduled Jobs / Event Triggers tabs, "Refresh" on the History tab); Run History **spans both** — execution records for both scheduled jobs and triggers live here. + +The old routes redirect automatically: `/cron-jobs` and `/settings/triggers` each land on the matching Scheduler tab. +::: + ### Entry point -`Triggers` (sidebar) → list + **+ New** drawer. +`Settings → Scheduler` (sidebar) → **Event Triggers** tab. In v1.4.0 the trigger list was redesigned from the old wide table into **rule cards** — one card per trigger, showing pattern type / target / enabled state at a glance. Click **+ New Trigger** to open the drawer. ### Creating a trigger The drawer has structured forms per pattern type — no hand-written `pattern_json`: -- `cron` → cron expression input + timezone dropdown + next-fire preview +- `cron` → cron expression input + timezone dropdown + next-fire preview. The expression can be typed by hand, or click the edit button beside the input to open the **visual cron editor** (see below) - `channel_message` → channel type (optional) + sender id exact-match (optional) - `agent_lifecycle` → agent (optional) + phase: `spawned` / `terminated` / `crashed` (optional) - `content_match` → substring (**required**), matched case-insensitively against envelope `data.content` @@ -119,6 +125,40 @@ The drawer has structured forms per pattern type — no hand-written `pattern_js Save → trigger persists; with `enabled=true` it's registered with the right engine immediately (cron → ShedLock; others → envelope router). +### Visual cron editor (new in 1.4.0) + +You don't have to hand-write the cron expression. Click the edit button beside the expression input to open a **segmented editor**: minute / hour / day / month / day-of-week each get a tab, and each segment offers "every / specific value / range / step"; a row of **presets** up top (every minute, on the hour, daily at midnight, every Monday…) fills it in with one click; at the bottom is a **live human-readable preview** that translates the current expression into plain language (e.g. "every day at 09:00"). + +This editor is the **same component shared by Scheduled Jobs and Triggers**: + +- **Scheduled Jobs** use **5-field** cron (minute hour day month day-of-week) +- **Triggers** use **6-field** cron (with seconds: second minute hour day month day-of-week) — an extra leading seconds field + +The input itself also carries a one-line readable preview, so you can confirm what your hand-typed expression parsed to without opening the editor. + +--- + +## Scheduled-task types (task type) + +Every job on the **Scheduled Jobs** tab of the Scheduler has a `task_type` that decides what it does when it runs. This is the authoritative list of cron task types (the six event-trigger pattern types are covered above): + +| task type | Behavior | Binds an employee? | Notes | +|---|---|---|---| +| `text` / `agent` / `reminder` | Starts an employee conversation on the cron schedule | **Yes** (agent required) | Classic scheduled conversation; the result routes to the conversation | +| `wiki_process` | Processes a knowledge base offline on the cron schedule | **No** | New in 1.4.0 — see below | + +### `wiki_process`: off-peak KB processing (new in 1.4.0) + +`wiki_process` lets you schedule **knowledge-base processing** to run offline during low-traffic windows instead of saturating the processing queue the moment an upload finishes. It **binds no employee** — it's a system task: no conversation, no chat. + +When creating one you only fill in: + +- **cron expression** (use the visual editor above, 5-field) +- **KB selector** — which KB this job processes +- an optional **"force reprocess"** toggle — when on, already-processed raw materials are rerun too (`force`) + +On each tick, the job **asynchronously queues** that KB's raw materials for processing and logs one row in Run History, of the form `queued N raw material(s)` (a `(force)` suffix is appended when force is on). **Note it does not route to any conversation** — it just hands work to the processing queue; check progress on the [LLM Wiki](./wiki.md) page. + ### Payload template The `payload_template` field is a Pebble template string; the rendered output becomes the input to the dispatch target (agent conversation or workflow run). diff --git a/mateclaw-server/src/main/resources/docs/en/workflow.md b/mateclaw-server/src/main/resources/docs/en/workflow.md index e1d08a22..16042d49 100644 --- a/mateclaw-server/src/main/resources/docs/en/workflow.md +++ b/mateclaw-server/src/main/resources/docs/en/workflow.md @@ -203,6 +203,10 @@ Every run persists as `mate_workflow_run` + `mate_workflow_run_step`. Detail vie A workflow run can only start through [Triggers](./triggers.md) or via `await_approval` resume — v0 has no "fire one now" endpoint. See API reference above for details. +::: tip 1.4.0: triggers now live in the Scheduler +As of v1.4.0, **Scheduled Jobs** and **Triggers** are merged into a single **Scheduler** page (`Settings → Scheduler`, route `/settings/scheduler`) with three tabs: **Scheduled Jobs / Event Triggers / Run History**. To attach a trigger to a workflow, create a `target_type=workflow` rule on the Scheduler's **Event Triggers** tab. See [Triggers](./triggers.md). +::: + --- ## API reference diff --git a/mateclaw-server/src/main/resources/docs/en/workspaces.md b/mateclaw-server/src/main/resources/docs/en/workspaces.md index 9fa79947..f0628f0b 100644 --- a/mateclaw-server/src/main/resources/docs/en/workspaces.md +++ b/mateclaw-server/src/main/resources/docs/en/workspaces.md @@ -38,20 +38,31 @@ What's **not** scoped (i.e., global): ## Workspace roles -Each user is assigned to a workspace with one of four roles: +Each user is assigned to a workspace with one of four roles. Capabilities are **additive** — a higher role inherits everything below it: -| Role | Can do | -|------|--------| -| **Owner** | Everything, including deleting the workspace and managing members | -| **Admin** | Everything except deleting the workspace or changing the owner | -| **Member** | Use agents, read/write wiki, create conversations, invoke tools (subject to Tool Guard) | -| **Viewer** | Read-only — see agents and KBs, read conversations, can't create or modify | +| Role | Capabilities (added on top of the tier below) | +|------|-----------------------------------------------| +| **Viewer** | `chat`, `view:wiki`. Read-only. So that chat works, a Viewer can also read the active model and read an employee's workspace files. | +| **Member** | Viewer + `view:memory`, `view:dashboard`, `manage:wiki`, `manage:agents` | +| **Admin** | Member + `manage:skills`, `manage:channels`, `manage:models`, `manage:security`, `manage:settings` | +| **Owner** | Same as Admin, plus owner-only: delete the workspace, transfer ownership | A user can belong to multiple workspaces with different roles. When they switch workspace, their effective permissions switch with them. -### Role scope +### Global admin vs workspace role -Roles control **UI visibility** and **API access**. The console hides menu items users don't have permission to use — a viewer role on a workspace doesn't see the Security menu or the workspace management page at all. The backend enforces the same rules on every API endpoint, so hitting a protected endpoint as a viewer returns `403 Forbidden`. +These are two independent permission systems: + +- **Global admin** — `mate_user.role='admin'`, system-wide. Manages users, creates workspaces, and spans **all** workspaces with owner-equivalent power even where it isn't a member. +- **Workspace role** — `mate_workspace_member.role`, one per workspace, the four roles above. + +System-level endpoints (models / providers / OAuth / datasources, user management, workspace creation) require a global admin (`@RequireGlobalAdmin`); workspace-scoped endpoints (skills / tools / plugins) require a workspace role — reads need Member, writes need Admin. + +### Capability scope — the backend is the source of truth + +Roles control **UI visibility** and **API access**, and **the backend is the single source of truth for capabilities**: it holds a `RoleCapabilities` mapping, and the frontend never derives them locally. After a workspace switch, or on a capability-related 403, the frontend calls `GET /api/v1/workspaces/{id}/access`, which returns `memberRole`, `isGlobalAdmin`, `effectiveRole`, and `capabilities`. + +The frontend gates on this: routes declare a required capability; the sidebar filters by capability (no menu flash before load); a Viewer lands on `/chat`; the sidebar also shows notification badges (pending approvals, stuck employees). The backend enforces the same rules on every API endpoint, so a request lacking the capability returns `403 Forbidden`. --- @@ -79,24 +90,58 @@ curl -X POST http://localhost:18088/api/v1/workspaces \ --- -## Inviting members +## Members & roles -`Settings → Members → Add Member`. Enter an existing MateClaw user's username, pick a role, save. +`Settings → Members`. All member management requires **Admin or above**. -The member immediately sees the workspace in their workspace switcher on next page load. No invite email, no acceptance flow — the member's account already exists in MateClaw. +### Add a member -### Via API +Enter a username, pick a role (defaults to `member`), save. + +- If the user **doesn't exist**, the account is **created on the spot** — a password is required in that case. +- If the user **exists** and you supply a password, their **password is reset** (useful when an admin removes a member, then re-adds them with a new password). +- Nickname is optional. + +The member immediately sees the workspace in their workspace switcher on next page load. No invite email, no acceptance flow. ```bash +# Add by username; creates the account with the given password if it doesn't exist curl -X POST http://localhost:18088/api/v1/workspaces/1/members \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ - "userId": 42, + "username": "alice", + "password": "init-pass-123", + "nickname": "Alice", "role": "member" }' ``` +### Update a member's role (Admin+, cannot change the Owner) + +```bash +curl -X PUT http://localhost:18088/api/v1/workspaces/1/members/42 \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{"role": "admin"}' +``` + +> The path is `/members/{memberId}`, **not** `/members/{memberId}/role`. + +### Remove a member (Admin+, cannot remove the Owner) + +```bash +curl -X DELETE http://localhost:18088/api/v1/workspaces/1/members/42 \ + -H "Authorization: Bearer " +``` + +### List members + +```bash +curl http://localhost:18088/api/v1/workspaces/1/members \ + -H "Authorization: Bearer " +``` + --- ## Switching workspace diff --git a/mateclaw-server/src/main/resources/docs/zh/agents.md b/mateclaw-server/src/main/resources/docs/zh/agents.md index 52400d5a..a2feb22c 100644 --- a/mateclaw-server/src/main/resources/docs/zh/agents.md +++ b/mateclaw-server/src/main/resources/docs/zh/agents.md @@ -116,6 +116,55 @@ head: 例子:让代码 Agent 处理 Jira 工单,同时让研究 Agent 拉竞品数据,同时让写作 Agent 起草 Slack 回复。三路并行,结果汇总给编排者。 +### 多级子员工委派树 + +::: tip 1.4.0 新增 +委派不再只有一层。一个父员工可以委派给子员工,子员工还能再往下委派——**递归最深 3 级**。一支临时团队可以为某个具体任务自己长出层级。 +::: + +三个委派工具,覆盖三种节奏: + +- **`delegateToAgent`** —— 同步委派。把一个子任务交给指定员工,等它跑完、拿到最终结果再返回。可选 `inheritParentContext`:把父会话最近的上下文一起带给子员工,省去重复交代背景。 +- **`delegateParallel`** —— 扇出委派。同时派给多个子员工,各自在隔离会话里跑,结果统一收集回来。 +- **`delegateAsync`** —— 后台委派。立刻返回一个 `task_id`,子员工在后台跑;之后用 **`taskOutput`** 取结果。`taskOutput` 带**归属闸门**——只有最初发起委派的**同一个会话 + 同一个用户**才能读到结果,防止跨会话/跨用户泄露。 + +子员工默认被拒绝一组工具,保证树不失控: + +- `delegateToAgent` / `delegateParallel`(递归护栏——子员工不能再发起同步/并行委派,避免委派风暴) +- `setGoal` 系列 + `remember` 系列(目标与记忆的所有权留在父员工手里) +- `create_employee`(子员工不能凭空造新员工) + +这组默认拒绝列表可通过 `mateclaw.delegation.child-denied-tools` 调整。 + +委派和[目标系统](./goals)配合使用——父员工定目标、拆任务、把子任务委派下去,子员工专注执行。 + +### UI —— 嵌套子员工时间线 + 常驻计划面板 + +ChatConsole 把整棵委派树画出来,不是一串扁平日志: + +- **委派开始**事件清晰标出 +- 每个子员工显示**名字 / 层级深度 / 任务摘要** +- **完成徽标**:成功 / 超时 / 错误,外加耗时、内容长度 +- 每个子员工有稳定的 **id + parentId + depth**,所以嵌套关系在时间线里一眼能看清谁派给了谁 +- **计划面板常驻**——不再只有 Plan-and-Execute 模式才显示,委派树的进度也并入同一个面板 + +--- + +## 一句话造一支团队:数字员工搭建技能 + +::: tip 1.4.0 新增 +不想一个一个手动建员工?给一句话,让"数字员工搭建"技能替你把整支团队搭出来。 +::: + +这个技能从你的一句话出发,走完整条链路: + +1. **澄清需求**——先把模糊的一句话问清楚,确认你真正要解决的问题 +2. **设计角色**——拆成 **2 到 6 个**互补的角色 +3. **逐个创建**——对每个角色调用 `create_employee` 建出真实可用的员工 +4. **串成工作流草稿**——把这几个员工链接成一条[工作流](./workflow)草稿,开箱即可调整 + +配套工具 **`list_capability_catalog`** 让技能先看清当前部署里有哪些工具 / 技能 / 知识库可用,再据此分配角色能力。创建出来的员工**默认即启用**,不用再手动开开关。 + --- ## 深度思考 @@ -233,6 +282,7 @@ System prompt 是数字员工的声音、优先级、约束的来源。**角色 这些是运行时自己在做的事,目的是让 Agent 在你不想去 debug 的那种地方不脆弱: - **上下文修剪**——上下文窗口快满时,早期轮次由 LLM 总结、摘要替换原文。缓存 30 分钟。摘要以用户消息形式注入,不是系统消息——防止历史内容被提升成系统级指令的注入风险。 +- **结构化压缩(prompt 过长时)**——当模型返回"prompt 过长"时,运行时走一条四级递进的结构化压缩链:**软裁剪 → 硬清理 → 预修剪 → LLM 结构化摘要**。无论走到哪一级,都**永远保留前缀**——system prompt + 目标锚点不动;最终摘要以 UserMessage 形式注入。委派工具的返回结果**永远不会被压缩**(它们是子员工的成果,丢了就找不回来)。某次摘要失败后有 **10 分钟冷却**,避免在同一个超限回合里反复硬调 LLM。 - **思考恢复**——流式中途断了,已经写出的思考和内容会持久化,会话重载时还在。 - **迭代上限处理**——到达 `max_iterations` 不会崩溃,而是强制让 LLM 用现有信息生成一个尽力而为的总结答案。 - **僵尸流清理**——后台跟踪每一个打开的 SSE 流,被遗弃的会被自动回收。 diff --git a/mateclaw-server/src/main/resources/docs/zh/api.md b/mateclaw-server/src/main/resources/docs/zh/api.md index 78d14858..f67c6c76 100644 --- a/mateclaw-server/src/main/resources/docs/zh/api.md +++ b/mateclaw-server/src/main/resources/docs/zh/api.md @@ -16,7 +16,7 @@ Authorization: Bearer ``` -深入的行为细节去读对应的功能页——[聊天与消息](./chat)、[Agent 引擎](./agents)、[工具系统](./tools)、[安全与审批](./security)、[LLM Wiki](./wiki)、[多模态创作](./multimodal)、[记忆系统](./memory)、[多渠道接入](./channels)、[模型配置](./models)、[工作空间](./workspaces)、[Doctor](./doctor)。 +深入的行为细节去读对应的功能页——[聊天与消息](./chat)、[Agent 引擎](./agents)、[工具系统](./tools)、[安全与审批](./security)、[LLM Wiki](./wiki)、[多模态创作](./multimodal)、[记忆系统](./memory)、[多渠道接入](./channels)、[模型配置](./models)、[工作空间](./workspaces)、[目标](./goals)、[Doctor](./doctor)。 --- @@ -83,7 +83,9 @@ curl -N http://localhost:18088/api/v1/chat/1/stream?conversationId=conv-abc123 \ ``` GET /api/v1/conversations # 列表(?page&size&agentId) +GET /api/v1/conversations/page?page=&size=&keyword= # 分页会话(带关键词搜索) GET /api/v1/conversations/{id}/messages # 取消息 +PUT /api/v1/conversations/{id}/model # 设置该会话使用的模型 DELETE /api/v1/conversations/{id} # 删除 DELETE /api/v1/conversations/{id}/messages # 清空消息 GET /api/v1/conversations/{id}/status # 会话状态 @@ -109,6 +111,10 @@ DELETE /api/v1/agents/{id}/workspace/files/{filename} # 删除 GET /api/v1/agents/{id}/workspace/prompt-files # 哪些文件被注入 PUT /api/v1/agents/{id}/workspace/prompt-files # 设置注入的文件列表 +GET /api/v1/agents/{agentId}/workspace/memory/export # 导出记忆快照 +POST /api/v1/agents/{agentId}/workspace/memory/import/preview # 预览导入(不落库) +POST /api/v1/agents/{agentId}/workspace/memory/import # 导入记忆快照 + GET /api/v1/agents/templates # 列出模板 POST /api/v1/agents/templates/{id} # 从模板创建 ``` @@ -121,6 +127,7 @@ POST /api/v1/agents/templates/{id} # 从模板创建 GET /api/v1/tools # 列表 PUT /api/v1/tools/{id} # 更新 PUT /api/v1/tools/{id}/toggle?enabled={bool} # 开关 +PUT /api/v1/tools/{id}/disclosure-tier # 设置披露层级(core / extension) POST /api/v1/tools/{name}/test # 直接测试 ``` @@ -323,6 +330,9 @@ GET /api/v1/channels/health # 聚合健康 GET /api/v1/channels/webhook/weixin/qrcode # 微信 iLink 二维码 GET /api/v1/channels/webhook/weixin/qrcode/status # 扫码状态 + +POST /api/v1/channels/qrcode/qq/begin # 发起 QQ 扫码绑定 +GET /api/v1/channels/qrcode/qq/status # QQ 扫码绑定状态 ``` ### 渠道 webhook 回调 @@ -396,6 +406,19 @@ GET /api/v1/triggers/{id}/events # 该 trigger 的事件 --- +## 目标(1.4.0+) + +目标完成评分、自动跟进的行为细节见 [目标](./goals)。 + +``` +POST /api/v1/goals # 新建目标 +GET /api/v1/goals/{id} # 获取目标 +PATCH /api/v1/goals/{id} # 更新目标(部分) +GET /api/v1/goals/{id}/events # 该目标的评估事件历史 +``` + +--- + ## Token 用量 ``` @@ -435,10 +458,27 @@ GET /api/v1/workspaces/{id} # 获取 POST /api/v1/workspaces # 创建 PUT /api/v1/workspaces/{id} # 更新 DELETE /api/v1/workspaces/{id} # 删除(仅 owner) -GET /api/v1/workspaces/{id}/members # 列成员 -POST /api/v1/workspaces/{id}/members # 添加成员 -DELETE /api/v1/workspaces/{id}/members/{userId} # 移除成员 -PUT /api/v1/workspaces/{id}/members/{userId}/role # 变更角色 +GET /api/v1/workspaces/{id}/access # 当前用户访问信息(见下) +``` + +### 成员与 RBAC(1.4.0+) + +`/access` 返回调用者在该工作空间内的有效权限,前端据此渲染路由和菜单: + +```json +{ + "memberRole": "editor", + "isGlobalAdmin": false, + "effectiveRole": "editor", + "capabilities": ["workspace.read", "conversation.write", "..."] +} +``` + +``` +GET /api/v1/workspaces/{id}/members # 列成员 +POST /api/v1/workspaces/{id}/members # 添加成员 +PUT /api/v1/workspaces/{id}/members/{memberId} # 更新成员(角色等) +DELETE /api/v1/workspaces/{id}/members/{memberId} # 移除成员 ``` --- diff --git a/mateclaw-server/src/main/resources/docs/zh/architecture.md b/mateclaw-server/src/main/resources/docs/zh/architecture.md index 33dc2c31..75bfc597 100644 --- a/mateclaw-server/src/main/resources/docs/zh/architecture.md +++ b/mateclaw-server/src/main/resources/docs/zh/architecture.md @@ -134,7 +134,7 @@ mateclaw/ - `agent/graph/StateGraphReActAgent.java`——装配 ReAct 循环 - `agent/graph/plan/StateGraphPlanExecuteAgent.java`——装配 Plan-and-Execute 图 -- `agent/graph/node/`——`ReasoningNode`、`ActionNode`、`ObservationNode`、`FinalAnswerNode`、`SummarizingNode`、`LimitExceededNode` +- `agent/graph/node/`——`ReasoningNode`、`ActionNode`、`ObservationNode`、`FinalAnswerNode`、`SummarizingNode`、`LimitExceededNode`、`GoalEvaluationNode` - `agent/graph/plan/node/`——`PlanGenerationNode`、`StepExecutionNode`、`PlanSummaryNode`、`DirectAnswerNode` - `agent/graph/edge/` + `plan/edge/`——基于状态决定下一个节点的 dispatcher 函数 - `agent/graph/state/MateClawStateKeys.java`——共享 state 对象的 key @@ -149,6 +149,17 @@ mateclaw/ **不要**创建新的 `XxxAgent` 类。你会把图已经在做的事情重新实现一遍。 +### 目标评估节点(1.4.0+) + +图(ReAct 和 Plan-Execute 都有)现在在 `FinalAnswerNode` 把最终答案流式输出之后再跑一个 `GoalEvaluationNode`:它给目标完成度打分,并可选地注入一条自动跟进消息,把没达成的目标继续推进。 + +### 其他 1.4.0 运行时变化 + +- **渐进式工具/技能披露**——工具披露层把工具分成核心层(core)和扩展层(extension)两档;`enable_tool` / `load_skill` 让员工按需激活扩展工具、按需加载技能,从而把系统提示保持得足够小。 +- **多级子员工委派树**——父员工到子员工的委派是递归的、有深度上限的,构成一棵树;子图的事件实时回流到根会话。 +- **ChannelToolProvider SPI**——渠道(比如飞书)可以把平台能力直接作为员工工具暴露出来,不需要单独的 MCP 服务器。 +- **工作空间 RBAC**——能力(capability)由后端的「角色 → 能力」映射解析,同时门禁 REST 接口和前端路由/菜单。 + ### 共享 state key | Key | 用途 | diff --git a/mateclaw-server/src/main/resources/docs/zh/backstage.md b/mateclaw-server/src/main/resources/docs/zh/backstage.md index 46c9a290..69036d9f 100644 --- a/mateclaw-server/src/main/resources/docs/zh/backstage.md +++ b/mateclaw-server/src/main/resources/docs/zh/backstage.md @@ -19,8 +19,12 @@ head: ## 怎么打开 -- **路由:** `/backstage` -- **侧边栏:** "运维"区下的顶级条目 +::: tip 1.4.0:实时视图并入员工页 +v1.4.0 起,这块实时运行时视图被折叠进了**员工(Employees)页**。`/backstage` 现在会**重定向到** `/agents?view=live`;员工页顶部有一个 **花名册(Roster)/ 实时(Live)** 的分段切换——"实时" 就是本文描述的运行时控制台。下面提到的"路由 `/backstage`"仍然可用,只是会落到员工页的实时视图。 +::: + +- **路由:** `/backstage`(重定向到 `/agents?view=live`) +- **侧边栏:** 员工页的 **实时** 分段;当有员工卡死时,侧边栏会冒出一个**橙色"卡死员工"小圆点**,点它直接跳到这个实时视图 - **权限:** JWT 必须带 `ROLE_ADMIN`。非 admin 调用 `/api/v1/admin/agent-runtime/*` 全部 403,路由守卫还会把侧边栏入口直接藏起来。 --- diff --git a/mateclaw-server/src/main/resources/docs/zh/channels.md b/mateclaw-server/src/main/resources/docs/zh/channels.md index 7a7543ef..accf2aea 100644 --- a/mateclaw-server/src/main/resources/docs/zh/channels.md +++ b/mateclaw-server/src/main/resources/docs/zh/channels.md @@ -20,6 +20,21 @@ v1.3.0 在渠道层做了一批长跑稳定性 + 群协作的工作: 企业微信的细节调优全部在 [企业微信深度优化](./wecom-tuning) 里。 ::: +::: tip 1.4.0 渠道层增强 +v1.4.0 把飞书做成了"一等公民"渠道——交互卡片、流式卡片、审批卡片、原生工具、媒体收发,外加 QQ 扫码绑定: + +- **飞书交互卡片(Schema 2.0)**:结构化回复自动渲染成飞书交互卡片,短文本仍走纯文本 +- **飞书审批卡片**:工具守卫的审批流以"同意 / 拒绝"按钮卡片送达,点一下就把工具跑完 +- **飞书流式卡片(CardKit)**:回复逐字刷新进同一张卡片 +- **飞书入站语音转写**:语音消息走 STT 转成文字喂给 Agent +- **飞书入站文件 / 音视频下载**:不再只下图片;`media_download_enabled` **默认在 1.4.0 改为 true** +- **飞书渠道原生工具**:日历查询、文档读 / 写,无需配置 MCP 服务器 +- **QQ 扫码绑定**:QQ 也有了和钉钉 / 飞书一致的扫码绑定引导 +- **全 IM 渠道按会话选模型**:IM 会话与 Web 一样按会话记住模型 + +飞书的细节全部在下面[飞书](#飞书)一节里展开。 +::: + --- ## 九个渠道 @@ -247,6 +262,97 @@ curl -X POST http://localhost:18088/api/v1/channels \ Webhook URL:`https://your-domain/api/v1/channels/webhook/feishu` +### 飞书 1.4.0 增强 + +v1.4.0 把飞书从"能收发文本"升级成了完整的富交互渠道。下面这些大多数零配置就能用,列出来是为了让你知道开关在哪、默认值是什么。 + +#### 交互卡片(Schema 2.0) + +结构化回复——JSON、带表头 / 表格 / 列表的 Markdown、长文本——会自动渲染成飞书**交互卡片**;短的纯文本仍然以普通文本消息发出。 + +| 配置项 | 默认 | 说明 | +|--------|------|------| +| `card_format` | `auto` | `auto` 按内容自动判断;`always` 强制走卡片(调试用);`never` 强制纯文本 | +| `card_header` | `AI 助手` | 卡片标题文案,设为空串可隐藏 header | + +JSON 卡片 payload 上限约 32 KB,超出后自动降级为纯文本。 + +#### 审批卡片 + +工具守卫(tool-guard)的审批流以一张带**同意 / 拒绝**按钮的卡片送达。点**同意**会注入一条合成的 `/approve`、点**拒绝**注入 `/deny`,Agent 随即把获批的工具完整跑完——审批和执行在同一个会话里闭环,不用切回 Web 控制台。 + +#### 流式卡片(CardKit) + +回复逐字刷新进**同一张卡片**,而不是等整段生成完再发。 + +- `card_streaming_enabled`(默认 `true`) +- 首 token 立即出现,之后按 500ms 节流刷新 +- CardKit 调用失败时自动回退到"先攒齐再一次性发出" + +#### 入站语音转写 + +飞书语音消息走语音识别(STT)转成文字后喂给 Agent——Agent 收到的是真正的文字,而不是一个 `[audio]` 占位。**配置好 STT 后自动启用**,无需额外开关。 + +#### 入站文件 / 音视频下载 + +1.4.0 之前只下载图片;现在文件、音频、视频也会被下载、本地缓存,并通过 `/api/v1/files/generated/{id}` 提供给 Agent。 + +::: warning 默认值变化 +`media_download_enabled` 在 1.4.0 **默认改为 `true`**。如果你在意磁盘占用或隐私,可以显式设为 `false` 退出。 +::: + +大小与格式约束:图片上限 10 MB(超出自动压缩),文件 / 音频 / 视频上限 30 MB;音频仅支持 opus、视频仅支持 mp4,其余格式降级为普通文件处理。 + +#### 出站生成文件 → 原生附件 + +Agent 生成的文件 URL 会被还原成飞书**原生附件**直接发出。若缓存已失效(cache miss),回复里会附带一句重试提示,而不是甩一个失效链接。 + +#### 渠道原生工具(无需 MCP 服务器) + +绑定飞书渠道后,Agent 直接获得三个飞书原生工具,**不需要单独配 MCP 服务器**: + +| 工具 | 类型 | 默认 | +|------|------|------| +| `feishu_calendar_list_events` | 读 | 开 | +| `feishu_doc_read` | 读 | 开 | +| `feishu_doc_create` | 写 | 关,审批门控 | + +数据库内置的守卫规则会给写类工具(如 `feishu_doc_create`)自动套上 `NEEDS_APPROVAL`,触发上面的审批卡片流程。 + +#### 发送者上下文注入 + +群聊里 Agent 需要知道"谁在说话"。飞书消息进来时,Agent 的 prompt 会自动带上 Channel / Sender /(群聊时)Chat 几行上下文。**零配置。** + +#### DONE 反应 + +成功回复后,机器人会在那条入站消息上贴一个 ✅ 表情,作为"已处理"的轻量回执。`enable_done_reaction`(默认 `true`)。 + +#### @机器人 过滤 + +群聊里默认有人发言机器人就响应。把 `require_mention` 设为 `true`(默认 `false`)后,只有 @机器人 才触发——判定走飞书 SDK 的 mentions 字段。机器人自身的 open_id 在启动时预取,并带 60 秒负缓存(取不到时门"放行",不会因为一次失败把整个群锁死)。 + +```bash +curl -X POST http://localhost:18088/api/v1/channels \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "name": "飞书机器人", + "type": "feishu", + "agentId": 1, + "config": { + "appId": "cli_your_app_id", + "appSecret": "your-app-secret", + "card_format": "auto", + "card_header": "AI 助手", + "card_streaming_enabled": true, + "media_download_enabled": true, + "enable_done_reaction": true, + "require_mention": false + }, + "enabled": true + }' +``` + --- ## 企业微信 @@ -377,6 +483,25 @@ curl -X POST http://localhost:18088/api/v1/channels \ ## QQ +WebSocket / 回调两种模式,官方机器人平台。 + +### 一键扫码绑定(推荐,v1.4.0+) + +和钉钉 / 飞书一样,QQ 也支持扫码绑定——不用手动去开放平台抄 AppID / AppSecret。 + +1. `渠道 → 新建 → 类型选 QQ` +2. 表单里点**扫码绑定 QQ 应用**——展开一张 QR 码 +3. 用 QQ 扫码并**确认授权** +4. 回到表单,**AppID 和 AppSecret 已自动回填** + +::: tip 它在做什么 +背后走 QQ 开放平台的精简版(Lite)授权门户:MateClaw 生成一个临时会话,凭证通过 AES-256-GCM 加密交换落地到表单。会话 12 分钟内有效,过期自动失效。**整个过程没有手抄凭证这一步。** +::: + +### 手动配置应用(备选) + +如果扫码在你的网络下走不通: + 1. [QQ 开放平台](https://q.qq.com/) → 创建机器人应用 ![QQ 开放平台](/images/channels/qq/01-open-platform.png) ![创建机器人](/images/channels/qq/02-create-bot.png) @@ -510,6 +635,12 @@ IM 渠道(企业微信、微信、钉钉)都支持语音输入。语音识 --- +## 按会话选模型(全 IM 渠道) + +从 1.4.0 起,IM 渠道的会话和 Web 一样会**按会话记住模型**——每个 IM 会话在创建时 seed 一个会话级模型,之后的回复都尊重这个选择,而不是永远用 Agent 的默认模型。Web 侧的切换细节见 [聊天与消息](./chat)。 + +--- + ## 值得知道的事 - **Webhook 模式需要 HTTPS。** 生产部署应该用 Nginx + SSL 挡在 MateClaw 前面。 diff --git a/mateclaw-server/src/main/resources/docs/zh/chat.md b/mateclaw-server/src/main/resources/docs/zh/chat.md index 84b07adb..8eefbdda 100644 --- a/mateclaw-server/src/main/resources/docs/zh/chat.md +++ b/mateclaw-server/src/main/resources/docs/zh/chat.md @@ -171,6 +171,62 @@ SSE 流 / 直接响应 ← segment 一段一段送 Segment 的结构是渐进展示的底层。它也让**数据库成为单一事实源**——UI 可以把任何一条历史回复完整地复现成它流式时的样子。 +### 按会话选模型 + +::: tip 1.4.0 新增 +聊天顶栏的模型选择器现在把模型**绑定在会话上**,而不是全局开关。详见 [issue #150](https://github.com/matevip/mateclaw/issues/150)。 +::: + +在顶栏切换模型,只影响**当前这个会话**:选择会随会话存下来,并从**下一条消息**开始生效。没有显式设置过的会话,回落到工作空间默认模型。运行时模型指示器始终和会话上钉住的那一个保持同步——你看到的就是下一回合真正会用的。 + +这条隔离也让模型配置更健壮:**一个写错的模型 id 不再拖垮它所在的整个 Provider**。坏会话只影响自己,其他会话照常跑。 + +### 会话列表管理 + +::: tip 1.4.0 新增 +会话侧栏从一条单纯的历史列表,升级成了一个可操作的运营面板。详见 [issue #144](https://github.com/matevip/mateclaw/issues/144)。 +::: + +- **置顶 / 取消置顶**——从每行的 `⋮` 溢出菜单操作,重要的会话固定在列表顶部的「置顶」分组里。 +- **多选批量删除**——进入多选模式后,每行出现复选框,勾选若干条一次性删除。 +- **按员工筛选**——当工作空间里有 **2 个及以上员工**时,侧栏顶部出现一个下拉,按员工过滤会话列表(只有一个员工时不显示,避免无意义的控件)。 +- **状态点**——一眼看出每个会话的状态:正在生成(蓝色脉冲)、存在进行中的目标、有未读内容。 + +### 全局快捷键 + +::: tip 1.4.0 新增 +两个全局快捷键,让你不碰鼠标就能在对话之间跳转。提示常驻在侧栏底部。 +::: + +| 快捷键 | 行为 | +|--------|------| +| `Ctrl/Cmd + K` | 打开员工选择器,跳到任意一个聊天 | +| `Ctrl/Cmd + N` | 新建一个会话 | + +`Ctrl+N` 在你正于输入框 / 文本域里打字时不会触发,留给浏览器原生行为。 + +### 会话管理页 + +::: tip 1.4.0 新增 +当会话多到侧栏装不下时,从聊天顶栏的溢出菜单进「会话管理」,去一个专门的管理页(`/sessions`)。 +::: + +这个页面是为「会话很多」而生的: + +- **服务端分页**——不再一次把上千条会话塞进侧栏。 +- **按标题 / ID 搜索**——输入即筛,定位到具体会话。 +- **深度卡片布局**——每个会话一张卡片,信息密度比侧栏更高。 +- **行内可编辑的模型 chip**——每行直接显示并切换该会话的模型,不用先进会话。 +- **返回按钮**——一键回到聊天控制台。 + +### 共享的员工选择器 + +::: tip 1.4.0 新增 +一个共享的选择器对话框,被三处复用:侧栏、`Ctrl+K` 快捷键、以及新建会话弹窗。 +::: + +三个入口打开的是**同一个对话框**,行为完全一致。对话框里的 Agent 图标**按员工做了颜色区分**,多员工工作空间里一眼就能认出谁是谁。 + --- ## 上下文窗口管理 diff --git a/mateclaw-server/src/main/resources/docs/zh/console.md b/mateclaw-server/src/main/resources/docs/zh/console.md index 06ce86e3..8a68eb69 100644 --- a/mateclaw-server/src/main/resources/docs/zh/console.md +++ b/mateclaw-server/src/main/resources/docs/zh/console.md @@ -38,6 +38,13 @@ **你没权限看的页面会被隐藏**。 +### 侧栏通知徽标(1.4.0 新增) + +侧栏会在两处冒出实时徽标,提示需要你处理的事: + +- **待审批**——红色数字角标,点击跳到 [安全与审批](./security) +- **卡死员工**——橙色小圆点,点击跳到员工页的**实时**运行时视图(见 [Backstage](./backstage)) + ### 认证守卫 除了 `/login` 之外每条路由都被路由守卫保护。开发时设置 `VITE_SKIP_AUTH=true` 绕过。 @@ -68,7 +75,7 @@ 首次登录自动显示。四步向导: 1. **欢迎**——简短的产品概览 -2. **配一个模型**——选一个供应商粘贴 API Key(或 OAuth 进 ChatGPT Plus、或自动探测 Ollama) +2. **配一个模型**——选一个供应商粘贴 API Key(或 OAuth 进 ChatGPT Plus、或自动探测 Ollama);1.4.0 起这一步直接做**供应商启用**——勾上要用的供应商即开即用 3. **挑一个 Agent 模板**——根据选择种一个默认 Agent 4. **发第一条消息**——一个测试 prompt,让你能看到流式工作 @@ -162,10 +169,15 @@ Agent 的 CRUD,表格呈现。 **路由:** `/sessions` +::: tip 1.4.0:真正的会话管理页 +v1.4.0 起 `/sessions` 是一个独立的会话管理页,从**聊天页头部的溢出菜单**进入。它带**服务端分页** + 按**标题 / ID** 搜索,采用层次化的**卡片布局**,每行还有一个**可原地编辑的模型芯片**——直接在列表里给某个会话改默认模型。 +::: + 浏览所有 Agent 和渠道下的对话。 -- 按关键字搜索 +- 按关键字搜索(标题 / ID,服务端分页) - 会话标题、ID、Agent、消息数、状态、上次活跃时间 +- 每行**可原地编辑的模型芯片** - 渠道来源图标 - 跳进聊天控制台 - 删除历史会话 @@ -222,9 +234,13 @@ Agent 的 CRUD,表格呈现。 --- -### 12. 定时任务 +### 12. 定时任务(调度中心) -**路由:** `/cron-jobs` +**路由:** `/settings/scheduler`(旧 `/cron-jobs` 自动重定向) + +::: tip 1.4.0:合并为调度中心 +v1.4.0 起,**定时任务**和**触发器**合并为单个**调度中心**页面(`设置 → 调度中心`),分**计划任务 / 事件触发器 / 运行历史**三个 tab,每个 tab 旁带条目计数,右上角动作按钮随当前 tab 变化。计划任务支持 `wiki_process` 类型(错峰处理知识库)和**可视化 cron 编辑器**。详见 [触发器](./triggers)。 +::: 按 cron 调度触发 Agent 对话的计划任务。 @@ -262,6 +278,7 @@ Agent 的 CRUD,表格呈现。 **路由:** `/dashboard` - 汇总卡片——活跃 Agent、今天对话数、今天工具调用数、待审批数 +- **模型配置卡片**(1.4.0 新增)——列出已启用的 LLM 供应商,每个带**连通状态**和**当前活跃模型**,并附一个跳到模型设置的链接 - **趋势图**——7 / 30 / 90 天的消息 / 工具调用 / token 用量 - **Top Agent / Top 工具**——按用量排名 - 近期审批活动 @@ -278,7 +295,7 @@ Agent 的 CRUD,表格呈现。 ### 17. 设置 -子路由布局,四个子页面。 +子路由布局,四个子页面。设置子导航底部钉了一个浮动按钮,可**折叠/展开**子导航(1.4.0 新增)。 #### 17.1 模型 @@ -508,7 +525,7 @@ fetch('/api/v1/chat/stream', { /mcp-servers —— MCP 服务 /channels —— 渠道 -/cron-jobs —— 定时任务 +/settings/scheduler —— 调度中心(计划任务 / 事件触发器 / 运行历史;旧 /cron-jobs 重定向到此) /datasources —— 数据源 /token-usage —— Token 用量 /dashboard —— 仪表盘 diff --git a/mateclaw-server/src/main/resources/docs/zh/memory.md b/mateclaw-server/src/main/resources/docs/zh/memory.md index 10d18cff..d0a10750 100644 --- a/mateclaw-server/src/main/resources/docs/zh/memory.md +++ b/mateclaw-server/src/main/resources/docs/zh/memory.md @@ -302,6 +302,21 @@ mateclaw: | `write_workspace_memory_file` | 创建或覆盖一个文件(全覆盖) | | `edit_workspace_memory_file` | 按精确查找替换编辑(增量更新,支持 `replaceAll`) | +### 关键词搜索自己的记忆 + +::: tip 1.4.0 新增 +员工不止能读整个文件——它在对话中可以按**关键词搜索自己工作空间里的全部记忆文件**,直接定位到某一行。 +::: + +这是一个 Agent 运行时能力:员工给一个关键词,系统在它自己的工作空间记忆文件里做检索: + +- **分词**——中文按 2 字滑动窗口切,拉丁文按空格切,两种语言都能命中 +- **按文件加权打分**——`AGENTS.md` / `MEMORY.md` / `PROFILE.md` 这类核心文件的命中权重高于每日笔记 +- **返回结果**——每条命中给出:文件名 + 行号 + 80 字上下文片段(命中词高亮) + 相关性分数 +- **扫描范围**——最多扫约 50 个候选文件,按分数从高到低排序 + +适用场景:员工想确认"我之前是不是记过这件事"、跨多天笔记找回某个具体决定,而不需要把整份文件读进上下文。 + ### 示例 **列表:** @@ -343,6 +358,41 @@ mateclaw: --- +## 记忆快照导出 / 导入 + +::: tip 1.4.0 新增 +一个员工积累的整份记忆可以打包成一个 ZIP 带走——备份、迁移到另一套部署、或者克隆一个"已经认识你"的同事。 +::: + +快照把一个员工的核心记忆打包成单个 ZIP: + +- `AGENTS.md` / `MEMORY.md` / `PROFILE.md` / `SOUL.md` / `KNOWLEDGE.md` +- 每日笔记(`memory/YYYY-MM-DD.md`) +- 一份 `manifest.json`(记录包里有什么、来自哪个员工) + +### 三个端点 + +| 方法 | 路径 | 权限 | 作用 | +|------|------|------|------| +| GET | `/api/v1/agents/{agentId}/workspace/memory/export` | Viewer | 导出 ZIP——只读权限也能做备份 | +| POST | `.../workspace/memory/import/preview` | Member | **干跑**:解析 ZIP,逐文件给出 create / update / skip 分类,不写任何东西 | +| POST | `.../workspace/memory/import` | Member | 应用导入,**原子写入** | + +先 preview 看清差异,确认后再 import——导入前你永远知道会改动什么。 + +### 安全护栏 + +- **白名单**——只接受上面列出的那几类文件,其余忽略 +- **防 zip 炸弹**——条目数 ≤ 500、单条解压 ≤ 1 MB、总计 ≤ 16 MB,超了直接拒绝 +- **不序列化 UI 开关状态**——`enabled` / `sortOrder` 不进快照;导入到新员工时由目标端按种子规则决定,不会把源端的开关状态强加过来 + +### UI + +- **Agent Context 页面右侧面板**有 **Export / Import** 两个按钮 +- 导入时先弹出**差异对比**(哪些新建、哪些覆盖、哪些跳过),确认后才真正写入 + +--- + ## 配置参考 ### 记忆提取 & 整合 diff --git a/mateclaw-server/src/main/resources/docs/zh/models.md b/mateclaw-server/src/main/resources/docs/zh/models.md index 541bdff5..db649f09 100644 --- a/mateclaw-server/src/main/resources/docs/zh/models.md +++ b/mateclaw-server/src/main/resources/docs/zh/models.md @@ -19,7 +19,8 @@ MateClaw 不关心你用哪个 LLM。它通过五个协议适配器跟所有主 | **OpenAI OAuth(ChatGPT Plus/Pro)** | 通过订阅用 GPT-4o、o3、o4-mini | openai | 浏览器 OAuth,**不需要 API Key** | | **Anthropic** | Claude 4.7、Claude 4.6 Sonnet、Claude 4.5 Haiku | anthropic | 原生 Messages API | | **Anthropic Claude Code OAuth** | 通过 Claude Pro/Max/Team 订阅用 Claude 4.7 / 4.6 | anthropic | 浏览器 OAuth + 手动粘贴流,**不需要 API Key** | -| **Google Gemini** | Gemini 2 Pro、Gemini 2 Flash | gemini | Google Generative AI API | +| **Google Gemini** _(原生)_ | gemini-2.5-flash、gemini-3-pro-image-preview、gemini-2.5-flash-image | gemini | 原生 `generateContent` API(非 OpenAI 兼容)——见下方"原生 Gemini" | +| **xAI / Grok** | Grok 3、Grok 4 | openai | OpenAI 兼容(base URL + API Key);UI 带 xAI 品牌图标 | | **DeepSeek** | deepseek-chat、deepseek-coder、**DeepSeek V4 flash + pro**(支持思考模式) | openai | OpenAI 兼容 | | **Kimi(Moonshot)** | moonshot-v1-8k/32k/128k | openai | OpenAI 兼容 | | **智谱 AI** | GLM-5-Turbo、GLM-5V-Turbo、GLM-5、GLM-5.1 | openai | OpenAI 兼容 | @@ -75,6 +76,23 @@ MateClaw 不关心你用哪个 LLM。它通过五个协议适配器跟所有主 --- +## 原生 Gemini + +::: tip 1.4.0 新增 +Gemini 不再走 OpenAI 兼容层——MateClaw 直接对接 Google 的**原生 `generateContent` API**。 +::: + +很多产品把 Gemini 当成"又一个 OpenAI 兼容端点"来接,结果在系统指令、函数调用、内联图片这些地方处处碰壁。MateClaw 走的是 Gemini 自己的协议: + +- **原生 chat builder** —— 正确映射 `systemInstruction`(系统指令)、`functionCall` / `functionResponse`(工具调用回合)、以及内联图片 part(多模态输入) +- **流式 SSE 解析** —— 按 Gemini 的流式响应格式逐块解析 +- **JSON Schema 清洗** —— 自动剥掉 Gemini 不接受的 JSON Schema 关键字,避免工具定义被拒 +- **启动探活** —— 启动时发一个轻量请求确认凭证与模型可用 + +配置方式:`设置 → 模型 → 添加供应商`,选 **Gemini** 供应商,填 API Key。示例模型:`gemini-2.5-flash`、`gemini-3-pro-image-preview`、`gemini-2.5-flash-image`。图像生成走原生路径,详见 [多模态创作 → 图像生成](./multimodal#图像生成-六个供应商)。 + +--- + ## 添加一个供应商 **新装的 MateClaw 主列表是空的。这是故意的。** @@ -255,6 +273,10 @@ ollama pull qwen3 不用配 `EMBEDDING_API_KEY` 环境变量。嵌入模型就是 `mate_model_config` 里 `model_type='embedding'` 的普通行。`设置 → 模型` 里和聊天模型列在一起。知识库从下拉里选它的嵌入模型。 +::: tip 1.4.0 新增([issue #79](https://github.com/matevip/mateclaw/issues/79)) +**任意供应商都能提供嵌入模型。** 在 `设置 → 模型` 的嵌入区域里,配一个来自任何供应商的嵌入模型——直接**复用那家供应商的 API Key**,不再单独要 `EMBEDDING_API_KEY`。每个知识库从下拉里挑自己的嵌入模型。无密钥的本地代理用一个空操作占位 key;协议从该供应商的聊天模型 / protocol 设置里自动解析,不用再手填。 +::: + ### Anthropic prompt 缓存 系统 prompt、Agent 人格、工具定义——在 Anthropic 兼容端点上自动带 `cache_control: ephemeral`。第一次请求热身,之后每次缓存命中。Dashboard 里有 `cache_read_tokens` / `cache_write_tokens` 日维度统计。 @@ -276,7 +298,9 @@ ollama pull qwen3 **Kimi K2.5 thinking**:模型自带 thinking,也不接受 `reasoning_effort`。 -**多轮 tool call + thinking**:带 thinking 的模型(DeepSeek-Reasoner / GPT-5 / Kimi K2.5)在 ReAct 多轮 tool call 场景下,历史消息的 `reasoning_content` 会正确回传给 provider;跨用户问题边界时自动清除,同一问题内的子轮次全部保留——符合 DeepSeek 的"同问题子轮必须回传、跨问题时清"契约。 +**多轮 tool call + thinking**:带 thinking 的模型(DeepSeek-Reasoner / GPT-5 / Kimi K2.5 / 小米 MiMo)在 ReAct 多轮 tool call 场景下,历史消息的 `reasoning_content` 会正确回传给 provider;跨用户问题边界时自动清除,同一问题内的子轮次全部保留——符合 DeepSeek 的"同问题子轮必须回传、跨问题时清"契约。 + +**小米 MiMo 思考模式多轮修复**([issue #189](https://github.com/matevip/mateclaw/issues/189)):MiMo 思考模式的 `reasoning_content` 现在能在多轮对话里正确保留,不再在后续轮次丢失。 --- @@ -299,6 +323,11 @@ MateClaw 用一个**活跃模型**作为全局默认。没有指定自己模型 也支持按 Agent 覆盖:把某个 Agent 绑定到特定模型配置。 +::: tip 1.4.0 新增 +- **按会话选模型**([issue #150](https://github.com/matevip/mateclaw/issues/150)):在聊天界面里可以为**当前这一条会话**临时切换模型,不影响全局活跃模型和别的会话。详见 [聊天与消息](./chat)。 +- **单个坏模型 id 不再连累整个供应商**:发现 / 探活时遇到一个无效的模型标识符,只跳过那一个模型,供应商下其余模型照常可用。 +::: + --- ## 单模型测试 diff --git a/mateclaw-server/src/main/resources/docs/zh/multimodal.md b/mateclaw-server/src/main/resources/docs/zh/multimodal.md index 31a3abf7..ea276064 100644 --- a/mateclaw-server/src/main/resources/docs/zh/multimodal.md +++ b/mateclaw-server/src/main/resources/docs/zh/multimodal.md @@ -17,7 +17,7 @@ | **DashScope** | 通义万相 | 阿里的图像模型,默认云端选项 | | **OpenAI** | DALL-E 3 | 标准 DALL-E 端点 | | **fal.ai** | Flux | 通过 fal.ai 跑 Flux,快 | -| **Google Imagen** | Imagen 3 | 需要 Google Cloud 凭证 | +| **Google(Nano Banana)** | gemini-3-pro-image-preview、gemini-2.5-flash-image | 走原生 Gemini 路径;**支持图像编辑**——见下方 [Nano Banana](#nano-banana) | | **智谱** | CogView | 对中文 prompt 原生支持 | | **MiniMax** | —— | 同步异步都可以 | @@ -61,6 +61,17 @@ Agent:image_generate(prompt="把背景改成森林", 在 [模型配置](./models#两个-dashscope-区别) 文档里有更全的模型清单。 +#### Nano Banana + +::: tip 1.4.0 新增 +Google 的图像生成走 **Nano Banana Pro**(`gemini-3-pro-image-preview`),通过[原生 Gemini 路径](./models#原生-gemini)调用,不经过 OpenAI 兼容层。 +::: + +因为走的是原生 `generateContent` 端点,图像工具会把输入图片作为**内联 part**直接传给模型——所以 Nano Banana 不只是文生图,**还支持图像编辑**(图生图)。用法和上面的 [Image edit](#image-edit) 完全一致:传 `image` / `images` 参数引用一张或多张参考图即可。 + +- **Nano Banana Pro** —— `gemini-3-pro-image-preview`(默认) +- **Nano Banana** —— `gemini-2.5-flash-image`(另一个 Google 图像模型) + ### 视频生成 —— 六个供应商 - **DashScope**——通义万相视频 diff --git a/mateclaw-server/src/main/resources/docs/zh/releases.md b/mateclaw-server/src/main/resources/docs/zh/releases.md index ec028af4..0e63f1a7 100644 --- a/mateclaw-server/src/main/resources/docs/zh/releases.md +++ b/mateclaw-server/src/main/resources/docs/zh/releases.md @@ -10,6 +10,7 @@ | 版本 | 日期 | 亮点 | |------|------|------| +| [v1.4.0](./releases/1.4.0) | 2026-05-23 | 持久化目标——员工锁住目标自己跟到完成 · 子员工委派变成一棵树(递归 3 层 + 异步 + 数字员工构建器) · 渐进式工具/技能披露(`enable_tool` + `load_skill`) · 工作空间 RBAC(四级角色 + 能力门禁) · 飞书做成一等公民(互动/审批/流式卡片 + 语音/文件音视频 + 渠道原生工具) | | [v1.3.0](./releases/1.3.0) | 2026-05-13 | 工作流元年——7 种 step mode 把员工组装成业务流程 · 触发器 6 种 pattern 让事件自动启动流程 · Wiki 从搜索索引升级为处理流水线(用户模板 + 跨材料聚合 + reverse-citation) · MCP per-agent 工具绑定 + 多模态旁路路由 · 4 个 JVM 原生文档生成工具 + 图像编辑 | | [v1.2.0](./releases/1.2.0) | 2026-05-05 | 智能体改名"数字员工"(角色 / 目标 / 背景故事 + 5 职业模板) · 技能成了骨架(manifest + 模板向导 + LESSONS 自我进化) · ACP 接入:Claude Code / Codex 变成你的员工 · Admin 运行时控制台让你看见每个员工正在干什么 | | [v1.1.137](./releases/1.1.137) | 2026-04-29 | 它会从昨天学习了 · 一个模型坏了不会整体掉线 · "差一点就好"的地方现在好了 · 知识库变成了一座图书馆 | diff --git a/mateclaw-server/src/main/resources/docs/zh/security.md b/mateclaw-server/src/main/resources/docs/zh/security.md index 6fe9a7c5..bce775c2 100644 --- a/mateclaw-server/src/main/resources/docs/zh/security.md +++ b/mateclaw-server/src/main/resources/docs/zh/security.md @@ -202,6 +202,10 @@ curl -X POST http://localhost:18088/api/v1/security/guard/rules \ }' ``` +### 凭证规则的开关(1.4.0) + +凭证规则现在支持**逐条开关**——每条规则可单独 enable / disable,可单独设定决定(allow / deny / require_approval),整套守护规则还可以 **JSON 导出 / 导入**,方便在多套部署之间迁移或版本化管理。 + ### 危险模式检测 除了用户定义的规则之外,MateClaw 的 shell 工具内置了一套危险模式检测——不管你的规则怎么写,有些模式本身就是危险的。`find -delete`、`rm -rf /`、用管道把 `bash` 接到下载上之类的模式,**即使有规则本来会 allow,也会强制触发更高级别的审批**。 @@ -370,14 +374,20 @@ mateclaw: - **记忆文件**——每个 Agent 的记忆在它工作空间的目录下面 - **渠道**——每个渠道归属于一个工作空间 -### 角色 +### 角色(四级 RBAC) -| 角色 | 能做什么 | -|------|----------| -| **Owner** | 所有事,包括删除工作空间 | -| **Admin** | 除了删除工作空间或变更 owner 之外的所有事 | -| **Member** | 用 Agent、读写 wiki、创建会话 | -| **Viewer** | 只读——看得到 Agent 和 KB,不能创建或修改 | +权限**叠加**——高角色继承低角色的全部能力。 + +| 角色 | 能力(继承下层后新增) | +|------|------------------------| +| **Viewer** | `chat`、`view:wiki`。只读。为了让聊天能跑通,Viewer 还能读取当前激活模型、读取员工的工作空间文件。 | +| **Member** | Viewer + `view:memory`、`view:dashboard`、`manage:wiki`、`manage:agents` | +| **Admin** | Member + `manage:skills`、`manage:channels`、`manage:models`、`manage:security`、`manage:settings` | +| **Owner** | 与 Admin 相同,外加 owner 专属:删除工作空间、转移所有权 | + +**后端是能力的唯一真相源**——后端维护一份 `RoleCapabilities` 映射,前端从不本地推导。切换工作空间后、或遇到与权限相关的 403 时,前端调用 `GET /api/v1/workspaces/{id}/access`,拿回 `memberRole`、`isGlobalAdmin`、`effectiveRole`、`capabilities`。 + +**全局管理员 vs 工作空间角色**:`mate_user.role='admin'` 是系统级全局管理员——管理用户、创建工作空间,以 owner 等同的权限横跨**所有**工作空间(即便它不是某工作空间的成员);`mate_workspace_member.role` 是每工作空间的角色。系统级端点(模型 / provider / OAuth / 数据源、用户管理、创建工作空间)要求全局管理员(`@RequireGlobalAdmin`);工作空间级端点(技能 / 工具 / 插件)要求工作空间角色——读需要 Member、写需要 Admin。 完整细节在 [工作空间](./workspaces)。 diff --git a/mateclaw-server/src/main/resources/docs/zh/skills.md b/mateclaw-server/src/main/resources/docs/zh/skills.md index aa7773f7..88b8b992 100644 --- a/mateclaw-server/src/main/resources/docs/zh/skills.md +++ b/mateclaw-server/src/main/resources/docs/zh/skills.md @@ -95,6 +95,32 @@ parameters: | `default` | — | 调用者省略时的默认值 | | `description` | ✅ | 这个参数控制什么 | +### 脚本的类型化包装工具(v1.4 新增) + +SKILL.md 可以声明一个 `scripts:` 块,把每个脚本入口变成**独立的、带类型化 JSON Schema 的命名工具**。Agent 看到的不再是一个泛用的 `runSkillScript`,而是一个个 `skill__` 工具,直接填写 schema 描述的参数。 + +```yaml +scripts: + - id: summarize + path: scripts/dispatch.py + fixedArgs: ["summarize"] # 每次调用前原样拼在最前 + parameters: + - name: url + type: string + required: true + - id: translate + path: scripts/dispatch.py + fixedArgs: ["translate"] + parameters: + - name: lang + type: string + required: true +``` + +- **每个入口一个类型化工具**——模型拿到的是类型化参数,不是一串自由格式的 arg。 +- **`fixedArgs` 让一个 dispatcher 脚本支撑多个入口**——上面两条都调 `dispatch.py`,靠固定的首参区分,不用每个命令一个文件。 +- **包装工具随技能生命周期注册/注销**——技能上线时出现,禁用或归档时消失。路径穿越被拦死:只能触达技能自己 `scripts/` 目录下的脚本。纯数据库技能(没有目录)不暴露任何包装工具。 + --- ## 运行时管道 @@ -316,7 +342,7 @@ parameters: ## 工作空间隔离 -每个工作空间都有自己的一份技能副本。给某个工作空间启用一个技能时,它的文件被 stage 到那个工作空间的目录下、技能的工具被 scope 到这个工作空间、技能写任何文件都在工作空间边界内。见 [工作空间](./workspaces)。 +每个工作空间都有自己的一份技能副本。给某个工作空间启用一个技能时,它的文件被 stage 到那个工作空间的目录下、技能的工具被 scope 到这个工作空间、技能写任何文件都在工作空间边界内。v1.4 起技能**目录与运行时也按工作空间隔离**,每个工作空间只看到、只运行属于自己的技能。见 [工作空间](./workspaces)。 --- @@ -351,6 +377,18 @@ Agent 的记忆和你一起长大。不用再反复说"记住我喜欢按这个 你得到的不是一份 SKILL.md,是一个**多文件 bundle**——SKILL.md、references/、scripts/、密钥引用,全在一起。 +### `skill-authoring` 元技能(v1.4 新增) + +现在有一个内置的 `skill-authoring` 技能,启动时自动播种,教 Agent(或你)正确编写 SKILL.md。它涵盖: + +- **必填 frontmatter** 以及每个字段的含义 +- **校验器限制**——name 必须匹配 `^[a-z0-9][a-z0-9._-]{0,63}$`,内容 ≤ 100k 字符 +- **内置 vs 自定义**的编写流程 +- scripts/ 与 references/ 的**目录摆放** +- 会导致校验失败或静默出错的**常见坑** + +把它绑到一个 Agent 上,"给我写一个能……的技能"第一次就产出合法 bundle,不用来回校验三轮。 + --- ## 安装前的 Preflight 检查 @@ -471,6 +509,68 @@ v1.3 起,`ToolExecutionExecutor` 检测到这种情况且 `readSkillFile` 已 --- +## 渐进式技能披露(v1.4 新增) + +把每个技能完整的 SKILL.md 全塞进 system prompt 不可扩展——既炸 token 预算,又让 prompt 缓存每回合失效。v1.4 反过来:prompt 里只放一张紧凑目录,Agent **按需拉取**某个技能的指令。 + +**`load_skill(skillName, filePath?)`** 在 Agent 决定用某个技能的当下,加载它的 SKILL.md(或通过可选的 `filePath` 加载 bundle 里任意文件): + +- **经消息历史注入,不进 system prompt**——加载的内容作为一个会话回合到达,所以 system prompt(及其缓存)整个会话保持逐字节稳定。 +- **加载过的技能会被置顶**到后续回合的运行时目录顶端,Agent 一直看得见自己刚拉进来的东西。 +- 目录引导会告诉模型用技能前先 `load_skill(skillName=)`,用户点名某个具体技能时直接调它。 + +```yaml +mateclaw: + skill: + disclosure: + load-skill-tool: + enabled: true # 默认;设为 false 回退到旧的 readSkillFile 流程 +``` + +关闭时,目录引导改指向 `readSkillFile`,`load_skill` 不再注册。 + +--- + +## 技能生命周期管理员(v1.4 新增) + +会合成技能的 Agent 会攒下垃圾——三周前的一次性技能还在目录里占着位子。**管理员(curator)** 是一个每日扫描,把闲置的、**Agent 创建的**技能沿 `active → stale → archived` 老化,让它们退场而不删除任何东西。 + +- 闲置超过 `staleAfterDays`(默认 30 天)→ **stale**;闲置超过 `archiveAfterDays`(默认 90 天)→ **archived**(工作空间移到 `.archived/` 子目录)。`restore` 把归档技能拉回来。 +- **永不触碰**:内置、置顶、MCP/ACP/虚拟技能,以及任何以受保护前缀开头的名字(默认 `sys-`、`ops-`)。 + +### 设置 → 技能管理员 面板 + +- **预览(dry-run)**——在真正执行前,看清下一次扫描会移动哪些技能。 +- **暂停 / 恢复**整个扫描;**激活 / 停用**单个技能。 +- **上次运行 / 下次运行**时间戳,以及**各状态计数**(active / stale / archived)。 + +### 配置 + +```yaml +mateclaw: + skill: + curator: + enabled: true + cron: "0 0 2 * * *" # 每天 02:00 + staleAfterDays: 30 + archiveAfterDays: 90 + scope: AGENT_CREATED # AGENT_CREATED | ALL_DYNAMIC | OFF + protectPrefixes: ["sys-", "ops-"] +``` + +`scope: AGENT_CREATED` 只动有来源对话的技能;`ALL_DYNAMIC` 还会扫手动创建的 dynamic 技能;`OFF` 无视 `enabled` 直接关闭扫描。 + +### 技能市场里的生命周期 + +技能页接住了生命周期: + +- **生命周期标签页**——已启用 / Stale / 已归档。 +- 卡片显示**「最近使用」**徽章。 +- 详情抽屉新增**手动归档 / 恢复 / 置顶**。 +- 手动归档一个**仍被绑定**的技能会触发**二次确认握手**——不会在某个数字员工还在用它时悄悄把技能抽走。 + +--- + ## ACP 桥接:把外部编码 Agent 接进来 ACP(Agent Client Protocol)是一种把外部 Agent 客户端(Claude Code、Codex、其他兼容客户端)以技能身份接入 MateClaw 的协议。 @@ -487,6 +587,10 @@ ACP(Agent Client Protocol)是一种把外部 Agent 客户端(Claude Code 数字员工调用 ACP 技能的方式,和调内置工具没区别。 +### MCP/ACP 技能的虚拟 SKILL.md(v1.4 新增) + +MCP / ACP 衍生的技能过去是不透明的工具包,没有可读指令。v1.4 从每个 MCP/ACP 服务的元数据(transport、command、args、env、暴露的工具)**合成一份只读的虚拟 SKILL.md**,让这些集成在技能页里变成**可浏览的技能目录**。因为是合成的,虚拟 SKILL.md 每次列举调用都重建——没有过期的持久副本要维护——而且 `load_skill` 能像读真技能一样读它,让 Agent 在调用第一个工具前就拿到这个集成能干什么的说明。 + --- ## 详情抽屉:所有信息一处看 diff --git a/mateclaw-server/src/main/resources/docs/zh/tools.md b/mateclaw-server/src/main/resources/docs/zh/tools.md index 91435cc2..41461f7e 100644 --- a/mateclaw-server/src/main/resources/docs/zh/tools.md +++ b/mateclaw-server/src/main/resources/docs/zh/tools.md @@ -54,12 +54,33 @@ Tool Guard 是守门员。超时是**每个工具独立**的(这样一个慢 **2. MCP 服务。** 说 Model Context Protocol 的外部进程动态暴露工具。MateClaw 通过 `tools/list` 发现它们。见 [MCP 协议](./mcp)。 +> **每 Agent 的 MCP 工具范围(1.4.0+,#117)**:当一个 Agent **没有勾选任何具体的 MCP 工具行**时,已启用的 MCP 工具会**自动并入**它的工具集;一旦它勾选了某些具体 MCP 工具,就**只限定在这个集合**内。只绑技能 / 内置工具的 Agent 仍保留对全部 MCP 工具的访问。 + **3. 技能脚本。** 技能包可以带可执行脚本,运行时被包装成工具。见 [技能系统](./skills)。 工具发现是**黑名单式**的——默认所有可发现的工具都会被注册,需要排除哪个就显式排除。这样新加进来的工具不会因为白名单遗漏被默默忽略。 --- +## 渐进式工具披露(1.4.0+) + +工具一多,系统 prompt 就会被几十个完整的工具 schema 撑大——哪怕这次任务只用得上一两个。**渐进式披露**把工具分成两层,让 prompt 跟着**任务**走,而不是跟着**工具总数**走。 + +| 层级 | 系统 prompt 里怎么呈现 | 能不能直接调 | +|------|------------------------|--------------| +| **核心层(CORE)** | 始终完整广播,带完整 schema | 开箱即用 | +| **扩展层(EXTENSION)** | 只列一份压缩目录——名字 + 来源 + 一行说明,完整 schema 隐藏 | 先用 `enable_tool` 激活才能调 | + +**默认分层**:生成类工具(`image_generate`、`music_generate`、`video_generate`、`model3d_generate`)和 `browser_use` 默认放进**扩展层**;其余全部是**核心层**。 + +- **页面控制**——Tools 页面分「核心 / 扩展」两栏,内置工具和渠道工具每行有一个层级开关;MCP / ACP 工具的层级是锁定的。 +- **持久化**——层级存在 `mate_tool.disclosure_tier` 和 `mate_mcp_server.disclosure_tier`。 +- **配置**——`mateclaw.tools.disclosure.mode`,默认 `progressive`;设成 `legacy` 则恢复"全部广播"的老行为。 + +**为什么这么做**:不让上下文被白白撑爆——系统 prompt 的体积应该跟当前任务的需要成正比,而不是跟你装了多少工具成正比。 + +--- + ## 二十个内置工具 | 工具 | 作用 | 危险 | @@ -88,6 +109,9 @@ Tool Guard 是守门员。超时是**每个工具独立**的(这样一个慢 | `CronJobTool` | 创建和管理定时任务 | ⚠️ | | `DatasourceTool` | 管理外部数据源连接 | ⚠️ | | `SqlQueryTool` | 对已连接数据源执行 SQL 查询 | ⚠️ | +| `send_file` | **1.4.0+** 把服务器上已有文件作为原生 IM 附件投递(#199) | — | +| `enable_tool` | **1.4.0+** 在本次会话里激活一个扩展层工具 | — | +| `load_skill` | **1.4.0+** 按需加载某个技能的 `SKILL.md` | — | 此外还有 [多模态创作](./multimodal) 的音乐生成工具 `MusicGenerateTool`。以及 [LLM Wiki](./wiki) 的 14 个 Wiki 工具:`wiki_read_page`、`wiki_read_many`、`wiki_list_pages`、`wiki_search_pages`、`wiki_semantic_search`、`wiki_compile_page`、`wiki_trace_source`、`wiki_create_page`、`wiki_delete_page`、`wiki_archive_page`、`wiki_unarchive_page`、`wiki_related_pages`、`wiki_explain_relation`、`wiki_enrich_page`。 @@ -191,6 +215,41 @@ Agent A:[调 WebSearchTool] 读取内置的 MateClaw 项目文档。让 Agent 回答"MateClaw 里 X 是怎么工作的"这种问题时,**去查真文档**而不是猜。 +### enable_tool —— 激活扩展层工具(1.4.0+) + +`enable_tool(toolName)` 把一个**扩展层**工具激活,使它在**本次会话剩余的回合**里完整可调。 + +- **会校验**——只有在 Agent 的有效工具集里的工具才能激活。 +- **下一回合生效**——激活在同一个 ReAct 循环的**下一次推理**时生效(Agent 先看到完整 schema,再发真正的调用)。 +- **会话级,不持久化**——激活只对当前会话有效,不写库;新会话回到默认分层。 + +### load_skill —— 按需加载技能(1.4.0+) + +`load_skill(skillName, filePath?)` 在需要时才把某个技能的 `SKILL.md` 加载进来——不传 `filePath` 读主文件,传了就读技能包内的子文件。 + +- **走消息历史注入**——加载的内容是注入到**消息历史**里,而不是系统 prompt,这样 **prompt 缓存保持稳定**(系统 prompt 不变,缓存不失效)。 +- **后续回合保持**——已加载的技能在之后的回合里**钉住**,不用反复加载。 +- **配置**——`mateclaw.skill.disclosure.load-skill-tool.enabled`,默认开启。 + +详见 [技能系统](./skills)。 + +### send_file —— 把已有文件作为原生附件投递(1.4.0+,#199) + +`send_file(filePath, fileName?)` 读取服务器上**一个已经存在的文件**,把它作为**原生 IM 附件**投递——不是一条文本下载链接。 + +- **进生成文件缓存**——文件被放进生成文件缓存,渠道适配器(飞书 / 钉钉 / Telegram)**自动识别并投递**。 +- **任意常见文件类型**,上限 **20 MB**。 +- **跟 `ReadFileTool` 的区别**——`ReadFileTool` 把文件**抽成文本**喂给 Agent 推理;`send_file` 把文件**原样发给用户**。 + +### ReadFileTool —— 超长行分页(1.4.0+,#190) + +针对单行特别长的文件,`ReadFileTool` 新增可选的 `startColumn`(在 `startLine` 内的 1-based 字符偏移),用来**从一行的中间续读**它的尾部。 + +- 截断时**始终返回** `nextStartLine`; +- 当这一行还有剩余没读完时,**额外返回** `nextStartColumn`。 + +把两者回填到下一次调用,就能把一个巨大的单行文件分段读完。 + --- ## Tool Guard —— 权限层 diff --git a/mateclaw-server/src/main/resources/docs/zh/triggers.md b/mateclaw-server/src/main/resources/docs/zh/triggers.md index 174fdcd6..a4bd4bdf 100644 --- a/mateclaw-server/src/main/resources/docs/zh/triggers.md +++ b/mateclaw-server/src/main/resources/docs/zh/triggers.md @@ -102,15 +102,21 @@ HTTP 入口(`POST /api/v1/triggers/events`)收到事件 → envelope wrap ## 在 UI 里管理触发器 +::: tip 1.4.0 调整:合并进"调度中心" +v1.4.0 起,**定时任务**和**触发器**合并为单个**调度中心**页面(`设置 → 调度中心`,路由 `/settings/scheduler`),分三个 tab:**计划任务**(Scheduled Jobs)/ **事件触发器**(Event Triggers)/ **运行历史**(Run History)。每个 tab 标题旁带条目计数;右上角动作按钮随当前 tab 变化(计划任务 / 触发器 tab 是"新建",历史 tab 是"刷新");运行历史**横跨两者**,定时任务和触发器的执行记录都在这里看。 + +老路由会自动重定向:`/cron-jobs` 和 `/settings/triggers` 分别落到调度中心对应的 tab。 +::: + ### 入口 -`Triggers`(侧栏)→ 列表 + **+ 新建** 抽屉。 +`设置 → 调度中心`(侧栏)→ **事件触发器** tab。触发器列表在 v1.4.0 里从原来的宽表格改版为**规则卡片**——每条 trigger 一张卡,pattern type / target / 启停状态一目了然。点 **+ 新建触发器** 打开抽屉。 ### 创建 trigger 抽屉里按 6 种 pattern type 各自结构化表单填字段——不需要手写 `pattern_json`: -- 选 `cron` → 给 cron 表达式输入框 + 时区下拉 + 试运行下一次触发时间预览 +- 选 `cron` → cron 表达式输入框 + 时区下拉 + 下一次触发时间预览。表达式可手输,也可点输入框旁的编辑按钮打开**可视化 cron 编辑器**(见下) - 选 `channel_message` → 渠道类型可选 + (可选)按 sender id 精确匹配 - 选 `agent_lifecycle` → agent 可选 + phase(spawned / terminated / crashed)可选 - 选 `content_match` → substring 输入(**必填**),匹配 envelope 的 `data.content` @@ -119,6 +125,40 @@ HTTP 入口(`POST /api/v1/triggers/events`)收到事件 → envelope wrap 填完保存 → trigger 入库;`enabled=true` 时立即注册到对应引擎(cron 注册到 ShedLock;其它走 envelope 路由)。 +### 可视化 cron 编辑器(1.4.0 新增) + +cron 表达式不必手写。点表达式输入框旁的编辑按钮打开**分段编辑器**:分钟 / 小时 / 日 / 月 / 星期 各占一个 tab,每段可选"每个 / 指定值 / 区间 / 步进";上方一排**预设**(每分钟、整点、每天午夜、每周一……)一键填入;底部是**实时可读预览**,把当前表达式翻译成人话(例如"每天 09:00")。 + +这个编辑器是**计划任务和触发器共用**的同一个组件: + +- **计划任务**用 **5 段** cron(分 时 日 月 周) +- **触发器**用 **6 段** cron(带秒:秒 分 时 日 月 周)——多出最前面的秒字段 + +输入框本身也带一行可读预览,不打开编辑器也能确认你手输的表达式解析成了什么。 + +--- + +## 调度任务类型(task type) + +调度中心 **计划任务** tab 里的每条任务都有一个 `task_type`,决定它跑起来做什么。这是 cron 任务类型的权威清单(事件触发器的 6 种 pattern type 见上文): + +| task type | 行为 | 是否绑定员工 | 备注 | +|---|---|---|---| +| `text` / `agent` / `reminder` | 按 cron 调起一次员工对话 | **是**(必填 agent) | 经典定时对话;结果路由到对应会话 | +| `wiki_process` | 按 cron 离线处理某个知识库 | **否** | 1.4.0 新增——见下 | + +### `wiki_process`:错峰处理知识库(1.4.0 新增) + +`wiki_process` 让你把**知识库的处理**安排到业务低峰时段离线跑,而不是上传完就立刻占满处理队列。它**不绑定任何员工**——它是个系统任务,不开对话、不进聊天。 + +新建时只需要填: + +- **cron 表达式**(用上面的可视化编辑器,5 段) +- **知识库选择器**——这次任务要处理哪个 KB +- 可选的 **"强制重新处理"** 开关——开了就连已处理过的原始材料一起重跑(`force`) + +每次到点,任务把该 KB 的原始材料**异步入队**处理,并在运行历史里记一行结果,形如 `queued N raw material(s)`(开了强制会带 `(force)` 后缀)。**注意它不路由到任何对话**——它只是把活儿丢进处理队列,进度去 [LLM Wiki](./wiki.md) 页面看。 + ### Payload template `payload_template` 字段是 Pebble 模板字符串,渲染后作为 dispatch target(agent 对话或 workflow run)的输入。 diff --git a/mateclaw-server/src/main/resources/docs/zh/workflow.md b/mateclaw-server/src/main/resources/docs/zh/workflow.md index f1d78e47..382db51b 100644 --- a/mateclaw-server/src/main/resources/docs/zh/workflow.md +++ b/mateclaw-server/src/main/resources/docs/zh/workflow.md @@ -203,6 +203,10 @@ v0 = internal alpha。**7 种 step mode + 6 种 trigger pattern**。`loop` / `in 工作流的实际启动只能通过 [触发器(Triggers)](./triggers.md) 或 `await_approval` 恢复——v0 没有"立即手动跑一次"的 endpoint。详见上方 API 参考。 +::: tip 1.4.0:触发器现在在调度中心里 +v1.4.0 起,**定时任务**和**触发器**合并为单个**调度中心**页面(`设置 → 调度中心`,路由 `/settings/scheduler`),分**计划任务 / 事件触发器 / 运行历史**三个 tab。要给工作流挂触发器,去调度中心的**事件触发器** tab 新建一条 `target_type=workflow` 的规则。详见 [触发器](./triggers.md)。 +::: + --- ## API 参考 diff --git a/mateclaw-server/src/main/resources/docs/zh/workspaces.md b/mateclaw-server/src/main/resources/docs/zh/workspaces.md index 17fc596f..1e94a9ac 100644 --- a/mateclaw-server/src/main/resources/docs/zh/workspaces.md +++ b/mateclaw-server/src/main/resources/docs/zh/workspaces.md @@ -34,24 +34,37 @@ MateClaw 在单次部署里支持多个团队的方式,是把每一种资源 - `mate_system_setting` 里的系统级设置 - 内置技能 +Agent、技能(catalog + 运行时)、会话、工作空间文件全部按工作空间 ID 隔离;**跨工作空间访问一律返回 403**。 + --- ## 工作空间角色 -每个用户在工作空间里被分配四种角色之一: +每个用户在工作空间里被分配四种角色之一。权限**叠加**——高角色继承低角色的全部能力: -| 角色 | 能做什么 | -|------|----------| -| **Owner** | 所有事,包括删除工作空间和管理成员 | -| **Admin** | 除了删除工作空间或变更 owner 之外的所有事 | -| **Member** | 用 Agent、读写 wiki、创建会话、调用工具(受 Tool Guard 约束) | -| **Viewer** | 只读——看得到 Agent 和 KB、读会话、**不能创建或修改** | +| 角色 | 能力(继承下层后新增) | +|------|------------------------| +| **Viewer** | `chat`、`view:wiki`。只读。为了让聊天能跑通,Viewer 还能读取当前激活模型、读取员工的工作空间文件。 | +| **Member** | Viewer + `view:memory`、`view:dashboard`、`manage:wiki`、`manage:agents` | +| **Admin** | Member + `manage:skills`、`manage:channels`、`manage:models`、`manage:security`、`manage:settings` | +| **Owner** | 与 Admin 相同,外加 owner 专属:删除工作空间、转移所有权 | 一个用户可以属于多个工作空间、**在不同工作空间有不同角色**。切换工作空间时,有效权限跟着切换。 -### 角色的 scope +### 全局管理员 vs 工作空间角色 -角色控制 **UI 可见性**和 **API 访问**。控制台隐藏用户没权限用的菜单项——一个对某工作空间只有 viewer 角色的用户,**完全看不到**安全菜单或工作空间管理页面。后端在每个 API 端点上执行同样的规则,所以 viewer 打一个受保护的端点返回 `403 Forbidden`。 +二者是两套独立的权限: + +- **全局管理员**——`mate_user.role='admin'`,系统级。管理用户、创建工作空间,以 owner 等同的权限横跨**所有**工作空间(即便它不是某工作空间的成员)。 +- **工作空间角色**——`mate_workspace_member.role`,每工作空间一份,就是上表那四种。 + +系统级端点(模型 / provider / OAuth / 数据源、用户管理、创建工作空间)要求全局管理员(`@RequireGlobalAdmin`);工作空间级端点(技能 / 工具 / 插件)要求工作空间角色——读需要 Member、写需要 Admin。 + +### 能力的 scope —— 后端是唯一真相源 + +角色控制 **UI 可见性**和 **API 访问**,而**后端是能力的唯一真相源**:后端维护一份 `RoleCapabilities` 映射,前端从不本地推导。切换工作空间后、或遇到与权限相关的 403 时,前端调用 `GET /api/v1/workspaces/{id}/access`,拿回 `memberRole`、`isGlobalAdmin`、`effectiveRole`、`capabilities`。 + +前端据此 gating:路由声明所需能力;侧栏按能力过滤(加载完成前不会闪现菜单);Viewer 登录后落在 `/chat`;侧栏还会显示通知角标(待审批、卡住的员工)。后端在每个 API 端点上执行同样的规则,所以能力不足的请求返回 `403 Forbidden`。 --- @@ -63,7 +76,7 @@ MateClaw 在单次部署里支持多个团队的方式,是把每一种资源 2. 可选描述 3. 保存 -你成为这个工作空间的 owner。现在可以邀请成员了。 +**只有全局管理员能创建工作空间。** 创建者自动成为这个工作空间的 **Owner**,现在可以添加成员了。 ### 走 API @@ -79,24 +92,58 @@ curl -X POST http://localhost:18088/api/v1/workspaces \ --- -## 邀请成员 +## 成员与角色 -`设置 → 成员 → 添加成员`。输入一个已存在的 MateClaw 用户名,选角色,保存。 +`设置 → 成员`。所有成员管理操作都需要 **Admin 及以上**。 -成员**下次页面加载时**立刻在工作空间切换器里看到这个工作空间。没有邀请邮件,没有接受流程——成员的账号已经在 MateClaw 里了。 +### 添加成员 -### 走 API +输入用户名,选角色(默认 `member`),保存。 + +- 用户名**不存在**时,会顺手**创建账号**——此时必须提供密码。 +- 用户名**已存在**且你又填了密码,则**重置该用户的密码**(管理员把人移除后用新密码重新加回来时很有用)。 +- 昵称可选。 + +成员**下次页面加载时**立刻在工作空间切换器里看到这个工作空间。没有邀请邮件,没有接受流程。 ```bash +# 用 username 添加;不存在则按提供的密码建号 curl -X POST http://localhost:18088/api/v1/workspaces/1/members \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ - "userId": 42, + "username": "alice", + "password": "init-pass-123", + "nickname": "Alice", "role": "member" }' ``` +### 更新成员角色(Admin+,不能改 Owner) + +```bash +curl -X PUT http://localhost:18088/api/v1/workspaces/1/members/42 \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{"role": "admin"}' +``` + +> 路径是 `/members/{memberId}`,**不是** `/members/{memberId}/role`。 + +### 移除成员(Admin+,不能移除 Owner) + +```bash +curl -X DELETE http://localhost:18088/api/v1/workspaces/1/members/42 \ + -H "Authorization: Bearer " +``` + +### 列出成员 + +```bash +curl http://localhost:18088/api/v1/workspaces/1/members \ + -H "Authorization: Bearer " +``` + --- ## 切换工作空间 @@ -108,7 +155,9 @@ curl -X POST http://localhost:18088/api/v1/workspaces/1/members \ - Wiki 列表、技能列表、渠道列表等全部改变 - 活跃的对话**保持打开**(它们属于自己的工作空间) -工作空间选择**按用户持久化**——你再次登录时落到上次用的工作空间。 +当前工作空间 ID 以**字符串**形式存在浏览器 localStorage 里(Snowflake ID 安全,不会被 `Number` 截断)。任何时候都有一个**默认工作空间兜底**——即便本地没有记录,你也总会落到一个可用的工作空间。 + +`GET /api/v1/workspaces` 返回的每个工作空间都带 `memberRole` / `effectiveRole` / `isGlobalAdmin`,前端据此渲染切换器和侧栏。 --- @@ -165,7 +214,7 @@ Wiki KB 的数据**永远不会离开它的工作空间**。工作空间 B 里 ## 删除一个工作空间 -**只有 owner 能删工作空间。** `设置 → 工作空间 → [工作空间] → 删除`。 +**只有 Owner 能删工作空间。** `设置 → 工作空间 → [工作空间] → 删除`。如果工作空间下还**拥有 Wiki 知识库**,删除会失败——先迁移或删掉这些 KB 再删工作空间。 删工作空间会: @@ -211,12 +260,13 @@ curl http://localhost:18088/api/v1/workspaces/1/members \ curl -X POST http://localhost:18088/api/v1/workspaces/1/members \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ - -d '{"userId": 42, "role": "member"}' + -d '{"username": "alice", "password": "init-pass-123", "role": "member"}' curl -X DELETE http://localhost:18088/api/v1/workspaces/1/members/42 \ -H "Authorization: Bearer " -curl -X PUT http://localhost:18088/api/v1/workspaces/1/members/42/role \ +# 更新角色:路径是 /members/{memberId},不是 /members/{memberId}/role +curl -X PUT http://localhost:18088/api/v1/workspaces/1/members/42 \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{"role": "admin"}'