mirror of https://github.com/openclaw/openclaw.git
docs(plugins): refresh bundled plugin runtime docs
This commit is contained in:
parent
caeeecf399
commit
341e617c84
26
AGENTS.md
26
AGENTS.md
|
|
@ -1,7 +1,7 @@
|
|||
# Repository Guidelines
|
||||
|
||||
- Repo: https://github.com/openclaw/openclaw
|
||||
- In chat replies, file references must be repo-root relative only (example: `extensions/bluebubbles/src/channel.ts:80`); never absolute paths or `~/...`.
|
||||
- In chat replies, file references must be repo-root relative only (example: `src/telegram/index.ts:80`); never absolute paths or `~/...`.
|
||||
- Do not edit files covered by security-focused `CODEOWNERS` rules unless a listed owner explicitly asked for the change or is already reviewing it with you. Treat those paths as restricted surfaces, not drive-by cleanup.
|
||||
|
||||
## Project Structure & Module Organization
|
||||
|
|
@ -9,28 +9,28 @@
|
|||
- Source code: `src/` (CLI wiring in `src/cli`, commands in `src/commands`, web provider in `src/provider-web.ts`, infra in `src/infra`, media pipeline in `src/media`).
|
||||
- Tests: colocated `*.test.ts`.
|
||||
- Docs: `docs/` (images, queue, Pi config). Built output lives in `dist/`.
|
||||
- Nomenclature: use "plugin" / "plugins" in docs, UI, changelogs, and contributor guidance. `extensions/*` remains the internal directory/package path to avoid repo-wide churn from a rename.
|
||||
- Bundled plugin naming: for repo-owned workspace plugins, keep the canonical plugin id aligned across `openclaw.plugin.json:id`, `extensions/<id>` by default, and package names anchored to the same id (`@openclaw/<id>` or approved suffix forms like `-provider`, `-plugin`, `-speech`, `-sandbox`, `-media-understanding`). Keep `openclaw.install.npmSpec` equal to the package name and `openclaw.channel.id` equal to the plugin id when present. Exceptions must be explicit and covered by the repo invariant test.
|
||||
- Plugins: live under `extensions/*` (workspace packages). Keep plugin-only deps in the extension `package.json`; do not add them to the root `package.json` unless core uses them.
|
||||
- Nomenclature: use "plugin" / "plugins" in docs, UI, changelogs, and contributor guidance. The bundled workspace plugin tree remains the internal package layout to avoid repo-wide churn from a rename.
|
||||
- Bundled plugin naming: for repo-owned workspace plugins, keep the canonical plugin id aligned across `openclaw.plugin.json:id`, the default workspace folder name, and package names anchored to the same id (`@openclaw/<id>` or approved suffix forms like `-provider`, `-plugin`, `-speech`, `-sandbox`, `-media-understanding`). Keep `openclaw.install.npmSpec` equal to the package name and `openclaw.channel.id` equal to the plugin id when present. Exceptions must be explicit and covered by the repo invariant test.
|
||||
- Plugins: live in the bundled workspace plugin tree (workspace packages). Keep plugin-only deps in the extension `package.json`; do not add them to the root `package.json` unless core uses them.
|
||||
- Plugins: install runs `npm install --omit=dev` in plugin dir; runtime deps must live in `dependencies`. Avoid `workspace:*` in `dependencies` (npm install breaks); put `openclaw` in `devDependencies` or `peerDependencies` instead (runtime resolves `openclaw/plugin-sdk` via jiti alias).
|
||||
- Import boundaries: extension production code should treat `openclaw/plugin-sdk/*` plus local `api.ts` / `runtime-api.ts` barrels as the public surface. Do not import core `src/**`, `src/plugin-sdk-internal/**`, or another extension's `src/**` directly.
|
||||
- Installers served from `https://openclaw.ai/*`: live in the sibling repo `../openclaw.ai` (`public/install.sh`, `public/install-cli.sh`, `public/install.ps1`).
|
||||
- Messaging channels: always consider **all** built-in + extension channels when refactoring shared logic (routing, allowlists, pairing, command gating, onboarding, docs).
|
||||
- Core channel docs: `docs/channels/`
|
||||
- Core channel code: `src/telegram`, `src/discord`, `src/slack`, `src/signal`, `src/imessage`, `src/web` (WhatsApp web), `src/channels`, `src/routing`
|
||||
- Extensions (channel plugins): `extensions/*` (e.g. `extensions/msteams`, `extensions/matrix`, `extensions/zalo`, `extensions/zalouser`, `extensions/voice-call`)
|
||||
- When adding channels/extensions/apps/docs, update `.github/labeler.yml` and create matching GitHub labels (use existing channel/extension label colors).
|
||||
- Bundled plugin channels: the workspace plugin tree (for example Matrix, Zalo, ZaloUser, Voice Call)
|
||||
- When adding channels/plugins/apps/docs, update `.github/labeler.yml` and create matching GitHub labels (use existing channel/plugin label colors).
|
||||
|
||||
## Architecture Boundaries
|
||||
|
||||
- Start here for the repo map:
|
||||
- `extensions/*` = bundled plugins and the closest example surface for third-party plugins
|
||||
- bundled workspace plugin tree = bundled plugins and the closest example surface for third-party plugins
|
||||
- `src/plugin-sdk/*` = the public plugin contract that extensions are allowed to import
|
||||
- `src/channels/*` = core channel implementation details behind the plugin/channel boundary
|
||||
- `src/plugins/*` = plugin discovery, manifest validation, loader, registry, and contract enforcement
|
||||
- `src/gateway/protocol/*` = typed Gateway control-plane and node wire protocol
|
||||
- Progressive disclosure lives in local boundary guides:
|
||||
- `extensions/AGENTS.md`
|
||||
- bundled-plugin-tree `AGENTS.md`
|
||||
- `src/plugin-sdk/AGENTS.md`
|
||||
- `src/channels/AGENTS.md`
|
||||
- `src/plugins/AGENTS.md`
|
||||
|
|
@ -39,7 +39,7 @@
|
|||
- Public docs: `docs/plugins/building-plugins.md`, `docs/plugins/architecture.md`, `docs/plugins/sdk-overview.md`, `docs/plugins/sdk-entrypoints.md`, `docs/plugins/sdk-runtime.md`, `docs/plugins/manifest.md`, `docs/plugins/sdk-channel-plugins.md`, `docs/plugins/sdk-provider-plugins.md`
|
||||
- Definition files: `src/plugin-sdk/plugin-entry.ts`, `src/plugin-sdk/core.ts`, `src/plugin-sdk/provider-entry.ts`, `src/plugin-sdk/channel-contract.ts`, `scripts/lib/plugin-sdk-entrypoints.json`, `package.json`
|
||||
- Rule: extensions must cross into core only through `openclaw/plugin-sdk/*`, manifest metadata, and documented runtime helpers. Do not import `src/**` from extension production code.
|
||||
- Rule: core code and tests must not deep-import bundled plugin internals such as `extensions/<id>/src/**` or `extensions/<id>/onboard.js`. If core needs a bundled plugin helper, expose it through `extensions/<id>/api.ts` and, when it is a real cross-package contract, through `src/plugin-sdk/<id>.ts`.
|
||||
- Rule: core code and tests must not deep-import bundled plugin internals such as a plugin's `src/**` files or `onboard.js`. If core needs a bundled plugin helper, expose it through that plugin's `api.ts` and, when it is a real cross-package contract, through `src/plugin-sdk/<id>.ts`.
|
||||
- Compatibility: new plugin seams are allowed, but they must be added as documented, backwards-compatible, versioned contracts. We have third-party plugins in the wild and do not break them casually.
|
||||
- Channel boundary:
|
||||
- Public docs: `docs/plugins/sdk-channel-plugins.md`, `docs/plugins/architecture.md`
|
||||
|
|
@ -57,11 +57,11 @@
|
|||
- Rule: protocol changes are contract changes. Prefer additive evolution; incompatible changes require explicit versioning, docs, and client/codegen follow-through.
|
||||
- Bundled plugin contract boundary:
|
||||
- Public docs: `docs/plugins/architecture.md`, `docs/plugins/manifest.md`, `docs/plugins/sdk-overview.md`
|
||||
- Definition files: `src/plugins/contracts/registry.ts`, `src/plugins/types.ts`, `src/extensions/public-artifacts.ts`
|
||||
- Definition files: `src/plugins/contracts/registry.ts`, `src/plugins/types.ts`, `src/plugins/public-artifacts.ts`
|
||||
- Rule: keep manifest metadata, runtime registration, public SDK exports, and contract tests aligned. Do not create a hidden path around the declared plugin interfaces.
|
||||
- Extension test boundary:
|
||||
- Keep extension-owned onboarding/config/provider coverage under `extensions/<id>/**` when feasible.
|
||||
- If core tests need bundled plugin behavior, consume it through public `src/plugin-sdk/<id>.ts` facades or `extensions/<id>/api.ts`, not private extension modules.
|
||||
- Keep extension-owned onboarding/config/provider coverage under the owning bundled plugin package when feasible.
|
||||
- If core tests need bundled plugin behavior, consume it through public `src/plugin-sdk/<id>.ts` facades or the plugin's `api.ts`, not private extension modules.
|
||||
|
||||
## Docs Linking (Mintlify)
|
||||
|
||||
|
|
@ -148,7 +148,7 @@
|
|||
- Dynamic import guardrail: do not mix `await import("x")` and static `import ... from "x"` for the same module in production code paths. If you need lazy loading, create a dedicated `*.runtime.ts` boundary (that re-exports from `x`) and dynamically import that boundary from lazy callers only.
|
||||
- Dynamic import verification: after refactors that touch lazy-loading/module boundaries, run `pnpm build` and check for `[INEFFECTIVE_DYNAMIC_IMPORT]` warnings before submitting.
|
||||
- Extension SDK self-import guardrail: inside an extension package, do not import that same extension via `openclaw/plugin-sdk/<extension>` from production files. Route internal imports through a local barrel such as `./api.ts` or `./runtime-api.ts`, and keep the `plugin-sdk/<extension>` path as the external contract only.
|
||||
- Extension package boundary guardrail: inside `extensions/<id>/**`, do not use relative imports/exports that resolve outside that same `extensions/<id>` package root. If shared code belongs in the plugin SDK, import `openclaw/plugin-sdk/<subpath>` instead of reaching into `src/plugin-sdk/**` or other repo paths via `../`.
|
||||
- Extension package boundary guardrail: inside a bundled plugin package, do not use relative imports/exports that resolve outside that same package root. If shared code belongs in the plugin SDK, import `openclaw/plugin-sdk/<subpath>` instead of reaching into `src/plugin-sdk/**` or other repo paths via `../`.
|
||||
- Extension API surface rule: `openclaw/plugin-sdk/<subpath>` is the only public cross-package contract for extension-facing SDK code. If an extension needs a new seam, add a public subpath first; do not reach into `src/plugin-sdk/**` by relative path.
|
||||
- Never share class behavior via prototype mutation (`applyPrototypeMixins`, `Object.defineProperty` on `.prototype`, or exporting `Class.prototype` for merges). Use explicit inheritance/composition (`A extends B extends C`) or helper composition so TypeScript can typecheck.
|
||||
- If this pattern is needed, stop and get explicit approval before shipping; default behavior is to split/refactor into an explicit class hierarchy and keep members strongly typed.
|
||||
|
|
|
|||
18
CHANGELOG.md
18
CHANGELOG.md
|
|
@ -112,7 +112,7 @@ Docs: https://docs.openclaw.ai
|
|||
- Mattermost/replies: keep pairing replies, slash-command fallback replies, and model-picker messages on the resolved config path so `exec:` SecretRef bot tokens work across all outbound reply branches. (#48347) thanks @mathiasnagler.
|
||||
- Microsoft Teams/config: accept the existing `welcomeCard`, `groupWelcomeCard`, `promptStarters`, and feedback/reflection keys in strict config validation so already-supported Teams runtime settings stop failing schema checks. (#54679) Thanks @gumclaw.
|
||||
- MCP/channels: add a Gateway-backed channel MCP bridge with Codex/Claude-facing conversation tools, Claude channel notifications, and safer stdio bridge lifecycle handling for reconnects and routed session discovery.
|
||||
- Plugins/SDK: thread `moduleUrl` through plugin-sdk alias resolution so user-installed plugins outside the openclaw directory (e.g. `~/.openclaw/extensions/`) correctly resolve `openclaw/plugin-sdk/*` subpath imports, and gate `plugin-sdk:check-exports` in `release:check`. (#54283) Thanks @xieyongliang.
|
||||
- Plugins/SDK: thread `moduleUrl` through plugin-sdk alias resolution so user-installed plugins outside the openclaw directory correctly resolve `openclaw/plugin-sdk/*` subpath imports, and gate `plugin-sdk:check-exports` in `release:check`. (#54283) Thanks @xieyongliang.
|
||||
- Config/web fetch: allow the documented `tools.web.fetch.maxResponseBytes` setting in runtime schema validation so valid configs no longer fail with unrecognized-key errors. (#53401) Thanks @erhhung.
|
||||
- Message tool/buttons: keep the shared `buttons` schema optional in merged tool definitions so plain `action=send` calls stop failing validation when no buttons are provided. (#54418) Thanks @adzendo.
|
||||
- Agents/openai-compatible tool calls: deduplicate repeated tool call ids across live assistant messages and replayed history so OpenAI-compatible backends no longer reject duplicate `tool_call_id` values with HTTP 400. (#40996) Thanks @xaeon2026.
|
||||
|
|
@ -140,7 +140,7 @@ Docs: https://docs.openclaw.ai
|
|||
- GitHub Copilot/auth refresh: treat large `expires_at` values as seconds epochs and clamp far-future runtime auth refresh timers so Copilot token refresh cannot fall into a `setTimeout` overflow hot loop. (#55360) Thanks @michael-abdo.
|
||||
- Agents/status: use the persisted runtime session model in `session_status` when no explicit override exists, and honor per-agent `thinkingDefault` in both `session_status` and `/status`. (#55425) Thanks @scoootscooob, @xaeon2026, and @ysfbsf.
|
||||
- Heartbeat/runner: guarantee the interval timer is re-armed after heartbeat runs and unexpected runner errors so scheduled heartbeats do not silently stop after an interrupted cycle. (#52270) Thanks @MiloStack.
|
||||
- Config/Doctor: rewrite stale bundled plugin load paths from legacy `extensions/*` locations to the packaged bundled path, including directory-name mismatches and slash-suffixed config entries. (#55054) Thanks @SnowSky1.
|
||||
- Config/Doctor: rewrite stale bundled plugin load paths from legacy bundled-plugin locations to the packaged bundled path, including directory-name mismatches and slash-suffixed config entries. (#55054) Thanks @SnowSky1.
|
||||
- WhatsApp/mentions: stop treating mentions embedded in quoted messages as direct mentions so replying to a message that @mentioned the bot no longer falsely triggers mention gating. (#52711) Thanks @lurebat.
|
||||
- Matrix: keep separate 2-person rooms out of DM routing after `m.direct` seeds successfully, while still honoring explicit `is_direct` state and startup fallback recovery. (#54890) thanks @private-peter
|
||||
- Agents/ollama fallback: surface non-2xx Ollama HTTP errors with a leading status code so HTTP 503 responses trigger model fallback again. (#55214) Thanks @bugkill3r.
|
||||
|
|
@ -469,7 +469,7 @@ Docs: https://docs.openclaw.ai
|
|||
- secrets: harden read-only SecretRef command paths and diagnostics. (#47794) Thanks @joshavant.
|
||||
- Scope message SecretRef resolution and harden doctor/status paths. (#48728) Thanks @joshavant.
|
||||
- Build/memory tools: emit `dist/cli/memory-cli.js` as a stable core entry so runtime `memory_search` loading no longer depends on hashed `memory-cli-*` bundle names. (#51759) Thanks @oliviareid-svg.
|
||||
- Plugins/testing: add a public `openclaw/plugin-sdk/testing` surface for plugin-author test helpers, and move bundled-extension-only test bridges out of `extensions/` into private repo test helpers.
|
||||
- Plugins/testing: add a public `openclaw/plugin-sdk/testing` surface for plugin-author test helpers, and move bundled-plugin-only test bridges into private repo test helpers.
|
||||
- Agents/steering docs: update embedded Pi steering docs and runner comments for the current upstream behavior, where queued steering is injected after the active assistant turn finishes its tool calls instead of skipping the remaining tools mid-turn. Thanks @vincentkoc.
|
||||
- Doctor/refactor: start splitting doctor provider checks into `src/commands/doctor/providers/*` by extracting Telegram first-run and group allowlist warnings into a provider-specific module, keeping the current setup guidance and warning behavior intact. Thanks @vincentkoc.
|
||||
- Refactor/channels: remove the legacy channel shim directories and point channel-specific imports directly at the extension-owned implementations. (#45967) Thanks @scoootscooob.
|
||||
|
|
@ -624,7 +624,7 @@ Docs: https://docs.openclaw.ai
|
|||
- Zalo/plugin runtime: export `resolveClientIp` from `openclaw/plugin-sdk/zalo` so installed builds no longer crash on startup when the webhook monitor loads from the packaged extension instead of the monorepo source tree. (#46549) Thanks @No898.
|
||||
- Docker/live tests: mount external CLI auth homes into writable container copies, derive Codex OAuth expiry from JWT `exp`, refresh synced CLI creds instead of trusting stale cached expiry, and make gateway live probes wait on transcript output so `pnpm test:docker:all` stays green in Linux.
|
||||
- Gateway/watch mode: restart on bundled-plugin package and manifest metadata changes, rebuild `dist` for extension source and `tsdown.config.ts` changes, and still ignore extension docs. (#47571) Thanks @gumadeiras.
|
||||
- Gateway/watch mode: recreate bundled plugin runtime metadata after clean or stale `dist` states, so `pnpm gateway:watch` no longer fails on missing `dist/extensions/*/openclaw.plugin.json` manifests after a rebuild. Thanks @gumadeiras.
|
||||
- Gateway/watch mode: recreate bundled plugin runtime metadata after clean or stale `dist` states, so `pnpm gateway:watch` no longer fails on missing bundled-plugin manifests after a rebuild. Thanks @gumadeiras.
|
||||
- Control UI: scope persisted session selection per gateway, prevent stale session bleed across tokenized gateway opens, and cap stored gateway session history. (#47453) Thanks @sallyom.
|
||||
- Models/OpenAI Codex OAuth: start the remote manual-input race for Codex login and keep the pasted-input prompt aligned with the actual accepted values, so remote/VPS auth no longer stalls waiting on an unreachable localhost callback. (#51631) Thanks @cash-echo-bot.
|
||||
- Group mention gating: reject invalid and unsafe nested-repetition `mentionPatterns`, reuse the shared safe config-regex compiler across mention stripping and detection, and cache strip-time regex compilation so noisy groups avoid repeated recompiles.
|
||||
|
|
@ -636,11 +636,11 @@ Docs: https://docs.openclaw.ai
|
|||
- Gateway/agent events: stop broadcasting false end-of-run `seq gap` errors to clients, and isolate node-driven ingress turns with per-turn run IDs so stale tail events cannot leak into later session runs. (#43751) Thanks @caesargattuso.
|
||||
- Nodes/pending actions: re-check queued foreground actions against the current node command policy before returning them to the node. (#46815) Thanks @zpbrent and @vincentkoc.
|
||||
- Windows/gateway status: accept `schtasks` `Last Result` output as an alias for `Last Run Result`, so running scheduled-task installs no longer show `Runtime: unknown`. (#47844) Thanks @MoerAI.
|
||||
- ACP/acpx: resolve the bundled plugin root from the actual plugin directory so plugin-local installs stay under `dist/extensions/acpx` instead of escaping to `dist/extensions` and failing runtime setup. (#47601) Thanks @ngutman.
|
||||
- ACP/acpx: resolve the bundled plugin root from the actual plugin directory so plugin-local installs stay under the bundled dist plugin tree instead of escaping upward and failing runtime setup. (#47601) Thanks @ngutman.
|
||||
- Gateway/WS handshake: raise the default pre-auth handshake timeout to 10 seconds and add `OPENCLAW_HANDSHAKE_TIMEOUT_MS` as a runtime override so busy local gateways stop dropping healthy CLI connections at 3 seconds. (#49262) Thanks @fuller-stack-dev.
|
||||
- Gateway/websocket pairing bypass for disabled auth: skip device-pairing enforcement for Control UI operator sessions when `gateway.auth.mode=none`, so reverse-proxied dashboards no longer get stuck on `pairing required` despite auth being explicitly disabled. (#47148) Thanks @ademczuk.
|
||||
- Agents/usage tracking: stop forcing `supportsUsageInStreaming: false` on non-native OpenAI-completions providers so compatible backends report token usage and cost again instead of showing all zeros. (#46500) Fixes #46142. Thanks @ademczuk.
|
||||
- ACP/acpx: keep plugin-local backend installs under `extensions/acpx` in live repo checkouts so rebuilds no longer delete the runtime binary, and avoid package-lock churn during runtime repair.
|
||||
- ACP/acpx: keep plugin-local backend installs under the bundled ACPX plugin package in live repo checkouts so rebuilds no longer delete the runtime binary, and avoid package-lock churn during runtime repair.
|
||||
- Agents/compaction: rerun transcript repair after `session.compact()` so orphaned `tool_result` blocks cannot survive compaction and break later Anthropic requests. (#16095) thanks @claw-sylphx.
|
||||
- Agents/compaction: trigger overflow recovery from the tool-result guard once post-compaction context still exceeds the safe threshold, so long tool loops compact before the next model call hard-fails. (#29371) thanks @keshav55.
|
||||
- macOS/exec approvals: harden exec-host request HMAC verification to use a timing-safe compare and keep malformed or truncated signatures fail-closed in focused IPC auth coverage.
|
||||
|
|
@ -1410,7 +1410,7 @@ Docs: https://docs.openclaw.ai
|
|||
- Gateway/loopback announce URLs: treat `http://` and `https://` aliases with the same loopback/private-network policy as websocket URLs so loopback cron announce delivery no longer fails secure URL validation. (#39064) Thanks @Narcooo.
|
||||
- Models/default provider fallback: when the hardcoded default provider is removed from `models.providers`, resolve defaults from configured providers instead of reporting stale removed-provider defaults in status output. (#38947) Thanks @davidemanuelDEV.
|
||||
- Agents/cache-trace stability: guard stable stringify against circular references in trace payloads so near-limit payloads no longer crash with `Maximum call stack size exceeded`; adds regression coverage. (#38935) Thanks @MumuTW.
|
||||
- Extensions/diffs CI stability: add `headers` to the `localReq` test helper in `extensions/diffs/index.test.ts` so forwarding-hint checks no longer crash with `req.headers` undefined. (supersedes #39063) Thanks @Shennng.
|
||||
- Extensions/diffs CI stability: add `headers` to the diffs plugin `localReq` test helper so forwarding-hint checks no longer crash with `req.headers` undefined. (supersedes #39063) Thanks @Shennng.
|
||||
- Agents/compaction thresholding: apply `agents.defaults.contextTokens` cap to the model passed into embedded run and `/compact` session creation so auto-compaction thresholds use the effective context window, not native model max context. (#39099) Thanks @MumuTW.
|
||||
- Models/merge mode provider precedence: when `models.mode: "merge"` is active and config explicitly sets a provider `baseUrl`, keep config as source of truth instead of preserving stale runtime `models.json` `baseUrl` values; includes normalized provider-key coverage. (#39103) Thanks @BigUncle.
|
||||
- UI/Control chat tool streaming: render tool events live in webchat without requiring refresh by enabling `tool-events` capability, fixing stream/event correlation, and resetting/reloading stream state around tool results and terminal events. (#39104) Thanks @jakepresent.
|
||||
|
|
@ -2618,7 +2618,7 @@ Docs: https://docs.openclaw.ai
|
|||
- Security/Agents: make owner-ID obfuscation use a dedicated HMAC secret from configuration (`ownerDisplaySecret`) and update hashing behavior so obfuscation is decoupled from gateway token handling for improved control. (#7343) Thanks @vincentkoc.
|
||||
- Security/Infra: switch gateway lock and tool-call synthetic IDs from SHA-1 to SHA-256 with unchanged truncation length to strengthen hash basis while keeping deterministic behavior and lock key format. (#7343) Thanks @vincentkoc.
|
||||
- Dependencies/Tooling: add non-blocking dead-code scans in CI via Knip/ts-prune/ts-unused-exports to surface unused dependencies and exports earlier. (#22468) Thanks @vincentkoc.
|
||||
- Dependencies/Unused Dependencies: remove or scope unused root and extension deps (`@larksuiteoapi/node-sdk`, `signal-utils`, `ollama`, `lit`, `@lit/context`, `@lit-labs/signals`, `@microsoft/agents-hosting-express`, `@microsoft/agents-hosting-extensions-teams`, and plugin-local `openclaw` devDeps in `extensions/open-prose`, `extensions/lobster`, and `extensions/llm-task`). (#22471, #22495) Thanks @vincentkoc.
|
||||
- Dependencies/Unused Dependencies: remove or scope unused root and extension deps (`@larksuiteoapi/node-sdk`, `signal-utils`, `ollama`, `lit`, `@lit/context`, `@lit-labs/signals`, `@microsoft/agents-hosting-express`, `@microsoft/agents-hosting-extensions-teams`, and plugin-local `openclaw` devDeps in the Open Prose, Lobster, and LLM Task plugin packages). (#22471, #22495) Thanks @vincentkoc.
|
||||
- Dependencies/A2UI: harden dependency resolution after root cleanup (resolve `lit`, `@lit/context`, `@lit-labs/signals`, and `signal-utils` from workspace/root) and simplify bundling fallback behavior, including `pnpm dlx rolldown` compatibility. (#22481, #22507) Thanks @vincentkoc.
|
||||
|
||||
### Fixes
|
||||
|
|
@ -3421,7 +3421,7 @@ Docs: https://docs.openclaw.ai
|
|||
- Feishu: probe status uses the resolved account context for multi-account credential checks. (#11233) Thanks @onevcat.
|
||||
- Feishu: add streaming card replies via Card Kit API and preserve `renderMode=auto` fallback behavior for plain-text responses. (#10379) Thanks @xzq-xu.
|
||||
- Feishu DocX: preserve top-level converted block order using `firstLevelBlockIds` when writing/appending documents. (#13994) Thanks @Cynosure159.
|
||||
- Feishu plugin packaging: remove `workspace:*` `openclaw` dependency from `extensions/feishu` and sync lockfile for install compatibility. (#14423) Thanks @jackcooper2015.
|
||||
- Feishu plugin packaging: remove `workspace:*` `openclaw` dependency from the Feishu plugin package and sync lockfile for install compatibility. (#14423) Thanks @jackcooper2015.
|
||||
- CLI/Wizard: exit with code 1 when `configure`, `agents add`, or interactive `onboard` wizards are canceled, so `set -e` automation stops correctly. (#14156) Thanks @0xRaini.
|
||||
- Media: strip `MEDIA:` lines with local paths instead of leaking as visible text. (#14399) Thanks @0xRaini.
|
||||
- Config/Cron: exclude `maxTokens` from config redaction and honor `deleteAfterRun` on skipped cron jobs. (#13342) Thanks @niceysam.
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@
|
|||
<li>Mattermost/replies: keep pairing replies, slash-command fallback replies, and model-picker messages on the resolved config path so <code>exec:</code> SecretRef bot tokens work across all outbound reply branches. (#48347) thanks @mathiasnagler.</li>
|
||||
<li>Microsoft Teams/config: accept the existing <code>welcomeCard</code>, <code>groupWelcomeCard</code>, <code>promptStarters</code>, and feedback/reflection keys in strict config validation so already-supported Teams runtime settings stop failing schema checks. (#54679) Thanks @gumclaw.</li>
|
||||
<li>MCP/channels: add a Gateway-backed channel MCP bridge with Codex/Claude-facing conversation tools, Claude channel notifications, and safer stdio bridge lifecycle handling for reconnects and routed session discovery.</li>
|
||||
<li>Plugins/SDK: thread <code>moduleUrl</code> through plugin-sdk alias resolution so user-installed plugins outside the openclaw directory (e.g. <code>~/.openclaw/extensions/</code>) correctly resolve <code>openclaw/plugin-sdk/*</code> subpath imports, and gate <code>plugin-sdk:check-exports</code> in <code>release:check</code>. (#54283) Thanks @xieyongliang.</li>
|
||||
<li>Plugins/SDK: thread <code>moduleUrl</code> through plugin-sdk alias resolution so user-installed plugins outside the openclaw directory correctly resolve <code>openclaw/plugin-sdk/*</code> subpath imports, and gate <code>plugin-sdk:check-exports</code> in <code>release:check</code>. (#54283) Thanks @xieyongliang.</li>
|
||||
<li>Config/web fetch: allow the documented <code>tools.web.fetch.maxResponseBytes</code> setting in runtime schema validation so valid configs no longer fail with unrecognized-key errors. (#53401) Thanks @erhhung.</li>
|
||||
<li>Message tool/buttons: keep the shared <code>buttons</code> schema optional in merged tool definitions so plain <code>action=send</code> calls stop failing validation when no buttons are provided. (#54418) Thanks @adzendo.</li>
|
||||
<li>Agents/openai-compatible tool calls: deduplicate repeated tool call ids across live assistant messages and replayed history so OpenAI-compatible backends no longer reject duplicate <code>tool_call_id</code> values with HTTP 400. (#40996) Thanks @xaeon2026.</li>
|
||||
|
|
@ -106,7 +106,7 @@
|
|||
<li>GitHub Copilot/auth refresh: treat large <code>expires_at</code> values as seconds epochs and clamp far-future runtime auth refresh timers so Copilot token refresh cannot fall into a <code>setTimeout</code> overflow hot loop. (#55360) Thanks @michael-abdo.</li>
|
||||
<li>Agents/status: use the persisted runtime session model in <code>session_status</code> when no explicit override exists, and honor per-agent <code>thinkingDefault</code> in both <code>session_status</code> and <code>/status</code>. (#55425) Thanks @scoootscooob, @xaeon2026, and @ysfbsf.</li>
|
||||
<li>Heartbeat/runner: guarantee the interval timer is re-armed after heartbeat runs and unexpected runner errors so scheduled heartbeats do not silently stop after an interrupted cycle. (#52270) Thanks @MiloStack.</li>
|
||||
<li>Config/Doctor: rewrite stale bundled plugin load paths from legacy <code>extensions/*</code> locations to the packaged bundled path, including directory-name mismatches and slash-suffixed config entries. (#55054) Thanks @SnowSky1.</li>
|
||||
<li>Config/Doctor: rewrite stale bundled plugin load paths from legacy bundled-plugin locations to the packaged bundled path, including directory-name mismatches and slash-suffixed config entries. (#55054) Thanks @SnowSky1.</li>
|
||||
<li>WhatsApp/mentions: stop treating mentions embedded in quoted messages as direct mentions so replying to a message that @mentioned the bot no longer falsely triggers mention gating. (#52711) Thanks @lurebat.</li>
|
||||
<li>Matrix: keep separate 2-person rooms out of DM routing after <code>m.direct</code> seeds successfully, while still honoring explicit <code>is_direct</code> state and startup fallback recovery. (#54890) thanks @private-peter</li>
|
||||
<li>Agents/ollama fallback: surface non-2xx Ollama HTTP errors with a leading status code so HTTP 503 responses trigger model fallback again. (#55214) Thanks @bugkill3r.</li>
|
||||
|
|
@ -237,4 +237,4 @@
|
|||
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.3.23/OpenClaw-2026.3.23.zip" length="24522883" type="application/octet-stream" sparkle:edSignature="ptBgHYLBqq/TSdONYCfIB5d6aP/ij/9G0gYQ5mJI9jf8Y31sbQIh5CqpJVxEEWLTMIGQKsHQir/kXZjtRvvZAg=="/>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
</rss>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ openclaw plugins install @openclaw/line
|
|||
Local checkout (when running from a git repo):
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/line
|
||||
openclaw plugins install ./path/to/local/line-plugin
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ openclaw plugins install @openclaw/matrix
|
|||
Install from a local checkout:
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/matrix
|
||||
openclaw plugins install ./path/to/local/matrix-plugin
|
||||
```
|
||||
|
||||
See [Plugins](/tools/plugin) for plugin behavior and install rules.
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ openclaw plugins install @openclaw/mattermost
|
|||
Local checkout (when running from a git repo):
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/mattermost
|
||||
openclaw plugins install ./path/to/local/mattermost-plugin
|
||||
```
|
||||
|
||||
If you choose Mattermost during setup and a git checkout is detected,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ openclaw plugins install @openclaw/msteams
|
|||
Local checkout (when running from a git repo):
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/msteams
|
||||
openclaw plugins install ./path/to/local/msteams-plugin
|
||||
```
|
||||
|
||||
If you choose Teams during setup and a git checkout is detected,
|
||||
|
|
@ -242,7 +242,7 @@ This is often easier than hand-editing JSON manifests.
|
|||
|
||||
1. **Install the Microsoft Teams plugin**
|
||||
- From npm: `openclaw plugins install @openclaw/msteams`
|
||||
- From a local checkout: `openclaw plugins install ./extensions/msteams`
|
||||
- From a local checkout: `openclaw plugins install ./path/to/local/msteams-plugin`
|
||||
|
||||
2. **Bot registration**
|
||||
- Create an Azure Bot (see above) and note:
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ openclaw plugins install @openclaw/nextcloud-talk
|
|||
Local checkout (when running from a git repo):
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/nextcloud-talk
|
||||
openclaw plugins install ./path/to/local/nextcloud-talk-plugin
|
||||
```
|
||||
|
||||
If you choose Nextcloud Talk during setup and a git checkout is detected,
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ openclaw plugins install @openclaw/nostr
|
|||
Use a local checkout (dev workflows):
|
||||
|
||||
```bash
|
||||
openclaw plugins install --link <path-to-openclaw>/extensions/nostr
|
||||
openclaw plugins install --link <path-to-local-nostr-plugin>
|
||||
```
|
||||
|
||||
Restart the Gateway after installing or enabling plugins.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Synology Chat is plugin-based and not part of the default core channel install.
|
|||
Install from a local checkout:
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/synology-chat
|
||||
openclaw plugins install ./path/to/local/synology-chat-plugin
|
||||
```
|
||||
|
||||
Details: [Plugins](/tools/plugin)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ openclaw plugins install @openclaw/tlon
|
|||
Local checkout (when running from a git repo):
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/tlon
|
||||
openclaw plugins install ./path/to/local/tlon-plugin
|
||||
```
|
||||
|
||||
Details: [Plugins](/tools/plugin)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ openclaw plugins install @openclaw/twitch
|
|||
Local checkout (when running from a git repo):
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/twitch
|
||||
openclaw plugins install ./path/to/local/twitch-plugin
|
||||
```
|
||||
|
||||
Details: [Plugins](/tools/plugin)
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ Zalo ships as a plugin and is not bundled with the core install.
|
|||
## Quick setup (beginner)
|
||||
|
||||
1. Install the Zalo plugin:
|
||||
- From a source checkout: `openclaw plugins install ./extensions/zalo`
|
||||
- From a source checkout: `openclaw plugins install ./path/to/local/zalo-plugin`
|
||||
- From npm (if published): `openclaw plugins install @openclaw/zalo`
|
||||
- Or pick **Zalo** in setup and confirm the install prompt
|
||||
2. Set the token:
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ Status: experimental. This integration automates a **personal Zalo account** via
|
|||
Zalo Personal ships as a plugin and is not bundled with the core install.
|
||||
|
||||
- Install via CLI: `openclaw plugins install @openclaw/zalouser`
|
||||
- Or from a source checkout: `openclaw plugins install ./extensions/zalouser`
|
||||
- Or from a source checkout: `openclaw plugins install ./path/to/local/zalouser-plugin`
|
||||
- Details: [Plugins](/tools/plugin)
|
||||
|
||||
No external `zca`/`openzca` CLI binary is required.
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ the plugin allowlist, and linked `plugins.load.paths` entries when applicable.
|
|||
For active memory plugins, the memory slot resets to `memory-core`.
|
||||
|
||||
By default, uninstall also removes the plugin install directory under the active
|
||||
state dir extensions root (`$OPENCLAW_STATE_DIR/extensions/<id>`). Use
|
||||
state-dir plugin root. Use
|
||||
`--keep-files` to keep files on disk.
|
||||
|
||||
`--keep-config` is supported as a deprecated alias for `--keep-files`.
|
||||
|
|
|
|||
|
|
@ -459,7 +459,7 @@ Plugins run **in-process** with the Gateway. Treat them as trusted code:
|
|||
- Review plugin config before enabling.
|
||||
- Restart the Gateway after plugin changes.
|
||||
- If you install plugins (`openclaw plugins install <package>`), treat it like running untrusted code:
|
||||
- The install path is `~/.openclaw/extensions/<pluginId>/` (or `$OPENCLAW_STATE_DIR/extensions/<pluginId>/`).
|
||||
- The install path is the per-plugin directory under the active plugin install root.
|
||||
- OpenClaw uses `npm pack` and then runs `npm install --omit=dev` in that directory (npm lifecycle scripts can execute code during install).
|
||||
- Prefer pinned, exact versions (`@scope/pkg@1.2.3`), and inspect the unpacked code on disk before enabling.
|
||||
|
||||
|
|
@ -859,7 +859,7 @@ Assume anything under `~/.openclaw/` (or `$OPENCLAW_STATE_DIR/`) may contain sec
|
|||
- `secrets.json` (optional): file-backed secret payload used by `file` SecretRef providers (`secrets.providers`).
|
||||
- `agents/<agentId>/agent/auth.json`: legacy compatibility file. Static `api_key` entries are scrubbed when discovered.
|
||||
- `agents/<agentId>/sessions/**`: session transcripts (`*.jsonl`) + routing metadata (`sessions.json`) that can contain private messages and tool output.
|
||||
- `extensions/**`: installed plugins (plus their `node_modules/`).
|
||||
- bundled plugin packages: installed plugins (plus their `node_modules/`).
|
||||
- `sandboxes/**`: tool sandbox workspaces; can accumulate copies of files you read/write inside the sandbox.
|
||||
|
||||
Hardening tips:
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
|
|||
|
||||
- Command: `pnpm test`
|
||||
- Config: `scripts/test-parallel.mjs` (runs `vitest.unit.config.ts`, `vitest.extensions.config.ts`, `vitest.gateway.config.ts`)
|
||||
- Files: `src/**/*.test.ts`, `extensions/**/*.test.ts`
|
||||
- Files: `src/**/*.test.ts`, bundled plugin `**/*.test.ts`
|
||||
- Scope:
|
||||
- Pure unit tests
|
||||
- In-process integration tests (gateway auth, routing, tooling, parsing, config)
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ If the old store reports room keys that were never backed up, OpenClaw warns ins
|
|||
`Legacy Matrix encrypted state was detected, but the Matrix plugin helper is unavailable. Install or repair @openclaw/matrix so OpenClaw can inspect the old rust crypto store before upgrading.`
|
||||
|
||||
- Meaning: OpenClaw found old encrypted Matrix state, but it could not load the helper entrypoint from the Matrix plugin that normally inspects that store.
|
||||
- What to do: reinstall or repair the Matrix plugin (`openclaw plugins install @openclaw/matrix`, or `openclaw plugins install ./extensions/matrix` for a repo checkout), then rerun `openclaw doctor --fix` or restart the gateway.
|
||||
- What to do: reinstall or repair the Matrix plugin (`openclaw plugins install @openclaw/matrix`, or `openclaw plugins install ./path/to/local/matrix-plugin` for a repo checkout), then rerun `openclaw doctor --fix` or restart the gateway.
|
||||
|
||||
`Matrix plugin helper path is unsafe: ... Reinstall @openclaw/matrix and try again.`
|
||||
|
||||
|
|
@ -312,7 +312,7 @@ If you accept losing unrecoverable old encrypted history, you can instead reset
|
|||
`Matrix is installed from a custom path that no longer exists: ...`
|
||||
|
||||
- Meaning: your plugin install record points at a local path that is gone.
|
||||
- What to do: reinstall with `openclaw plugins install @openclaw/matrix`, or if you are running from a repo checkout, `openclaw plugins install ./extensions/matrix`.
|
||||
- What to do: reinstall with `openclaw plugins install @openclaw/matrix`, or if you are running from a repo checkout, `openclaw plugins install ./path/to/local/matrix-plugin`.
|
||||
|
||||
## If encrypted history still does not come back
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ pnpm test -- \
|
|||
"src/agents/pi-tools*.test.ts" \
|
||||
"src/agents/pi-settings.test.ts" \
|
||||
"src/agents/pi-tool-definition-adapter*.test.ts" \
|
||||
"src/agents/pi-extensions/**/*.test.ts"
|
||||
"src/agents/pi-hooks/**/*.test.ts"
|
||||
```
|
||||
|
||||
To include the live provider exercise:
|
||||
|
|
@ -44,7 +44,7 @@ This covers the main Pi unit suites:
|
|||
- `src/agents/pi-tools*.test.ts`
|
||||
- `src/agents/pi-settings.test.ts`
|
||||
- `src/agents/pi-tool-definition-adapter.test.ts`
|
||||
- `src/agents/pi-extensions/*.test.ts`
|
||||
- `src/agents/pi-hooks/*.test.ts`
|
||||
|
||||
## Manual Testing
|
||||
|
||||
|
|
|
|||
16
docs/pi.md
16
docs/pi.md
|
|
@ -88,7 +88,7 @@ src/agents/
|
|||
├── pi-tools.types.ts # AnyAgentTool type alias
|
||||
├── pi-tool-definition-adapter.ts # AgentTool -> ToolDefinition adapter
|
||||
├── pi-settings.ts # Settings overrides
|
||||
├── pi-extensions/ # Custom pi extensions
|
||||
├── pi-hooks/ # Custom pi hooks
|
||||
│ ├── compaction-safeguard.ts # Safeguard extension
|
||||
│ ├── compaction-safeguard-runtime.ts
|
||||
│ ├── context-pruning.ts # Cache-TTL context pruning extension
|
||||
|
|
@ -132,10 +132,10 @@ src/agents/
|
|||
Channel-specific message action runtimes now live in the plugin-owned extension
|
||||
directories instead of under `src/agents/tools`, for example:
|
||||
|
||||
- `extensions/discord/src/actions/runtime*.ts`
|
||||
- `extensions/slack/src/action-runtime.ts`
|
||||
- `extensions/telegram/src/action-runtime.ts`
|
||||
- `extensions/whatsapp/src/action-runtime.ts`
|
||||
- the Discord plugin action runtime files
|
||||
- the Slack plugin action runtime file
|
||||
- the Telegram plugin action runtime file
|
||||
- the WhatsApp plugin action runtime file
|
||||
|
||||
## Core Integration Flow
|
||||
|
||||
|
|
@ -390,7 +390,7 @@ OpenClaw loads custom pi extensions for specialized behavior:
|
|||
|
||||
### Compaction Safeguard
|
||||
|
||||
`src/agents/pi-extensions/compaction-safeguard.ts` adds guardrails to compaction, including adaptive token budgeting plus tool failure and file operation summaries:
|
||||
`src/agents/pi-hooks/compaction-safeguard.ts` adds guardrails to compaction, including adaptive token budgeting plus tool failure and file operation summaries:
|
||||
|
||||
```typescript
|
||||
if (resolveCompactionMode(params.cfg) === "safeguard") {
|
||||
|
|
@ -401,7 +401,7 @@ if (resolveCompactionMode(params.cfg) === "safeguard") {
|
|||
|
||||
### Context Pruning
|
||||
|
||||
`src/agents/pi-extensions/context-pruning.ts` implements cache-TTL based context pruning:
|
||||
`src/agents/pi-hooks/context-pruning.ts` implements cache-TTL based context pruning:
|
||||
|
||||
```typescript
|
||||
if (cfg?.agents?.defaults?.contextPruning?.mode === "cache-ttl") {
|
||||
|
|
@ -558,7 +558,7 @@ Pi integration coverage spans these suites:
|
|||
- `src/agents/pi-tools*.test.ts`
|
||||
- `src/agents/pi-tool-definition-adapter*.test.ts`
|
||||
- `src/agents/pi-settings.test.ts`
|
||||
- `src/agents/pi-extensions/**/*.test.ts`
|
||||
- `src/agents/pi-hooks/**/*.test.ts`
|
||||
|
||||
Live/opt-in:
|
||||
|
||||
|
|
|
|||
|
|
@ -969,16 +969,17 @@ authoring plugins:
|
|||
New code should import the narrower primitives instead.
|
||||
- Bundled extension internals remain private. External plugins should use only
|
||||
`openclaw/plugin-sdk/*` subpaths. OpenClaw core/test code may use the repo
|
||||
public entry points under `extensions/<id>/index.js`, `api.js`, `runtime-api.js`,
|
||||
`setup-entry.js`, and narrowly scoped files such as `login-qr-api.js`. Never
|
||||
import `extensions/<id>/src/*` from core or from another extension.
|
||||
public entry points under a plugin package root such as `index.js`, `api.js`,
|
||||
`runtime-api.js`, `setup-entry.js`, and narrowly scoped files such as
|
||||
`login-qr-api.js`. Never import a plugin package's `src/*` from core or from
|
||||
another extension.
|
||||
- Repo entry point split:
|
||||
`extensions/<id>/api.js` is the helper/types barrel,
|
||||
`extensions/<id>/runtime-api.js` is the runtime-only barrel,
|
||||
`extensions/<id>/index.js` is the bundled plugin entry,
|
||||
and `extensions/<id>/setup-entry.js` is the setup plugin entry.
|
||||
`<plugin-package-root>/api.js` is the helper/types barrel,
|
||||
`<plugin-package-root>/runtime-api.js` is the runtime-only barrel,
|
||||
`<plugin-package-root>/index.js` is the bundled plugin entry,
|
||||
and `<plugin-package-root>/setup-entry.js` is the setup plugin entry.
|
||||
- No bundled channel-branded public subpaths remain. Channel-specific helper and
|
||||
runtime seams live under `extensions/<id>/api.js` and `extensions/<id>/runtime-api.js`;
|
||||
runtime seams live under `<plugin-package-root>/api.js` and `<plugin-package-root>/runtime-api.js`;
|
||||
the public SDK contract is the generic shared primitives instead.
|
||||
|
||||
Compatibility note:
|
||||
|
|
@ -1216,7 +1217,7 @@ Example:
|
|||
},
|
||||
"install": {
|
||||
"npmSpec": "@openclaw/nextcloud-talk",
|
||||
"localPath": "extensions/nextcloud-talk",
|
||||
"localPath": "<bundled-plugin-local-path>",
|
||||
"defaultChoice": "npm"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,10 +115,10 @@ and provider plugins have dedicated guides linked above.
|
|||
|
||||
OpenClaw checks ClawHub first, then falls back to npm.
|
||||
|
||||
**In-repo plugins:** place under `extensions/` — automatically discovered.
|
||||
**In-repo plugins:** place under the bundled plugin workspace tree — automatically discovered.
|
||||
|
||||
```bash
|
||||
pnpm test -- extensions/my-plugin/
|
||||
pnpm test -- <bundled-plugin-root>/my-plugin/
|
||||
```
|
||||
|
||||
</Step>
|
||||
|
|
@ -222,7 +222,7 @@ internal imports — never import your own plugin through its SDK path.
|
|||
<Check>Entry point uses `defineChannelPluginEntry` or `definePluginEntry`</Check>
|
||||
<Check>All imports use focused `plugin-sdk/<subpath>` paths</Check>
|
||||
<Check>Internal imports use local modules, not SDK self-imports</Check>
|
||||
<Check>Tests pass (`pnpm test -- extensions/my-plugin/`)</Check>
|
||||
<Check>Tests pass (`pnpm test -- <bundled-plugin-root>/my-plugin/`)</Check>
|
||||
<Check>`pnpm check` passes (in-repo plugins)</Check>
|
||||
|
||||
## Beta Release Testing
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ dispatch.
|
|||
|
||||
// Your inbound handler dispatches the message to OpenClaw.
|
||||
// The exact wiring depends on your platform SDK —
|
||||
// see a real example in extensions/msteams or extensions/googlechat.
|
||||
// see a real example in the bundled Microsoft Teams or Google Chat plugin package.
|
||||
await handleAcmeChatInbound(api, event);
|
||||
|
||||
res.statusCode = 200;
|
||||
|
|
@ -279,7 +279,7 @@ dispatch.
|
|||
<Note>
|
||||
Inbound message handling is channel-specific. Each channel plugin owns
|
||||
its own inbound pipeline. Look at bundled channel plugins
|
||||
(e.g. `extensions/msteams`, `extensions/googlechat`) for real patterns.
|
||||
(for example the Microsoft Teams or Google Chat plugin package) for real patterns.
|
||||
</Note>
|
||||
|
||||
</Step>
|
||||
|
|
@ -320,7 +320,7 @@ dispatch.
|
|||
```
|
||||
|
||||
```bash
|
||||
pnpm test -- extensions/acme-chat/
|
||||
pnpm test -- <bundled-plugin-root>/acme-chat/
|
||||
```
|
||||
|
||||
For shared test helpers, see [Testing](/plugins/sdk-testing).
|
||||
|
|
@ -331,7 +331,7 @@ dispatch.
|
|||
## File structure
|
||||
|
||||
```
|
||||
extensions/acme-chat/
|
||||
<bundled-plugin-root>/acme-chat/
|
||||
├── package.json # openclaw.channel metadata
|
||||
├── openclaw.plugin.json # Manifest with config schema
|
||||
├── index.ts # defineChannelPluginEntry
|
||||
|
|
|
|||
|
|
@ -386,7 +386,7 @@ API key auth, and dynamic model resolution.
|
|||
## File structure
|
||||
|
||||
```
|
||||
extensions/acme-ai/
|
||||
<bundled-plugin-root>/acme-ai/
|
||||
├── package.json # openclaw.providers metadata
|
||||
├── openclaw.plugin.json # Manifest with providerAuthEnvVars
|
||||
├── index.ts # definePluginEntry + registerProvider
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ const setupWizard: ChannelSetupWizard = {
|
|||
|
||||
The `ChannelSetupWizard` type supports `credentials`, `textInputs`,
|
||||
`dmPolicy`, `allowFrom`, `groupAccess`, `prepare`, `finalize`, and more.
|
||||
See bundled plugins (e.g. `extensions/discord/src/channel.setup.ts`) for
|
||||
See bundled plugin packages (for example the Discord plugin `src/channel.setup.ts`) for
|
||||
full examples.
|
||||
|
||||
For DM allowlist prompts that only need the standard
|
||||
|
|
@ -319,7 +319,7 @@ openclaw plugins install clawhub:@myorg/openclaw-my-plugin # ClawHub only
|
|||
openclaw plugins install npm:@myorg/openclaw-my-plugin # npm only
|
||||
```
|
||||
|
||||
**In-repo plugins:** place under `extensions/` and they are automatically
|
||||
**In-repo plugins:** place under the bundled plugin workspace tree and they are automatically
|
||||
discovered during build.
|
||||
|
||||
**Users can browse and install:**
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ These tests assert:
|
|||
For a specific plugin:
|
||||
|
||||
```bash
|
||||
pnpm test -- extensions/my-channel/
|
||||
pnpm test -- <bundled-plugin-root>/my-channel/
|
||||
```
|
||||
|
||||
For contract tests only:
|
||||
|
|
@ -240,10 +240,10 @@ OpenClaw uses Vitest with V8 coverage thresholds. For plugin tests:
|
|||
pnpm test
|
||||
|
||||
# Run specific plugin tests
|
||||
pnpm test -- extensions/my-channel/src/channel.test.ts
|
||||
pnpm test -- <bundled-plugin-root>/my-channel/src/channel.test.ts
|
||||
|
||||
# Run with a specific test name filter
|
||||
pnpm test -- extensions/my-channel/ -t "resolves account"
|
||||
pnpm test -- <bundled-plugin-root>/my-channel/ -t "resolves account"
|
||||
|
||||
# Run with coverage
|
||||
pnpm test:coverage
|
||||
|
|
|
|||
|
|
@ -44,8 +44,9 @@ Restart the Gateway afterwards.
|
|||
### Option B: install from a local folder (dev, no copying)
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/voice-call
|
||||
cd ./extensions/voice-call && pnpm install
|
||||
PLUGIN_SRC=./path/to/local/voice-call-plugin
|
||||
openclaw plugins install "$PLUGIN_SRC"
|
||||
cd "$PLUGIN_SRC" && pnpm install
|
||||
```
|
||||
|
||||
Restart the Gateway afterwards.
|
||||
|
|
|
|||
|
|
@ -37,8 +37,9 @@ Restart the Gateway afterwards.
|
|||
### Option B: install from a local folder (dev)
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/zalouser
|
||||
cd ./extensions/zalouser && pnpm install
|
||||
PLUGIN_SRC=./path/to/local/zalouser-plugin
|
||||
openclaw plugins install "$PLUGIN_SRC"
|
||||
cd "$PLUGIN_SRC" && pnpm install
|
||||
```
|
||||
|
||||
Restart the Gateway afterwards.
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ openclaw plugins enable open-prose
|
|||
|
||||
Restart the Gateway after enabling the plugin.
|
||||
|
||||
Dev/local checkout: `openclaw plugins install ./extensions/open-prose`
|
||||
Dev/local checkout: `openclaw plugins install ./path/to/local/open-prose-plugin`
|
||||
|
||||
Related docs: [Plugins](/tools/plugin), [Plugin manifest](/plugins/manifest), [Skills](/tools/skills).
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ You will be prompted to select an endpoint:
|
|||
- **Global** - International users (`api.minimax.io`)
|
||||
- **CN** - Users in China (`api.minimaxi.com`)
|
||||
|
||||
See [MiniMax plugin README](https://github.com/openclaw/openclaw/tree/main/extensions/minimax) for details.
|
||||
See the MiniMax plugin package README in the OpenClaw repo for details.
|
||||
|
||||
### MiniMax M2.7 (API key)
|
||||
|
||||
|
|
|
|||
|
|
@ -624,7 +624,7 @@ openclaw config set plugins.entries.acpx.enabled true
|
|||
Local workspace install during development:
|
||||
|
||||
```bash
|
||||
openclaw plugins install ./extensions/acpx
|
||||
openclaw plugins install ./path/to/local/acpx-plugin
|
||||
```
|
||||
|
||||
Then verify backend health:
|
||||
|
|
@ -637,7 +637,7 @@ Then verify backend health:
|
|||
|
||||
By default, the bundled acpx backend plugin (`acpx`) uses the plugin-local pinned binary:
|
||||
|
||||
1. Command defaults to `extensions/acpx/node_modules/.bin/acpx`.
|
||||
1. Command defaults to the plugin-local `node_modules/.bin/acpx` inside the ACPX plugin package.
|
||||
2. Expected version defaults to the extension pin.
|
||||
3. Startup registers ACP backend immediately as not-ready.
|
||||
4. A background ensure job verifies `acpx --version`.
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ replacement plugin to reuse.
|
|||
The bundled browser plugin also owns the browser runtime implementation now.
|
||||
Core keeps only shared Plugin SDK helpers plus compatibility re-exports for
|
||||
older internal import paths. In practice, removing or replacing
|
||||
`extensions/browser` removes the browser feature set instead of leaving a
|
||||
Removing the browser plugin package removes the browser feature set instead of leaving a
|
||||
second core-owned runtime behind.
|
||||
|
||||
Browser config changes still require a Gateway restart so the bundled plugin
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ For a new capability, expect to touch these areas:
|
|||
- `src/plugins/runtime/index.ts`
|
||||
- `src/plugin-sdk/<capability>.ts`
|
||||
- `src/plugin-sdk/<capability>-runtime.ts`
|
||||
- one or more `extensions/<vendor>/...`
|
||||
- one or more bundled plugin packages
|
||||
- config/docs/tests
|
||||
|
||||
## Example: image generation
|
||||
|
|
|
|||
|
|
@ -156,11 +156,11 @@ OpenClaw scans for plugins in this order (first match wins):
|
|||
</Step>
|
||||
|
||||
<Step title="Workspace extensions">
|
||||
`\<workspace\>/.openclaw/extensions/*.ts` and `\<workspace\>/.openclaw/extensions/*/index.ts`.
|
||||
`\<workspace\>/.openclaw/<plugin-root>/*.ts` and `\<workspace\>/.openclaw/<plugin-root>/*/index.ts`.
|
||||
</Step>
|
||||
|
||||
<Step title="Global extensions">
|
||||
`~/.openclaw/extensions/*.ts` and `~/.openclaw/extensions/*/index.ts`.
|
||||
`~/.openclaw/<plugin-root>/*.ts` and `~/.openclaw/<plugin-root>/*/index.ts`.
|
||||
</Step>
|
||||
|
||||
<Step title="Bundled plugins">
|
||||
|
|
|
|||
|
|
@ -1,47 +1,57 @@
|
|||
---
|
||||
title: Pi 开发工作流程
|
||||
read_when:
|
||||
- 在 OpenClaw 中处理 Pi 集成代码或测试时
|
||||
- 运行 Pi 专用的代码规范检查、类型检查和实时测试流程时
|
||||
summary: Pi 集成的开发工作流:构建、测试和实时验证
|
||||
title: Pi 开发工作流
|
||||
x-i18n:
|
||||
generated_at: "2026-02-03T10:07:59Z"
|
||||
model: claude-opus-4-5
|
||||
provider: pi
|
||||
source_hash: 65bd0580dd03df05321ced35a036ce6fb815ce3ddac1d35c9976279adcbf87c0
|
||||
generated_at: "2026-03-29T04:06:57Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 7be1c0f9ecf4315115b2e8188f7472eebba2a8424296661184a02bf5ad6e90c5
|
||||
source_path: pi-dev.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Pi 开发工作流程
|
||||
# Pi 开发工作流
|
||||
|
||||
本指南总结了在 OpenClaw 中开发 Pi 集成的合理工作流程。
|
||||
本指南总结了在 OpenClaw 中处理 Pi 集成时的一套合理工作流。
|
||||
|
||||
## 类型检查和代码检查
|
||||
## 类型检查与代码规范检查
|
||||
|
||||
- 类型检查和构建:`pnpm build`
|
||||
- 代码检查:`pnpm lint`
|
||||
- 代码规范检查:`pnpm lint`
|
||||
- 格式检查:`pnpm format`
|
||||
- 推送前完整检查:`pnpm lint && pnpm build && pnpm test`
|
||||
- 推送前的完整检查:`pnpm lint && pnpm build && pnpm test`
|
||||
|
||||
## 运行 Pi 测试
|
||||
|
||||
使用专用脚本运行 Pi 集成测试集:
|
||||
直接使用 Vitest 运行面向 Pi 的测试集:
|
||||
|
||||
```bash
|
||||
scripts/pi/run-tests.sh
|
||||
pnpm test -- \
|
||||
"src/agents/pi-*.test.ts" \
|
||||
"src/agents/pi-embedded-*.test.ts" \
|
||||
"src/agents/pi-tools*.test.ts" \
|
||||
"src/agents/pi-settings.test.ts" \
|
||||
"src/agents/pi-tool-definition-adapter*.test.ts" \
|
||||
"src/agents/pi-hooks/**/*.test.ts"
|
||||
```
|
||||
|
||||
要包含执行真实提供商行为的实时测试:
|
||||
如果还要包含提供商的实时演练:
|
||||
|
||||
```bash
|
||||
scripts/pi/run-tests.sh --live
|
||||
OPENCLAW_LIVE_TEST=1 pnpm test -- src/agents/pi-embedded-runner-extraparams.live.test.ts
|
||||
```
|
||||
|
||||
该脚本通过以下 glob 模式运行所有 Pi 相关的单元测试:
|
||||
这涵盖了主要的 Pi 单元测试套件:
|
||||
|
||||
- `src/agents/pi-*.test.ts`
|
||||
- `src/agents/pi-embedded-*.test.ts`
|
||||
- `src/agents/pi-tools*.test.ts`
|
||||
- `src/agents/pi-settings.test.ts`
|
||||
- `src/agents/pi-tool-definition-adapter.test.ts`
|
||||
- `src/agents/pi-extensions/*.test.ts`
|
||||
- `src/agents/pi-hooks/*.test.ts`
|
||||
|
||||
## 手动测试
|
||||
|
||||
|
|
@ -51,27 +61,27 @@ scripts/pi/run-tests.sh --live
|
|||
- `pnpm gateway:dev`
|
||||
- 直接触发智能体:
|
||||
- `pnpm openclaw agent --message "Hello" --thinking low`
|
||||
- 使用 TUI 进行交互式调试:
|
||||
- 使用终端界面进行交互式调试:
|
||||
- `pnpm tui`
|
||||
|
||||
对于工具调用行为,提示执行 `read` 或 `exec` 操作,以便查看工具流式传输和负载处理。
|
||||
对于工具调用行为,请提示执行 `read` 或 `exec` 操作,这样你就可以看到工具的流式传输和负载处理。
|
||||
|
||||
## 完全重置
|
||||
## 彻底重置
|
||||
|
||||
状态存储在 OpenClaw 状态目录下。默认为 `~/.openclaw`。如果设置了 `OPENCLAW_STATE_DIR`,则使用该目录。
|
||||
状态存储在 OpenClaw 状态目录下。默认路径是 `~/.openclaw`。如果设置了 `OPENCLAW_STATE_DIR`,则改用该目录。
|
||||
|
||||
要重置所有内容:
|
||||
如需重置全部内容:
|
||||
|
||||
- `openclaw.json` 用于配置
|
||||
- `credentials/` 用于认证配置文件和 token
|
||||
- `credentials/` 用于凭证配置文件和令牌
|
||||
- `agents/<agentId>/sessions/` 用于智能体会话历史
|
||||
- `agents/<agentId>/sessions.json` 用于会话索引
|
||||
- `sessions/` 如果存在旧版路径
|
||||
- `workspace/` 如果你想要一个空白工作区
|
||||
- `sessions/`,如果存在旧版路径
|
||||
- `workspace/`,如果你想要一个空白工作区
|
||||
|
||||
如果只想重置会话,删除该智能体的 `agents/<agentId>/sessions/` 和 `agents/<agentId>/sessions.json`。如果不想重新认证,保留 `credentials/`。
|
||||
如果你只想重置会话,请删除该智能体的 `agents/<agentId>/sessions/` 和 `agents/<agentId>/sessions.json`。如果你不想重新进行身份验证,请保留 `credentials/`。
|
||||
|
||||
## 参考资料
|
||||
|
||||
- https://docs.openclaw.ai/testing
|
||||
- https://docs.openclaw.ai/start/getting-started
|
||||
- [测试](/help/testing)
|
||||
- [入门指南](/start/getting-started)
|
||||
|
|
|
|||
282
docs/zh-CN/pi.md
282
docs/zh-CN/pi.md
|
|
@ -1,45 +1,49 @@
|
|||
---
|
||||
read_when:
|
||||
- 理解 OpenClaw 中 Pi SDK 集成设计时
|
||||
- 修改 Pi 的智能体会话生命周期、工具或提供商接线时
|
||||
summary: OpenClaw 内嵌 Pi 智能体集成与会话生命周期的架构
|
||||
title: Pi 集成架构
|
||||
x-i18n:
|
||||
generated_at: "2026-02-03T07:53:24Z"
|
||||
model: claude-opus-4-5
|
||||
provider: pi
|
||||
source_hash: 98b12f1211f70b1a25f58e68c7a4d0fe3827412ca53ba0ea2cd41ac9c0448458
|
||||
generated_at: "2026-03-29T04:10:02Z"
|
||||
model: gpt-5.4
|
||||
provider: openai
|
||||
source_hash: 43a5d646ed66fab1492b6f18fb1623d895922ecf539e52e069d99e7e83c0be11
|
||||
source_path: pi.md
|
||||
workflow: 15
|
||||
---
|
||||
|
||||
# Pi 集成架构
|
||||
|
||||
本文档描述了 OpenClaw 如何与 [pi-coding-agent](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent) 及其相关包(`pi-ai`、`pi-agent-core`、`pi-tui`)集成以实现其 AI 智能体能力。
|
||||
本文档介绍 OpenClaw 如何与 [pi-coding-agent](https://github.com/badlogic/pi-mono/tree/main/packages/coding-agent) 及其同级软件包(`pi-ai`、`pi-agent-core`、`pi-tui`)集成,以提供其 AI 智能体能力。
|
||||
|
||||
## 概述
|
||||
## 概览
|
||||
|
||||
OpenClaw 使用 pi SDK 将 AI 编码智能体嵌入到其消息 Gateway 网关架构中。OpenClaw 不是将 pi 作为子进程生成或使用 RPC 模式,而是通过 `createAgentSession()` 直接导入并实例化 pi 的 `AgentSession`。这种嵌入式方法提供了:
|
||||
OpenClaw 使用 pi SDK 将 AI 编码智能体嵌入到其消息 Gateway 网关架构中。OpenClaw 不会将 pi 作为子进程启动,也不会使用 RPC 模式,而是通过 `createAgentSession()` 直接导入并实例化 pi 的 `AgentSession`。这种内嵌方式提供了:
|
||||
|
||||
- 对会话生命周期和事件处理的完全控制
|
||||
- 自定义工具注入(消息、沙箱、渠道特定操作)
|
||||
- 每个渠道/上下文的系统提示自定义
|
||||
- 支持分支/压缩的会话持久化
|
||||
- 带故障转移的多账户认证配置文件轮换
|
||||
- 按渠道 / 上下文定制系统提示词
|
||||
- 支持分支 / 压缩的会话持久化
|
||||
- 带故障转移的多账户凭证配置轮换
|
||||
- 与提供商无关的模型切换
|
||||
|
||||
## 包依赖
|
||||
## 软件包依赖
|
||||
|
||||
```json
|
||||
{
|
||||
"@mariozechner/pi-agent-core": "0.49.3",
|
||||
"@mariozechner/pi-ai": "0.49.3",
|
||||
"@mariozechner/pi-coding-agent": "0.49.3",
|
||||
"@mariozechner/pi-tui": "0.49.3"
|
||||
"@mariozechner/pi-agent-core": "0.61.1",
|
||||
"@mariozechner/pi-ai": "0.61.1",
|
||||
"@mariozechner/pi-coding-agent": "0.61.1",
|
||||
"@mariozechner/pi-tui": "0.61.1"
|
||||
}
|
||||
```
|
||||
|
||||
| 包 | 用途 |
|
||||
| 软件包 | 用途 |
|
||||
| ----------------- | ------------------------------------------------------------------------------------------ |
|
||||
| `pi-ai` | 核心 LLM 抽象:`Model`、`streamSimple`、消息类型、提供商 API |
|
||||
| `pi-agent-core` | 智能体循环、工具执行、`AgentMessage` 类型 |
|
||||
| `pi-coding-agent` | 高级 SDK:`createAgentSession`、`SessionManager`、`AuthStorage`、`ModelRegistry`、内置工具 |
|
||||
| `pi-coding-agent` | 高层 SDK:`createAgentSession`、`SessionManager`、`AuthStorage`、`ModelRegistry`、内置工具 |
|
||||
| `pi-tui` | 终端 UI 组件(用于 OpenClaw 的本地 TUI 模式) |
|
||||
|
||||
## 文件结构
|
||||
|
|
@ -91,7 +95,7 @@ src/agents/
|
|||
├── pi-tools.types.ts # AnyAgentTool type alias
|
||||
├── pi-tool-definition-adapter.ts # AgentTool -> ToolDefinition adapter
|
||||
├── pi-settings.ts # Settings overrides
|
||||
├── pi-extensions/ # Custom pi extensions
|
||||
├── pi-hooks/ # Custom pi hooks
|
||||
│ ├── compaction-safeguard.ts # Safeguard extension
|
||||
│ ├── compaction-safeguard-runtime.ts
|
||||
│ ├── context-pruning.ts # Cache-TTL context pruning extension
|
||||
|
|
@ -122,24 +126,28 @@ src/agents/
|
|||
│ ├── browser-tool.ts
|
||||
│ ├── canvas-tool.ts
|
||||
│ ├── cron-tool.ts
|
||||
│ ├── discord-actions*.ts
|
||||
│ ├── gateway-tool.ts
|
||||
│ ├── image-tool.ts
|
||||
│ ├── message-tool.ts
|
||||
│ ├── nodes-tool.ts
|
||||
│ ├── session*.ts
|
||||
│ ├── slack-actions.ts
|
||||
│ ├── telegram-actions.ts
|
||||
│ ├── web-*.ts
|
||||
│ └── whatsapp-actions.ts
|
||||
│ └── ...
|
||||
└── ...
|
||||
```
|
||||
|
||||
渠道特定的消息操作运行时现在位于插件自有的扩展目录中,而不是放在 `src/agents/tools` 下,例如:
|
||||
|
||||
- `extensions/discord/src/actions/runtime*.ts`
|
||||
- `extensions/slack/src/action-runtime.ts`
|
||||
- `extensions/telegram/src/action-runtime.ts`
|
||||
- `extensions/whatsapp/src/action-runtime.ts`
|
||||
|
||||
## 核心集成流程
|
||||
|
||||
### 1. 运行嵌入式智能体
|
||||
### 1. 运行内嵌智能体
|
||||
|
||||
主入口点是 `pi-embedded-runner/run.ts` 中的 `runEmbeddedPiAgent()`:
|
||||
主入口是 `pi-embedded-runner/run.ts` 中的 `runEmbeddedPiAgent()`:
|
||||
|
||||
```typescript
|
||||
import { runEmbeddedPiAgent } from "./agents/pi-embedded-runner.js";
|
||||
|
|
@ -161,9 +169,9 @@ const result = await runEmbeddedPiAgent({
|
|||
});
|
||||
```
|
||||
|
||||
### 2. 会话创建
|
||||
### 2. 创建会话
|
||||
|
||||
在 `runEmbeddedAttempt()`(由 `runEmbeddedPiAgent()` 调用)内部,使用 pi SDK:
|
||||
在 `runEmbeddedAttempt()`(由 `runEmbeddedPiAgent()` 调用)内部,会使用 pi SDK:
|
||||
|
||||
```typescript
|
||||
import {
|
||||
|
|
@ -200,7 +208,7 @@ applySystemPromptOverrideToSession(session, systemPromptOverride);
|
|||
|
||||
### 3. 事件订阅
|
||||
|
||||
`subscribeEmbeddedPiSession()` 订阅 pi 的 `AgentSession` 事件:
|
||||
`subscribeEmbeddedPiSession()` 会订阅 pi 的 `AgentSession` 事件:
|
||||
|
||||
```typescript
|
||||
const subscription = subscribeEmbeddedPiSession({
|
||||
|
|
@ -219,37 +227,39 @@ const subscription = subscribeEmbeddedPiSession({
|
|||
|
||||
处理的事件包括:
|
||||
|
||||
- `message_start` / `message_end` / `message_update`(流式文本/思考)
|
||||
- `message_start` / `message_end` / `message_update`(流式文本 / 思考)
|
||||
- `tool_execution_start` / `tool_execution_update` / `tool_execution_end`
|
||||
- `turn_start` / `turn_end`
|
||||
- `agent_start` / `agent_end`
|
||||
- `auto_compaction_start` / `auto_compaction_end`
|
||||
|
||||
### 4. 提示
|
||||
### 4. 发送提示
|
||||
|
||||
设置完成后,会话被提示:
|
||||
完成设置后,会向会话发送提示:
|
||||
|
||||
```typescript
|
||||
await session.prompt(effectivePrompt, { images: imageResult.images });
|
||||
```
|
||||
|
||||
SDK 处理完整的智能体循环:发送到 LLM、执行工具调用、流式响应。
|
||||
SDK 会处理完整的智能体循环:发送给 LLM、执行工具调用、流式返回响应。
|
||||
|
||||
图像注入仅限当前提示:OpenClaw 会从当前提示中加载图像引用,并仅通过 `images` 将其传入该轮。它不会重新扫描较早的历史轮次来重新注入图像负载。
|
||||
|
||||
## 工具架构
|
||||
|
||||
### 工具管道
|
||||
### 工具流水线
|
||||
|
||||
1. **基础工具**:pi 的 `codingTools`(read、bash、edit、write)
|
||||
2. **自定义替换**:OpenClaw 将 bash 替换为 `exec`/`process`,为沙箱自定义 read/edit/write
|
||||
3. **OpenClaw 工具**:消息、浏览器、画布、会话、定时任务、Gateway 网关等
|
||||
4. **渠道工具**:Discord/Telegram/Slack/WhatsApp 特定的操作工具
|
||||
5. **策略过滤**:工具按配置文件、提供商、智能体、群组、沙箱策略过滤
|
||||
6. **Schema 规范化**:为 Gemini/OpenAI 的特殊情况清理 Schema
|
||||
7. **AbortSignal 包装**:工具被包装以尊重中止信号
|
||||
2. **自定义替换**:OpenClaw 用 `exec` / `process` 替换 bash,并为沙箱定制 read / edit / write
|
||||
3. **OpenClaw 工具**:消息、浏览器、画布、会话、cron、Gateway 网关 等
|
||||
4. **渠道工具**:Discord / Telegram / Slack / WhatsApp 特定操作工具
|
||||
5. **策略过滤**:按配置、提供商、智能体、群组、沙箱策略过滤工具
|
||||
6. **模式归一化**:清理模式以适配 Gemini / OpenAI 的特殊行为
|
||||
7. **AbortSignal 包装**:包装工具以遵循中止信号
|
||||
|
||||
### 工具定义适配器
|
||||
|
||||
pi-agent-core 的 `AgentTool` 与 pi-coding-agent 的 `ToolDefinition` 有不同的 `execute` 签名。`pi-tool-definition-adapter.ts` 中的适配器桥接了这一点:
|
||||
pi-agent-core 的 `AgentTool` 与 pi-coding-agent 的 `ToolDefinition` 在 `execute` 签名上不同。`pi-tool-definition-adapter.ts` 中的适配器用于桥接这一差异:
|
||||
|
||||
```typescript
|
||||
export function toToolDefinitions(tools: AnyAgentTool[]): ToolDefinition[] {
|
||||
|
|
@ -268,7 +278,7 @@ export function toToolDefinitions(tools: AnyAgentTool[]): ToolDefinition[] {
|
|||
|
||||
### 工具拆分策略
|
||||
|
||||
`splitSdkTools()` 通过 `customTools` 传递所有工具:
|
||||
`splitSdkTools()` 会通过 `customTools` 传入所有工具:
|
||||
|
||||
```typescript
|
||||
export function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled: boolean }) {
|
||||
|
|
@ -279,13 +289,13 @@ export function splitSdkTools(options: { tools: AnyAgentTool[]; sandboxEnabled:
|
|||
}
|
||||
```
|
||||
|
||||
这确保 OpenClaw 的策略过滤、沙箱集成和扩展工具集在各提供商之间保持一致。
|
||||
这样可以确保 OpenClaw 的策略过滤、沙箱集成和扩展工具集在不同提供商之间保持一致。
|
||||
|
||||
## 系统提示构建
|
||||
## 系统提示词构建
|
||||
|
||||
系统提示在 `buildAgentSystemPrompt()`(`system-prompt.ts`)中构建。它组装一个完整的提示,包含工具、工具调用风格、安全护栏、OpenClaw CLI 参考、Skills、文档、工作区、沙箱、消息、回复标签、语音、静默回复、心跳、运行时元数据等部分,以及启用时的记忆和反应,还有可选的上下文文件和额外系统提示内容。部分内容在子智能体使用的最小提示模式下会被裁剪。
|
||||
系统提示词在 `buildAgentSystemPrompt()`(`system-prompt.ts`)中构建。它会组装完整提示词,包含工具、工具调用风格、安全护栏、OpenClaw CLI 参考、Skills、文档、工作区、沙箱、消息、回复标签、语音、静默回复、心跳、运行时元数据等部分,并在启用时包含 Memory 和 Reactions,以及可选的上下文文件和额外系统提示词内容。为子智能体使用的最小提示词模式会对各部分进行裁剪。
|
||||
|
||||
提示在会话创建后通过 `applySystemPromptOverrideToSession()` 应用:
|
||||
系统提示词会在会话创建后通过 `applySystemPromptOverrideToSession()` 应用:
|
||||
|
||||
```typescript
|
||||
const systemPromptOverride = createSystemPromptOverride(appendPrompt);
|
||||
|
|
@ -296,17 +306,17 @@ applySystemPromptOverrideToSession(session, systemPromptOverride);
|
|||
|
||||
### 会话文件
|
||||
|
||||
会话是具有树结构(id/parentId 链接)的 JSONL 文件。Pi 的 `SessionManager` 处理持久化:
|
||||
会话是具有树状结构(通过 id / parentId 关联)的 JSONL 文件。Pi 的 `SessionManager` 负责持久化:
|
||||
|
||||
```typescript
|
||||
const sessionManager = SessionManager.open(params.sessionFile);
|
||||
```
|
||||
|
||||
OpenClaw 用 `guardSessionManager()` 包装它以确保工具结果安全。
|
||||
OpenClaw 通过 `guardSessionManager()` 对其进行包装,以保证工具结果安全。
|
||||
|
||||
### 会话缓存
|
||||
|
||||
`session-manager-cache.ts` 缓存 SessionManager 实例以避免重复的文件解析:
|
||||
`session-manager-cache.ts` 会缓存 `SessionManager` 实例,以避免重复解析文件:
|
||||
|
||||
```typescript
|
||||
await prewarmSessionFile(params.sessionFile);
|
||||
|
|
@ -316,11 +326,11 @@ trackSessionManagerAccess(params.sessionFile);
|
|||
|
||||
### 历史限制
|
||||
|
||||
`limitHistoryTurns()` 根据渠道类型(私信 vs 群组)裁剪对话历史。
|
||||
`limitHistoryTurns()` 会根据渠道类型(私信 与群组)裁剪对话历史。
|
||||
|
||||
### 压缩
|
||||
|
||||
自动压缩在上下文溢出时触发。`compactEmbeddedPiSessionDirect()` 处理手动压缩:
|
||||
上下文溢出时会触发自动压缩。`compactEmbeddedPiSessionDirect()` 负责手动压缩:
|
||||
|
||||
```typescript
|
||||
const compactResult = await compactEmbeddedPiSessionDirect({
|
||||
|
|
@ -328,18 +338,18 @@ const compactResult = await compactEmbeddedPiSessionDirect({
|
|||
});
|
||||
```
|
||||
|
||||
## 认证与模型解析
|
||||
## 身份验证与模型解析
|
||||
|
||||
### 认证配置文件
|
||||
### 凭证配置
|
||||
|
||||
OpenClaw 维护一个认证配置文件存储,每个提供商有多个 API 密钥:
|
||||
OpenClaw 维护一个凭证配置存储,为每个提供商保存多个 API 密钥:
|
||||
|
||||
```typescript
|
||||
const authStore = ensureAuthProfileStore(agentDir, { allowKeychainPrompt: false });
|
||||
const profileOrder = resolveAuthProfileOrder({ cfg, store: authStore, provider, preferredProfile });
|
||||
```
|
||||
|
||||
配置文件在失败时轮换,并带有冷却跟踪:
|
||||
配置会在失败时轮换,并跟踪冷却状态:
|
||||
|
||||
```typescript
|
||||
await markAuthProfileFailure({ store, profileId, reason, cfg, agentDir });
|
||||
|
|
@ -364,7 +374,7 @@ authStorage.setRuntimeApiKey(model.provider, apiKeyInfo.apiKey);
|
|||
|
||||
### 故障转移
|
||||
|
||||
`FailoverError` 在配置了回退时触发模型回退:
|
||||
配置了回退时,`FailoverError` 会触发模型故障转移:
|
||||
|
||||
```typescript
|
||||
if (fallbackConfigured && isFailoverErrorMessage(errorText)) {
|
||||
|
|
@ -380,11 +390,11 @@ if (fallbackConfigured && isFailoverErrorMessage(errorText)) {
|
|||
|
||||
## Pi 扩展
|
||||
|
||||
OpenClaw 加载自定义 pi 扩展以实现特殊行为:
|
||||
OpenClaw 会加载自定义的 pi 扩展,以实现专门行为:
|
||||
|
||||
### 压缩安全护栏
|
||||
### 压缩保护
|
||||
|
||||
`pi-extensions/compaction-safeguard.ts` 为压缩添加护栏,包括自适应令牌预算以及工具失败和文件操作摘要:
|
||||
`src/agents/pi-hooks/compaction-safeguard.ts` 会为压缩添加护栏,包括自适应 token 预算,以及工具失败和文件操作摘要:
|
||||
|
||||
```typescript
|
||||
if (resolveCompactionMode(params.cfg) === "safeguard") {
|
||||
|
|
@ -395,7 +405,7 @@ if (resolveCompactionMode(params.cfg) === "safeguard") {
|
|||
|
||||
### 上下文裁剪
|
||||
|
||||
`pi-extensions/context-pruning.ts` 实现基于缓存 TTL 的上下文裁剪:
|
||||
`src/agents/pi-hooks/context-pruning.ts` 实现了基于 cache-TTL 的上下文裁剪:
|
||||
|
||||
```typescript
|
||||
if (cfg?.agents?.defaults?.contextPruning?.mode === "cache-ttl") {
|
||||
|
|
@ -409,19 +419,19 @@ if (cfg?.agents?.defaults?.contextPruning?.mode === "cache-ttl") {
|
|||
}
|
||||
```
|
||||
|
||||
## 流式传输与块回复
|
||||
## 流式传输与分块回复
|
||||
|
||||
### 块分块
|
||||
### 分块处理
|
||||
|
||||
`EmbeddedBlockChunker` 管理将流式文本分成离散的回复块:
|
||||
`EmbeddedBlockChunker` 负责将流式文本管理为离散的回复块:
|
||||
|
||||
```typescript
|
||||
const blockChunker = blockChunking ? new EmbeddedBlockChunker(blockChunking) : null;
|
||||
```
|
||||
|
||||
### 思考/最终标签剥离
|
||||
### 思考 / 最终标签剥离
|
||||
|
||||
流式输出被处理以剥离 `<think>`/`<thinking>` 块并提取 `<final>` 内容:
|
||||
流式输出会经过处理,以去除 `<think>` / `<thinking>` 块并提取 `<final>` 内容:
|
||||
|
||||
```typescript
|
||||
const stripBlockTags = (text: string, state: { thinking: boolean; final: boolean }) => {
|
||||
|
|
@ -432,7 +442,7 @@ const stripBlockTags = (text: string, state: { thinking: boolean; final: boolean
|
|||
|
||||
### 回复指令
|
||||
|
||||
回复指令如 `[[media:url]]`、`[[voice]]`、`[[reply:id]]` 被解析和提取:
|
||||
会解析并提取诸如 `[[media:url]]`、`[[voice]]`、`[[reply:id]]` 之类的回复指令:
|
||||
|
||||
```typescript
|
||||
const { text: cleanedText, mediaUrls, audioAsVoice, replyToId } = consumeReplyDirectives(chunk);
|
||||
|
|
@ -442,7 +452,7 @@ const { text: cleanedText, mediaUrls, audioAsVoice, replyToId } = consumeReplyDi
|
|||
|
||||
### 错误分类
|
||||
|
||||
`pi-embedded-helpers.ts` 对错误进行分类以进行适当处理:
|
||||
`pi-embedded-helpers.ts` 会对错误进行分类,以便进行适当处理:
|
||||
|
||||
```typescript
|
||||
isContextOverflowError(errorText) // Context too large
|
||||
|
|
@ -455,7 +465,7 @@ classifyFailoverReason(errorText) // "auth" | "rate_limit" | "quota" | "time
|
|||
|
||||
### 思考级别回退
|
||||
|
||||
如果思考级别不受支持,它会回退:
|
||||
如果某个思考级别不受支持,它会回退:
|
||||
|
||||
```typescript
|
||||
const fallbackThinking = pickFallbackThinkingLevel({
|
||||
|
|
@ -470,7 +480,7 @@ if (fallbackThinking) {
|
|||
|
||||
## 沙箱集成
|
||||
|
||||
当启用沙箱模式时,工具和路径受到约束:
|
||||
启用沙箱模式时,工具和路径都会受到约束:
|
||||
|
||||
```typescript
|
||||
const sandbox = await resolveSandboxContext({
|
||||
|
|
@ -490,24 +500,24 @@ if (sandboxRoot) {
|
|||
|
||||
### Anthropic
|
||||
|
||||
- 拒绝魔术字符串清除
|
||||
- 连续角色的回合验证
|
||||
- 清理拒绝魔法字符串
|
||||
- 针对连续角色的轮次验证
|
||||
- Claude Code 参数兼容性
|
||||
|
||||
### Google/Gemini
|
||||
### Google / Gemini
|
||||
|
||||
- 回合排序修复(`applyGoogleTurnOrderingFix`)
|
||||
- 工具 schema 清理(`sanitizeToolsForGoogle`)
|
||||
- 会话历史清理(`sanitizeSessionHistory`)
|
||||
- 轮次顺序修复(`applyGoogleTurnOrderingFix`)
|
||||
- 工具模式净化(`sanitizeToolsForGoogle`)
|
||||
- 会话历史净化(`sanitizeSessionHistory`)
|
||||
|
||||
### OpenAI
|
||||
|
||||
- Codex 模型的 `apply_patch` 工具
|
||||
- 面向 Codex 模型的 `apply_patch` 工具
|
||||
- 思考级别降级处理
|
||||
|
||||
## TUI 集成
|
||||
|
||||
OpenClaw 还有一个本地 TUI 模式,直接使用 pi-tui 组件:
|
||||
OpenClaw 还提供本地 TUI 模式,可直接使用 pi-tui 组件:
|
||||
|
||||
```typescript
|
||||
// src/tui/tui.ts
|
||||
|
|
@ -516,104 +526,46 @@ import { ... } from "@mariozechner/pi-tui";
|
|||
|
||||
这提供了与 pi 原生模式类似的交互式终端体验。
|
||||
|
||||
## 与 Pi CLI 的主要区别
|
||||
## 与 Pi CLI 的关键差异
|
||||
|
||||
| 方面 | Pi CLI | OpenClaw 嵌入式 |
|
||||
| -------- | ----------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| 调用方式 | `pi` 命令 / RPC | 通过 `createAgentSession()` 的 SDK |
|
||||
| 工具 | 默认编码工具 | 自定义 OpenClaw 工具套件 |
|
||||
| 系统提示 | AGENTS.md + prompts | 按渠道/上下文动态生成 |
|
||||
| 会话存储 | `~/.pi/agent/sessions/` | `~/.openclaw/agents/<agentId>/sessions/`(或 `$OPENCLAW_STATE_DIR/agents/<agentId>/sessions/`) |
|
||||
| 认证 | 单一凭证 | 带轮换的多配置文件 |
|
||||
| 扩展 | 从磁盘加载 | 编程方式 + 磁盘路径 |
|
||||
| 事件处理 | TUI 渲染 | 基于回调(onBlockReply 等) |
|
||||
| 方面 | Pi CLI | OpenClaw 内嵌版 |
|
||||
| ---------- | ----------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| 调用方式 | `pi` 命令 / RPC | 通过 `createAgentSession()` 使用 SDK |
|
||||
| 工具 | 默认编码工具 | 自定义 OpenClaw 工具套件 |
|
||||
| 系统提示词 | AGENTS.md + prompts | 按渠道 / 上下文动态生成 |
|
||||
| 会话存储 | `~/.pi/agent/sessions/` | `~/.openclaw/agents/<agentId>/sessions/`(或 `$OPENCLAW_STATE_DIR/agents/<agentId>/sessions/`) |
|
||||
| 身份验证 | 单一凭证 | 支持轮换的多配置 |
|
||||
| 扩展 | 从磁盘加载 | 通过编程方式 + 磁盘路径 |
|
||||
| 事件处理 | TUI 渲染 | 基于回调(`onBlockReply` 等) |
|
||||
|
||||
## 未来考虑
|
||||
|
||||
可能需要重构的领域:
|
||||
潜在的重构方向包括:
|
||||
|
||||
1. **工具签名对齐**:目前在 pi-agent-core 和 pi-coding-agent 签名之间适配
|
||||
2. **会话管理器包装**:`guardSessionManager` 增加了安全性但增加了复杂性
|
||||
1. **工具签名对齐**:当前需要在 pi-agent-core 与 pi-coding-agent 的签名之间进行适配
|
||||
2. **会话管理器包装**:`guardSessionManager` 增加了安全性,但也提高了复杂度
|
||||
3. **扩展加载**:可以更直接地使用 pi 的 `ResourceLoader`
|
||||
4. **流式处理器复杂性**:`subscribeEmbeddedPiSession` 已经变得很大
|
||||
5. **提供商特殊情况**:许多提供商特定的代码路径,pi 可能可以处理
|
||||
4. **流式处理器复杂度**:`subscribeEmbeddedPiSession` 已经变得较大
|
||||
5. **提供商特殊行为**:存在许多提供商特定代码路径,未来 pi 或许可以统一处理
|
||||
|
||||
## 测试
|
||||
|
||||
所有涵盖 pi 集成及其扩展的现有测试:
|
||||
Pi 集成的覆盖范围包括以下测试套件:
|
||||
|
||||
- `src/agents/pi-embedded-block-chunker.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.buildbootstrapcontextfiles.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.classifyfailoverreason.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.downgradeopenai-reasoning.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.formatassistanterrortext.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.formatrawassistanterrorforui.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.image-dimension-error.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.image-size-error.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.isautherrormessage.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.isbillingerrormessage.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.iscloudcodeassistformaterror.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.iscompactionfailureerror.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.iscontextoverflowerror.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.isfailovererrormessage.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.islikelycontextoverflowerror.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.ismessagingtoolduplicate.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.messaging-duplicate.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.normalizetextforcomparison.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.resolvebootstrapmaxchars.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.sanitize-session-messages-images.keeps-tool-call-tool-result-ids-unchanged.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.sanitize-session-messages-images.removes-empty-assistant-text-blocks-but-preserves.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.sanitizegoogleturnordering.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.sanitizesessionmessagesimages-thought-signature-stripping.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.sanitizetoolcallid.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.sanitizeuserfacingtext.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.stripthoughtsignatures.test.ts`
|
||||
- `src/agents/pi-embedded-helpers.validate-turns.test.ts`
|
||||
- `src/agents/pi-embedded-runner-extraparams.live.test.ts`(实时)
|
||||
- `src/agents/pi-embedded-runner-extraparams.test.ts`
|
||||
- `src/agents/pi-embedded-runner.applygoogleturnorderingfix.test.ts`
|
||||
- `src/agents/pi-embedded-runner.buildembeddedsandboxinfo.test.ts`
|
||||
- `src/agents/pi-embedded-runner.createsystempromptoverride.test.ts`
|
||||
- `src/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.falls-back-provider-default-per-dm-not.test.ts`
|
||||
- `src/agents/pi-embedded-runner.get-dm-history-limit-from-session-key.returns-undefined-sessionkey-is-undefined.test.ts`
|
||||
- `src/agents/pi-embedded-runner.google-sanitize-thinking.test.ts`
|
||||
- `src/agents/pi-embedded-runner.guard.test.ts`
|
||||
- `src/agents/pi-embedded-runner.limithistoryturns.test.ts`
|
||||
- `src/agents/pi-embedded-runner.resolvesessionagentids.test.ts`
|
||||
- `src/agents/pi-embedded-runner.run-embedded-pi-agent.auth-profile-rotation.test.ts`
|
||||
- `src/agents/pi-embedded-runner.sanitize-session-history.test.ts`
|
||||
- `src/agents/pi-embedded-runner.splitsdktools.test.ts`
|
||||
- `src/agents/pi-embedded-runner.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.code-span-awareness.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.reply-tags.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.calls-onblockreplyflush-before-tool-execution-start-preserve.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-append-text-end-content-is.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-call-onblockreplyflush-callback-is-not.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-duplicate-text-end-repeats-full.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.does-not-emit-duplicate-block-replies-text.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-block-replies-text-end-does-not.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.emits-reasoning-as-separate-message-enabled.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.filters-final-suppresses-output-without-start-tag.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.includes-canvas-action-metadata-tool-summaries.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.keeps-assistanttexts-final-answer-block-replies-are.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.keeps-indented-fenced-blocks-intact.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.reopens-fenced-blocks-splitting-inside-them.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.splits-long-single-line-fenced-blocks-reopen.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.streams-soft-chunks-paragraph-preference.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.subscribeembeddedpisession.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.suppresses-message-end-block-replies-message-tool.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.subscribe-embedded-pi-session.waits-multiple-compaction-retries-before-resolving.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe.tools.test.ts`
|
||||
- `src/agents/pi-embedded-utils.test.ts`
|
||||
- `src/agents/pi-extensions/compaction-safeguard.test.ts`
|
||||
- `src/agents/pi-extensions/context-pruning.test.ts`
|
||||
- `src/agents/pi-*.test.ts`
|
||||
- `src/agents/pi-auth-json.test.ts`
|
||||
- `src/agents/pi-embedded-*.test.ts`
|
||||
- `src/agents/pi-embedded-helpers*.test.ts`
|
||||
- `src/agents/pi-embedded-runner*.test.ts`
|
||||
- `src/agents/pi-embedded-runner/**/*.test.ts`
|
||||
- `src/agents/pi-embedded-subscribe*.test.ts`
|
||||
- `src/agents/pi-tools*.test.ts`
|
||||
- `src/agents/pi-tool-definition-adapter*.test.ts`
|
||||
- `src/agents/pi-settings.test.ts`
|
||||
- `src/agents/pi-tool-definition-adapter.test.ts`
|
||||
- `src/agents/pi-tools-agent-config.test.ts`
|
||||
- `src/agents/pi-tools.create-openclaw-coding-tools.adds-claude-style-aliases-schemas-without-dropping-b.test.ts`
|
||||
- `src/agents/pi-tools.create-openclaw-coding-tools.adds-claude-style-aliases-schemas-without-dropping-d.test.ts`
|
||||
- `src/agents/pi-tools.create-openclaw-coding-tools.adds-claude-style-aliases-schemas-without-dropping-f.test.ts`
|
||||
- `src/agents/pi-tools.create-openclaw-coding-tools.adds-claude-style-aliases-schemas-without-dropping.test.ts`
|
||||
- `src/agents/pi-tools.policy.test.ts`
|
||||
- `src/agents/pi-tools.safe-bins.test.ts`
|
||||
- `src/agents/pi-tools.workspace-paths.test.ts`
|
||||
- `src/agents/pi-hooks/**/*.test.ts`
|
||||
|
||||
实时 / 按需启用:
|
||||
|
||||
- `src/agents/pi-embedded-runner-extraparams.live.test.ts`(启用 `OPENCLAW_LIVE_TEST=1`)
|
||||
|
||||
有关当前运行命令,请参见 [Pi 开发工作流](/pi-dev)。
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ If the user is vague ("text my mom"), ask for the recipient handle or chat guid
|
|||
- Prefer `chat_guid` targets when you have them (especially for group chats).
|
||||
- BlueBubbles supports rich actions, but some are macOS-version dependent (for example, edit may be broken on macOS 26 Tahoe).
|
||||
- The gateway may expose both short and full message ids; full ids are more durable across restarts.
|
||||
- Developer reference for the underlying plugin lives in `extensions/bluebubbles/README.md`.
|
||||
- Developer reference for the underlying plugin lives in the BlueBubbles plugin package README.
|
||||
|
||||
## Ideas to try
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue