mirror of https://github.com/openclaw/openclaw.git
Merge remote-tracking branch 'origin/main' into cs/codex-native-web-search-spec
# Conflicts: # src/agents/pi-embedded-runner/extra-params.ts # src/agents/pi-embedded-runner/openai-stream-wrappers.ts
This commit is contained in:
commit
e1e51171b0
|
|
@ -42,10 +42,13 @@ pnpm test:parallels:macos \
|
|||
## Notes
|
||||
|
||||
- Snapshot target: closest to `macOS 26.3.1 fresh`.
|
||||
- Snapshot resolver now prefers matching `*-poweroff*` clones when the base hint also matches. That lets the harness reuse disk-only recovery snapshots without passing a longer hint.
|
||||
- If Windows/Linux snapshot restore logs show `PET_QUESTION_SNAPSHOT_STATE_INCOMPATIBLE_CPU`, drop the suspended state once, create a `*-poweroff*` replacement snapshot, and rerun. The smoke scripts now auto-start restored power-off snapshots.
|
||||
- Harness configures Discord inside the guest; no checked-in token/config.
|
||||
- Use the `openclaw` wrapper for guest `message send/read`; `node openclaw.mjs message ...` does not expose the lazy message subcommands the same way.
|
||||
- Write `channels.discord.guilds` in one JSON object (`--strict-json`), not dotted `config set channels.discord.guilds.<snowflake>...` paths; numeric snowflakes get treated like array indexes.
|
||||
- Avoid `prlctl enter` / expect for long Discord setup scripts; it line-wraps/corrupts long commands. Use `prlctl exec --current-user /bin/sh -lc ...` for the Discord config phase.
|
||||
- Full 3-OS sweeps: the shared build lock is safe in parallel, but snapshot restore is still a Parallels bottleneck. Prefer serialized Windows/Linux restore-heavy reruns if the host is already under load.
|
||||
- Harness cleanup deletes the temporary Discord smoke messages at exit.
|
||||
- Per-phase logs: `/tmp/openclaw-parallels-smoke.*`
|
||||
- Machine summary: pass `--json`
|
||||
|
|
|
|||
|
|
@ -206,6 +206,9 @@ jobs:
|
|||
- runtime: node
|
||||
task: channels
|
||||
command: pnpm test:channels
|
||||
- runtime: node
|
||||
task: contracts
|
||||
command: pnpm test:contracts
|
||||
- runtime: node
|
||||
task: protocol
|
||||
command: pnpm protocol:check
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ Docs: https://docs.openclaw.ai
|
|||
- secrets: harden read-only SecretRef command paths and diagnostics. (#47794) Thanks @joshavant.
|
||||
- Browser/existing-session: support `browser.profiles.<name>.userDataDir` so Chrome DevTools MCP can attach to Brave, Edge, and other Chromium-based browsers through their own user data directories. (#48170) Thanks @velvet-shark.
|
||||
- Skills/prompt budget: preserve all registered skills via a compact catalog fallback before dropping entries when the full prompt format exceeds `maxSkillsPromptChars`. (#47553) Thanks @snese.
|
||||
- Plugins/bundles: make enabled bundle MCP servers expose runnable tools in embedded Pi, and default relative bundle MCP launches to the bundle root so marketplace bundles like Context7 work through Pi instead of stopping at config import.
|
||||
- Scope message SecretRef resolution and harden doctor/status paths. (#48728) Thanks @joshavant.
|
||||
|
||||
### Breaking
|
||||
|
||||
|
|
@ -78,6 +80,7 @@ Docs: https://docs.openclaw.ai
|
|||
- Z.AI/onboarding: add `glm-5-turbo` to the default Z.AI provider catalog so onboarding-generated configs expose the new model alongside the existing GLM defaults. (#46670) Thanks @tomsun28.
|
||||
- Zalo Personal/group gating: stop reapplying `dmPolicy.allowFrom` as a sender gate for already-allowlisted groups when `groupAllowFrom` is unset, so any member of an allowed group can trigger replies while DMs stay restricted. (#46663) Fixes #40146. Thanks @Takhoffman.
|
||||
- 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.
|
||||
- Plugins/install precedence: keep bundled plugins ahead of auto-discovered globals by default, but let an explicitly installed plugin record win its own duplicate-id tie so installed channel plugins load from `~/.openclaw/extensions` after `openclaw plugins install`. (#46722) Thanks @Takhoffman.
|
||||
- Control UI/logging: make browser-safe logger imports avoid eager temp-dir resolution so the bundled Control UI no longer crashes to a blank screen when logging reaches `tmp-openclaw-dir`. (#48469) Fixes #48062. Thanks @7inspire.
|
||||
- Plugins/scoped ids: preserve scoped plugin ids during install and config keying, and keep bundled plugins ahead of discovered duplicate ids by default so `@scope/name` plugins no longer collide with unscoped installs. (#47413) Thanks @vincentkoc.
|
||||
|
|
@ -105,6 +108,8 @@ Docs: https://docs.openclaw.ai
|
|||
- 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.
|
||||
- Plugins/subagents: preserve gateway-owned plugin subagent access across runtime, tool, and embedded-runner load paths so gateway plugin tools and context engines can still spawn and manage subagents after the loader cache split. (#46648) Thanks @jalehman.
|
||||
- Control UI/overview: keep the language dropdown aligned with the persisted locale during dashboard startup so refreshing the page does not fall back to English before locale hydration completes. (#48019) Thanks @git-jxj.
|
||||
- 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.
|
||||
|
||||
## 2026.3.13
|
||||
|
||||
|
|
@ -183,7 +188,6 @@ Docs: https://docs.openclaw.ai
|
|||
- Auth/login lockout recovery: clear stale `auth_permanent` and `billing` disabled state for all profiles matching the target provider when `openclaw models auth login` is invoked, so users locked out by expired or revoked OAuth tokens can recover by re-authenticating instead of waiting for the cooldown timer to expire. (#43057)
|
||||
- Auto-reply/context-engine compaction: persist the exact embedded-run metadata compaction count for main and followup runner session accounting, so metadata-only auto-compactions no longer undercount multi-compaction runs. (#42629) thanks @uf-hy.
|
||||
- Auth/Codex CLI reuse: sync reused Codex CLI credentials into the supported `openai-codex:default` OAuth profile instead of reviving the deprecated `openai-codex:codex-cli` slot, so doctor cleanup no longer loops. (#45353) thanks @Gugu-sugar.
|
||||
- WhatsApp/group replies: recognize implicit reply-to-bot mentions when WhatsApp sends the quoted sender in `@lid` format, including device-suffixed self identities. (#23029) Thanks @sparkyrider.
|
||||
|
||||
## 2026.3.12
|
||||
|
||||
|
|
@ -276,6 +280,9 @@ Docs: https://docs.openclaw.ai
|
|||
- Docs/Brave pricing: escape literal dollar signs in Brave Search cost text so the docs render the free credit and per-request pricing correctly. (#44989) Thanks @keelanfh.
|
||||
- Feishu/file uploads: preserve literal UTF-8 filenames in `im.file.create` so Chinese and other non-ASCII filenames no longer appear percent-encoded in chat. (#34262) Thanks @fabiaodemianyang and @KangShuaiFu.
|
||||
- Agents/compaction safeguard: trim large kept `toolResult` payloads consistently for budgeting, pruning, and identifier seeding, then restore preserved payloads after prune so oversized safeguard summaries stay stable. (#44133) thanks @SayrWolfridge.
|
||||
- Agents/compaction: compare post-compaction token sanity checks against full-session pre-compaction totals and skip the check when token estimation fails, so sessions with large bootstrap context keep real token counts instead of falling back to unknown. (#28347) thanks @efe-arv.
|
||||
- Discord/gateway startup: treat plain-text and transient `/gateway/bot` metadata fetch failures as transient startup errors so Discord gateway boot no longer crashes on unhandled rejections. (#44397) Thanks @jalehman.
|
||||
- Agents/Ollama overflow: rewrite Ollama `prompt too long` API payloads through the normal context-overflow sanitizer so embedded sessions keep the friendly overflow copy and auto-compaction trigger. (#34019) thanks @lishuaigit.
|
||||
|
||||
## 2026.3.11
|
||||
|
||||
|
|
|
|||
|
|
@ -91,7 +91,9 @@ Welcome to the lobster tank! 🦞
|
|||
- Run tests: `pnpm build && pnpm check && pnpm test`
|
||||
- For extension/plugin changes, run the fast local lane first:
|
||||
- `pnpm test:extension <extension-name>`
|
||||
- If you changed shared plugin or channel surfaces, still run the broader relevant lanes (`pnpm test:extensions`, `pnpm test:channels`, or `pnpm test`) before asking for review
|
||||
- `pnpm test:extension --list` to see valid extension ids
|
||||
- If you changed shared plugin or channel surfaces, run `pnpm test:contracts`
|
||||
- If you changed broader runtime behavior, still run the relevant wider lanes (`pnpm test:extensions`, `pnpm test:channels`, or `pnpm test`) before asking for review
|
||||
- If you have access to Codex, run `codex review --base origin/main` locally before opening or updating your PR. Treat this as the current highest standard of AI review, even if GitHub Codex review also runs.
|
||||
- Ensure CI checks pass
|
||||
- Keep PRs focused (one thing per PR; do not mix unrelated concerns)
|
||||
|
|
|
|||
14
README.md
14
README.md
|
|
@ -23,10 +23,10 @@ It answers you on the channels you already use (WhatsApp, Telegram, Slack, Disco
|
|||
|
||||
If you want a personal, single-user assistant that feels local, fast, and always-on, this is it.
|
||||
|
||||
[Website](https://openclaw.ai) · [Docs](https://docs.openclaw.ai) · [Vision](VISION.md) · [DeepWiki](https://deepwiki.com/openclaw/openclaw) · [Getting Started](https://docs.openclaw.ai/start/getting-started) · [Updating](https://docs.openclaw.ai/install/updating) · [Showcase](https://docs.openclaw.ai/start/showcase) · [FAQ](https://docs.openclaw.ai/help/faq) · [Wizard](https://docs.openclaw.ai/start/wizard) · [Nix](https://github.com/openclaw/nix-openclaw) · [Docker](https://docs.openclaw.ai/install/docker) · [Discord](https://discord.gg/clawd)
|
||||
[Website](https://openclaw.ai) · [Docs](https://docs.openclaw.ai) · [Vision](VISION.md) · [DeepWiki](https://deepwiki.com/openclaw/openclaw) · [Getting Started](https://docs.openclaw.ai/start/getting-started) · [Updating](https://docs.openclaw.ai/install/updating) · [Showcase](https://docs.openclaw.ai/start/showcase) · [FAQ](https://docs.openclaw.ai/help/faq) · [Onboarding](https://docs.openclaw.ai/start/wizard) · [Nix](https://github.com/openclaw/nix-openclaw) · [Docker](https://docs.openclaw.ai/install/docker) · [Discord](https://discord.gg/clawd)
|
||||
|
||||
Preferred setup: run the onboarding wizard (`openclaw onboard`) in your terminal.
|
||||
The wizard guides you step by step through setting up the gateway, workspace, channels, and skills. The CLI wizard is the recommended path and works on **macOS, Linux, and Windows (via WSL2; strongly recommended)**.
|
||||
Preferred setup: run `openclaw onboard` in your terminal.
|
||||
OpenClaw Onboard guides you step by step through setting up the gateway, workspace, channels, and skills. It is the recommended CLI setup path and works on **macOS, Linux, and Windows (via WSL2; strongly recommended)**.
|
||||
Works with npm, pnpm, or bun.
|
||||
New install? Start here: [Getting started](https://docs.openclaw.ai/start/getting-started)
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ npm install -g openclaw@latest
|
|||
openclaw onboard --install-daemon
|
||||
```
|
||||
|
||||
The wizard installs the Gateway daemon (launchd/systemd user service) so it stays running.
|
||||
OpenClaw Onboard installs the Gateway daemon (launchd/systemd user service) so it stays running.
|
||||
|
||||
## Quick start (TL;DR)
|
||||
|
||||
|
|
@ -132,7 +132,7 @@ Run `openclaw doctor` to surface risky/misconfigured DM policies.
|
|||
- **[Live Canvas](https://docs.openclaw.ai/platforms/mac/canvas)** — agent-driven visual workspace with [A2UI](https://docs.openclaw.ai/platforms/mac/canvas#canvas-a2ui).
|
||||
- **[First-class tools](https://docs.openclaw.ai/tools)** — browser, canvas, nodes, cron, sessions, and Discord/Slack actions.
|
||||
- **[Companion apps](https://docs.openclaw.ai/platforms/macos)** — macOS menu bar app + iOS/Android [nodes](https://docs.openclaw.ai/nodes).
|
||||
- **[Onboarding](https://docs.openclaw.ai/start/wizard) + [skills](https://docs.openclaw.ai/tools/skills)** — wizard-driven setup with bundled/managed/workspace skills.
|
||||
- **[Onboarding](https://docs.openclaw.ai/start/wizard) + [skills](https://docs.openclaw.ai/tools/skills)** — onboarding-driven setup with bundled/managed/workspace skills.
|
||||
|
||||
## Star History
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ Run `openclaw doctor` to surface risky/misconfigured DM policies.
|
|||
### Core platform
|
||||
|
||||
- [Gateway WS control plane](https://docs.openclaw.ai/gateway) with sessions, presence, config, cron, webhooks, [Control UI](https://docs.openclaw.ai/web), and [Canvas host](https://docs.openclaw.ai/platforms/mac/canvas#canvas-a2ui).
|
||||
- [CLI surface](https://docs.openclaw.ai/tools/agent-send): gateway, agent, send, [wizard](https://docs.openclaw.ai/start/wizard), and [doctor](https://docs.openclaw.ai/gateway/doctor).
|
||||
- [CLI surface](https://docs.openclaw.ai/tools/agent-send): gateway, agent, send, [onboarding](https://docs.openclaw.ai/start/wizard), and [doctor](https://docs.openclaw.ai/gateway/doctor).
|
||||
- [Pi agent runtime](https://docs.openclaw.ai/concepts/agent) in RPC mode with tool streaming and block streaming.
|
||||
- [Session model](https://docs.openclaw.ai/concepts/session): `main` for direct chats, group isolation, activation modes, queue modes, reply-back. Group rules: [Groups](https://docs.openclaw.ai/channels/groups).
|
||||
- [Media pipeline](https://docs.openclaw.ai/nodes/images): images/audio/video, transcription hooks, size caps, temp file lifecycle. Audio details: [Audio](https://docs.openclaw.ai/nodes/audio).
|
||||
|
|
@ -422,7 +422,7 @@ Use these when you’re past the onboarding flow and want the deeper reference.
|
|||
- [Run the Gateway by the book with the operational runbook.](https://docs.openclaw.ai/gateway)
|
||||
- [Learn how the Control UI/Web surfaces work and how to expose them safely.](https://docs.openclaw.ai/web)
|
||||
- [Understand remote access over SSH tunnels or tailnets.](https://docs.openclaw.ai/gateway/remote)
|
||||
- [Follow the onboarding wizard flow for a guided setup.](https://docs.openclaw.ai/start/wizard)
|
||||
- [Follow OpenClaw Onboard for a guided setup.](https://docs.openclaw.ai/start/wizard)
|
||||
- [Wire external triggers via the webhook surface.](https://docs.openclaw.ai/automation/webhook)
|
||||
- [Set up Gmail Pub/Sub triggers.](https://docs.openclaw.ai/automation/gmail-pubsub)
|
||||
- [Learn the macOS menu bar companion details.](https://docs.openclaw.ai/platforms/mac/menu-bar)
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
|
|||
|
||||
## Onboarding
|
||||
|
||||
BlueBubbles is available in the interactive setup wizard:
|
||||
BlueBubbles is available in interactive onboarding:
|
||||
|
||||
```
|
||||
openclaw onboard
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ openclaw pairing approve discord <CODE>
|
|||
|
||||
<Note>
|
||||
Token resolution is account-aware. Config token values win over env fallback. `DISCORD_BOT_TOKEN` is only used for the default account.
|
||||
For advanced outbound calls (message tool/channel actions), an explicit per-call `token` is used for that call. Account policy/retry settings still come from the selected account in the active runtime snapshot.
|
||||
For advanced outbound calls (message tool/channel actions), an explicit per-call `token` is used for that call. This applies to send and read/probe-style actions (for example read/search/fetch/thread/pins/permissions). Account policy/retry settings still come from the selected account in the active runtime snapshot.
|
||||
</Note>
|
||||
|
||||
## Recommended: Set up a guild workspace
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ openclaw plugins install @openclaw/feishu
|
|||
|
||||
There are two ways to add the Feishu channel:
|
||||
|
||||
### Method 1: setup wizard (recommended)
|
||||
### Method 1: onboarding (recommended)
|
||||
|
||||
If you just installed OpenClaw, run the setup wizard:
|
||||
If you just installed OpenClaw, run onboarding:
|
||||
|
||||
```bash
|
||||
openclaw onboard
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ Nostr is a decentralized protocol for social networking. This channel enables Op
|
|||
|
||||
### Onboarding (recommended)
|
||||
|
||||
- The setup wizard (`openclaw onboard`) and `openclaw channels add` list optional channel plugins.
|
||||
- Onboarding (`openclaw onboard`) and `openclaw channels add` list optional channel plugins.
|
||||
- Selecting Nostr prompts you to install the plugin on demand.
|
||||
|
||||
Install defaults:
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ Token resolution order is account-aware. In practice, config values win over env
|
|||
|
||||
`channels.telegram.allowFrom` accepts numeric Telegram user IDs. `telegram:` / `tg:` prefixes are accepted and normalized.
|
||||
`dmPolicy: "allowlist"` with empty `allowFrom` blocks all DMs and is rejected by config validation.
|
||||
The setup wizard accepts `@username` input and resolves it to numeric IDs.
|
||||
Onboarding accepts `@username` input and resolves it to numeric IDs.
|
||||
If you upgraded and your config contains `@username` allowlist entries, run `openclaw doctor --fix` to resolve them (best-effort; requires a Telegram bot token).
|
||||
If you previously relied on pairing-store allowlist files, `openclaw doctor --fix` can recover entries into `channels.telegram.allowFrom` in allowlist flows (for example when `dmPolicy: "allowlist"` has no explicit IDs yet).
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ Notes:
|
|||
- Doctor includes a memory-search readiness check and can recommend `openclaw configure --section model` when embedding credentials are missing.
|
||||
- If sandbox mode is enabled but Docker is unavailable, doctor reports a high-signal warning with remediation (`install Docker` or `openclaw config set agents.defaults.sandbox.mode off`).
|
||||
- If `gateway.auth.token`/`gateway.auth.password` are SecretRef-managed and unavailable in the current command path, doctor reports a read-only warning and does not write plaintext fallback credentials.
|
||||
- If channel SecretRef inspection fails in a fix path, doctor continues and reports a warning instead of exiting early.
|
||||
- Telegram `allowFrom` username auto-resolution (`doctor --fix`) requires a resolvable Telegram token in the current command path. If token inspection is unavailable, doctor reports a warning and skips auto-resolution for that pass.
|
||||
|
||||
## macOS: `launchctl` env overrides
|
||||
|
||||
|
|
|
|||
|
|
@ -318,22 +318,22 @@ Initialize config + workspace.
|
|||
Options:
|
||||
|
||||
- `--workspace <dir>`: agent workspace path (default `~/.openclaw/workspace`).
|
||||
- `--wizard`: run the setup wizard.
|
||||
- `--non-interactive`: run wizard without prompts.
|
||||
- `--mode <local|remote>`: wizard mode.
|
||||
- `--wizard`: run onboarding.
|
||||
- `--non-interactive`: run onboarding without prompts.
|
||||
- `--mode <local|remote>`: onboard mode.
|
||||
- `--remote-url <url>`: remote Gateway URL.
|
||||
- `--remote-token <token>`: remote Gateway token.
|
||||
|
||||
Wizard auto-runs when any wizard flags are present (`--non-interactive`, `--mode`, `--remote-url`, `--remote-token`).
|
||||
Onboarding auto-runs when any onboarding flags are present (`--non-interactive`, `--mode`, `--remote-url`, `--remote-token`).
|
||||
|
||||
### `onboard`
|
||||
|
||||
Interactive wizard to set up gateway, workspace, and skills.
|
||||
Interactive onboarding for gateway, workspace, and skills.
|
||||
|
||||
Options:
|
||||
|
||||
- `--workspace <dir>`
|
||||
- `--reset` (reset config + credentials + sessions before wizard)
|
||||
- `--reset` (reset config + credentials + sessions before onboarding)
|
||||
- `--reset-scope <config|config+creds+sessions|full>` (default `config+creds+sessions`; use `full` to also remove workspace)
|
||||
- `--non-interactive`
|
||||
- `--mode <local|remote>`
|
||||
|
|
|
|||
|
|
@ -50,6 +50,16 @@ Name lookup:
|
|||
- `--dry-run`
|
||||
- `--verbose`
|
||||
|
||||
## SecretRef behavior
|
||||
|
||||
- `openclaw message` resolves supported channel SecretRefs before running the selected action.
|
||||
- Resolution is scoped to the active action target when possible:
|
||||
- channel-scoped when `--channel` is set (or inferred from prefixed targets like `discord:...`)
|
||||
- account-scoped when `--account` is set (channel globals + selected account surfaces)
|
||||
- when `--account` is omitted, OpenClaw does not force a `default` account SecretRef scope
|
||||
- Unresolved SecretRefs on unrelated channels do not block a targeted message action.
|
||||
- If the selected channel/account SecretRef is unresolved, the command fails closed for that action.
|
||||
|
||||
## Actions
|
||||
|
||||
### Core
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
summary: "CLI reference for `openclaw onboard` (interactive setup wizard)"
|
||||
summary: "CLI reference for `openclaw onboard` (interactive onboarding)"
|
||||
read_when:
|
||||
- You want guided setup for gateway, workspace, auth, channels, and skills
|
||||
title: "onboard"
|
||||
|
|
@ -7,11 +7,11 @@ title: "onboard"
|
|||
|
||||
# `openclaw onboard`
|
||||
|
||||
Interactive setup wizard (local or remote Gateway setup).
|
||||
Interactive onboarding for local or remote Gateway setup.
|
||||
|
||||
## Related guides
|
||||
|
||||
- CLI onboarding hub: [Setup Wizard (CLI)](/start/wizard)
|
||||
- CLI onboarding hub: [Onboarding (CLI)](/start/wizard)
|
||||
- Onboarding overview: [Onboarding Overview](/start/onboarding-overview)
|
||||
- CLI onboarding reference: [CLI Setup Reference](/start/wizard-cli-reference)
|
||||
- CLI automation: [CLI Automation](/start/wizard-cli-automation)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
summary: "CLI reference for `openclaw setup` (initialize config + workspace)"
|
||||
read_when:
|
||||
- You’re doing first-run setup without the full setup wizard
|
||||
- You’re doing first-run setup without full CLI onboarding
|
||||
- You want to set the default workspace path
|
||||
title: "setup"
|
||||
---
|
||||
|
|
@ -13,7 +13,7 @@ Initialize `~/.openclaw/openclaw.json` and the agent workspace.
|
|||
Related:
|
||||
|
||||
- Getting started: [Getting started](/start/getting-started)
|
||||
- Wizard: [Onboarding](/start/onboarding)
|
||||
- CLI onboarding: [Onboarding (CLI)](/start/wizard)
|
||||
|
||||
## Examples
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ openclaw setup
|
|||
openclaw setup --workspace ~/.openclaw/workspace
|
||||
```
|
||||
|
||||
To run the wizard via setup:
|
||||
To run onboarding via setup:
|
||||
|
||||
```bash
|
||||
openclaw setup --wizard
|
||||
|
|
|
|||
|
|
@ -27,3 +27,4 @@ Notes:
|
|||
- Read-only status surfaces (`status`, `status --json`, `status --all`) resolve supported SecretRefs for their targeted config paths when possible.
|
||||
- If a supported channel SecretRef is configured but unavailable in the current command path, status stays read-only and reports degraded output instead of crashing. Human output shows warnings such as “configured token unavailable in this command path”, and JSON output includes `secretDiagnostics`.
|
||||
- When command-local SecretRef resolution succeeds, status prefers the resolved snapshot and clears transient “secret unavailable” channel markers from the final output.
|
||||
- `status --all` includes a Secrets overview row and a diagnosis section that summarizes secret diagnostics (truncated for readability) without stopping report generation.
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@ Related:
|
|||
- Use fallbacks for cost/latency-sensitive tasks and lower-stakes chat.
|
||||
- For tool-enabled agents or untrusted inputs, avoid older/weaker model tiers.
|
||||
|
||||
## Setup wizard (recommended)
|
||||
## Onboarding (recommended)
|
||||
|
||||
If you don’t want to hand-edit config, run the setup wizard:
|
||||
If you don’t want to hand-edit config, run onboarding:
|
||||
|
||||
```bash
|
||||
openclaw onboard
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ openclaw models status
|
|||
openclaw doctor
|
||||
```
|
||||
|
||||
If you’d rather not manage env vars yourself, the setup wizard can store
|
||||
If you’d rather not manage env vars yourself, onboarding can store
|
||||
API keys for daemon use: `openclaw onboard`.
|
||||
|
||||
See [Help](/help) for details on env inheritance (`env.shellEnv`,
|
||||
|
|
|
|||
|
|
@ -2950,7 +2950,7 @@ Notes:
|
|||
|
||||
## Wizard
|
||||
|
||||
Metadata written by CLI wizards (`onboard`, `configure`, `doctor`):
|
||||
Metadata written by CLI guided setup flows (`onboard`, `configure`, `doctor`):
|
||||
|
||||
```json5
|
||||
{
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ See the [full reference](/gateway/configuration-reference) for every available f
|
|||
<Tabs>
|
||||
<Tab title="Interactive wizard">
|
||||
```bash
|
||||
openclaw onboard # full setup wizard
|
||||
openclaw onboard # full onboarding flow
|
||||
openclaw configure # config wizard
|
||||
```
|
||||
</Tab>
|
||||
|
|
|
|||
|
|
@ -738,7 +738,7 @@ In minimal mode, the Gateway still broadcasts enough for device discovery (`role
|
|||
Gateway auth is **required by default**. If no token/password is configured,
|
||||
the Gateway refuses WebSocket connections (fail‑closed).
|
||||
|
||||
The setup wizard generates a token by default (even for loopback) so
|
||||
Onboarding generates a token by default (even for loopback) so
|
||||
local clients must authenticate.
|
||||
|
||||
Set a token so **all** WS clients must authenticate:
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ Quick answers plus deeper troubleshooting for real-world setups (local dev, VPS,
|
|||
- [How do I install OpenClaw on a VPS?](#how-do-i-install-openclaw-on-a-vps)
|
||||
- [Where are the cloud/VPS install guides?](#where-are-the-cloudvps-install-guides)
|
||||
- [Can I ask OpenClaw to update itself?](#can-i-ask-openclaw-to-update-itself)
|
||||
- [What does the setup wizard actually do?](#what-does-the-setup-wizard-actually-do)
|
||||
- [What does onboarding actually do?](#what-does-onboarding-actually-do)
|
||||
- [Do I need a Claude or OpenAI subscription to run this?](#do-i-need-a-claude-or-openai-subscription-to-run-this)
|
||||
- [Can I use Claude Max subscription without an API key](#can-i-use-claude-max-subscription-without-an-api-key)
|
||||
- [How does Anthropic "setup-token" auth work?](#how-does-anthropic-setuptoken-auth-work)
|
||||
|
|
@ -317,7 +317,7 @@ Install docs: [Install](/install), [Installer flags](/install/installer), [Updat
|
|||
|
||||
### What's the recommended way to install and set up OpenClaw
|
||||
|
||||
The repo recommends running from source and using the setup wizard:
|
||||
The repo recommends running from source and using onboarding:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://openclaw.ai/install.sh | bash
|
||||
|
|
@ -627,7 +627,7 @@ More detail: [Install](/install) and [Installer flags](/install/installer).
|
|||
|
||||
### How do I install OpenClaw on Linux
|
||||
|
||||
Short answer: follow the Linux guide, then run the setup wizard.
|
||||
Short answer: follow the Linux guide, then run onboarding.
|
||||
|
||||
- Linux quick path + service install: [Linux](/platforms/linux).
|
||||
- Full walkthrough: [Getting Started](/start/getting-started).
|
||||
|
|
@ -685,7 +685,7 @@ openclaw gateway restart
|
|||
|
||||
Docs: [Update](/cli/update), [Updating](/install/updating).
|
||||
|
||||
### What does the setup wizard actually do
|
||||
### What does onboarding actually do
|
||||
|
||||
`openclaw onboard` is the recommended setup path. In **local mode** it walks you through:
|
||||
|
||||
|
|
@ -723,7 +723,7 @@ If you want the clearest and safest supported path for production, use an Anthro
|
|||
|
||||
### How does Anthropic setuptoken auth work
|
||||
|
||||
`claude setup-token` generates a **token string** via the Claude Code CLI (it is not available in the web console). You can run it on **any machine**. Choose **Anthropic token (paste setup-token)** in the wizard or paste it with `openclaw models auth paste-token --provider anthropic`. The token is stored as an auth profile for the **anthropic** provider and used like an API key (no auto-refresh). More detail: [OAuth](/concepts/oauth).
|
||||
`claude setup-token` generates a **token string** via the Claude Code CLI (it is not available in the web console). You can run it on **any machine**. Choose **Anthropic token (paste setup-token)** in onboarding or paste it with `openclaw models auth paste-token --provider anthropic`. The token is stored as an auth profile for the **anthropic** provider and used like an API key (no auto-refresh). More detail: [OAuth](/concepts/oauth).
|
||||
|
||||
### Where do I find an Anthropic setuptoken
|
||||
|
||||
|
|
@ -733,7 +733,7 @@ It is **not** in the Anthropic Console. The setup-token is generated by the **Cl
|
|||
claude setup-token
|
||||
```
|
||||
|
||||
Copy the token it prints, then choose **Anthropic token (paste setup-token)** in the wizard. If you want to run it on the gateway host, use `openclaw models auth setup-token --provider anthropic`. If you ran `claude setup-token` elsewhere, paste it on the gateway host with `openclaw models auth paste-token --provider anthropic`. See [Anthropic](/providers/anthropic).
|
||||
Copy the token it prints, then choose **Anthropic token (paste setup-token)** in onboarding. If you want to run it on the gateway host, use `openclaw models auth setup-token --provider anthropic`. If you ran `claude setup-token` elsewhere, paste it on the gateway host with `openclaw models auth paste-token --provider anthropic`. See [Anthropic](/providers/anthropic).
|
||||
|
||||
### Do you support Claude subscription auth (Claude Pro or Max)
|
||||
|
||||
|
|
@ -767,15 +767,15 @@ Yes - via pi-ai's **Amazon Bedrock (Converse)** provider with **manual config**.
|
|||
|
||||
### How does Codex auth work
|
||||
|
||||
OpenClaw supports **OpenAI Code (Codex)** via OAuth (ChatGPT sign-in). The wizard can run the OAuth flow and will set the default model to `openai-codex/gpt-5.4` when appropriate. See [Model providers](/concepts/model-providers) and [Wizard](/start/wizard).
|
||||
OpenClaw supports **OpenAI Code (Codex)** via OAuth (ChatGPT sign-in). Onboarding can run the OAuth flow and will set the default model to `openai-codex/gpt-5.4` when appropriate. See [Model providers](/concepts/model-providers) and [Onboarding (CLI)](/start/wizard).
|
||||
|
||||
### Do you support OpenAI subscription auth Codex OAuth
|
||||
|
||||
Yes. OpenClaw fully supports **OpenAI Code (Codex) subscription OAuth**.
|
||||
OpenAI explicitly allows subscription OAuth usage in external tools/workflows
|
||||
like OpenClaw. The setup wizard can run the OAuth flow for you.
|
||||
like OpenClaw. Onboarding can run the OAuth flow for you.
|
||||
|
||||
See [OAuth](/concepts/oauth), [Model providers](/concepts/model-providers), and [Wizard](/start/wizard).
|
||||
See [OAuth](/concepts/oauth), [Model providers](/concepts/model-providers), and [Onboarding (CLI)](/start/wizard).
|
||||
|
||||
### How do I set up Gemini CLI OAuth
|
||||
|
||||
|
|
@ -844,7 +844,7 @@ without WhatsApp/Telegram.
|
|||
|
||||
`channels.telegram.allowFrom` is **the human sender's Telegram user ID** (numeric). It is not the bot username.
|
||||
|
||||
The setup wizard accepts `@username` input and resolves it to a numeric ID, but OpenClaw authorization uses numeric IDs only.
|
||||
Onboarding accepts `@username` input and resolves it to a numeric ID, but OpenClaw authorization uses numeric IDs only.
|
||||
|
||||
Safer (no third-party bot):
|
||||
|
||||
|
|
@ -1909,7 +1909,7 @@ openclaw onboard --install-daemon
|
|||
|
||||
Notes:
|
||||
|
||||
- The setup wizard also offers **Reset** if it sees an existing config. See [Wizard](/start/wizard).
|
||||
- Onboarding also offers **Reset** if it sees an existing config. See [Onboarding (CLI)](/start/wizard).
|
||||
- If you used profiles (`--profile` / `OPENCLAW_PROFILE`), reset each state dir (defaults are `~/.openclaw-<profile>`).
|
||||
- Dev reset: `openclaw gateway --dev --reset` (dev-only; wipes dev config + credentials + sessions + workspace).
|
||||
|
||||
|
|
|
|||
|
|
@ -362,7 +362,7 @@ If you want to rely on env keys (e.g. exported in your `~/.profile`), run local
|
|||
|
||||
## Docker runners (optional “works in Linux” checks)
|
||||
|
||||
These run `pnpm test:live` inside the repo Docker image, mounting your local config dir and workspace (and sourcing `~/.profile` if mounted). They also bind-mount CLI auth homes like `~/.codex`, `~/.claude`, `~/.qwen`, and `~/.minimax` when present so external-CLI OAuth stays available in-container:
|
||||
These run `pnpm test:live` inside the repo Docker image, mounting your local config dir and workspace (and sourcing `~/.profile` if mounted). They also bind-mount CLI auth homes like `~/.codex`, `~/.claude`, `~/.qwen`, and `~/.minimax` when present, then copy them into the container home before the run so external-CLI OAuth can refresh tokens without mutating the host auth store:
|
||||
|
||||
- Direct models: `pnpm test:docker:live-models` (script: `scripts/test-live-models-docker.sh`)
|
||||
- Gateway + dev agent: `pnpm test:docker:live-gateway` (script: `scripts/test-live-gateway-models-docker.sh`)
|
||||
|
|
@ -373,6 +373,9 @@ These run `pnpm test:live` inside the repo Docker image, mounting your local con
|
|||
The live-model Docker runners also bind-mount the current checkout read-only and
|
||||
stage it into a temporary workdir inside the container. This keeps the runtime
|
||||
image slim while still running Vitest against your exact local source/config.
|
||||
`test:docker:live-models` still runs `pnpm test:live`, so pass through
|
||||
`OPENCLAW_LIVE_GATEWAY_*` as well when you need to narrow or exclude gateway
|
||||
live coverage from that Docker lane.
|
||||
|
||||
Manual ACP plain-language thread smoke (not CI):
|
||||
|
||||
|
|
@ -384,8 +387,9 @@ Useful env vars:
|
|||
- `OPENCLAW_CONFIG_DIR=...` (default: `~/.openclaw`) mounted to `/home/node/.openclaw`
|
||||
- `OPENCLAW_WORKSPACE_DIR=...` (default: `~/.openclaw/workspace`) mounted to `/home/node/.openclaw/workspace`
|
||||
- `OPENCLAW_PROFILE_FILE=...` (default: `~/.profile`) mounted to `/home/node/.profile` and sourced before running tests
|
||||
- External CLI auth dirs under `$HOME` (`.codex`, `.claude`, `.qwen`, `.minimax`) are mounted read-only to the matching `/home/node/...` paths when present
|
||||
- External CLI auth dirs under `$HOME` (`.codex`, `.claude`, `.qwen`, `.minimax`) are mounted read-only under `/host-auth/...`, then copied into `/home/node/...` before tests start
|
||||
- `OPENCLAW_LIVE_GATEWAY_MODELS=...` / `OPENCLAW_LIVE_MODELS=...` to narrow the run
|
||||
- `OPENCLAW_LIVE_GATEWAY_PROVIDERS=...` / `OPENCLAW_LIVE_PROVIDERS=...` to filter providers in-container
|
||||
- `OPENCLAW_LIVE_REQUIRE_PROFILE_KEYS=1` to ensure creds come from the profile store (not env)
|
||||
|
||||
## Docs sanity
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ title: "OpenClaw"
|
|||
<Card title="Get Started" href="/start/getting-started" icon="rocket">
|
||||
Install OpenClaw and bring up the Gateway in minutes.
|
||||
</Card>
|
||||
<Card title="Run the Wizard" href="/start/wizard" icon="sparkles">
|
||||
<Card title="Run Onboarding" href="/start/wizard" icon="sparkles">
|
||||
Guided setup with `openclaw onboard` and pairing flows.
|
||||
</Card>
|
||||
<Card title="Open the Control UI" href="/web/control-ui" icon="layout-dashboard">
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ From repo root:
|
|||
This script:
|
||||
|
||||
- builds the gateway image locally (or pulls a remote image if `OPENCLAW_IMAGE` is set)
|
||||
- runs the setup wizard
|
||||
- runs onboarding
|
||||
- prints optional provider setup hints
|
||||
- starts the gateway via Docker Compose
|
||||
- generates a gateway token and writes it to `.env`
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ For VPS/cloud hosts, avoid third-party "1-click" marketplace images when possibl
|
|||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Installer script" icon="rocket" defaultOpen>
|
||||
Downloads the CLI, installs it globally via npm, and launches the setup wizard.
|
||||
Downloads the CLI, installs it globally via npm, and launches onboarding.
|
||||
|
||||
<Tabs>
|
||||
<Tab title="macOS / Linux / WSL2">
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ and you configure everything via the `/setup` web wizard.
|
|||
## What you get
|
||||
|
||||
- Hosted OpenClaw Gateway + Control UI
|
||||
- Web setup wizard at `/setup` (no terminal commands)
|
||||
- Web setup at `/setup` (no terminal commands)
|
||||
- Persistent storage via Northflank Volume (`/data`) so config/credentials/workspace survive redeploys
|
||||
|
||||
## Setup flow
|
||||
|
|
@ -32,7 +32,7 @@ and you configure everything via the `/setup` web wizard.
|
|||
4. Click **Run setup**.
|
||||
5. Open the Control UI at `https://<your-northflank-domain>/openclaw`
|
||||
|
||||
If Telegram DMs are set to pairing, the setup wizard can approve the pairing code.
|
||||
If Telegram DMs are set to pairing, web setup can approve the pairing code.
|
||||
|
||||
## Getting chat tokens
|
||||
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@ Railway will either:
|
|||
|
||||
Then open:
|
||||
|
||||
- `https://<your-railway-domain>/setup` — setup wizard (password protected)
|
||||
- `https://<your-railway-domain>/setup` — web setup (password protected)
|
||||
- `https://<your-railway-domain>/openclaw` — Control UI
|
||||
|
||||
## What you get
|
||||
|
||||
- Hosted OpenClaw Gateway + Control UI
|
||||
- Web setup wizard at `/setup` (no terminal commands)
|
||||
- Web setup at `/setup` (no terminal commands)
|
||||
- Persistent storage via Railway Volume (`/data`) so config/credentials/workspace survive redeploys
|
||||
- Backup export at `/setup/export` to migrate off Railway later
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ Set these variables on the service:
|
|||
3. (Optional) Add Telegram/Discord/Slack tokens.
|
||||
4. Click **Run setup**.
|
||||
|
||||
If Telegram DMs are set to pairing, the setup wizard can approve the pairing code.
|
||||
If Telegram DMs are set to pairing, web setup can approve the pairing code.
|
||||
|
||||
## Getting chat tokens
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ The Blueprint defaults to `starter`. To use free tier, change `plan: free` in yo
|
|||
|
||||
## After deployment
|
||||
|
||||
### Complete the setup wizard
|
||||
### Complete web setup
|
||||
|
||||
1. Navigate to `https://<your-service>.onrender.com/setup`
|
||||
2. Enter your `SETUP_PASSWORD`
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ curl -fsSL https://openclaw.ai/install.sh | bash
|
|||
|
||||
Notes:
|
||||
|
||||
- Add `--no-onboard` if you don’t want the setup wizard to run again.
|
||||
- Add `--no-onboard` if you don’t want onboarding to run again.
|
||||
- For **source installs**, use:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ title: "Media Understanding"
|
|||
|
||||
OpenClaw can **summarize inbound media** (image/audio/video) before the reply pipeline runs. It auto‑detects when local tools or provider keys are available, and can be disabled or customized. If understanding is off, models still receive the original files/URLs as usual.
|
||||
|
||||
Vendor-specific media behavior is registered by vendor plugins, while OpenClaw
|
||||
core owns the shared `tools.media` config, fallback order, and reply-pipeline
|
||||
integration.
|
||||
|
||||
## Goals
|
||||
|
||||
- Optional: pre‑digest inbound media into short text for faster routing + better command parsing.
|
||||
|
|
@ -184,7 +188,10 @@ If you set `capabilities`, the entry only runs for those media types. For shared
|
|||
lists, OpenClaw can infer defaults:
|
||||
|
||||
- `openai`, `anthropic`, `minimax`: **image**
|
||||
- `moonshot`: **image + video**
|
||||
- `google` (Gemini API): **image + audio + video**
|
||||
- `mistral`: **audio**
|
||||
- `zai`: **image**
|
||||
- `groq`: **audio**
|
||||
- `deepgram`: **audio**
|
||||
|
||||
|
|
@ -193,11 +200,11 @@ If you omit `capabilities`, the entry is eligible for the list it appears in.
|
|||
|
||||
## Provider support matrix (OpenClaw integrations)
|
||||
|
||||
| Capability | Provider integration | Notes |
|
||||
| ---------- | ------------------------------------------------ | --------------------------------------------------------- |
|
||||
| Image | OpenAI / Anthropic / Google / others via `pi-ai` | Any image-capable model in the registry works. |
|
||||
| Audio | OpenAI, Groq, Deepgram, Google, Mistral | Provider transcription (Whisper/Deepgram/Gemini/Voxtral). |
|
||||
| Video | Google (Gemini API) | Provider video understanding. |
|
||||
| Capability | Provider integration | Notes |
|
||||
| ---------- | -------------------------------------------------- | ----------------------------------------------------------------------- |
|
||||
| Image | OpenAI, Anthropic, Google, MiniMax, Moonshot, Z.AI | Vendor plugins register image support against core media understanding. |
|
||||
| Audio | OpenAI, Groq, Deepgram, Google, Mistral | Provider transcription (Whisper/Deepgram/Gemini/Voxtral). |
|
||||
| Video | Google, Moonshot | Provider video understanding via vendor plugins. |
|
||||
|
||||
## Model selection guidance
|
||||
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ Since the Pi is just the Gateway (models run in the cloud), use API-based models
|
|||
|
||||
## Auto-Start on Boot
|
||||
|
||||
The setup wizard sets this up, but to verify:
|
||||
Onboarding sets this up, but to verify:
|
||||
|
||||
```bash
|
||||
# Check service is enabled
|
||||
|
|
|
|||
|
|
@ -104,11 +104,15 @@ loader. Cursor command markdown works through the same path.
|
|||
- `HOOK.md`
|
||||
- `handler.ts` or `handler.js`
|
||||
|
||||
#### MCP for CLI backends
|
||||
#### MCP for Pi
|
||||
|
||||
- enabled bundles can contribute MCP server config
|
||||
- current runtime wiring is used by the `claude-cli` backend
|
||||
- OpenClaw merges bundle MCP config into the backend `--mcp-config` file
|
||||
- OpenClaw merges bundle MCP config into the effective embedded Pi settings as
|
||||
`mcpServers`
|
||||
- OpenClaw also exposes supported bundle MCP tools during embedded Pi agent
|
||||
turns by launching supported stdio MCP servers as subprocesses
|
||||
- project-local Pi settings still apply after bundle defaults, so workspace
|
||||
settings can override bundle MCP entries when needed
|
||||
|
||||
#### Embedded Pi settings
|
||||
|
||||
|
|
@ -133,7 +137,6 @@ diagnostics/info output, but OpenClaw does not run them yet:
|
|||
- Cursor `.cursor/agents`
|
||||
- Cursor `.cursor/hooks.json`
|
||||
- Cursor `.cursor/rules`
|
||||
- Cursor `mcpServers` outside the current mapped runtime paths
|
||||
- Codex inline/app metadata beyond capability reporting
|
||||
|
||||
## Capability reporting
|
||||
|
|
@ -153,7 +156,8 @@ Current exceptions:
|
|||
- Claude `commands` is considered supported because it maps to skills
|
||||
- Claude `settings` is considered supported because it maps to embedded Pi settings
|
||||
- Cursor `commands` is considered supported because it maps to skills
|
||||
- bundle MCP is considered supported where OpenClaw actually imports it
|
||||
- bundle MCP is considered supported because it maps into embedded Pi settings
|
||||
and exposes supported stdio tools to embedded Pi
|
||||
- Codex `hooks` is considered supported only for OpenClaw hook-pack layouts
|
||||
|
||||
## Format differences
|
||||
|
|
@ -195,6 +199,8 @@ Claude-specific notes:
|
|||
|
||||
- `commands/` is treated like skill content
|
||||
- `settings.json` is imported into embedded Pi settings
|
||||
- `.mcp.json` and manifest `mcpServers` can expose supported stdio tools to
|
||||
embedded Pi
|
||||
- `hooks/hooks.json` is detected, but not executed as Claude automation
|
||||
|
||||
### Cursor
|
||||
|
|
@ -246,7 +252,9 @@ Current behavior:
|
|||
- bundle discovery reads files inside the plugin root with boundary checks
|
||||
- skills and hook-pack paths must stay inside the plugin root
|
||||
- bundle settings files are read with the same boundary checks
|
||||
- OpenClaw does not execute arbitrary bundle runtime code in-process
|
||||
- supported stdio bundle MCP servers may be launched as subprocesses for
|
||||
embedded Pi tool calls
|
||||
- OpenClaw does not load arbitrary bundle runtime modules in-process
|
||||
|
||||
This makes bundle support safer by default than native plugin modules, but you
|
||||
should still treat third-party bundles as trusted content for the features they
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@ Example with a stable public host:
|
|||
|
||||
## TTS for calls
|
||||
|
||||
Voice Call uses the core `messages.tts` configuration (OpenAI or ElevenLabs) for
|
||||
Voice Call uses the core `messages.tts` configuration for
|
||||
streaming speech on calls. You can override it under the plugin config with the
|
||||
**same shape** — it deep‑merges with `messages.tts`.
|
||||
|
||||
|
|
@ -222,7 +222,7 @@ streaming speech on calls. You can override it under the plugin config with the
|
|||
|
||||
Notes:
|
||||
|
||||
- **Edge TTS is ignored for voice calls** (telephony audio needs PCM; Edge output is unreliable).
|
||||
- **Microsoft speech is ignored for voice calls** (telephony audio needs PCM; the current Microsoft transport does not expose telephony PCM output).
|
||||
- Core TTS is used when Twilio media streaming is enabled; otherwise calls fall back to provider native voices.
|
||||
|
||||
### More examples
|
||||
|
|
|
|||
|
|
@ -16,15 +16,15 @@ Ollama is a local LLM runtime that makes it easy to run open-source models on yo
|
|||
|
||||
## Quick start
|
||||
|
||||
### Onboarding wizard (recommended)
|
||||
### Onboarding (recommended)
|
||||
|
||||
The fastest way to set up Ollama is through the setup wizard:
|
||||
The fastest way to set up Ollama is through onboarding:
|
||||
|
||||
```bash
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
Select **Ollama** from the provider list. The wizard will:
|
||||
Select **Ollama** from the provider list. Onboarding will:
|
||||
|
||||
1. Ask for the Ollama base URL where your instance can be reached (default `http://127.0.0.1:11434`).
|
||||
2. Let you choose **Cloud + Local** (cloud models and local models) or **Local** (local models only).
|
||||
|
|
|
|||
|
|
@ -1,24 +1,24 @@
|
|||
---
|
||||
summary: "Full reference for the CLI setup wizard: every step, flag, and config field"
|
||||
summary: "Full reference for CLI onboarding: every step, flag, and config field"
|
||||
read_when:
|
||||
- Looking up a specific wizard step or flag
|
||||
- Looking up a specific onboarding step or flag
|
||||
- Automating onboarding with non-interactive mode
|
||||
- Debugging wizard behavior
|
||||
title: "Setup Wizard Reference"
|
||||
sidebarTitle: "Wizard Reference"
|
||||
- Debugging onboarding behavior
|
||||
title: "Onboarding Reference"
|
||||
sidebarTitle: "Onboarding Reference"
|
||||
---
|
||||
|
||||
# Setup Wizard Reference
|
||||
# Onboarding Reference
|
||||
|
||||
This is the full reference for the `openclaw onboard` CLI wizard.
|
||||
For a high-level overview, see [Setup Wizard](/start/wizard).
|
||||
This is the full reference for `openclaw onboard`.
|
||||
For a high-level overview, see [Onboarding (CLI)](/start/wizard).
|
||||
|
||||
## Flow details (local mode)
|
||||
|
||||
<Steps>
|
||||
<Step title="Existing config detection">
|
||||
- If `~/.openclaw/openclaw.json` exists, choose **Keep / Modify / Reset**.
|
||||
- Re-running the wizard does **not** wipe anything unless you explicitly choose **Reset**
|
||||
- Re-running onboarding does **not** wipe anything unless you explicitly choose **Reset**
|
||||
(or pass `--reset`).
|
||||
- CLI `--reset` defaults to `config+creds+sessions`; use `--reset-scope full`
|
||||
to also remove workspace.
|
||||
|
|
@ -31,9 +31,9 @@ For a high-level overview, see [Setup Wizard](/start/wizard).
|
|||
</Step>
|
||||
<Step title="Model/Auth">
|
||||
- **Anthropic API key**: uses `ANTHROPIC_API_KEY` if present or prompts for a key, then saves it for daemon use.
|
||||
- **Anthropic OAuth (Claude Code CLI)**: on macOS the wizard checks Keychain item "Claude Code-credentials" (choose "Always Allow" so launchd starts don't block); on Linux/Windows it reuses `~/.claude/.credentials.json` if present.
|
||||
- **Anthropic OAuth (Claude Code CLI)**: on macOS onboarding checks Keychain item "Claude Code-credentials" (choose "Always Allow" so launchd starts don't block); on Linux/Windows it reuses `~/.claude/.credentials.json` if present.
|
||||
- **Anthropic token (paste setup-token)**: run `claude setup-token` on any machine, then paste the token (you can name it; blank = default).
|
||||
- **OpenAI Code (Codex) subscription (Codex CLI)**: if `~/.codex/auth.json` exists, the wizard can reuse it.
|
||||
- **OpenAI Code (Codex) subscription (Codex CLI)**: if `~/.codex/auth.json` exists, onboarding can reuse it.
|
||||
- **OpenAI Code (Codex) subscription (OAuth)**: browser flow; paste the `code#state`.
|
||||
- Sets `agents.defaults.model` to `openai-codex/gpt-5.2` when model is unset or `openai/*`.
|
||||
- **OpenAI API key**: uses `OPENAI_API_KEY` if present or prompts for a key, then stores it in auth profiles.
|
||||
|
|
@ -55,7 +55,7 @@ For a high-level overview, see [Setup Wizard](/start/wizard).
|
|||
- More detail: [Moonshot AI (Kimi + Kimi Coding)](/providers/moonshot)
|
||||
- **Skip**: no auth configured yet.
|
||||
- Pick a default model from detected options (or enter provider/model manually). For best quality and lower prompt-injection risk, choose the strongest latest-generation model available in your provider stack.
|
||||
- Wizard runs a model check and warns if the configured model is unknown or missing auth.
|
||||
- Onboarding runs a model check and warns if the configured model is unknown or missing auth.
|
||||
- API key storage mode defaults to plaintext auth-profile values. Use `--secret-input-mode ref` to store env-backed refs instead (for example `keyRef: { source: "env", provider: "default", id: "OPENAI_API_KEY" }`).
|
||||
- OAuth credentials live in `~/.openclaw/credentials/oauth.json`; auth profiles live in `~/.openclaw/agents/<agentId>/agent/auth-profiles.json` (API keys + OAuth).
|
||||
- More detail: [/concepts/oauth](/concepts/oauth)
|
||||
|
|
@ -106,7 +106,7 @@ For a high-level overview, see [Setup Wizard](/start/wizard).
|
|||
- macOS: LaunchAgent
|
||||
- Requires a logged-in user session; for headless, use a custom LaunchDaemon (not shipped).
|
||||
- Linux (and Windows via WSL2): systemd user unit
|
||||
- Wizard attempts to enable lingering via `loginctl enable-linger <user>` so the Gateway stays up after logout.
|
||||
- Onboarding attempts to enable lingering via `loginctl enable-linger <user>` so the Gateway stays up after logout.
|
||||
- May prompt for sudo (writes `/var/lib/systemd/linger`); it tries without sudo first.
|
||||
- **Runtime selection:** Node (recommended; required for WhatsApp/Telegram). Bun is **not recommended**.
|
||||
- If token auth requires a token and `gateway.auth.token` is SecretRef-managed, daemon install validates it but does not persist resolved plaintext token values into supervisor service environment metadata.
|
||||
|
|
@ -128,8 +128,8 @@ For a high-level overview, see [Setup Wizard](/start/wizard).
|
|||
</Steps>
|
||||
|
||||
<Note>
|
||||
If no GUI is detected, the wizard prints SSH port-forward instructions for the Control UI instead of opening a browser.
|
||||
If the Control UI assets are missing, the wizard attempts to build them; fallback is `pnpm ui:build` (auto-installs UI deps).
|
||||
If no GUI is detected, onboarding prints SSH port-forward instructions for the Control UI instead of opening a browser.
|
||||
If the Control UI assets are missing, onboarding attempts to build them; fallback is `pnpm ui:build` (auto-installs UI deps).
|
||||
</Note>
|
||||
|
||||
## Non-interactive mode
|
||||
|
|
@ -183,12 +183,12 @@ openclaw agents add work \
|
|||
|
||||
## Gateway wizard RPC
|
||||
|
||||
The Gateway exposes the wizard flow over RPC (`wizard.start`, `wizard.next`, `wizard.cancel`, `wizard.status`).
|
||||
The Gateway exposes the onboarding flow over RPC (`wizard.start`, `wizard.next`, `wizard.cancel`, `wizard.status`).
|
||||
Clients (macOS app, Control UI) can render steps without re‑implementing onboarding logic.
|
||||
|
||||
## Signal setup (signal-cli)
|
||||
|
||||
The wizard can install `signal-cli` from GitHub releases:
|
||||
Onboarding can install `signal-cli` from GitHub releases:
|
||||
|
||||
- Downloads the appropriate release asset.
|
||||
- Stores it under `~/.openclaw/tools/signal-cli/<version>/`.
|
||||
|
|
@ -223,12 +223,12 @@ Typical fields in `~/.openclaw/openclaw.json`:
|
|||
WhatsApp credentials go under `~/.openclaw/credentials/whatsapp/<accountId>/`.
|
||||
Sessions are stored under `~/.openclaw/agents/<agentId>/sessions/`.
|
||||
|
||||
Some channels are delivered as plugins. When you pick one during setup, the wizard
|
||||
Some channels are delivered as plugins. When you pick one during setup, onboarding
|
||||
will prompt to install it (npm or a local path) before it can be configured.
|
||||
|
||||
## Related docs
|
||||
|
||||
- Wizard overview: [Setup Wizard](/start/wizard)
|
||||
- Onboarding overview: [Onboarding (CLI)](/start/wizard)
|
||||
- macOS app onboarding: [Onboarding](/start/onboarding)
|
||||
- Config reference: [Gateway configuration](/gateway/configuration)
|
||||
- Providers: [WhatsApp](/channels/whatsapp), [Telegram](/channels/telegram), [Discord](/channels/discord), [Google Chat](/channels/googlechat), [Signal](/channels/signal), [BlueBubbles](/channels/bluebubbles) (iMessage), [iMessage](/channels/imessage) (legacy)
|
||||
|
|
|
|||
|
|
@ -52,13 +52,13 @@ Check your Node version with `node --version` if you are unsure.
|
|||
</Note>
|
||||
|
||||
</Step>
|
||||
<Step title="Run the setup wizard">
|
||||
<Step title="Run onboarding">
|
||||
```bash
|
||||
openclaw onboard --install-daemon
|
||||
```
|
||||
|
||||
The wizard configures auth, gateway settings, and optional channels.
|
||||
See [Setup Wizard](/start/wizard) for details.
|
||||
Onboarding configures auth, gateway settings, and optional channels.
|
||||
See [Onboarding (CLI)](/start/wizard) for details.
|
||||
|
||||
</Step>
|
||||
<Step title="Check the Gateway">
|
||||
|
|
@ -114,8 +114,8 @@ Full environment variable reference: [Environment vars](/help/environment).
|
|||
## Go deeper
|
||||
|
||||
<Columns>
|
||||
<Card title="Setup Wizard (details)" href="/start/wizard">
|
||||
Full CLI wizard reference and advanced options.
|
||||
<Card title="Onboarding (CLI)" href="/start/wizard">
|
||||
Full CLI onboarding reference and advanced options.
|
||||
</Card>
|
||||
<Card title="macOS app onboarding" href="/start/onboarding">
|
||||
First run flow for the macOS app.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ Use these hubs to discover every page, including deep dives and reference docs t
|
|||
- [Getting Started](/start/getting-started)
|
||||
- [Quick start](/start/quickstart)
|
||||
- [Onboarding](/start/onboarding)
|
||||
- [Wizard](/start/wizard)
|
||||
- [Onboarding (CLI)](/start/wizard)
|
||||
- [Setup](/start/setup)
|
||||
- [Dashboard (local Gateway)](http://127.0.0.1:18789/)
|
||||
- [Help](/help)
|
||||
|
|
|
|||
|
|
@ -14,21 +14,21 @@ and how you prefer to configure providers.
|
|||
|
||||
## Choose your onboarding path
|
||||
|
||||
- **CLI wizard** for macOS, Linux, and Windows (via WSL2).
|
||||
- **CLI onboarding** for macOS, Linux, and Windows (via WSL2).
|
||||
- **macOS app** for a guided first run on Apple silicon or Intel Macs.
|
||||
|
||||
## CLI setup wizard
|
||||
## CLI onboarding
|
||||
|
||||
Run the wizard in a terminal:
|
||||
Run onboarding in a terminal:
|
||||
|
||||
```bash
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
Use the CLI wizard when you want full control of the Gateway, workspace,
|
||||
Use CLI onboarding when you want full control of the Gateway, workspace,
|
||||
channels, and skills. Docs:
|
||||
|
||||
- [Setup Wizard (CLI)](/start/wizard)
|
||||
- [Onboarding (CLI)](/start/wizard)
|
||||
- [`openclaw onboard` command](/cli/onboard)
|
||||
|
||||
## macOS app onboarding
|
||||
|
|
@ -41,7 +41,7 @@ Use the OpenClaw app when you want a fully guided setup on macOS. Docs:
|
|||
|
||||
If you need an endpoint that is not listed, including hosted providers that
|
||||
expose standard OpenAI or Anthropic APIs, choose **Custom Provider** in the
|
||||
CLI wizard. You will be asked to:
|
||||
CLI onboarding. You will be asked to:
|
||||
|
||||
- Pick OpenAI-compatible, Anthropic-compatible, or **Unknown** (auto-detect).
|
||||
- Enter a base URL and API key (if required by the provider).
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ Quick start is now part of [Getting Started](/start/getting-started).
|
|||
<Card title="Getting Started" href="/start/getting-started">
|
||||
Install OpenClaw and run your first chat in minutes.
|
||||
</Card>
|
||||
<Card title="Onboarding Wizard" href="/start/wizard">
|
||||
Full CLI wizard reference and advanced options.
|
||||
<Card title="Onboarding (CLI)" href="/start/wizard">
|
||||
Full CLI onboarding reference and advanced options.
|
||||
</Card>
|
||||
</Columns>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ title: "Setup"
|
|||
|
||||
<Note>
|
||||
If you are setting up for the first time, start with [Getting Started](/start/getting-started).
|
||||
For wizard details, see [Onboarding Wizard](/start/wizard).
|
||||
For onboarding details, see [Onboarding (CLI)](/start/wizard).
|
||||
</Note>
|
||||
|
||||
Last updated: 2026-01-01
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ openclaw onboard --non-interactive \
|
|||
Add `--json` for a machine-readable summary.
|
||||
|
||||
Use `--secret-input-mode ref` to store env-backed refs in auth profiles instead of plaintext values.
|
||||
Interactive selection between env refs and configured provider refs (`file` or `exec`) is available in the setup wizard flow.
|
||||
Interactive selection between env refs and configured provider refs (`file` or `exec`) is available in the onboarding flow.
|
||||
|
||||
In non-interactive `ref` mode, provider env vars must be set in the process environment.
|
||||
Passing inline key flags without the matching env var now fails fast.
|
||||
|
|
@ -210,6 +210,6 @@ Notes:
|
|||
|
||||
## Related docs
|
||||
|
||||
- Onboarding hub: [Setup Wizard (CLI)](/start/wizard)
|
||||
- Onboarding hub: [Onboarding (CLI)](/start/wizard)
|
||||
- Full reference: [CLI Setup Reference](/start/wizard-cli-reference)
|
||||
- Command reference: [`openclaw onboard`](/cli/onboard)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ sidebarTitle: "CLI reference"
|
|||
# CLI Setup Reference
|
||||
|
||||
This page is the full reference for `openclaw onboard`.
|
||||
For the short guide, see [Setup Wizard (CLI)](/start/wizard).
|
||||
For the short guide, see [Onboarding (CLI)](/start/wizard).
|
||||
|
||||
## What the wizard does
|
||||
|
||||
|
|
@ -294,6 +294,6 @@ Signal setup behavior:
|
|||
|
||||
## Related docs
|
||||
|
||||
- Onboarding hub: [Setup Wizard (CLI)](/start/wizard)
|
||||
- Onboarding hub: [Onboarding (CLI)](/start/wizard)
|
||||
- Automation and scripts: [CLI Automation](/start/wizard-cli-automation)
|
||||
- Command reference: [`openclaw onboard`](/cli/onboard)
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
---
|
||||
summary: "CLI setup wizard: guided setup for gateway, workspace, channels, and skills"
|
||||
summary: "CLI onboarding: guided setup for gateway, workspace, channels, and skills"
|
||||
read_when:
|
||||
- Running or configuring the setup wizard
|
||||
- Running or configuring CLI onboarding
|
||||
- Setting up a new machine
|
||||
title: "Setup Wizard (CLI)"
|
||||
title: "Onboarding (CLI)"
|
||||
sidebarTitle: "Onboarding: CLI"
|
||||
---
|
||||
|
||||
# Setup Wizard (CLI)
|
||||
# Onboarding (CLI)
|
||||
|
||||
The setup wizard is the **recommended** way to set up OpenClaw on macOS,
|
||||
CLI onboarding is the **recommended** way to set up OpenClaw on macOS,
|
||||
Linux, or Windows (via WSL2; strongly recommended).
|
||||
It configures a local Gateway or a remote Gateway connection, plus channels, skills,
|
||||
and workspace defaults in one guided flow.
|
||||
|
|
@ -35,7 +35,7 @@ openclaw agents add <name>
|
|||
</Note>
|
||||
|
||||
<Tip>
|
||||
The setup wizard includes a web search step where you can pick a provider
|
||||
CLI onboarding includes a web search step where you can pick a provider
|
||||
(Perplexity, Brave, Gemini, Grok, or Kimi) and paste your API key so the agent
|
||||
can use `web_search`. You can also configure this later with
|
||||
`openclaw configure --section web`. Docs: [Web tools](/tools/web).
|
||||
|
|
@ -43,7 +43,7 @@ can use `web_search`. You can also configure this later with
|
|||
|
||||
## QuickStart vs Advanced
|
||||
|
||||
The wizard starts with **QuickStart** (defaults) vs **Advanced** (full control).
|
||||
Onboarding starts with **QuickStart** (defaults) vs **Advanced** (full control).
|
||||
|
||||
<Tabs>
|
||||
<Tab title="QuickStart (defaults)">
|
||||
|
|
@ -61,7 +61,7 @@ The wizard starts with **QuickStart** (defaults) vs **Advanced** (full control).
|
|||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## What the wizard configures
|
||||
## What onboarding configures
|
||||
|
||||
**Local mode (default)** walks you through these steps:
|
||||
|
||||
|
|
@ -84,9 +84,9 @@ The wizard starts with **QuickStart** (defaults) vs **Advanced** (full control).
|
|||
7. **Skills** — Installs recommended skills and optional dependencies.
|
||||
|
||||
<Note>
|
||||
Re-running the wizard does **not** wipe anything unless you explicitly choose **Reset** (or pass `--reset`).
|
||||
Re-running onboarding does **not** wipe anything unless you explicitly choose **Reset** (or pass `--reset`).
|
||||
CLI `--reset` defaults to config, credentials, and sessions; use `--reset-scope full` to include workspace.
|
||||
If the config is invalid or contains legacy keys, the wizard asks you to run `openclaw doctor` first.
|
||||
If the config is invalid or contains legacy keys, onboarding asks you to run `openclaw doctor` first.
|
||||
</Note>
|
||||
|
||||
**Remote mode** only configures the local client to connect to a Gateway elsewhere.
|
||||
|
|
@ -95,7 +95,7 @@ It does **not** install or change anything on the remote host.
|
|||
## Add another agent
|
||||
|
||||
Use `openclaw agents add <name>` to create a separate agent with its own workspace,
|
||||
sessions, and auth profiles. Running without `--workspace` launches the wizard.
|
||||
sessions, and auth profiles. Running without `--workspace` launches onboarding.
|
||||
|
||||
What it sets:
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ What it sets:
|
|||
Notes:
|
||||
|
||||
- Default workspaces follow `~/.openclaw/workspace-<agentId>`.
|
||||
- Add `bindings` to route inbound messages (the wizard can do this).
|
||||
- Add `bindings` to route inbound messages (onboarding can do this).
|
||||
- Non-interactive flags: `--model`, `--agent-dir`, `--bind`, `--non-interactive`.
|
||||
|
||||
## Full reference
|
||||
|
|
@ -115,7 +115,7 @@ For detailed step-by-step breakdowns and config outputs, see
|
|||
[CLI Setup Reference](/start/wizard-cli-reference).
|
||||
For non-interactive examples, see [CLI Automation](/start/wizard-cli-automation).
|
||||
For the deeper technical reference, including RPC details, see
|
||||
[Wizard Reference](/reference/wizard).
|
||||
[Onboarding Reference](/reference/wizard).
|
||||
|
||||
## Related docs
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,96 @@ The important design boundary:
|
|||
That split lets OpenClaw validate config, explain missing/disabled plugins, and
|
||||
build UI/schema hints before the full runtime is active.
|
||||
|
||||
## Capability ownership model
|
||||
|
||||
OpenClaw treats a native plugin as the ownership boundary for a **company** or a
|
||||
**feature**, not as a grab bag of unrelated integrations.
|
||||
|
||||
That means:
|
||||
|
||||
- a company plugin should usually own all of that company's OpenClaw-facing
|
||||
surfaces
|
||||
- a feature plugin should usually own the full feature surface it introduces
|
||||
- channels should consume shared core capabilities instead of re-implementing
|
||||
provider behavior ad hoc
|
||||
|
||||
Examples:
|
||||
|
||||
- the bundled `openai` plugin owns OpenAI model-provider behavior and OpenAI
|
||||
speech + media-understanding behavior
|
||||
- the bundled `elevenlabs` plugin owns ElevenLabs speech behavior
|
||||
- the bundled `microsoft` plugin owns Microsoft speech behavior
|
||||
- the bundled `google`, `minimax`, `mistral`, `moonshot`, and `zai` plugins own
|
||||
their media-understanding backends
|
||||
- the `voice-call` plugin is a feature plugin: it owns call transport, tools,
|
||||
CLI, routes, and runtime, but it consumes core TTS/STT capability instead of
|
||||
inventing a second speech stack
|
||||
|
||||
The intended end state is:
|
||||
|
||||
- OpenAI lives in one plugin even if it spans text models, speech, images, and
|
||||
future video
|
||||
- another vendor can do the same for its own surface area
|
||||
- channels do not care which vendor plugin owns the provider; they consume the
|
||||
shared capability contract exposed by core
|
||||
|
||||
This is the key distinction:
|
||||
|
||||
- **plugin** = ownership boundary
|
||||
- **capability** = core contract that multiple plugins can implement or consume
|
||||
|
||||
So if OpenClaw adds a new domain such as video, the first question is not
|
||||
"which provider should hardcode video handling?" The first question is "what is
|
||||
the core video capability contract?" Once that contract exists, vendor plugins
|
||||
can register against it and channel/feature plugins can consume it.
|
||||
|
||||
If the capability does not exist yet, the right move is usually:
|
||||
|
||||
1. define the missing capability in core
|
||||
2. expose it through the plugin API/runtime in a typed way
|
||||
3. wire channels/features against that capability
|
||||
4. let vendor plugins register implementations
|
||||
|
||||
This keeps ownership explicit while avoiding core behavior that depends on a
|
||||
single vendor or a one-off plugin-specific code path.
|
||||
|
||||
### Capability layering
|
||||
|
||||
Use this mental model when deciding where code belongs:
|
||||
|
||||
- **core capability layer**: shared orchestration, policy, fallback, config
|
||||
merge rules, delivery semantics, and typed contracts
|
||||
- **vendor plugin layer**: vendor-specific APIs, auth, model catalogs, speech
|
||||
synthesis, image generation, future video backends, usage endpoints
|
||||
- **channel/feature plugin layer**: Slack/Discord/voice-call/etc. integration
|
||||
that consumes core capabilities and presents them on a surface
|
||||
|
||||
For example, TTS follows this shape:
|
||||
|
||||
- core owns reply-time TTS policy, fallback order, prefs, and channel delivery
|
||||
- `openai`, `elevenlabs`, and `microsoft` own synthesis implementations
|
||||
- `voice-call` consumes the telephony TTS runtime helper
|
||||
|
||||
That same pattern should be preferred for future capabilities.
|
||||
|
||||
### Capability example: video understanding
|
||||
|
||||
OpenClaw already treats image/audio/video understanding as one shared
|
||||
capability. The same ownership model applies there:
|
||||
|
||||
1. core defines the media-understanding contract
|
||||
2. vendor plugins register `describeImage`, `transcribeAudio`, and
|
||||
`describeVideo` as applicable
|
||||
3. channels and feature plugins consume the shared core behavior instead of
|
||||
wiring directly to vendor code
|
||||
|
||||
That avoids baking one provider's video assumptions into core. The plugin owns
|
||||
the vendor surface; core owns the capability contract and fallback behavior.
|
||||
|
||||
If OpenClaw adds a new domain later, such as video generation, use the same
|
||||
sequence again: define the core capability first, then let vendor plugins
|
||||
register implementations against it.
|
||||
|
||||
## Compatible bundles
|
||||
|
||||
OpenClaw also recognizes two compatible external bundle layouts:
|
||||
|
|
@ -124,18 +214,23 @@ plugins:
|
|||
OpenClaw skill loader
|
||||
- supported now: Claude bundle `settings.json` defaults for embedded Pi agent
|
||||
settings (with shell override keys sanitized)
|
||||
- supported now: bundle MCP config, merged into embedded Pi agent settings as
|
||||
`mcpServers`, with supported stdio bundle MCP tools exposed during embedded
|
||||
Pi agent turns
|
||||
- supported now: Cursor `.cursor/commands/*.md` roots, mapped into the normal
|
||||
OpenClaw skill loader
|
||||
- supported now: Codex bundle hook directories that use the OpenClaw hook-pack
|
||||
layout (`HOOK.md` + `handler.ts`/`handler.js`)
|
||||
- detected but not wired yet: other declared bundle capabilities such as
|
||||
agents, Claude hook automation, Cursor rules/hooks/MCP metadata, MCP/app/LSP
|
||||
agents, Claude hook automation, Cursor rules/hooks metadata, app/LSP
|
||||
metadata, output styles
|
||||
|
||||
That means bundle install/discovery/list/info/enablement all work, and bundle
|
||||
skills, Claude command-skills, Claude bundle settings defaults, and compatible
|
||||
Codex hook directories load when the bundle is enabled, but bundle runtime code
|
||||
is not executed in-process.
|
||||
Codex hook directories load when the bundle is enabled. Supported bundle MCP
|
||||
servers may also run as subprocesses for embedded Pi tool calls when they use
|
||||
supported stdio transport, but bundle runtime modules are not loaded
|
||||
in-process.
|
||||
|
||||
Bundle hook support is limited to the normal OpenClaw hook directory format
|
||||
(`HOOK.md` plus `handler.ts`/`handler.js` under the declared hook roots).
|
||||
|
|
@ -193,6 +288,8 @@ Important trust note:
|
|||
- Model Studio provider catalog — bundled as `modelstudio` (enabled by default)
|
||||
- Moonshot provider runtime — bundled as `moonshot` (enabled by default)
|
||||
- NVIDIA provider catalog — bundled as `nvidia` (enabled by default)
|
||||
- ElevenLabs speech provider — bundled as `elevenlabs` (enabled by default)
|
||||
- Microsoft speech provider — bundled as `microsoft` (enabled by default; legacy `edge` input maps here)
|
||||
- OpenAI provider runtime — bundled as `openai` (enabled by default; owns both `openai` and `openai-codex`)
|
||||
- OpenCode Go provider capabilities — bundled as `opencode-go` (enabled by default)
|
||||
- OpenCode Zen provider capabilities — bundled as `opencode` (enabled by default)
|
||||
|
|
@ -218,6 +315,8 @@ Native OpenClaw plugins can register:
|
|||
- Gateway HTTP routes
|
||||
- Agent tools
|
||||
- CLI commands
|
||||
- Speech providers
|
||||
- Web search providers
|
||||
- Background services
|
||||
- Context engines
|
||||
- Provider auth flows and model catalogs
|
||||
|
|
@ -229,6 +328,63 @@ Native OpenClaw plugins can register:
|
|||
Native OpenClaw plugins run **in‑process** with the Gateway, so treat them as trusted code.
|
||||
Tool authoring guide: [Plugin agent tools](/plugins/agent-tools).
|
||||
|
||||
Think of these registrations as **capability claims**. A plugin is not supposed
|
||||
to reach into random internals and "just make it work." It should register
|
||||
against explicit surfaces that OpenClaw understands, validates, and can expose
|
||||
consistently across config, onboarding, status, docs, and runtime behavior.
|
||||
|
||||
## Contracts and enforcement
|
||||
|
||||
The plugin API surface is intentionally typed and centralized in
|
||||
`OpenClawPluginApi`. That contract defines the supported registration points and
|
||||
the runtime helpers a plugin may rely on.
|
||||
|
||||
Why this matters:
|
||||
|
||||
- plugin authors get one stable internal standard
|
||||
- core can reject duplicate ownership such as two plugins registering the same
|
||||
provider id
|
||||
- startup can surface actionable diagnostics for malformed registration
|
||||
- contract tests can enforce bundled-plugin ownership and prevent silent drift
|
||||
|
||||
There are two layers of enforcement:
|
||||
|
||||
1. **runtime registration enforcement**
|
||||
The plugin registry validates registrations as plugins load. Examples:
|
||||
duplicate provider ids, duplicate speech provider ids, and malformed
|
||||
registrations produce plugin diagnostics instead of undefined behavior.
|
||||
2. **contract tests**
|
||||
Bundled plugins are captured in contract registries during test runs so
|
||||
OpenClaw can assert ownership explicitly. Today this is used for model
|
||||
providers, speech providers, web search providers, and bundled registration
|
||||
ownership.
|
||||
|
||||
The practical effect is that OpenClaw knows, up front, which plugin owns which
|
||||
surface. That lets core and channels compose seamlessly because ownership is
|
||||
declared, typed, and testable rather than implicit.
|
||||
|
||||
### What belongs in a contract
|
||||
|
||||
Good plugin contracts are:
|
||||
|
||||
- typed
|
||||
- small
|
||||
- capability-specific
|
||||
- owned by core
|
||||
- reusable by multiple plugins
|
||||
- consumable by channels/features without vendor knowledge
|
||||
|
||||
Bad plugin contracts are:
|
||||
|
||||
- vendor-specific policy hidden in core
|
||||
- one-off plugin escape hatches that bypass the registry
|
||||
- channel code reaching straight into a vendor implementation
|
||||
- ad hoc runtime objects that are not part of `OpenClawPluginApi` or
|
||||
`api.runtime`
|
||||
|
||||
When in doubt, raise the abstraction level: define the capability first, then
|
||||
let plugins plug into it.
|
||||
|
||||
## Provider runtime hooks
|
||||
|
||||
Provider plugins now have two layers:
|
||||
|
|
@ -519,25 +675,103 @@ to think of as short-lived performance caches, not persistence.
|
|||
|
||||
## Runtime helpers
|
||||
|
||||
Plugins can access selected core helpers via `api.runtime`. For telephony TTS:
|
||||
Plugins can access selected core helpers via `api.runtime`. For TTS:
|
||||
|
||||
```ts
|
||||
const clip = await api.runtime.tts.textToSpeech({
|
||||
text: "Hello from OpenClaw",
|
||||
cfg: api.config,
|
||||
});
|
||||
|
||||
const result = await api.runtime.tts.textToSpeechTelephony({
|
||||
text: "Hello from OpenClaw",
|
||||
cfg: api.config,
|
||||
});
|
||||
|
||||
const voices = await api.runtime.tts.listVoices({
|
||||
provider: "elevenlabs",
|
||||
cfg: api.config,
|
||||
});
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- Uses core `messages.tts` configuration (OpenAI or ElevenLabs).
|
||||
- `textToSpeech` returns the normal core TTS output payload for file/voice-note surfaces.
|
||||
- Uses core `messages.tts` configuration and provider selection.
|
||||
- Returns PCM audio buffer + sample rate. Plugins must resample/encode for providers.
|
||||
- Edge TTS is not supported for telephony.
|
||||
- `listVoices` is optional per provider. Use it for vendor-owned voice pickers or setup flows.
|
||||
- Voice listings can include richer metadata such as locale, gender, and personality tags for provider-aware pickers.
|
||||
- OpenAI and ElevenLabs support telephony today. Microsoft does not.
|
||||
|
||||
For STT/transcription, plugins can call:
|
||||
Plugins can also register speech providers via `api.registerSpeechProvider(...)`.
|
||||
|
||||
```ts
|
||||
const { text } = await api.runtime.stt.transcribeAudioFile({
|
||||
api.registerSpeechProvider({
|
||||
id: "acme-speech",
|
||||
label: "Acme Speech",
|
||||
isConfigured: ({ config }) => Boolean(config.messages?.tts),
|
||||
synthesize: async (req) => {
|
||||
return {
|
||||
audioBuffer: Buffer.from([]),
|
||||
outputFormat: "mp3",
|
||||
fileExtension: ".mp3",
|
||||
voiceCompatible: false,
|
||||
};
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- Keep TTS policy, fallback, and reply delivery in core.
|
||||
- Use speech providers for vendor-owned synthesis behavior.
|
||||
- Legacy Microsoft `edge` input is normalized to the `microsoft` provider id.
|
||||
- The preferred ownership model is company-oriented: one vendor plugin can own
|
||||
text, speech, image, and future media providers as OpenClaw adds those
|
||||
capability contracts.
|
||||
|
||||
For image/audio/video understanding, plugins register one typed
|
||||
media-understanding provider instead of a generic key/value bag:
|
||||
|
||||
```ts
|
||||
api.registerMediaUnderstandingProvider({
|
||||
id: "google",
|
||||
capabilities: ["image", "audio", "video"],
|
||||
describeImage: async (req) => ({ text: "..." }),
|
||||
transcribeAudio: async (req) => ({ text: "..." }),
|
||||
describeVideo: async (req) => ({ text: "..." }),
|
||||
});
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- Keep orchestration, fallback, config, and channel wiring in core.
|
||||
- Keep vendor behavior in the provider plugin.
|
||||
- Additive expansion should stay typed: new optional methods, new optional
|
||||
result fields, new optional capabilities.
|
||||
- If OpenClaw adds a new capability such as video generation later, define the
|
||||
core capability contract first, then let vendor plugins register against it.
|
||||
|
||||
For media-understanding runtime helpers, plugins can call:
|
||||
|
||||
```ts
|
||||
const image = await api.runtime.mediaUnderstanding.describeImageFile({
|
||||
filePath: "/tmp/inbound-photo.jpg",
|
||||
cfg: api.config,
|
||||
agentDir: "/tmp/agent",
|
||||
});
|
||||
|
||||
const video = await api.runtime.mediaUnderstanding.describeVideoFile({
|
||||
filePath: "/tmp/inbound-video.mp4",
|
||||
cfg: api.config,
|
||||
});
|
||||
```
|
||||
|
||||
For audio transcription, plugins can use either the media-understanding runtime
|
||||
or the older STT alias:
|
||||
|
||||
```ts
|
||||
const { text } = await api.runtime.mediaUnderstanding.transcribeAudioFile({
|
||||
filePath: "/tmp/inbound-audio.ogg",
|
||||
cfg: api.config,
|
||||
// Optional when MIME cannot be inferred reliably:
|
||||
|
|
@ -547,8 +781,37 @@ const { text } = await api.runtime.stt.transcribeAudioFile({
|
|||
|
||||
Notes:
|
||||
|
||||
- `api.runtime.mediaUnderstanding.*` is the preferred shared surface for
|
||||
image/audio/video understanding.
|
||||
- Uses core media-understanding audio configuration (`tools.media.audio`) and provider fallback order.
|
||||
- Returns `{ text: undefined }` when no transcription output is produced (for example skipped/unsupported input).
|
||||
- `api.runtime.stt.transcribeAudioFile(...)` remains as a compatibility alias.
|
||||
|
||||
For web search, plugins can consume the shared runtime helper instead of
|
||||
reaching into the agent tool wiring:
|
||||
|
||||
```ts
|
||||
const providers = api.runtime.webSearch.listProviders({
|
||||
config: api.config,
|
||||
});
|
||||
|
||||
const result = await api.runtime.webSearch.search({
|
||||
config: api.config,
|
||||
args: {
|
||||
query: "OpenClaw plugin runtime helpers",
|
||||
count: 5,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
Plugins can also register web-search providers via
|
||||
`api.registerWebSearchProvider(...)`.
|
||||
|
||||
Notes:
|
||||
|
||||
- Keep provider selection, credential resolution, and shared request semantics in core.
|
||||
- Use web-search providers for vendor-specific search transports.
|
||||
- `api.runtime.webSearch.*` is the preferred shared surface for feature/channel plugins that need search behavior without depending on the agent tool wrapper.
|
||||
|
||||
## Gateway HTTP routes
|
||||
|
||||
|
|
@ -1110,12 +1373,109 @@ Plugins export either:
|
|||
- `on(...)` for typed lifecycle hooks
|
||||
- `registerChannel`
|
||||
- `registerProvider`
|
||||
- `registerSpeechProvider`
|
||||
- `registerMediaUnderstandingProvider`
|
||||
- `registerWebSearchProvider`
|
||||
- `registerHttpRoute`
|
||||
- `registerCommand`
|
||||
- `registerCli`
|
||||
- `registerContextEngine`
|
||||
- `registerService`
|
||||
|
||||
In practice, `register(api)` is also where a plugin declares **ownership**.
|
||||
That ownership should map cleanly to either:
|
||||
|
||||
- a vendor surface such as OpenAI, ElevenLabs, or Microsoft
|
||||
- a feature surface such as Voice Call
|
||||
|
||||
Avoid splitting one vendor's capabilities across unrelated plugins unless there
|
||||
is a strong product reason to do so. The default should be one plugin per
|
||||
vendor/feature, with core capability contracts separating shared orchestration
|
||||
from vendor-specific behavior.
|
||||
|
||||
## Adding a new capability
|
||||
|
||||
When a plugin needs behavior that does not fit the current API, do not bypass
|
||||
the plugin system with a private reach-in. Add the missing capability.
|
||||
|
||||
Recommended sequence:
|
||||
|
||||
1. define the core contract
|
||||
Decide what shared behavior core should own: policy, fallback, config merge,
|
||||
lifecycle, channel-facing semantics, and runtime helper shape.
|
||||
2. add typed plugin registration/runtime surfaces
|
||||
Extend `OpenClawPluginApi` and/or `api.runtime` with the smallest useful
|
||||
typed seam.
|
||||
3. wire core + channel/feature consumers
|
||||
Channels and feature plugins should consume the new capability through core,
|
||||
not by importing a vendor implementation directly.
|
||||
4. register vendor implementations
|
||||
Vendor plugins then register their backends against the capability.
|
||||
5. add contract coverage
|
||||
Add tests so ownership and registration shape stay explicit over time.
|
||||
|
||||
This is how OpenClaw stays opinionated without becoming hardcoded to one
|
||||
provider's worldview.
|
||||
|
||||
### Capability checklist
|
||||
|
||||
When you add a new capability, the implementation should usually touch these
|
||||
surfaces together:
|
||||
|
||||
- core contract types in `src/<capability>/types.ts`
|
||||
- core runner/runtime helper in `src/<capability>/runtime.ts`
|
||||
- plugin API registration surface in `src/plugins/types.ts`
|
||||
- plugin registry wiring in `src/plugins/registry.ts`
|
||||
- plugin runtime exposure in `src/plugins/runtime/*` when feature/channel
|
||||
plugins need to consume it
|
||||
- capture/test helpers in `src/test-utils/plugin-registration.ts`
|
||||
- ownership/contract assertions in `src/plugins/contracts/registry.ts`
|
||||
- operator/plugin docs in `docs/`
|
||||
|
||||
If one of those surfaces is missing, that is usually a sign the capability is
|
||||
not fully integrated yet.
|
||||
|
||||
### Capability template
|
||||
|
||||
Minimal pattern:
|
||||
|
||||
```ts
|
||||
// core contract
|
||||
export type VideoGenerationProviderPlugin = {
|
||||
id: string;
|
||||
label: string;
|
||||
generateVideo: (req: VideoGenerationRequest) => Promise<VideoGenerationResult>;
|
||||
};
|
||||
|
||||
// plugin API
|
||||
api.registerVideoGenerationProvider({
|
||||
id: "openai",
|
||||
label: "OpenAI",
|
||||
async generateVideo(req) {
|
||||
return await generateOpenAiVideo(req);
|
||||
},
|
||||
});
|
||||
|
||||
// shared runtime helper for feature/channel plugins
|
||||
const clip = await api.runtime.videoGeneration.generateFile({
|
||||
prompt: "Show the robot walking through the lab.",
|
||||
cfg,
|
||||
});
|
||||
```
|
||||
|
||||
Contract test pattern:
|
||||
|
||||
```ts
|
||||
expect(findVideoGenerationProviderIdsForPlugin("openai")).toEqual(["openai"]);
|
||||
```
|
||||
|
||||
That keeps the rule simple:
|
||||
|
||||
- core owns the capability contract + orchestration
|
||||
- vendor plugins own vendor implementations
|
||||
- feature/channel plugins consume runtime helpers
|
||||
- contract tests keep ownership explicit
|
||||
|
||||
Context engine plugins can also register a runtime-owned context manager:
|
||||
|
||||
```ts
|
||||
|
|
|
|||
75
docs/tts.md
75
docs/tts.md
|
|
@ -9,26 +9,27 @@ title: "Text-to-Speech"
|
|||
|
||||
# Text-to-speech (TTS)
|
||||
|
||||
OpenClaw can convert outbound replies into audio using ElevenLabs, OpenAI, or Edge TTS.
|
||||
OpenClaw can convert outbound replies into audio using ElevenLabs, Microsoft, or OpenAI.
|
||||
It works anywhere OpenClaw can send audio; Telegram gets a round voice-note bubble.
|
||||
|
||||
## Supported services
|
||||
|
||||
- **ElevenLabs** (primary or fallback provider)
|
||||
- **Microsoft** (primary or fallback provider; current bundled implementation uses `node-edge-tts`, default when no API keys)
|
||||
- **OpenAI** (primary or fallback provider; also used for summaries)
|
||||
- **Edge TTS** (primary or fallback provider; uses `node-edge-tts`, default when no API keys)
|
||||
|
||||
### Edge TTS notes
|
||||
### Microsoft speech notes
|
||||
|
||||
Edge TTS uses Microsoft Edge's online neural TTS service via the `node-edge-tts`
|
||||
library. It's a hosted service (not local), uses Microsoft’s endpoints, and does
|
||||
not require an API key. `node-edge-tts` exposes speech configuration options and
|
||||
output formats, but not all options are supported by the Edge service. citeturn2search0
|
||||
The bundled Microsoft speech provider currently uses Microsoft Edge's online
|
||||
neural TTS service via the `node-edge-tts` library. It's a hosted service (not
|
||||
local), uses Microsoft endpoints, and does not require an API key.
|
||||
`node-edge-tts` exposes speech configuration options and output formats, but
|
||||
not all options are supported by the service. Legacy config and directive input
|
||||
using `edge` still works and is normalized to `microsoft`.
|
||||
|
||||
Because Edge TTS is a public web service without a published SLA or quota, treat it
|
||||
as best-effort. If you need guaranteed limits and support, use OpenAI or ElevenLabs.
|
||||
Microsoft's Speech REST API documents a 10‑minute audio limit per request; Edge TTS
|
||||
does not publish limits, so assume similar or lower limits. citeturn0search3
|
||||
Because this path is a public web service without a published SLA or quota,
|
||||
treat it as best-effort. If you need guaranteed limits and support, use OpenAI
|
||||
or ElevenLabs.
|
||||
|
||||
## Optional keys
|
||||
|
||||
|
|
@ -37,8 +38,9 @@ If you want OpenAI or ElevenLabs:
|
|||
- `ELEVENLABS_API_KEY` (or `XI_API_KEY`)
|
||||
- `OPENAI_API_KEY`
|
||||
|
||||
Edge TTS does **not** require an API key. If no API keys are found, OpenClaw defaults
|
||||
to Edge TTS (unless disabled via `messages.tts.edge.enabled=false`).
|
||||
Microsoft speech does **not** require an API key. If no API keys are found,
|
||||
OpenClaw defaults to Microsoft (unless disabled via
|
||||
`messages.tts.microsoft.enabled=false` or `messages.tts.edge.enabled=false`).
|
||||
|
||||
If multiple providers are configured, the selected provider is used first and the others are fallback options.
|
||||
Auto-summary uses the configured `summaryModel` (or `agents.defaults.model.primary`),
|
||||
|
|
@ -58,7 +60,7 @@ so that provider must also be authenticated if you enable summaries.
|
|||
No. Auto‑TTS is **off** by default. Enable it in config with
|
||||
`messages.tts.auto` or per session with `/tts always` (alias: `/tts on`).
|
||||
|
||||
Edge TTS **is** enabled by default once TTS is on, and is used automatically
|
||||
Microsoft speech **is** enabled by default once TTS is on, and is used automatically
|
||||
when no OpenAI or ElevenLabs API keys are available.
|
||||
|
||||
## Config
|
||||
|
|
@ -118,15 +120,15 @@ Full schema is in [Gateway configuration](/gateway/configuration).
|
|||
}
|
||||
```
|
||||
|
||||
### Edge TTS primary (no API key)
|
||||
### Microsoft primary (no API key)
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
tts: {
|
||||
auto: "always",
|
||||
provider: "edge",
|
||||
edge: {
|
||||
provider: "microsoft",
|
||||
microsoft: {
|
||||
enabled: true,
|
||||
voice: "en-US-MichelleNeural",
|
||||
lang: "en-US",
|
||||
|
|
@ -139,13 +141,13 @@ Full schema is in [Gateway configuration](/gateway/configuration).
|
|||
}
|
||||
```
|
||||
|
||||
### Disable Edge TTS
|
||||
### Disable Microsoft speech
|
||||
|
||||
```json5
|
||||
{
|
||||
messages: {
|
||||
tts: {
|
||||
edge: {
|
||||
microsoft: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
|
|
@ -205,9 +207,10 @@ Then run:
|
|||
- `tagged` only sends audio when the reply includes `[[tts]]` tags.
|
||||
- `enabled`: legacy toggle (doctor migrates this to `auto`).
|
||||
- `mode`: `"final"` (default) or `"all"` (includes tool/block replies).
|
||||
- `provider`: `"elevenlabs"`, `"openai"`, or `"edge"` (fallback is automatic).
|
||||
- `provider`: speech provider id such as `"elevenlabs"`, `"microsoft"`, or `"openai"` (fallback is automatic).
|
||||
- If `provider` is **unset**, OpenClaw prefers `openai` (if key), then `elevenlabs` (if key),
|
||||
otherwise `edge`.
|
||||
otherwise `microsoft`.
|
||||
- Legacy `provider: "edge"` still works and is normalized to `microsoft`.
|
||||
- `summaryModel`: optional cheap model for auto-summary; defaults to `agents.defaults.model.primary`.
|
||||
- Accepts `provider/model` or a configured model alias.
|
||||
- `modelOverrides`: allow the model to emit TTS directives (on by default).
|
||||
|
|
@ -227,15 +230,16 @@ Then run:
|
|||
- `elevenlabs.applyTextNormalization`: `auto|on|off`
|
||||
- `elevenlabs.languageCode`: 2-letter ISO 639-1 (e.g. `en`, `de`)
|
||||
- `elevenlabs.seed`: integer `0..4294967295` (best-effort determinism)
|
||||
- `edge.enabled`: allow Edge TTS usage (default `true`; no API key).
|
||||
- `edge.voice`: Edge neural voice name (e.g. `en-US-MichelleNeural`).
|
||||
- `edge.lang`: language code (e.g. `en-US`).
|
||||
- `edge.outputFormat`: Edge output format (e.g. `audio-24khz-48kbitrate-mono-mp3`).
|
||||
- See Microsoft Speech output formats for valid values; not all formats are supported by Edge.
|
||||
- `edge.rate` / `edge.pitch` / `edge.volume`: percent strings (e.g. `+10%`, `-5%`).
|
||||
- `edge.saveSubtitles`: write JSON subtitles alongside the audio file.
|
||||
- `edge.proxy`: proxy URL for Edge TTS requests.
|
||||
- `edge.timeoutMs`: request timeout override (ms).
|
||||
- `microsoft.enabled`: allow Microsoft speech usage (default `true`; no API key).
|
||||
- `microsoft.voice`: Microsoft neural voice name (e.g. `en-US-MichelleNeural`).
|
||||
- `microsoft.lang`: language code (e.g. `en-US`).
|
||||
- `microsoft.outputFormat`: Microsoft output format (e.g. `audio-24khz-48kbitrate-mono-mp3`).
|
||||
- See Microsoft Speech output formats for valid values; not all formats are supported by the bundled Edge-backed transport.
|
||||
- `microsoft.rate` / `microsoft.pitch` / `microsoft.volume`: percent strings (e.g. `+10%`, `-5%`).
|
||||
- `microsoft.saveSubtitles`: write JSON subtitles alongside the audio file.
|
||||
- `microsoft.proxy`: proxy URL for Microsoft speech requests.
|
||||
- `microsoft.timeoutMs`: request timeout override (ms).
|
||||
- `edge.*`: legacy alias for the same Microsoft settings.
|
||||
|
||||
## Model-driven overrides (default on)
|
||||
|
||||
|
|
@ -260,7 +264,7 @@ Here you go.
|
|||
|
||||
Available directive keys (when enabled):
|
||||
|
||||
- `provider` (`openai` | `elevenlabs` | `edge`, requires `allowProvider: true`)
|
||||
- `provider` (registered speech provider id, for example `openai`, `elevenlabs`, or `microsoft`; requires `allowProvider: true`)
|
||||
- `voice` (OpenAI voice) or `voiceId` (ElevenLabs)
|
||||
- `model` (OpenAI TTS model or ElevenLabs model id)
|
||||
- `stability`, `similarityBoost`, `style`, `speed`, `useSpeakerBoost`
|
||||
|
|
@ -319,13 +323,12 @@ These override `messages.tts.*` for that host.
|
|||
- 48kHz / 64kbps is a good voice-note tradeoff and required for the round bubble.
|
||||
- **Other channels**: MP3 (`mp3_44100_128` from ElevenLabs, `mp3` from OpenAI).
|
||||
- 44.1kHz / 128kbps is the default balance for speech clarity.
|
||||
- **Edge TTS**: uses `edge.outputFormat` (default `audio-24khz-48kbitrate-mono-mp3`).
|
||||
- `node-edge-tts` accepts an `outputFormat`, but not all formats are available
|
||||
from the Edge service. citeturn2search0
|
||||
- Output format values follow Microsoft Speech output formats (including Ogg/WebM Opus). citeturn1search0
|
||||
- **Microsoft**: uses `microsoft.outputFormat` (default `audio-24khz-48kbitrate-mono-mp3`).
|
||||
- The bundled transport accepts an `outputFormat`, but not all formats are available from the service.
|
||||
- Output format values follow Microsoft Speech output formats (including Ogg/WebM Opus).
|
||||
- Telegram `sendVoice` accepts OGG/MP3/M4A; use OpenAI/ElevenLabs if you need
|
||||
guaranteed Opus voice notes. citeturn1search1
|
||||
- If the configured Edge output format fails, OpenClaw retries with MP3.
|
||||
- If the configured Microsoft output format fails, OpenClaw retries with MP3.
|
||||
|
||||
OpenAI/ElevenLabs formats are fixed; Telegram expects Opus for voice-note UX.
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ Auth is supplied during the WebSocket handshake via:
|
|||
- `connect.params.auth.token`
|
||||
- `connect.params.auth.password`
|
||||
The dashboard settings panel keeps a token for the current browser tab session and selected gateway URL; passwords are not persisted.
|
||||
The setup wizard generates a gateway token by default, so paste it here on first connect.
|
||||
Onboarding generates a gateway token by default, so paste it here on first connect.
|
||||
|
||||
## Device pairing (first connection)
|
||||
|
||||
|
|
|
|||
|
|
@ -324,22 +324,22 @@ openclaw [--dev] [--profile <name>] <command>
|
|||
选项:
|
||||
|
||||
- `--workspace <dir>`:智能体工作区路径(默认 `~/.openclaw/workspace`)。
|
||||
- `--wizard`:运行设置向导。
|
||||
- `--non-interactive`:无提示运行向导。
|
||||
- `--mode <local|remote>`:向导模式。
|
||||
- `--wizard`:运行新手引导。
|
||||
- `--non-interactive`:无提示运行新手引导。
|
||||
- `--mode <local|remote>`:新手引导模式。
|
||||
- `--remote-url <url>`:远程 Gateway 网关 URL。
|
||||
- `--remote-token <token>`:远程 Gateway 网关 token。
|
||||
|
||||
只要存在任意向导标志(`--non-interactive`, `--mode`, `--remote-url`, `--remote-token`),就会自动运行向导。
|
||||
只要存在任意新手引导标志(`--non-interactive`, `--mode`, `--remote-url`, `--remote-token`),就会自动运行新手引导。
|
||||
|
||||
### `onboard`
|
||||
|
||||
用于设置 gateway、工作区和 Skills 的交互式向导。
|
||||
用于设置 gateway、工作区和 Skills 的交互式新手引导。
|
||||
|
||||
选项:
|
||||
|
||||
- `--workspace <dir>`
|
||||
- `--reset`(在运行向导前重置配置 + 凭据 + 会话)
|
||||
- `--reset`(在运行新手引导前重置配置 + 凭据 + 会话)
|
||||
- `--reset-scope <config|config+creds+sessions|full>`(默认 `config+creds+sessions`;使用 `full` 还会删除工作区)
|
||||
- `--non-interactive`
|
||||
- `--mode <local|remote>`
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
read_when:
|
||||
- 你想通过引导式设置来配置 Gateway 网关、工作区、身份验证、渠道和 Skills
|
||||
summary: "`openclaw onboard` 的 CLI 参考(交互式设置向导)"
|
||||
summary: "`openclaw onboard` 的 CLI 参考(交互式新手引导)"
|
||||
title: onboard
|
||||
x-i18n:
|
||||
generated_at: "2026-03-16T06:21:32Z"
|
||||
|
|
@ -14,11 +14,11 @@ x-i18n:
|
|||
|
||||
# `openclaw onboard`
|
||||
|
||||
交互式设置向导(本地或远程 Gateway 网关设置)。
|
||||
交互式新手引导(本地或远程 Gateway 网关设置)。
|
||||
|
||||
## 相关指南
|
||||
|
||||
- CLI 新手引导中心:[设置向导(CLI)](/start/wizard)
|
||||
- CLI 新手引导中心:[CLI 新手引导](/start/wizard)
|
||||
- 新手引导概览:[新手引导概览](/start/onboarding-overview)
|
||||
- CLI 新手引导参考:[CLI 设置参考](/start/wizard-cli-reference)
|
||||
- CLI 自动化:[CLI 自动化](/start/wizard-cli-automation)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
read_when:
|
||||
- 你正在进行首次运行设置,但不使用完整的设置向导
|
||||
- 你正在进行首次运行设置,但不使用完整的 CLI 新手引导
|
||||
- 你想设置默认工作区路径
|
||||
summary: "`openclaw setup` 的 CLI 参考(初始化配置 + 工作区)"
|
||||
title: setup
|
||||
|
|
@ -20,7 +20,7 @@ x-i18n:
|
|||
相关内容:
|
||||
|
||||
- 入门指南:[入门指南](/start/getting-started)
|
||||
- 向导:[新手引导](/start/onboarding)
|
||||
- CLI 新手引导:[CLI 新手引导](/start/wizard)
|
||||
|
||||
## 示例
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ openclaw setup
|
|||
openclaw setup --workspace ~/.openclaw/workspace
|
||||
```
|
||||
|
||||
通过 setup 运行向导:
|
||||
通过 setup 运行新手引导:
|
||||
|
||||
```bash
|
||||
openclaw setup --wizard
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ x-i18n:
|
|||
- [如何在 VPS 上安装 OpenClaw?](#how-do-i-install-openclaw-on-a-vps)
|
||||
- [云/VPS 安装指南在哪里?](#where-are-the-cloudvps-install-guides)
|
||||
- [可以让 OpenClaw 自行更新吗?](#can-i-ask-openclaw-to-update-itself)
|
||||
- [新手引导向导具体做了什么?](#what-does-the-onboarding-wizard-actually-do)
|
||||
- [新手引导具体做了什么?](#新手引导具体做了什么)
|
||||
- [运行 OpenClaw 需要 Claude 或 OpenAI 订阅吗?](#do-i-need-a-claude-or-openai-subscription-to-run-this)
|
||||
- [能否使用 Claude Max 订阅而不需要 API 密钥?](#can-i-use-claude-max-subscription-without-an-api-key)
|
||||
- [Anthropic "setup-token" 认证如何工作?](#how-does-anthropic-setuptoken-auth-work)
|
||||
|
|
@ -310,14 +310,14 @@ openclaw doctor
|
|||
|
||||
### 安装和设置 OpenClaw 的推荐方式是什么
|
||||
|
||||
仓库推荐从源码运行并使用新手引导向导:
|
||||
仓库推荐从源码运行并使用新手引导:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://openclaw.ai/install.sh | bash
|
||||
openclaw onboard --install-daemon
|
||||
```
|
||||
|
||||
向导还可以自动构建 UI 资源。新手引导后,通常在端口 **18789** 上运行 Gateway 网关。
|
||||
新手引导还可以自动构建 UI 资源。新手引导后,通常在端口 **18789** 上运行 Gateway 网关。
|
||||
|
||||
从源码安装(贡献者/开发者):
|
||||
|
||||
|
|
@ -334,7 +334,7 @@ openclaw onboard
|
|||
|
||||
### 新手引导后如何打开仪表板
|
||||
|
||||
向导现在会在新手引导完成后立即使用带令牌的仪表板 URL 打开浏览器,并在摘要中打印完整链接(带令牌)。保持该标签页打开;如果没有自动启动,请在同一台机器上复制/粘贴打印的 URL。令牌保持在本地主机上——不会从浏览器获取任何内容。
|
||||
新手引导现在会在完成后立即使用带令牌的仪表板 URL 打开浏览器,并在摘要中打印完整链接(带令牌)。保持该标签页打开;如果没有自动启动,请在同一台机器上复制/粘贴打印的 URL。令牌保持在本地主机上,不会从浏览器获取任何内容。
|
||||
|
||||
### 如何在本地和远程环境中验证仪表板令牌
|
||||
|
||||
|
|
@ -562,7 +562,7 @@ curl -fsSL https://openclaw.ai/install.sh | bash -s -- --install-method git
|
|||
|
||||
### 如何在 Linux 上安装 OpenClaw
|
||||
|
||||
简短回答:按照 Linux 指南操作,然后运行新手引导向导。
|
||||
简短回答:按照 Linux 指南操作,然后运行新手引导。
|
||||
|
||||
- Linux 快速路径 + 服务安装:[Linux](/platforms/linux)。
|
||||
- 完整指南:[入门](/start/getting-started)。
|
||||
|
|
@ -614,7 +614,7 @@ openclaw gateway restart
|
|||
|
||||
文档:[更新](/cli/update)、[更新指南](/install/updating)。
|
||||
|
||||
### 新手引导向导具体做了什么
|
||||
### 新手引导具体做了什么
|
||||
|
||||
`openclaw onboard` 是推荐的设置路径。在**本地模式**下,它引导你完成:
|
||||
|
||||
|
|
@ -642,7 +642,7 @@ Claude Pro/Max 订阅**不包含 API 密钥**,因此这是订阅账户的正
|
|||
|
||||
### Anthropic setup-token 认证如何工作
|
||||
|
||||
`claude setup-token` 通过 Claude Code CLI 生成一个**令牌字符串**(在 Web 控制台中不可用)。你可以在**任何机器**上运行它。在向导中选择 **Anthropic token (paste setup-token)** 或使用 `openclaw models auth paste-token --provider anthropic` 粘贴。令牌作为 **anthropic** 提供商的认证配置文件存储,像 API 密钥一样使用(无自动刷新)。更多详情:[OAuth](/concepts/oauth)。
|
||||
`claude setup-token` 通过 Claude Code CLI 生成一个**令牌字符串**(在 Web 控制台中不可用)。你可以在**任何机器**上运行它。在新手引导中选择 **Anthropic token (paste setup-token)** 或使用 `openclaw models auth paste-token --provider anthropic` 粘贴。令牌作为 **anthropic** 提供商的认证配置文件存储,像 API 密钥一样使用(无自动刷新)。更多详情:[OAuth](/concepts/oauth)。
|
||||
|
||||
### 在哪里获取 Anthropic setup-token
|
||||
|
||||
|
|
@ -652,7 +652,7 @@ Claude Pro/Max 订阅**不包含 API 密钥**,因此这是订阅账户的正
|
|||
claude setup-token
|
||||
```
|
||||
|
||||
复制它打印的令牌,然后在向导中选择 **Anthropic token (paste setup-token)**。如果你想在 Gateway 网关主机上运行,使用 `openclaw models auth setup-token --provider anthropic`。如果你在其他地方运行了 `claude setup-token`,在 Gateway 网关主机上使用 `openclaw models auth paste-token --provider anthropic` 粘贴。参阅 [Anthropic](/providers/anthropic)。
|
||||
复制它打印的令牌,然后在新手引导中选择 **Anthropic token (paste setup-token)**。如果你想在 Gateway 网关主机上运行,使用 `openclaw models auth setup-token --provider anthropic`。如果你在其他地方运行了 `claude setup-token`,在 Gateway 网关主机上使用 `openclaw models auth paste-token --provider anthropic` 粘贴。参阅 [Anthropic](/providers/anthropic)。
|
||||
|
||||
### 是否支持 Claude 订阅认证(Claude Pro/Max)
|
||||
|
||||
|
|
@ -673,13 +673,13 @@ claude setup-token
|
|||
|
||||
### Codex 认证如何工作
|
||||
|
||||
OpenClaw 通过 OAuth(ChatGPT 登录)支持 **OpenAI Code (Codex)**。向导可以运行 OAuth 流程,并在适当时将默认模型设置为 `openai-codex/gpt-5.2`。参阅[模型提供商](/concepts/model-providers)和[向导](/start/wizard)。
|
||||
OpenClaw 通过 OAuth(ChatGPT 登录)支持 **OpenAI Code (Codex)**。新手引导可以运行 OAuth 流程,并在适当时将默认模型设置为 `openai-codex/gpt-5.2`。参阅[模型提供商](/concepts/model-providers)和[CLI 新手引导](/start/wizard)。
|
||||
|
||||
### 是否支持 OpenAI 订阅认证(Codex OAuth)
|
||||
|
||||
是的。OpenClaw 完全支持 **OpenAI Code (Codex) 订阅 OAuth**。新手引导向导可以为你运行 OAuth 流程。
|
||||
是的。OpenClaw 完全支持 **OpenAI Code (Codex) 订阅 OAuth**。新手引导可以为你运行 OAuth 流程。
|
||||
|
||||
参阅 [OAuth](/concepts/oauth)、[模型提供商](/concepts/model-providers)和[向导](/start/wizard)。
|
||||
参阅 [OAuth](/concepts/oauth)、[模型提供商](/concepts/model-providers)和[CLI 新手引导](/start/wizard)。
|
||||
|
||||
### 如何设置 Gemini CLI OAuth
|
||||
|
||||
|
|
@ -1632,7 +1632,7 @@ openclaw onboard --install-daemon
|
|||
|
||||
注意:
|
||||
|
||||
- 新手引导向导在看到现有配置时也提供**重置**选项。参阅[向导](/start/wizard)。
|
||||
- 新手引导在看到现有配置时也提供**重置**选项。参阅[CLI 新手引导](/start/wizard)。
|
||||
- 如果你使用了配置文件(`--profile` / `OPENCLAW_PROFILE`),重置每个状态目录(默认为 `~/.openclaw-<profile>`)。
|
||||
- 开发重置:`openclaw gateway --dev --reset`(仅限开发;清除开发配置 + 凭据 + 会话 + 工作区)。
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ x-i18n:
|
|||
<Card title="入门指南" href="/start/getting-started" icon="rocket">
|
||||
安装 OpenClaw 并在几分钟内启动 Gateway 网关。
|
||||
</Card>
|
||||
<Card title="运行向导" href="/start/wizard" icon="sparkles">
|
||||
<Card title="运行新手引导" href="/start/wizard" icon="sparkles">
|
||||
通过 `openclaw onboard` 和配对流程进行引导式设置。
|
||||
</Card>
|
||||
<Card title="打开控制界面" href="/web/control-ui" icon="layout-dashboard">
|
||||
|
|
|
|||
|
|
@ -60,13 +60,13 @@ x-i18n:
|
|||
</Note>
|
||||
|
||||
</Step>
|
||||
<Step title="运行设置向导">
|
||||
<Step title="运行新手引导">
|
||||
```bash
|
||||
openclaw onboard --install-daemon
|
||||
```
|
||||
|
||||
向导会配置认证、Gateway 网关设置和可选渠道。
|
||||
详情请参见 [Setup Wizard](/start/wizard)。
|
||||
新手引导会配置认证、Gateway 网关设置和可选渠道。
|
||||
详情请参见 [CLI 新手引导](/start/wizard)。
|
||||
|
||||
</Step>
|
||||
<Step title="检查 Gateway 网关">
|
||||
|
|
@ -122,8 +122,8 @@ x-i18n:
|
|||
## 深入了解
|
||||
|
||||
<Columns>
|
||||
<Card title="设置向导(详情)" href="/start/wizard">
|
||||
完整的 CLI 向导参考和高级选项。
|
||||
<Card title="CLI 新手引导" href="/start/wizard">
|
||||
完整的 CLI 新手引导参考和高级选项。
|
||||
</Card>
|
||||
<Card title="macOS 应用新手引导" href="/start/onboarding">
|
||||
macOS 应用的首次运行流程。
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ x-i18n:
|
|||
- [入门指南](/start/getting-started)
|
||||
- [快速开始](/start/quickstart)
|
||||
- [新手引导](/start/onboarding)
|
||||
- [向导](/start/wizard)
|
||||
- [CLI 新手引导](/start/wizard)
|
||||
- [安装配置](/start/setup)
|
||||
- [仪表盘(本地 Gateway 网关)](http://127.0.0.1:18789/)
|
||||
- [帮助](/help)
|
||||
|
|
|
|||
|
|
@ -21,21 +21,21 @@ OpenClaw 支持多种新手引导路径,具体取决于 Gateway 网关运行
|
|||
|
||||
## 选择你的新手引导路径
|
||||
|
||||
- 适用于 macOS、Linux 和 Windows(通过 WSL2)的 **CLI 向导**。
|
||||
- 适用于 macOS、Linux 和 Windows(通过 WSL2)的 **CLI 新手引导**。
|
||||
- 适用于 Apple silicon 或 Intel Mac 的 **macOS 应用**,提供引导式首次运行体验。
|
||||
|
||||
## CLI 设置向导
|
||||
## CLI 新手引导
|
||||
|
||||
在终端中运行向导:
|
||||
在终端中运行新手引导:
|
||||
|
||||
```bash
|
||||
openclaw onboard
|
||||
```
|
||||
|
||||
当你希望完全控制 Gateway 网关、工作区、
|
||||
渠道和 Skills 时,请使用 CLI 向导。文档:
|
||||
渠道和 Skills 时,请使用 CLI 新手引导。文档:
|
||||
|
||||
- [设置向导(CLI)](/start/wizard)
|
||||
- [CLI 新手引导](/start/wizard)
|
||||
- [`openclaw onboard` 命令](/cli/onboard)
|
||||
|
||||
## macOS 应用新手引导
|
||||
|
|
@ -48,7 +48,7 @@ openclaw onboard
|
|||
|
||||
如果你需要一个未列出的端点,包括那些
|
||||
公开标准 OpenAI 或 Anthropic API 的托管提供商,请在
|
||||
CLI 向导中选择 **Custom Provider**。系统会要求你:
|
||||
在 CLI 新手引导中选择 **Custom Provider**。系统会要求你:
|
||||
|
||||
- 选择兼容 OpenAI、兼容 Anthropic,或 **Unknown**(自动检测)。
|
||||
- 输入基础 URL 和 API 密钥(如果提供商需要)。
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
---
|
||||
read_when:
|
||||
- 运行或配置设置向导
|
||||
- 运行或配置 CLI 新手引导
|
||||
- 设置一台新机器
|
||||
sidebarTitle: "Onboarding: CLI"
|
||||
summary: CLI 设置向导:用于 Gateway 网关、工作区、渠道和 Skills 的引导式设置
|
||||
title: 设置向导(CLI)
|
||||
summary: CLI 新手引导:用于 Gateway 网关、工作区、渠道和 Skills 的引导式设置
|
||||
title: CLI 新手引导
|
||||
x-i18n:
|
||||
generated_at: "2026-03-16T06:28:38Z"
|
||||
model: gpt-5.4
|
||||
|
|
@ -14,9 +14,9 @@ x-i18n:
|
|||
workflow: 15
|
||||
---
|
||||
|
||||
# 设置向导(CLI)
|
||||
# CLI 新手引导
|
||||
|
||||
设置向导是在 macOS、
|
||||
CLI 新手引导是在 macOS、
|
||||
Linux 或 Windows(通过 WSL2;强烈推荐)上设置 OpenClaw 的**推荐**方式。
|
||||
它可在一次引导式流程中配置本地 Gateway 网关或远程 Gateway 网关连接,以及渠道、Skills
|
||||
和工作区默认值。
|
||||
|
|
@ -42,7 +42,7 @@ openclaw agents add <name>
|
|||
</Note>
|
||||
|
||||
<Tip>
|
||||
设置向导包含一个 web search 步骤,你可以选择一个提供商
|
||||
CLI 新手引导包含一个 web search 步骤,你可以选择一个提供商
|
||||
(Perplexity、Brave、Gemini、Grok 或 Kimi),并粘贴你的 API 密钥,以便智能体
|
||||
可以使用 `web_search`。你也可以稍后通过
|
||||
`openclaw configure --section web` 进行配置。文档:[Web 工具](/tools/web)。
|
||||
|
|
@ -50,7 +50,7 @@ openclaw agents add <name>
|
|||
|
||||
## 快速开始与高级模式
|
||||
|
||||
向导开始时会让你选择**快速开始**(默认值)或**高级模式**(完全控制)。
|
||||
新手引导开始时会让你选择**快速开始**(默认值)或**高级模式**(完全控制)。
|
||||
|
||||
<Tabs>
|
||||
<Tab title="快速开始(默认值)">
|
||||
|
|
@ -68,7 +68,7 @@ openclaw agents add <name>
|
|||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## 向导会配置什么
|
||||
## 新手引导会配置什么
|
||||
|
||||
**本地模式(默认)**会引导你完成以下步骤:
|
||||
|
||||
|
|
@ -91,9 +91,9 @@ openclaw agents add <name>
|
|||
7. **Skills** —— 安装推荐的 Skills 和可选依赖项。
|
||||
|
||||
<Note>
|
||||
重新运行向导**不会**清除任何内容,除非你显式选择 **Reset**(或传入 `--reset`)。
|
||||
重新运行新手引导**不会**清除任何内容,除非你显式选择 **Reset**(或传入 `--reset`)。
|
||||
CLI `--reset` 默认会重置配置、凭证和会话;如需包含工作区,请使用 `--reset-scope full`。
|
||||
如果配置无效或包含旧版键,向导会先要求你运行 `openclaw doctor`。
|
||||
如果配置无效或包含旧版键,新手引导会先要求你运行 `openclaw doctor`。
|
||||
</Note>
|
||||
|
||||
**远程模式**只会配置本地客户端以连接到其他地方的 Gateway 网关。
|
||||
|
|
@ -102,7 +102,7 @@ CLI `--reset` 默认会重置配置、凭证和会话;如需包含工作区,
|
|||
## 添加另一个智能体
|
||||
|
||||
使用 `openclaw agents add <name>` 创建一个单独的智能体,它拥有自己的工作区、
|
||||
会话和认证配置文件。不带 `--workspace` 运行会启动向导。
|
||||
会话和认证配置文件。不带 `--workspace` 运行会启动新手引导。
|
||||
|
||||
它会设置:
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ CLI `--reset` 默认会重置配置、凭证和会话;如需包含工作区,
|
|||
说明:
|
||||
|
||||
- 默认工作区遵循 `~/.openclaw/workspace-<agentId>`。
|
||||
- 添加 `bindings` 以路由入站消息(向导可以完成这项操作)。
|
||||
- 添加 `bindings` 以路由入站消息(新手引导可以完成这项操作)。
|
||||
- 非交互式标志:`--model`、`--agent-dir`、`--bind`、`--non-interactive`。
|
||||
|
||||
## 完整参考
|
||||
|
|
@ -122,7 +122,7 @@ CLI `--reset` 默认会重置配置、凭证和会话;如需包含工作区,
|
|||
[CLI 设置参考](/start/wizard-cli-reference)。
|
||||
有关非交互式示例,请参见 [CLI 自动化](/start/wizard-cli-automation)。
|
||||
有关更深入的技术参考(包括 RPC 细节),请参见
|
||||
[向导参考](/reference/wizard)。
|
||||
[新手引导参考](/reference/wizard)。
|
||||
|
||||
## 相关文档
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import fs from "node:fs";
|
||||
import { chmod, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { resolvePreferredOpenClawTmpDir } from "../../../../src/infra/tmp-openclaw-dir.js";
|
||||
import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import type { ResolvedAcpxPluginConfig } from "../config.js";
|
||||
import { ACPX_PINNED_VERSION } from "../config.js";
|
||||
import { AcpxRuntime } from "../runtime.js";
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { formatCliCommand } from "openclaw/plugin-sdk/cli-runtime";
|
||||
import { parseDurationMs } from "openclaw/plugin-sdk/cli-runtime";
|
||||
import {
|
||||
emptyPluginConfigSchema,
|
||||
type OpenClawPluginApi,
|
||||
|
|
@ -7,25 +9,26 @@ import {
|
|||
} from "openclaw/plugin-sdk/core";
|
||||
import {
|
||||
CLAUDE_CLI_PROFILE_ID,
|
||||
applyAuthProfileConfig,
|
||||
buildTokenProfileId,
|
||||
createProviderApiKeyAuthMethod,
|
||||
ensureApiKeyFromOptionEnvOrPrompt,
|
||||
listProfilesForProvider,
|
||||
upsertAuthProfile,
|
||||
} from "../../src/agents/auth-profiles.js";
|
||||
import { suggestOAuthProfileIdForLegacyDefault } from "../../src/agents/auth-profiles/repair.js";
|
||||
import type { AuthProfileStore } from "../../src/agents/auth-profiles/types.js";
|
||||
import { normalizeModelCompat } from "../../src/agents/model-compat.js";
|
||||
import { formatCliCommand } from "../../src/cli/command-format.js";
|
||||
import { parseDurationMs } from "../../src/cli/parse-duration.js";
|
||||
import {
|
||||
normalizeApiKeyInput,
|
||||
suggestOAuthProfileIdForLegacyDefault,
|
||||
type AuthProfileStore,
|
||||
type ProviderAuthResult,
|
||||
normalizeSecretInput,
|
||||
normalizeSecretInputModeInput,
|
||||
promptSecretRefForSetup,
|
||||
resolveSecretInputModeForEnvSelection,
|
||||
} from "../../src/commands/auth-choice.apply-helpers.js";
|
||||
import { buildTokenProfileId, validateAnthropicSetupToken } from "../../src/commands/auth-token.js";
|
||||
import { applyAuthProfileConfig } from "../../src/commands/onboard-auth.js";
|
||||
import { fetchClaudeUsage } from "../../src/infra/provider-usage.fetch.js";
|
||||
import { createProviderApiKeyAuthMethod } from "../../src/plugins/provider-api-key-auth.js";
|
||||
import type { ProviderAuthResult } from "../../src/plugins/types.js";
|
||||
import { normalizeSecretInput } from "../../src/utils/normalize-secret-input.js";
|
||||
upsertAuthProfile,
|
||||
validateAnthropicSetupToken,
|
||||
validateApiKeyInput,
|
||||
} from "openclaw/plugin-sdk/provider-auth";
|
||||
import { normalizeModelCompat } from "openclaw/plugin-sdk/provider-models";
|
||||
import { fetchClaudeUsage } from "openclaw/plugin-sdk/provider-usage";
|
||||
import { anthropicMediaUnderstandingProvider } from "./media-understanding-provider.js";
|
||||
|
||||
const PROVIDER_ID = "anthropic";
|
||||
const DEFAULT_ANTHROPIC_MODEL = "anthropic/claude-sonnet-4-6";
|
||||
|
|
@ -394,6 +397,7 @@ const anthropicPlugin = {
|
|||
profileId: ctx.profileId,
|
||||
}),
|
||||
});
|
||||
api.registerMediaUnderstandingProvider(anthropicMediaUnderstandingProvider);
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
import {
|
||||
describeImageWithModel,
|
||||
describeImagesWithModel,
|
||||
type MediaUnderstandingProvider,
|
||||
} from "openclaw/plugin-sdk/media-understanding";
|
||||
|
||||
export const anthropicMediaUnderstandingProvider: MediaUnderstandingProvider = {
|
||||
id: "anthropic",
|
||||
capabilities: ["image"],
|
||||
describeImage: describeImageWithModel,
|
||||
describeImages: describeImagesWithModel,
|
||||
};
|
||||
|
|
@ -1,13 +1,12 @@
|
|||
import {
|
||||
applyAccountNameToChannelSection,
|
||||
migrateBaseNameToDefaultAccount,
|
||||
normalizeAccountId,
|
||||
patchScopedAccountConfig,
|
||||
} from "../../../src/channels/plugins/setup-helpers.js";
|
||||
import { setTopLevelChannelDmPolicyWithAllowFrom } from "../../../src/channels/plugins/setup-wizard-helpers.js";
|
||||
import type { ChannelSetupAdapter } from "../../../src/channels/plugins/types.adapters.js";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import type { DmPolicy } from "../../../src/config/types.js";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../../src/routing/session-key.js";
|
||||
prepareScopedSetupConfig,
|
||||
setTopLevelChannelDmPolicyWithAllowFrom,
|
||||
type ChannelSetupAdapter,
|
||||
type DmPolicy,
|
||||
type OpenClawConfig,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import { applyBlueBubblesConnectionConfig } from "./config-apply.js";
|
||||
|
||||
const channel = "bluebubbles" as const;
|
||||
|
|
@ -38,7 +37,7 @@ export function setBlueBubblesAllowFrom(
|
|||
export const blueBubblesSetupAdapter: ChannelSetupAdapter = {
|
||||
resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
|
||||
applyAccountName: ({ cfg, accountId, name }) =>
|
||||
applyAccountNameToChannelSection({
|
||||
prepareScopedSetupConfig({
|
||||
cfg,
|
||||
channelKey: channel,
|
||||
accountId,
|
||||
|
|
@ -57,19 +56,13 @@ export const blueBubblesSetupAdapter: ChannelSetupAdapter = {
|
|||
return null;
|
||||
},
|
||||
applyAccountConfig: ({ cfg, accountId, input }) => {
|
||||
const namedConfig = applyAccountNameToChannelSection({
|
||||
const next = prepareScopedSetupConfig({
|
||||
cfg,
|
||||
channelKey: channel,
|
||||
accountId,
|
||||
name: input.name,
|
||||
migrateBaseName: true,
|
||||
});
|
||||
const next =
|
||||
accountId !== DEFAULT_ACCOUNT_ID
|
||||
? migrateBaseNameToDefaultAccount({
|
||||
cfg: namedConfig,
|
||||
channelKey: channel,
|
||||
})
|
||||
: namedConfig;
|
||||
return applyBlueBubblesConnectionConfig({
|
||||
cfg: next,
|
||||
accountId,
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import {
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
formatDocsLink,
|
||||
mergeAllowFromEntries,
|
||||
resolveSetupAccountId,
|
||||
} from "../../../src/channels/plugins/setup-wizard-helpers.js";
|
||||
import type { ChannelSetupDmPolicy } from "../../../src/channels/plugins/setup-wizard-types.js";
|
||||
import type { ChannelSetupWizard } from "../../../src/channels/plugins/setup-wizard.js";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import type { DmPolicy } from "../../../src/config/types.js";
|
||||
import { DEFAULT_ACCOUNT_ID } from "../../../src/routing/session-key.js";
|
||||
import { formatDocsLink } from "../../../src/terminal/links.js";
|
||||
import type { WizardPrompter } from "../../../src/wizard/prompts.js";
|
||||
type ChannelSetupDmPolicy,
|
||||
type ChannelSetupWizard,
|
||||
type DmPolicy,
|
||||
type OpenClawConfig,
|
||||
type WizardPrompter,
|
||||
} from "openclaw/plugin-sdk/setup";
|
||||
import {
|
||||
listBlueBubblesAccountIds,
|
||||
resolveBlueBubblesAccount,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { emptyPluginConfigSchema, type OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
||||
import {
|
||||
createPluginBackedWebSearchProvider,
|
||||
getTopLevelCredentialValue,
|
||||
setTopLevelCredentialValue,
|
||||
} from "../../src/agents/tools/web-search-plugin-factory.js";
|
||||
import { emptyPluginConfigSchema } from "../../src/plugins/config-schema.js";
|
||||
import type { OpenClawPluginApi } from "../../src/plugins/types.js";
|
||||
} from "openclaw/plugin-sdk/provider-web-search";
|
||||
|
||||
const bravePlugin = {
|
||||
id: "brave",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
import { emptyPluginConfigSchema, type OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
||||
import {
|
||||
buildBytePlusCodingProvider,
|
||||
buildBytePlusProvider,
|
||||
} from "../../src/agents/models-config.providers.static.js";
|
||||
import { ensureModelAllowlistEntry } from "../../src/commands/model-allowlist.js";
|
||||
import { createProviderApiKeyAuthMethod } from "../../src/plugins/provider-api-key-auth.js";
|
||||
import { createProviderApiKeyAuthMethod } from "openclaw/plugin-sdk/provider-auth";
|
||||
import { ensureModelAllowlistEntry } from "openclaw/plugin-sdk/provider-onboard";
|
||||
import { buildBytePlusCodingProvider, buildBytePlusProvider } from "./provider-catalog.js";
|
||||
|
||||
const PROVIDER_ID = "byteplus";
|
||||
const BYTEPLUS_DEFAULT_MODEL_REF = "byteplus-plan/ark-code-latest";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
import {
|
||||
buildBytePlusModelDefinition,
|
||||
BYTEPLUS_BASE_URL,
|
||||
BYTEPLUS_CODING_BASE_URL,
|
||||
BYTEPLUS_CODING_MODEL_CATALOG,
|
||||
BYTEPLUS_MODEL_CATALOG,
|
||||
type ModelProviderConfig,
|
||||
} from "openclaw/plugin-sdk/provider-models";
|
||||
|
||||
export function buildBytePlusProvider(): ModelProviderConfig {
|
||||
return {
|
||||
baseUrl: BYTEPLUS_BASE_URL,
|
||||
api: "openai-completions",
|
||||
models: BYTEPLUS_MODEL_CATALOG.map(buildBytePlusModelDefinition),
|
||||
};
|
||||
}
|
||||
|
||||
export function buildBytePlusCodingProvider(): ModelProviderConfig {
|
||||
return {
|
||||
baseUrl: BYTEPLUS_CODING_BASE_URL,
|
||||
api: "openai-completions",
|
||||
models: BYTEPLUS_CODING_MODEL_CATALOG.map(buildBytePlusModelDefinition),
|
||||
};
|
||||
}
|
||||
|
|
@ -1,25 +1,27 @@
|
|||
import { emptyPluginConfigSchema, type OpenClawPluginApi } from "openclaw/plugin-sdk/core";
|
||||
import { upsertAuthProfile } from "../../src/agents/auth-profiles.js";
|
||||
import { ensureAuthProfileStore, listProfilesForProvider } from "../../src/agents/auth-profiles.js";
|
||||
import {
|
||||
applyAuthProfileConfig,
|
||||
buildApiKeyCredential,
|
||||
coerceSecretRef,
|
||||
ensureApiKeyFromOptionEnvOrPrompt,
|
||||
ensureAuthProfileStore,
|
||||
listProfilesForProvider,
|
||||
normalizeApiKeyInput,
|
||||
normalizeOptionalSecretInput,
|
||||
resolveNonEnvSecretRefApiKeyMarker,
|
||||
type SecretInput,
|
||||
upsertAuthProfile,
|
||||
validateApiKeyInput,
|
||||
} from "openclaw/plugin-sdk/provider-auth";
|
||||
import {
|
||||
buildCloudflareAiGatewayModelDefinition,
|
||||
resolveCloudflareAiGatewayBaseUrl,
|
||||
} from "../../src/agents/cloudflare-ai-gateway.js";
|
||||
import { resolveNonEnvSecretRefApiKeyMarker } from "../../src/agents/model-auth-markers.js";
|
||||
import {
|
||||
normalizeApiKeyInput,
|
||||
validateApiKeyInput,
|
||||
} from "../../src/commands/auth-choice.api-key.js";
|
||||
import { ensureApiKeyFromOptionEnvOrPrompt } from "../../src/commands/auth-choice.apply-helpers.js";
|
||||
import { buildApiKeyCredential } from "../../src/commands/onboard-auth.credentials.js";
|
||||
} from "openclaw/plugin-sdk/provider-models";
|
||||
import {
|
||||
applyCloudflareAiGatewayConfig,
|
||||
applyAuthProfileConfig,
|
||||
buildCloudflareAiGatewayConfigPatch,
|
||||
CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF,
|
||||
} from "../../src/commands/onboard-auth.js";
|
||||
import type { SecretInput } from "../../src/config/types.secrets.js";
|
||||
import { coerceSecretRef } from "../../src/config/types.secrets.js";
|
||||
import { normalizeOptionalSecretInput } from "../../src/utils/normalize-secret-input.js";
|
||||
} from "./onboard.js";
|
||||
|
||||
const PROVIDER_ID = "cloudflare-ai-gateway";
|
||||
const PROVIDER_ENV_VAR = "CLOUDFLARE_AI_GATEWAY_API_KEY";
|
||||
|
|
@ -53,30 +55,6 @@ function resolveMetadataFromCredential(
|
|||
};
|
||||
}
|
||||
|
||||
function buildCloudflareConfigPatch(params: { accountId: string; gatewayId: string }) {
|
||||
const baseUrl = resolveCloudflareAiGatewayBaseUrl(params);
|
||||
return {
|
||||
models: {
|
||||
providers: {
|
||||
[PROVIDER_ID]: {
|
||||
baseUrl,
|
||||
api: "anthropic-messages" as const,
|
||||
models: [buildCloudflareAiGatewayModelDefinition()],
|
||||
},
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
defaults: {
|
||||
models: {
|
||||
[CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF]: {
|
||||
alias: "Cloudflare AI Gateway",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function resolveCloudflareGatewayMetadataInteractive(ctx: {
|
||||
accountId?: string;
|
||||
gatewayId?: string;
|
||||
|
|
@ -180,7 +158,7 @@ const cloudflareAiGatewayPlugin = {
|
|||
),
|
||||
},
|
||||
],
|
||||
configPatch: buildCloudflareConfigPatch(metadata),
|
||||
configPatch: buildCloudflareAiGatewayConfigPatch(metadata),
|
||||
defaultModel: CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF,
|
||||
};
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
import {
|
||||
buildCloudflareAiGatewayModelDefinition,
|
||||
CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF,
|
||||
resolveCloudflareAiGatewayBaseUrl,
|
||||
} from "openclaw/plugin-sdk/provider-models";
|
||||
import {
|
||||
applyAgentDefaultModelPrimary,
|
||||
applyProviderConfigWithDefaultModel,
|
||||
type OpenClawConfig,
|
||||
} from "openclaw/plugin-sdk/provider-onboard";
|
||||
|
||||
export { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF };
|
||||
|
||||
export function buildCloudflareAiGatewayConfigPatch(params: {
|
||||
accountId: string;
|
||||
gatewayId: string;
|
||||
}) {
|
||||
const baseUrl = resolveCloudflareAiGatewayBaseUrl(params);
|
||||
return {
|
||||
models: {
|
||||
providers: {
|
||||
"cloudflare-ai-gateway": {
|
||||
baseUrl,
|
||||
api: "anthropic-messages" as const,
|
||||
models: [buildCloudflareAiGatewayModelDefinition()],
|
||||
},
|
||||
},
|
||||
},
|
||||
agents: {
|
||||
defaults: {
|
||||
models: {
|
||||
[CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF]: {
|
||||
alias: "Cloudflare AI Gateway",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function applyCloudflareAiGatewayProviderConfig(
|
||||
cfg: OpenClawConfig,
|
||||
params?: { accountId?: string; gatewayId?: string },
|
||||
): OpenClawConfig {
|
||||
const models = { ...cfg.agents?.defaults?.models };
|
||||
models[CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF] = {
|
||||
...models[CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF],
|
||||
alias: models[CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF]?.alias ?? "Cloudflare AI Gateway",
|
||||
};
|
||||
|
||||
const existingProvider = cfg.models?.providers?.["cloudflare-ai-gateway"] as
|
||||
| { baseUrl?: unknown }
|
||||
| undefined;
|
||||
const baseUrl =
|
||||
params?.accountId && params?.gatewayId
|
||||
? resolveCloudflareAiGatewayBaseUrl({
|
||||
accountId: params.accountId,
|
||||
gatewayId: params.gatewayId,
|
||||
})
|
||||
: typeof existingProvider?.baseUrl === "string"
|
||||
? existingProvider.baseUrl
|
||||
: undefined;
|
||||
if (!baseUrl) {
|
||||
return {
|
||||
...cfg,
|
||||
agents: {
|
||||
...cfg.agents,
|
||||
defaults: {
|
||||
...cfg.agents?.defaults,
|
||||
models,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return applyProviderConfigWithDefaultModel(cfg, {
|
||||
agentModels: models,
|
||||
providerId: "cloudflare-ai-gateway",
|
||||
api: "anthropic-messages",
|
||||
baseUrl,
|
||||
defaultModel: buildCloudflareAiGatewayModelDefinition(),
|
||||
});
|
||||
}
|
||||
|
||||
export function applyCloudflareAiGatewayConfig(
|
||||
cfg: OpenClawConfig,
|
||||
params?: { accountId?: string; gatewayId?: string },
|
||||
): OpenClawConfig {
|
||||
return applyAgentDefaultModelPrimary(
|
||||
applyCloudflareAiGatewayProviderConfig(cfg, params),
|
||||
CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
import {
|
||||
hasConfiguredSecretInput,
|
||||
normalizeSecretInputString,
|
||||
} from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { DiscordAccountConfig } from "../../../src/config/types.js";
|
||||
import {
|
||||
DEFAULT_ACCOUNT_ID,
|
||||
normalizeAccountId,
|
||||
type OpenClawConfig,
|
||||
type DiscordAccountConfig,
|
||||
} from "openclaw/plugin-sdk/discord";
|
||||
import {
|
||||
hasConfiguredSecretInput,
|
||||
normalizeSecretInputString,
|
||||
} from "../../../src/config/types.secrets.js";
|
||||
} from "../../../src/plugin-sdk-internal/accounts.js";
|
||||
import {
|
||||
mergeDiscordAccountConfig,
|
||||
resolveDefaultDiscordAccountId,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import type {
|
||||
OpenClawConfig,
|
||||
DiscordAccountConfig,
|
||||
DiscordActionConfig,
|
||||
} from "openclaw/plugin-sdk/discord";
|
||||
import { createAccountActionGate } from "../../../src/channels/plugins/account-action-gate.js";
|
||||
import { createAccountListHelpers } from "../../../src/channels/plugins/account-helpers.js";
|
||||
import { resolveAccountEntry } from "../../../src/routing/account-lookup.js";
|
||||
import { normalizeAccountId } from "../../../src/routing/session-key.js";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import type { DiscordAccountConfig, DiscordActionConfig } from "../../../src/config/types.js";
|
||||
import {
|
||||
createAccountActionGate,
|
||||
createAccountListHelpers,
|
||||
normalizeAccountId,
|
||||
resolveAccountEntry,
|
||||
} from "../../../src/plugin-sdk-internal/accounts.js";
|
||||
import { resolveDiscordToken } from "./token.js";
|
||||
|
||||
export type ResolvedDiscordAccount = {
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ import {
|
|||
readNumberParam,
|
||||
readStringArrayParam,
|
||||
readStringParam,
|
||||
} from "../../../../src/agents/tools/common.js";
|
||||
} from "openclaw/plugin-sdk/agent-runtime";
|
||||
import {
|
||||
isDiscordModerationAction,
|
||||
readDiscordModerationCommand,
|
||||
} from "../../../../src/agents/tools/discord-actions-moderation-shared.js";
|
||||
import { handleDiscordAction } from "../../../../src/agents/tools/discord-actions.js";
|
||||
import type { ChannelMessageActionContext } from "../../../../src/channels/plugins/types.js";
|
||||
} from "openclaw/plugin-sdk/agent-runtime";
|
||||
import { handleDiscordAction } from "openclaw/plugin-sdk/agent-runtime";
|
||||
import type { ChannelMessageActionContext } from "openclaw/plugin-sdk/channel-runtime";
|
||||
|
||||
type Ctx = Pick<
|
||||
ChannelMessageActionContext,
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ import {
|
|||
readNumberParam,
|
||||
readStringArrayParam,
|
||||
readStringParam,
|
||||
} from "../../../../src/agents/tools/common.js";
|
||||
import { readDiscordParentIdParam } from "../../../../src/agents/tools/discord-actions-shared.js";
|
||||
import { handleDiscordAction } from "../../../../src/agents/tools/discord-actions.js";
|
||||
import { resolveReactionMessageId } from "../../../../src/channels/plugins/actions/reaction-message-id.js";
|
||||
import type { ChannelMessageActionContext } from "../../../../src/channels/plugins/types.js";
|
||||
import { normalizeInteractiveReply } from "../../../../src/interactive/payload.js";
|
||||
import { readBooleanParam } from "../../../../src/plugin-sdk/boolean-param.js";
|
||||
} from "openclaw/plugin-sdk/agent-runtime";
|
||||
import { readDiscordParentIdParam } from "openclaw/plugin-sdk/agent-runtime";
|
||||
import { handleDiscordAction } from "openclaw/plugin-sdk/agent-runtime";
|
||||
import { readBooleanParam } from "openclaw/plugin-sdk/boolean-param";
|
||||
import { resolveReactionMessageId } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import type { ChannelMessageActionContext } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { normalizeInteractiveReply } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { buildDiscordInteractiveComponents } from "../shared-interactive.js";
|
||||
import { resolveDiscordChannelId } from "../targets.js";
|
||||
import { tryHandleDiscordMessageActionGuildAdmin } from "./handle-action.guild-admin.js";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
import { resolveFetch } from "../../../src/infra/fetch.js";
|
||||
import { resolveRetryConfig, retryAsync, type RetryConfig } from "../../../src/infra/retry.js";
|
||||
import { resolveFetch } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import {
|
||||
resolveRetryConfig,
|
||||
retryAsync,
|
||||
type RetryConfig,
|
||||
} from "openclaw/plugin-sdk/infra-runtime";
|
||||
|
||||
const DISCORD_API_BASE = "https://discord.com/api/v10";
|
||||
const DISCORD_API_RETRY_DEFAULTS = {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import type { DiscordGuildChannelConfig, DiscordGuildEntry } from "../../../src/config/types.js";
|
||||
import { isRecord } from "../../../src/utils.js";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type {
|
||||
DiscordGuildChannelConfig,
|
||||
DiscordGuildEntry,
|
||||
} from "openclaw/plugin-sdk/config-runtime";
|
||||
import { isRecord } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { inspectDiscordAccount } from "./account-inspect.js";
|
||||
import { fetchChannelPermissionsDiscord } from "./send.js";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import {
|
||||
createUnionActionGate,
|
||||
listTokenSourcedAccounts,
|
||||
} from "../../../src/channels/plugins/actions/shared.js";
|
||||
} from "openclaw/plugin-sdk/channel-runtime";
|
||||
import type {
|
||||
ChannelMessageActionAdapter,
|
||||
ChannelMessageActionName,
|
||||
} from "../../../src/channels/plugins/types.js";
|
||||
import type { DiscordActionConfig } from "../../../src/config/types.discord.js";
|
||||
} from "openclaw/plugin-sdk/channel-runtime";
|
||||
import type { DiscordActionConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { createDiscordActionGate, listEnabledDiscordAccounts } from "./accounts.js";
|
||||
import { handleDiscordMessageAction } from "./actions/handle-action.js";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,46 +1,12 @@
|
|||
import { createScopedChannelConfigBase } from "openclaw/plugin-sdk/compat";
|
||||
import {
|
||||
createScopedAccountConfigAccessors,
|
||||
formatAllowFromLowercase,
|
||||
} from "openclaw/plugin-sdk/compat";
|
||||
import {
|
||||
buildChannelConfigSchema,
|
||||
DiscordConfigSchema,
|
||||
getChatChannelMeta,
|
||||
type ChannelPlugin,
|
||||
} from "openclaw/plugin-sdk/discord";
|
||||
import { inspectDiscordAccount } from "./account-inspect.js";
|
||||
import {
|
||||
listDiscordAccountIds,
|
||||
resolveDefaultDiscordAccountId,
|
||||
resolveDiscordAccount,
|
||||
type ResolvedDiscordAccount,
|
||||
} from "./accounts.js";
|
||||
import { createDiscordSetupWizardProxy, discordSetupAdapter } from "./setup-core.js";
|
||||
|
||||
async function loadDiscordChannelRuntime() {
|
||||
return await import("./channel.runtime.js");
|
||||
}
|
||||
|
||||
const discordConfigAccessors = createScopedAccountConfigAccessors({
|
||||
resolveAccount: ({ cfg, accountId }) => resolveDiscordAccount({ cfg, accountId }),
|
||||
resolveAllowFrom: (account: ResolvedDiscordAccount) => account.config.dm?.allowFrom,
|
||||
formatAllowFrom: (allowFrom) => formatAllowFromLowercase({ allowFrom }),
|
||||
resolveDefaultTo: (account: ResolvedDiscordAccount) => account.config.defaultTo,
|
||||
});
|
||||
|
||||
const discordConfigBase = createScopedChannelConfigBase({
|
||||
sectionKey: "discord",
|
||||
listAccountIds: listDiscordAccountIds,
|
||||
resolveAccount: (cfg, accountId) => resolveDiscordAccount({ cfg, accountId }),
|
||||
inspectAccount: (cfg, accountId) => inspectDiscordAccount({ cfg, accountId }),
|
||||
defaultAccountId: resolveDefaultDiscordAccountId,
|
||||
clearBaseFields: ["token", "name"],
|
||||
});
|
||||
|
||||
const discordSetupWizard = createDiscordSetupWizardProxy(async () => ({
|
||||
discordSetupWizard: (await loadDiscordChannelRuntime()).discordSetupWizard,
|
||||
}));
|
||||
import { type ResolvedDiscordAccount } from "./accounts.js";
|
||||
import { discordConfigAccessors, discordConfigBase, discordSetupWizard } from "./plugin-shared.js";
|
||||
import { discordSetupAdapter } from "./setup-core.js";
|
||||
|
||||
export const discordSetupPlugin: ChannelPlugin<ResolvedDiscordAccount> = {
|
||||
id: "discord",
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
import { Separator, TextDisplay } from "@buape/carbon";
|
||||
import { createScopedChannelConfigBase } from "openclaw/plugin-sdk/compat";
|
||||
import {
|
||||
buildAccountScopedAllowlistConfigEditor,
|
||||
resolveLegacyDmAllowlistConfigPaths,
|
||||
} from "openclaw/plugin-sdk/allowlist-config-edit";
|
||||
import {
|
||||
buildAccountScopedDmSecurityPolicy,
|
||||
collectOpenProviderGroupPolicyWarnings,
|
||||
collectOpenGroupPolicyConfiguredRouteWarnings,
|
||||
createScopedAccountConfigAccessors,
|
||||
formatAllowFromLowercase,
|
||||
} from "openclaw/plugin-sdk/compat";
|
||||
collectOpenProviderGroupPolicyWarnings,
|
||||
} from "openclaw/plugin-sdk/channel-config-helpers";
|
||||
import { resolveOutboundSendDep } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { normalizeMessageChannel } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import {
|
||||
buildAgentSessionKey,
|
||||
resolveThreadSessionKeys,
|
||||
|
|
@ -31,13 +33,9 @@ import {
|
|||
type ChannelPlugin,
|
||||
type OpenClawConfig,
|
||||
} from "openclaw/plugin-sdk/discord";
|
||||
import { resolveOutboundSendDep } from "../../../src/infra/outbound/send-deps.js";
|
||||
import { normalizeMessageChannel } from "../../../src/utils/message-channel.js";
|
||||
import { inspectDiscordAccount } from "./account-inspect.js";
|
||||
import {
|
||||
listDiscordAccountIds,
|
||||
resolveDiscordAccount,
|
||||
resolveDefaultDiscordAccountId,
|
||||
type ResolvedDiscordAccount,
|
||||
} from "./accounts.js";
|
||||
import { collectDiscordAuditChannelIds } from "./audit.js";
|
||||
|
|
@ -50,11 +48,12 @@ import {
|
|||
normalizeDiscordMessagingTarget,
|
||||
normalizeDiscordOutboundTarget,
|
||||
} from "./normalize.js";
|
||||
import { discordConfigAccessors, discordConfigBase, discordSetupWizard } from "./plugin-shared.js";
|
||||
import type { DiscordProbe } from "./probe.js";
|
||||
import { resolveDiscordUserAllowlist } from "./resolve-users.js";
|
||||
import { getDiscordRuntime } from "./runtime.js";
|
||||
import { fetchChannelPermissionsDiscord } from "./send.js";
|
||||
import { createDiscordSetupWizardProxy, discordSetupAdapter } from "./setup-core.js";
|
||||
import { discordSetupAdapter } from "./setup-core.js";
|
||||
import { collectDiscordStatusIssues } from "./status-issues.js";
|
||||
import { parseDiscordTarget } from "./targets.js";
|
||||
import { DiscordUiContainer } from "./ui.js";
|
||||
|
|
@ -66,10 +65,6 @@ type DiscordSendFn = ReturnType<
|
|||
const meta = getChatChannelMeta("discord");
|
||||
const REQUIRED_DISCORD_PERMISSIONS = ["ViewChannel", "SendMessages"] as const;
|
||||
|
||||
async function loadDiscordChannelRuntime() {
|
||||
return await import("./channel.runtime.js");
|
||||
}
|
||||
|
||||
function formatDiscordIntents(intents?: {
|
||||
messageContent?: string;
|
||||
guildMembers?: string;
|
||||
|
|
@ -304,26 +299,6 @@ function resolveDiscordOutboundSessionRoute(params: {
|
|||
};
|
||||
}
|
||||
|
||||
const discordConfigAccessors = createScopedAccountConfigAccessors({
|
||||
resolveAccount: ({ cfg, accountId }) => resolveDiscordAccount({ cfg, accountId }),
|
||||
resolveAllowFrom: (account: ResolvedDiscordAccount) => account.config.dm?.allowFrom,
|
||||
formatAllowFrom: (allowFrom) => formatAllowFromLowercase({ allowFrom }),
|
||||
resolveDefaultTo: (account: ResolvedDiscordAccount) => account.config.defaultTo,
|
||||
});
|
||||
|
||||
const discordConfigBase = createScopedChannelConfigBase({
|
||||
sectionKey: "discord",
|
||||
listAccountIds: listDiscordAccountIds,
|
||||
resolveAccount: (cfg, accountId) => resolveDiscordAccount({ cfg, accountId }),
|
||||
inspectAccount: (cfg, accountId) => inspectDiscordAccount({ cfg, accountId }),
|
||||
defaultAccountId: resolveDefaultDiscordAccountId,
|
||||
clearBaseFields: ["token", "name"],
|
||||
});
|
||||
|
||||
const discordSetupWizard = createDiscordSetupWizardProxy(async () => ({
|
||||
discordSetupWizard: (await loadDiscordChannelRuntime()).discordSetupWizard,
|
||||
}));
|
||||
|
||||
export const discordPlugin: ChannelPlugin<ResolvedDiscordAccount> = {
|
||||
id: "discord",
|
||||
meta: {
|
||||
|
|
@ -375,14 +350,7 @@ export const discordPlugin: ChannelPlugin<ResolvedDiscordAccount> = {
|
|||
channelId: "discord",
|
||||
normalize: ({ cfg, accountId, values }) =>
|
||||
discordConfigAccessors.formatAllowFrom!({ cfg, accountId, allowFrom: values }),
|
||||
resolvePaths: (scope) =>
|
||||
scope === "dm"
|
||||
? {
|
||||
readPaths: [["allowFrom"], ["dm", "allowFrom"]],
|
||||
writePath: ["allowFrom"],
|
||||
cleanupPaths: [["dm", "allowFrom"]],
|
||||
}
|
||||
: null,
|
||||
resolvePaths: resolveLegacyDmAllowlistConfigPaths,
|
||||
}),
|
||||
},
|
||||
security: {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { chunkMarkdownTextWithMode, type ChunkMode } from "../../../src/auto-reply/chunk.js";
|
||||
import { chunkMarkdownTextWithMode, type ChunkMode } from "openclaw/plugin-sdk/reply-runtime";
|
||||
|
||||
export type ChunkDiscordTextOpts = {
|
||||
/** Max characters per Discord message. Default: 2000. */
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { RequestClient } from "@buape/carbon";
|
||||
import { loadConfig } from "../../../src/config/config.js";
|
||||
import { createDiscordRetryRunner, type RetryRunner } from "../../../src/infra/retry-policy.js";
|
||||
import type { RetryConfig } from "../../../src/infra/retry.js";
|
||||
import { normalizeAccountId } from "../../../src/routing/session-key.js";
|
||||
import { loadConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { createDiscordRetryRunner, type RetryRunner } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import type { RetryConfig } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
|
||||
import {
|
||||
mergeDiscordAccountConfig,
|
||||
resolveDiscordAccount,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../../src/routing/account-id.js";
|
||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/routing";
|
||||
|
||||
const DISCORD_DIRECTORY_CACHE_MAX_ENTRIES = 4000;
|
||||
const DISCORD_DISCRIMINATOR_SUFFIX = /#\d{4}$/;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { DirectoryConfigParams } from "../../../src/channels/plugins/directory-config.js";
|
||||
import type { ChannelDirectoryEntry } from "../../../src/channels/plugins/types.js";
|
||||
import type { DirectoryConfigParams } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import type { ChannelDirectoryEntry } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { resolveDiscordAccount } from "./accounts.js";
|
||||
import { fetchDiscord } from "./api.js";
|
||||
import { rememberDiscordDirectoryUser } from "./directory-cache.js";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { resolveTextChunkLimit } from "../../../src/auto-reply/chunk.js";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import { resolveAccountEntry } from "../../../src/routing/account-lookup.js";
|
||||
import { normalizeAccountId } from "../../../src/routing/session-key.js";
|
||||
import { type OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { resolveAccountEntry } from "openclaw/plugin-sdk/routing";
|
||||
import { normalizeAccountId } from "openclaw/plugin-sdk/routing";
|
||||
import { DISCORD_TEXT_CHUNK_LIMIT } from "./outbound-adapter.js";
|
||||
|
||||
const DEFAULT_DISCORD_DRAFT_STREAM_MIN = 200;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { RequestClient } from "@buape/carbon";
|
||||
import { Routes } from "discord-api-types/v10";
|
||||
import { createFinalizableDraftLifecycle } from "../../../src/channels/draft-stream-controls.js";
|
||||
import { createFinalizableDraftLifecycle } from "openclaw/plugin-sdk/channel-runtime";
|
||||
|
||||
/** Discord messages cap at 2000 characters. */
|
||||
const DISCORD_STREAM_MAX_CHARS = 2000;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { ReplyPayload } from "../../../src/auto-reply/types.js";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import { getExecApprovalReplyMetadata } from "../../../src/infra/exec-approval-reply.js";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { getExecApprovalReplyMetadata } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { resolveDiscordAccount } from "./accounts.js";
|
||||
|
||||
export function isDiscordExecApprovalClientEnabled(params: {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import type { EventEmitter } from "node:events";
|
||||
import { logVerbose } from "../../../src/globals.js";
|
||||
import type { RuntimeEnv } from "../../../src/runtime.js";
|
||||
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
|
||||
|
||||
type GatewayEmitter = Pick<EventEmitter, "on" | "removeListener">;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { MockFn } from "openclaw/plugin-sdk/test-utils";
|
||||
import { vi } from "vitest";
|
||||
import type { MockFn } from "../../../src/test-utils/vitest-mock-fn.js";
|
||||
|
||||
export const sendMock: MockFn = vi.fn();
|
||||
export const reactMock: MockFn = vi.fn();
|
||||
|
|
@ -15,8 +15,8 @@ vi.mock("./send.js", () => ({
|
|||
},
|
||||
}));
|
||||
|
||||
vi.mock("../../../src/auto-reply/dispatch.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../src/auto-reply/dispatch.js")>();
|
||||
vi.mock("openclaw/plugin-sdk/reply-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/reply-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
dispatchInboundMessage: (...args: unknown[]) => dispatchMock(...args),
|
||||
|
|
@ -36,10 +36,10 @@ function createPairingStoreMocks() {
|
|||
};
|
||||
}
|
||||
|
||||
vi.mock("../../../src/pairing/pairing-store.js", () => createPairingStoreMocks());
|
||||
vi.mock("openclaw/plugin-sdk/conversation-runtime", () => createPairingStoreMocks());
|
||||
|
||||
vi.mock("../../../src/config/sessions.js", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("../../../src/config/sessions.js")>();
|
||||
vi.mock("openclaw/plugin-sdk/config-runtime", async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/config-runtime")>();
|
||||
return {
|
||||
...actual,
|
||||
resolveStorePath: vi.fn(() => "/tmp/openclaw-sessions.json"),
|
||||
|
|
|
|||
|
|
@ -18,41 +18,41 @@ import {
|
|||
} from "@buape/carbon";
|
||||
import type { APIStringSelectComponent } from "discord-api-types/v10";
|
||||
import { ButtonStyle, ChannelType } from "discord-api-types/v10";
|
||||
import { resolveHumanDelayConfig } from "../../../../src/agents/identity.js";
|
||||
import { resolveChunkMode, resolveTextChunkLimit } from "../../../../src/auto-reply/chunk.js";
|
||||
import {
|
||||
formatInboundEnvelope,
|
||||
resolveEnvelopeFormatOptions,
|
||||
} from "../../../../src/auto-reply/envelope.js";
|
||||
import { finalizeInboundContext } from "../../../../src/auto-reply/reply/inbound-context.js";
|
||||
import { dispatchReplyWithBufferedBlockDispatcher } from "../../../../src/auto-reply/reply/provider-dispatcher.js";
|
||||
import { createReplyReferencePlanner } from "../../../../src/auto-reply/reply/reply-reference.js";
|
||||
import { resolveCommandAuthorizedFromAuthorizers } from "../../../../src/channels/command-gating.js";
|
||||
import { createReplyPrefixOptions } from "../../../../src/channels/reply-prefix.js";
|
||||
import { recordInboundSession } from "../../../../src/channels/session.js";
|
||||
import type { OpenClawConfig } from "../../../../src/config/config.js";
|
||||
import { isDangerousNameMatchingEnabled } from "../../../../src/config/dangerous-name-matching.js";
|
||||
import { resolveMarkdownTableMode } from "../../../../src/config/markdown-tables.js";
|
||||
import { readSessionUpdatedAt, resolveStorePath } from "../../../../src/config/sessions.js";
|
||||
import type { DiscordAccountConfig } from "../../../../src/config/types.discord.js";
|
||||
import { logVerbose } from "../../../../src/globals.js";
|
||||
import { enqueueSystemEvent } from "../../../../src/infra/system-events.js";
|
||||
import { logDebug, logError } from "../../../../src/logger.js";
|
||||
import { getAgentScopedMediaLocalRoots } from "../../../../src/media/local-roots.js";
|
||||
import { issuePairingChallenge } from "../../../../src/pairing/pairing-challenge.js";
|
||||
import { upsertChannelPairingRequest } from "../../../../src/pairing/pairing-store.js";
|
||||
import { resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
|
||||
import { resolveCommandAuthorizedFromAuthorizers } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { createReplyPrefixOptions } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { recordInboundSession } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { readSessionUpdatedAt, resolveStorePath } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { DiscordAccountConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { issuePairingChallenge } from "openclaw/plugin-sdk/conversation-runtime";
|
||||
import { upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
|
||||
import {
|
||||
buildPluginBindingResolvedText,
|
||||
parsePluginBindingApprovalCustomId,
|
||||
resolvePluginConversationBindingApproval,
|
||||
} from "../../../../src/plugins/conversation-binding.js";
|
||||
import { dispatchPluginInteractiveHandler } from "../../../../src/plugins/interactive.js";
|
||||
import { resolveAgentRoute } from "../../../../src/routing/resolve-route.js";
|
||||
import { createNonExitingRuntime, type RuntimeEnv } from "../../../../src/runtime.js";
|
||||
} from "openclaw/plugin-sdk/conversation-runtime";
|
||||
import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
|
||||
import { dispatchPluginInteractiveHandler } from "openclaw/plugin-sdk/plugin-runtime";
|
||||
import { resolveChunkMode, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import {
|
||||
formatInboundEnvelope,
|
||||
resolveEnvelopeFormatOptions,
|
||||
} from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { dispatchReplyWithBufferedBlockDispatcher } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { createReplyReferencePlanner } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
|
||||
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { createNonExitingRuntime, type RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
|
||||
import {
|
||||
readStoreAllowFromForDmPolicy,
|
||||
resolvePinnedMainDmOwnerFromAllowlist,
|
||||
} from "../../../../src/security/dm-policy-shared.js";
|
||||
} from "openclaw/plugin-sdk/security-runtime";
|
||||
import { logDebug, logError } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { resolveDiscordMaxLinesPerMessage } from "../accounts.js";
|
||||
import { resolveDiscordComponentEntry, resolveDiscordModalEntry } from "../components-registry.js";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import type { Guild, User } from "@buape/carbon";
|
||||
import type { AllowlistMatch } from "../../../../src/channels/allowlist-match.js";
|
||||
import type { AllowlistMatch } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import {
|
||||
buildChannelKeyCandidates,
|
||||
resolveChannelEntryMatchWithFallback,
|
||||
resolveChannelMatchConfig,
|
||||
type ChannelMatchSource,
|
||||
} from "../../../../src/channels/channel-config.js";
|
||||
import { evaluateGroupRouteAccessForPolicy } from "../../../../src/plugin-sdk/group-access.js";
|
||||
} from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { evaluateGroupRouteAccessForPolicy } from "openclaw/plugin-sdk/group-access";
|
||||
import { formatDiscordUserTag } from "./format.js";
|
||||
|
||||
export type DiscordAllowList = {
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ import {
|
|||
resolveProfilesUnavailableReason,
|
||||
type AuthProfileFailureReason,
|
||||
type AuthProfileStore,
|
||||
} from "../../../../src/agents/auth-profiles.js";
|
||||
} from "openclaw/plugin-sdk/agent-runtime";
|
||||
import type {
|
||||
DiscordAccountConfig,
|
||||
DiscordAutoPresenceConfig,
|
||||
} from "../../../../src/config/config.js";
|
||||
import { warn } from "../../../../src/globals.js";
|
||||
} from "openclaw/plugin-sdk/config-runtime";
|
||||
import { warn } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { resolveDiscordPresenceUpdate } from "./presence.js";
|
||||
|
||||
const DEFAULT_CUSTOM_ACTIVITY_TYPE = 4;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { DiscordSlashCommandConfig } from "../../../../src/config/types.discord.js";
|
||||
import type { DiscordSlashCommandConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
|
||||
export function resolveDiscordSlashCommandConfig(
|
||||
raw?: DiscordSlashCommandConfig,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { resolveCommandAuthorizedFromAuthorizers } from "../../../../src/channels/command-gating.js";
|
||||
import { resolveCommandAuthorizedFromAuthorizers } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import {
|
||||
readStoreAllowFromForDmPolicy,
|
||||
resolveDmGroupAccessWithLists,
|
||||
type DmGroupAccessDecision,
|
||||
} from "../../../../src/security/dm-policy-shared.js";
|
||||
} from "openclaw/plugin-sdk/security-runtime";
|
||||
import { normalizeDiscordAllowList, resolveDiscordAllowListMatch } from "./allow-list.js";
|
||||
|
||||
const DISCORD_ALLOW_LIST_PREFIXES = ["discord:", "user:", "pk:"];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { issuePairingChallenge } from "../../../../src/pairing/pairing-challenge.js";
|
||||
import { upsertChannelPairingRequest } from "../../../../src/pairing/pairing-store.js";
|
||||
import { issuePairingChallenge } from "openclaw/plugin-sdk/conversation-runtime";
|
||||
import { upsertChannelPairingRequest } from "openclaw/plugin-sdk/conversation-runtime";
|
||||
import type { DiscordDmCommandAccess } from "./dm-command-auth.js";
|
||||
|
||||
export async function handleDiscordDmCommandDecision(params: {
|
||||
|
|
|
|||
|
|
@ -10,30 +10,24 @@ import {
|
|||
type TopLevelComponents,
|
||||
} from "@buape/carbon";
|
||||
import { ButtonStyle, Routes } from "discord-api-types/v10";
|
||||
import type { OpenClawConfig } from "../../../../src/config/config.js";
|
||||
import { loadSessionStore, resolveStorePath } from "../../../../src/config/sessions.js";
|
||||
import type { DiscordExecApprovalConfig } from "../../../../src/config/types.discord.js";
|
||||
import { GatewayClient } from "../../../../src/gateway/client.js";
|
||||
import { createOperatorApprovalsGatewayClient } from "../../../../src/gateway/operator-approvals-client.js";
|
||||
import type { EventFrame } from "../../../../src/gateway/protocol/index.js";
|
||||
import { resolveExecApprovalCommandDisplay } from "../../../../src/infra/exec-approval-command-display.js";
|
||||
import { getExecApprovalApproverDmNoticeText } from "../../../../src/infra/exec-approval-reply.js";
|
||||
import { normalizeMessageChannel } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { loadSessionStore, resolveStorePath } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { DiscordExecApprovalConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { GatewayClient } from "openclaw/plugin-sdk/gateway-runtime";
|
||||
import { createOperatorApprovalsGatewayClient } from "openclaw/plugin-sdk/gateway-runtime";
|
||||
import type { EventFrame } from "openclaw/plugin-sdk/gateway-runtime";
|
||||
import { resolveExecApprovalCommandDisplay } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { getExecApprovalApproverDmNoticeText } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import type {
|
||||
ExecApprovalDecision,
|
||||
ExecApprovalRequest,
|
||||
ExecApprovalResolved,
|
||||
} from "../../../../src/infra/exec-approvals.js";
|
||||
import { logDebug, logError } from "../../../../src/logger.js";
|
||||
import {
|
||||
normalizeAccountId,
|
||||
resolveAgentIdFromSessionKey,
|
||||
} from "../../../../src/routing/session-key.js";
|
||||
import type { RuntimeEnv } from "../../../../src/runtime.js";
|
||||
import {
|
||||
compileSafeRegex,
|
||||
testRegexWithBoundedInput,
|
||||
} from "../../../../src/security/safe-regex.js";
|
||||
import { normalizeMessageChannel } from "../../../../src/utils/message-channel.js";
|
||||
} from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { normalizeAccountId, resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
|
||||
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { compileSafeRegex, testRegexWithBoundedInput } from "openclaw/plugin-sdk/security-runtime";
|
||||
import { logDebug, logError } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { createDiscordClient, stripUndefinedFields } from "../send.shared.js";
|
||||
import { DiscordUiContainer } from "../ui.js";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { GatewayIntents, GatewayPlugin } from "@buape/carbon/gateway";
|
||||
import type { APIGatewayBotInfo } from "discord-api-types/v10";
|
||||
import { HttpsProxyAgent } from "https-proxy-agent";
|
||||
import type { DiscordAccountConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { danger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import type { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { ProxyAgent, fetch as undiciFetch } from "undici";
|
||||
import WebSocket from "ws";
|
||||
import type { DiscordAccountConfig } from "../../../../src/config/types.js";
|
||||
import { danger } from "../../../../src/globals.js";
|
||||
import type { RuntimeEnv } from "../../../../src/runtime.js";
|
||||
|
||||
const DISCORD_GATEWAY_BOT_URL = "https://discord.com/api/v10/gateway/bot";
|
||||
const DEFAULT_DISCORD_GATEWAY_URL = "wss://gateway.discord.gg/";
|
||||
|
|
@ -20,7 +20,7 @@ type DiscordGatewayFetch = (
|
|||
) => Promise<DiscordGatewayMetadataResponse>;
|
||||
|
||||
export function resolveDiscordGatewayIntents(
|
||||
intentsConfig?: import("../../../../src/config/types.discord.js").DiscordIntentsConfig,
|
||||
intentsConfig?: import("openclaw/plugin-sdk/config-runtime").DiscordIntentsConfig,
|
||||
): number {
|
||||
let intents =
|
||||
GatewayIntents.Guilds |
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { buildUntrustedChannelMetadata } from "../../../../src/security/channel-metadata.js";
|
||||
import { buildUntrustedChannelMetadata } from "openclaw/plugin-sdk/security-runtime";
|
||||
import {
|
||||
resolveDiscordOwnerAllowFrom,
|
||||
type DiscordChannelConfigResolved,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { createRunStateMachine } from "../../../../src/channels/run-state-machine.js";
|
||||
import { danger } from "../../../../src/globals.js";
|
||||
import { formatDurationSeconds } from "../../../../src/infra/format-time/format-duration.ts";
|
||||
import { KeyedAsyncQueue } from "../../../../src/plugin-sdk/keyed-async-queue.js";
|
||||
import { createRunStateMachine } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { formatDurationSeconds } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
||||
import { danger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { materializeDiscordInboundJob, type DiscordInboundJob } from "./inbound-job.js";
|
||||
import type { RuntimeEnv } from "./message-handler.preflight.types.js";
|
||||
import { processDiscordMessage } from "./message-handler.process.js";
|
||||
|
|
|
|||
|
|
@ -8,16 +8,16 @@ import {
|
|||
ThreadUpdateListener,
|
||||
type User,
|
||||
} from "@buape/carbon";
|
||||
import type { OpenClawConfig } from "../../../../src/config/config.js";
|
||||
import { danger, logVerbose } from "../../../../src/globals.js";
|
||||
import { formatDurationSeconds } from "../../../../src/infra/format-time/format-duration.ts";
|
||||
import { enqueueSystemEvent } from "../../../../src/infra/system-events.js";
|
||||
import { createSubsystemLogger } from "../../../../src/logging/subsystem.js";
|
||||
import { resolveAgentRoute } from "../../../../src/routing/resolve-route.js";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { formatDurationSeconds } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
|
||||
import { danger, logVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import {
|
||||
readStoreAllowFromForDmPolicy,
|
||||
resolveDmGroupAccessWithLists,
|
||||
} from "../../../../src/security/dm-policy-shared.js";
|
||||
} from "openclaw/plugin-sdk/security-runtime";
|
||||
import {
|
||||
isDiscordGroupAllowedByPolicy,
|
||||
normalizeDiscordAllowList,
|
||||
|
|
@ -36,11 +36,9 @@ import { isThreadArchived } from "./thread-bindings.discord-api.js";
|
|||
import { closeDiscordThreadSessions } from "./thread-session-close.js";
|
||||
import { normalizeDiscordListenerTimeoutMs, runDiscordTaskWithTimeout } from "./timeouts.js";
|
||||
|
||||
type LoadedConfig = ReturnType<typeof import("../../../../src/config/config.js").loadConfig>;
|
||||
type RuntimeEnv = import("../../../../src/runtime.js").RuntimeEnv;
|
||||
type Logger = ReturnType<
|
||||
typeof import("../../../../src/logging/subsystem.js").createSubsystemLogger
|
||||
>;
|
||||
type LoadedConfig = ReturnType<typeof import("openclaw/plugin-sdk/config-runtime").loadConfig>;
|
||||
type RuntimeEnv = import("openclaw/plugin-sdk/runtime-env").RuntimeEnv;
|
||||
type Logger = ReturnType<typeof import("openclaw/plugin-sdk/runtime-env").createSubsystemLogger>;
|
||||
|
||||
export type DiscordMessageEvent = Parameters<MessageCreateListener["handle"]>[0];
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type { MockFn } from "openclaw/plugin-sdk/test-utils";
|
||||
import { vi } from "vitest";
|
||||
import type { MockFn } from "../../../../src/test-utils/vitest-mock-fn.js";
|
||||
|
||||
export const preflightDiscordMessageMock: MockFn = vi.fn();
|
||||
export const processDiscordMessageMock: MockFn = vi.fn();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { ChannelType } from "@buape/carbon";
|
||||
import type { OpenClawConfig } from "../../../../src/config/config.js";
|
||||
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { preflightDiscordMessage } from "./message-handler.preflight.js";
|
||||
import { createNoopThreadBindingManager } from "./thread-bindings.js";
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ export function createDiscordPreflightArgs(params: {
|
|||
discordConfig: params.discordConfig,
|
||||
accountId: "default",
|
||||
token: "token",
|
||||
runtime: {} as import("../../../../src/runtime.js").RuntimeEnv,
|
||||
runtime: {} as import("openclaw/plugin-sdk/runtime-env").RuntimeEnv,
|
||||
botUserId: params.botUserId ?? "openclaw-bot",
|
||||
guildHistories: new Map(),
|
||||
historyLimit: 0,
|
||||
|
|
|
|||
|
|
@ -1,36 +1,33 @@
|
|||
import { ChannelType, MessageType, type User } from "@buape/carbon";
|
||||
import { formatAllowlistMatchMeta } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { resolveControlCommandGate } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { logInboundDrop } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { resolveMentionGatingWithBypass } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { loadConfig } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/config-runtime";
|
||||
import {
|
||||
ensureConfiguredAcpRouteReady,
|
||||
resolveConfiguredAcpRoute,
|
||||
} from "../../../../src/acp/persistent-bindings.route.js";
|
||||
import { hasControlCommand } from "../../../../src/auto-reply/command-detection.js";
|
||||
import { shouldHandleTextCommands } from "../../../../src/auto-reply/commands-registry.js";
|
||||
import {
|
||||
recordPendingHistoryEntryIfEnabled,
|
||||
type HistoryEntry,
|
||||
} from "../../../../src/auto-reply/reply/history.js";
|
||||
import {
|
||||
buildMentionRegexes,
|
||||
matchesMentionWithExplicit,
|
||||
} from "../../../../src/auto-reply/reply/mentions.js";
|
||||
import { formatAllowlistMatchMeta } from "../../../../src/channels/allowlist-match.js";
|
||||
import { resolveControlCommandGate } from "../../../../src/channels/command-gating.js";
|
||||
import { logInboundDrop } from "../../../../src/channels/logging.js";
|
||||
import { resolveMentionGatingWithBypass } from "../../../../src/channels/mention-gating.js";
|
||||
import { loadConfig } from "../../../../src/config/config.js";
|
||||
import { isDangerousNameMatchingEnabled } from "../../../../src/config/dangerous-name-matching.js";
|
||||
import { logVerbose, shouldLogVerbose } from "../../../../src/globals.js";
|
||||
import { recordChannelActivity } from "../../../../src/infra/channel-activity.js";
|
||||
} from "openclaw/plugin-sdk/conversation-runtime";
|
||||
import {
|
||||
getSessionBindingService,
|
||||
type SessionBindingRecord,
|
||||
} from "../../../../src/infra/outbound/session-binding-service.js";
|
||||
import { enqueueSystemEvent } from "../../../../src/infra/system-events.js";
|
||||
import { logDebug } from "../../../../src/logger.js";
|
||||
import { getChildLogger } from "../../../../src/logging.js";
|
||||
import { buildPairingReply } from "../../../../src/pairing/pairing-messages.js";
|
||||
import { isPluginOwnedSessionBindingRecord } from "../../../../src/plugins/conversation-binding.js";
|
||||
import { DEFAULT_ACCOUNT_ID } from "../../../../src/routing/session-key.js";
|
||||
} from "openclaw/plugin-sdk/conversation-runtime";
|
||||
import { buildPairingReply } from "openclaw/plugin-sdk/conversation-runtime";
|
||||
import { isPluginOwnedSessionBindingRecord } from "openclaw/plugin-sdk/conversation-runtime";
|
||||
import { recordChannelActivity } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { enqueueSystemEvent } from "openclaw/plugin-sdk/infra-runtime";
|
||||
import { hasControlCommand } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { shouldHandleTextCommands } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import {
|
||||
recordPendingHistoryEntryIfEnabled,
|
||||
type HistoryEntry,
|
||||
} from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { buildMentionRegexes, matchesMentionWithExplicit } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/routing";
|
||||
import { logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { getChildLogger } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { logDebug } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { fetchPluralKitMessageInfo } from "../pluralkit.js";
|
||||
import { sendMessageDiscord } from "../send.js";
|
||||
import {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import type { ChannelType, Client, User } from "@buape/carbon";
|
||||
import type { HistoryEntry } from "../../../../src/auto-reply/reply/history.js";
|
||||
import type { ReplyToMode } from "../../../../src/config/config.js";
|
||||
import type { SessionBindingRecord } from "../../../../src/infra/outbound/session-binding-service.js";
|
||||
import type { resolveAgentRoute } from "../../../../src/routing/resolve-route.js";
|
||||
import type { ReplyToMode } from "openclaw/plugin-sdk/config-runtime";
|
||||
import type { SessionBindingRecord } from "openclaw/plugin-sdk/conversation-runtime";
|
||||
import type { HistoryEntry } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import type { resolveAgentRoute } from "openclaw/plugin-sdk/routing";
|
||||
import type { DiscordChannelConfigResolved, DiscordGuildEntryResolved } from "./allow-list.js";
|
||||
import type { DiscordChannelInfo } from "./message-utils.js";
|
||||
import type { DiscordThreadBindingLookup } from "./reply-delivery.js";
|
||||
|
|
@ -11,15 +11,17 @@ import type { DiscordSenderIdentity } from "./sender-identity.js";
|
|||
export type { DiscordSenderIdentity } from "./sender-identity.js";
|
||||
import type { DiscordThreadChannel } from "./threading.js";
|
||||
|
||||
export type LoadedConfig = ReturnType<typeof import("../../../../src/config/config.js").loadConfig>;
|
||||
export type RuntimeEnv = import("../../../../src/runtime.js").RuntimeEnv;
|
||||
export type LoadedConfig = ReturnType<
|
||||
typeof import("openclaw/plugin-sdk/config-runtime").loadConfig
|
||||
>;
|
||||
export type RuntimeEnv = import("openclaw/plugin-sdk/runtime-env").RuntimeEnv;
|
||||
|
||||
export type DiscordMessageEvent = import("./listeners.js").DiscordMessageEvent;
|
||||
|
||||
type DiscordMessagePreflightSharedFields = {
|
||||
cfg: LoadedConfig;
|
||||
discordConfig: NonNullable<
|
||||
import("../../../../src/config/config.js").OpenClawConfig["channels"]
|
||||
import("openclaw/plugin-sdk/config-runtime").OpenClawConfig["channels"]
|
||||
>["discord"];
|
||||
accountId: string;
|
||||
token: string;
|
||||
|
|
|
|||
|
|
@ -1,40 +1,40 @@
|
|||
import { ChannelType, type RequestClient } from "@buape/carbon";
|
||||
import { resolveAckReaction, resolveHumanDelayConfig } from "../../../../src/agents/identity.js";
|
||||
import { EmbeddedBlockChunker } from "../../../../src/agents/pi-embedded-block-chunker.js";
|
||||
import { resolveChunkMode } from "../../../../src/auto-reply/chunk.js";
|
||||
import { dispatchInboundMessage } from "../../../../src/auto-reply/dispatch.js";
|
||||
import {
|
||||
formatInboundEnvelope,
|
||||
resolveEnvelopeFormatOptions,
|
||||
} from "../../../../src/auto-reply/envelope.js";
|
||||
import {
|
||||
buildPendingHistoryContextFromMap,
|
||||
clearHistoryEntriesIfEnabled,
|
||||
} from "../../../../src/auto-reply/reply/history.js";
|
||||
import { finalizeInboundContext } from "../../../../src/auto-reply/reply/inbound-context.js";
|
||||
import { createReplyDispatcherWithTyping } from "../../../../src/auto-reply/reply/reply-dispatcher.js";
|
||||
import type { ReplyPayload } from "../../../../src/auto-reply/types.js";
|
||||
import { shouldAckReaction as shouldAckReactionGate } from "../../../../src/channels/ack-reactions.js";
|
||||
import { logTypingFailure, logAckFailure } from "../../../../src/channels/logging.js";
|
||||
import { createReplyPrefixOptions } from "../../../../src/channels/reply-prefix.js";
|
||||
import { recordInboundSession } from "../../../../src/channels/session.js";
|
||||
import { resolveAckReaction, resolveHumanDelayConfig } from "openclaw/plugin-sdk/agent-runtime";
|
||||
import { EmbeddedBlockChunker } from "openclaw/plugin-sdk/agent-runtime";
|
||||
import { shouldAckReaction as shouldAckReactionGate } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { logTypingFailure, logAckFailure } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { createReplyPrefixOptions } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { recordInboundSession } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import {
|
||||
createStatusReactionController,
|
||||
DEFAULT_TIMING,
|
||||
type StatusReactionAdapter,
|
||||
} from "../../../../src/channels/status-reactions.js";
|
||||
import { createTypingCallbacks } from "../../../../src/channels/typing.js";
|
||||
import { isDangerousNameMatchingEnabled } from "../../../../src/config/dangerous-name-matching.js";
|
||||
import { resolveDiscordPreviewStreamMode } from "../../../../src/config/discord-preview-streaming.js";
|
||||
import { resolveMarkdownTableMode } from "../../../../src/config/markdown-tables.js";
|
||||
import { readSessionUpdatedAt, resolveStorePath } from "../../../../src/config/sessions.js";
|
||||
import { danger, logVerbose, shouldLogVerbose } from "../../../../src/globals.js";
|
||||
import { convertMarkdownTables } from "../../../../src/markdown/tables.js";
|
||||
import { getAgentScopedMediaLocalRoots } from "../../../../src/media/local-roots.js";
|
||||
import { buildAgentSessionKey } from "../../../../src/routing/resolve-route.js";
|
||||
import { resolveThreadSessionKeys } from "../../../../src/routing/session-key.js";
|
||||
import { stripReasoningTagsFromText } from "../../../../src/shared/text/reasoning-tags.js";
|
||||
import { truncateUtf16Safe } from "../../../../src/utils.js";
|
||||
} from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { createTypingCallbacks } from "openclaw/plugin-sdk/channel-runtime";
|
||||
import { isDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { resolveDiscordPreviewStreamMode } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { readSessionUpdatedAt, resolveStorePath } from "openclaw/plugin-sdk/config-runtime";
|
||||
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime";
|
||||
import { resolveChunkMode } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { dispatchInboundMessage } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import {
|
||||
formatInboundEnvelope,
|
||||
resolveEnvelopeFormatOptions,
|
||||
} from "openclaw/plugin-sdk/reply-runtime";
|
||||
import {
|
||||
buildPendingHistoryContextFromMap,
|
||||
clearHistoryEntriesIfEnabled,
|
||||
} from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { finalizeInboundContext } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { createReplyDispatcherWithTyping } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import type { ReplyPayload } from "openclaw/plugin-sdk/reply-runtime";
|
||||
import { buildAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
||||
import { resolveThreadSessionKeys } from "openclaw/plugin-sdk/routing";
|
||||
import { danger, logVerbose, shouldLogVerbose } from "openclaw/plugin-sdk/runtime-env";
|
||||
import { convertMarkdownTables } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-runtime";
|
||||
import { resolveDiscordMaxLinesPerMessage } from "../accounts.js";
|
||||
import { chunkDiscordTextWithMode } from "../chunk.js";
|
||||
import { resolveDiscordDraftStreamingChunking } from "../draft-chunking.js";
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue