Compare commits

..

100 Commits

Author SHA1 Message Date
Vincent Koc
10b3f2cbc7 perf(ci): trigger install smoke only for install surfaces 2026-03-22 13:15:07 -07:00
Peter Steinberger
3025760867 perf: shrink unit fork exception manifest 2026-03-22 13:10:55 -07:00
Peter Steinberger
e04d203bff test: remove heartbeat runner jiti mock pollution 2026-03-22 13:10:55 -07:00
Peter Steinberger
cf8891a824 fix: stabilize docker live test lanes 2026-03-22 20:07:27 +00:00
Jacob Tomlinson
43ee9fff48 docs: fix message hook context fields and session-memory example output 2026-03-22 20:01:30 +00:00
Vincent Koc
4bd90f24d1 perf(ci): gate install smoke on changed-smoke (#52458) 2026-03-22 12:58:08 -07:00
Onur Solmaz
b369397b43 ACP: revert acpx-plugin package naming (#52456)
* ACP: revert acpx-plugin package naming

* Test: format acp install hints expectations
2026-03-22 20:55:48 +01:00
Peter Steinberger
ff941b0193 refactor: share nested account config merges 2026-03-22 19:53:51 +00:00
Peter Steinberger
6fa0027c61 refactor: simplify tlon and discord setup accounts 2026-03-22 19:53:51 +00:00
Vincent Koc
9bb5eb6c7f fix(test): repair channel regression suites 2026-03-22 12:51:36 -07:00
Peter Steinberger
0404c16217 test: harden media local roots path assertions 2026-03-22 19:47:11 +00:00
Peter Steinberger
16616e21df refactor: share synology chat account helpers 2026-03-22 19:45:59 +00:00
Peter Steinberger
3c071a397f refactor: share account id selection helpers 2026-03-22 19:45:59 +00:00
Peter Steinberger
bddb6fca7b refactor: share remaining account config helpers 2026-03-22 19:45:59 +00:00
Vincent Koc
66beff726b perf(ci): trim install smoke overhead (#52447)
* perf(ci): trim install smoke overhead

* perf(ci): skip discord opus native build noise

* fix(ci): use npm latest dist-tag in install smoke
2026-03-22 12:44:47 -07:00
Peter Steinberger
bd108dfe00 test: fix CI contract drift in channel suites 2026-03-22 19:44:10 +00:00
Vincent Koc
59837b25bd fix(doctor): scope discord off hint to legacy migration 2026-03-22 12:42:47 -07:00
Peter Steinberger
285f903462 test: flatten feishu docx hoisted mocks 2026-03-22 12:41:17 -07:00
Peter Steinberger
0329412af2 docs: note extension vitest threads default 2026-03-22 12:38:42 -07:00
Peter Steinberger
c1067e90c9 perf: default extension vitest lanes to threads 2026-03-22 12:38:42 -07:00
Peter Steinberger
fdc993e779 test: fix extension thread proof regressions 2026-03-22 12:38:42 -07:00
Vincent Koc
5f723ecd7f fix(doctor): explain discord streaming opt-in (#52450) 2026-03-22 12:37:03 -07:00
Peter Steinberger
c26655d397 fix: stabilize plugin sdk api baselines 2026-03-22 19:32:29 +00:00
Peter Steinberger
4240c64491 test: harden no-isolate oauth contract coverage 2026-03-22 12:31:36 -07:00
Peter Steinberger
52b9d2091e fix: ignore poisoned home env values 2026-03-22 12:31:36 -07:00
Peter Steinberger
c0f107e246 docs: note no-isolate cleanup expectations 2026-03-22 12:31:36 -07:00
Peter Steinberger
5b2ff17d3c chore: refresh plugin sdk api baselines 2026-03-22 19:30:15 +00:00
Vincent Koc
dbd26e49f1 fix(test): reduce startup-heavy hotspot retention (#52381) 2026-03-22 12:28:55 -07:00
Peter Steinberger
26d400bea6 docs: note unit vitest threads default 2026-03-22 12:25:51 -07:00
Peter Steinberger
e39d5b9ef8 perf: default unit vitest lanes to threads 2026-03-22 12:25:51 -07:00
Peter Steinberger
e64dbb00b3 fix: prefer source plugin-sdk root alias in tests 2026-03-22 12:25:51 -07:00
Vincent Koc
f85cfc8b6c fix(gateway): harden first-turn startup readiness (#52387)
* fix(gateway): harden first-turn startup readiness

* fix(gateway): scope startup model retry
2026-03-22 12:12:08 -07:00
Peter Steinberger
aef2c60aa5 test: fix no-isolate canvas and timer regressions 2026-03-22 12:10:08 -07:00
Peter Steinberger
e80d456608 fix: restore CI install and format checks 2026-03-22 19:09:46 +00:00
Peter Steinberger
c69b1da6a0 perf: expand base vitest thread lanes further 2026-03-22 12:08:45 -07:00
Vincent Koc
2ef4d472f2 fix(install): restore memory-core workspace link 2026-03-22 12:06:44 -07:00
Peter Steinberger
1822db9227 test: harden no-isolate timer and undici seams 2026-03-22 12:04:11 -07:00
Peter Steinberger
1b1167012f test(cli): split plugin cli test coverage by surface 2026-03-22 12:02:53 -07:00
Peter Steinberger
e3151af6bc refactor(cli): extract hook pack update flow 2026-03-22 12:02:52 -07:00
Peter Steinberger
5696e24c3f refactor(cli): use typed clawhub fallback decisions 2026-03-22 12:02:52 -07:00
Peter Steinberger
145e514bb5 refactor(cli): share plugin install persistence 2026-03-22 12:02:52 -07:00
Peter Steinberger
5920ea838d refactor(cli): extract plugin install and update commands 2026-03-22 12:02:52 -07:00
Peter Steinberger
c74a50e4f1 refactor: share merged account config helper 2026-03-22 19:01:52 +00:00
Peter Steinberger
d06413e335 refactor: share normalized account lookups 2026-03-22 19:01:52 +00:00
Peter Steinberger
017d295edb refactor: adopt shared account merge helpers 2026-03-22 19:01:52 +00:00
Peter Steinberger
ff759f991e refactor: share account config merge helper 2026-03-22 19:01:52 +00:00
Peter Steinberger
7ae09410b7 refactor: reuse shared account config lookups 2026-03-22 19:01:52 +00:00
Peter Steinberger
8e09568bc7 perf: expand base vitest thread lanes 2026-03-22 11:59:38 -07:00
Peter Steinberger
412a3eb1ac build: bump version to 2026.3.22 2026-03-22 11:58:33 -07:00
Vincent Koc
4113db7d78 fix(protocol): sync generated swift bindings 2026-03-22 11:58:25 -07:00
Vincent Koc
dbf3dd6559 docs: update plugin install references for ClawHub-first default
OpenClaw now tries ClawHub before npm for bare plugin specs.
Update install examples and guidance across:
- building-plugins.md: intro and publish step
- sdk-setup.md: publishing section with clawhub:/npm: prefix examples
- tools/plugin.md: CLI reference table
- community.md: submission guidance and quality bar
2026-03-22 11:58:11 -07:00
Vincent Koc
6d9d9319b2 fix(docs): resolve markdownlint regressions 2026-03-22 11:56:06 -07:00
Vincent Koc
1f93a99f47 docs(plugins): overhaul SDK pages with Mintlify components and IA restructure
- Rewrite building-plugins.md as focused quick-start with CardGroup routing
- Rewrite sdk-channel-plugins.md with Steps, CodeGroup, Accordion walkthrough
- Move SDK Migration under Building Plugins nav, rename to "Migrate to SDK"
- Fix code examples and use valid Lucide icons for Mintlify Cards
2026-03-22 11:51:09 -07:00
Vincent Koc
8f12303a72 fix(ci): unblock rc build and drift checks (#52429) 2026-03-22 11:50:52 -07:00
Peter Steinberger
c40488453e test: remove thread-unsafe cwd mutations 2026-03-22 11:47:28 -07:00
Peter Steinberger
7d1ab5baca fix: restore CI type and baseline checks 2026-03-22 18:46:50 +00:00
Peter Steinberger
75692249d2 perf: expand vitest thread lanes again 2026-03-22 11:40:03 -07:00
Vincent Koc
28838802d4 docs(plugins): add SDK reference and how-to guide pages (#52366)
* docs(plugins): add SDK reference and how-to guide pages

Create 7 new plugin SDK documentation pages:
- sdk-overview: import map, registration API reference
- sdk-entrypoints: definePluginEntry/defineChannelPluginEntry reference
- sdk-runtime: api.runtime namespace reference
- sdk-setup: packaging, manifests, config schemas reference
- sdk-channel-plugins: step-by-step channel plugin how-to
- sdk-provider-plugins: step-by-step provider plugin how-to
- sdk-testing: test utilities and patterns reference

Restructure plugin docs navigation with nested groups:
- Top-level: user-facing pages (Install, Community, Bundles)
- Building Plugins: Getting Started, Channel, Provider
- SDK Reference: Overview, Entry Points, Runtime, Setup, Testing, Migration, Manifest, Internals

Revise existing pages for new IA:
- building-plugins.md: tightened as quick-start, routes to detailed guides
- architecture.md: updated info box with links to new guides
- sdk-migration.md: expanded Related section

* docs(plugins): add Mintlify components (Steps, CodeGroup, Tabs, Accordion, CardGroup)

- Channel plugin guide: wrap walkthrough in Steps, use CodeGroup for
  package.json/manifest, Accordion for createChatChannelPlugin details,
  CardGroup for advanced topics
- Provider plugin guide: wrap walkthrough in Steps, use CodeGroup for
  package files, Tabs for hook examples, Accordion for all-hooks reference
- Getting started: use CardGroup for plugin-type picker and next steps,
  CodeGroup for package/manifest
- SDK Overview: wrap subpath tables in AccordionGroup for scannability

* fix(docs): address PR review feedback on plugin SDK pages

- Remove nonexistent api.runtime.channel.handleInboundMessage call,
  replace with realistic webhook pattern and note about channel-specific
  inbound handling (issue a)
- Fix registrationMode values: 'setup' -> 'setup-only' and 'setup-runtime'
  matching actual PluginRegistrationMode type (issue b)
- Fix createOptionalChannelSetupSurface params: channelId -> channel,
  add required label field (issue c)
- Fix broken anchor links: #multi-capability-providers ->
  #step-5-add-extra-capabilities, #plugin-kinds -> #registration-api (issue d)
- Add missing acmeChatApi import in channel plugin example (issue e)
- Fix undefined provider variable in provider test example (issue f)

* fix(docs): use correct createProviderApiKeyAuthMethod options

Replace incorrect params (provider, validate) with actual required fields
(providerId, methodId, optionKey, flagName, promptMessage) matching
src/plugins/provider-api-key-auth.ts.

* fix(docs): address second round of PR review feedback

- Add required model fields (reasoning, input, cost, contextWindow,
  maxTokens) to catalog example (issue b)
- Fix buildChannelConfigSchema to take a Zod schema argument (issue c)
- Replace fabricated setupWizard steps/run with real ChannelSetupWizard
  contract (channel, status, credentials) (issue d)
- Add required sessionFile/workspaceDir to runEmbeddedPiAgent (issue e)
- Fix wrapStreamFn to return StreamFn from ctx.streamFn (issue f)
2026-03-22 11:35:53 -07:00
Peter Steinberger
1ed40cdf54 perf: expand vitest thread lanes further 2026-03-22 11:34:19 -07:00
Onur Solmaz
b79560c7f0 ACP: fully rename acpx plugin (#52404)
* ACP: rename acpx plugin package

* ACP: fully rename acpx plugin

* ACP: remove old acpx paths

* Docs: add bundled plugin naming guardrails

* Docs: keep plugin naming guardrails internal

* ACP: keep acpx plugin id stable

* ACP: drop old acpx-plugin tree
2026-03-22 19:33:31 +01:00
Peter Steinberger
59b5583e0a test: merge registry-backed channel contract suites 2026-03-22 18:31:52 +00:00
Peter Steinberger
04b283ffc2 fix: restore clawhub archive installs and gateway params 2026-03-22 18:31:52 +00:00
Peter Steinberger
95ae8aabb7 perf: expand vitest thread lanes 2026-03-22 11:26:38 -07:00
Peter Steinberger
aa80b1eb7c feat(cli): unify hook pack installs under plugins 2026-03-22 11:20:50 -07:00
Peter Steinberger
b44152fcc8 perf: automate vitest thread candidate scans 2026-03-22 11:19:10 -07:00
Peter Steinberger
8d9686bd0f feat!: prefer clawhub plugin installs before npm 2026-03-22 18:17:45 +00:00
Peter Steinberger
13c239039a refactor: consolidate qmd mcporter state 2026-03-22 18:09:45 +00:00
Peter Steinberger
23a6e0ccd3 refactor: share remaining runtime listener state 2026-03-22 18:09:45 +00:00
Peter Steinberger
17739910e9 refactor: centralize channel plugin registry lookups 2026-03-22 18:09:45 +00:00
Peter Steinberger
2c919078e1 refactor: share memory and discord singleton state 2026-03-22 18:09:45 +00:00
Peter Steinberger
88d39b1542 refactor: simplify remaining runtime singletons 2026-03-22 18:09:45 +00:00
Peter Steinberger
89d65521fe refactor: dedupe extension runtime caches 2026-03-22 18:09:45 +00:00
Peter Steinberger
f095bbd7b0 refactor: simplify plugin runtime singletons 2026-03-22 18:09:45 +00:00
Peter Steinberger
9428b38452 refactor: consolidate core runtime state helpers 2026-03-22 18:09:45 +00:00
Peter Steinberger
ca986d05aa test: trim repeated archive install work 2026-03-22 18:05:44 +00:00
Peter Steinberger
1ceaad18a6 test: harden vitest no-isolate coverage 2026-03-22 10:48:21 -07:00
Peter Steinberger
719bfb46ff style: format macos sources for ci 2026-03-22 17:32:30 +00:00
Onur Solmaz
047485dda6 docs: improve plugin manifest reference (#52393)
* docs: improve plugin manifest reference

* docs: clarify manifest field semantics
2026-03-22 18:29:20 +01:00
Peter Steinberger
405d808409 fix: restore repo-wide gate after exec safe-bin refactor 2026-03-22 17:28:04 +00:00
Peter Steinberger
5863ce1f78 fix(media): narrow default local attachment roots 2026-03-22 10:24:47 -07:00
Peter Steinberger
2a66eaf473 test: harden voice call regression assertions 2026-03-22 17:23:01 +00:00
Peter Steinberger
c8a36c621e test: tighten msteams regression assertions 2026-03-22 17:23:01 +00:00
Peter Steinberger
14074d3337 fix: restore repo-wide gate after upstream sync 2026-03-22 17:16:43 +00:00
Peter Steinberger
0ac939059e refactor(exec): split safe-bin semantics 2026-03-22 10:14:46 -07:00
Kaneki
d551d8b8f7 fix: make Android current-location callback cancellation-safe (#52318) (thanks @Kaneki-x)
* Android: make current-location callback cancellation-safe

* fix: make Android current-location callback cancellation-safe (#52318) (thanks @Kaneki-x)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-22 22:40:45 +05:30
Peter Steinberger
af90ddd8d3 test: harden voice call manager regressions 2026-03-22 17:07:20 +00:00
Peter Steinberger
36c951769c test: harden voice call provider regressions 2026-03-22 17:07:20 +00:00
Peter Steinberger
689a7342c2 test: tighten msteams regression assertions 2026-03-22 17:07:20 +00:00
Peter Steinberger
090ac8831f test: tighten pairing and phone control assertions 2026-03-22 17:07:20 +00:00
Peter Steinberger
6c2a3b74e3 fix(exec): harden jq safe-bin policy 2026-03-22 10:04:40 -07:00
Peter Steinberger
91b2800241 feat: add native clawhub install flows 2026-03-22 17:03:49 +00:00
Kaneki
c7788773bf fix: serialize TalkModeManager player cleanup (#52310) (thanks @Kaneki-x)
* Android: fix MediaPlayer double-release race in TalkModeManager

* Android: guard currentPosition read against concurrent player release

* fix: serialize TalkModeManager player cleanup

* fix: serialize TalkModeManager player cleanup (#52310) (thanks @Kaneki-x)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-22 22:31:30 +05:30
Peter Steinberger
5cb2f45585 refactor(hooks): unify hook policy resolution 2026-03-22 09:59:51 -07:00
Peter Steinberger
c96c319db3 refactor(plugin-sdk): share direct dm ingress helpers 2026-03-22 09:57:51 -07:00
Peter Steinberger
8a111f1cb9 test: harden discord monitor regression assertions 2026-03-22 16:56:44 +00:00
Peter Steinberger
b0176f626c test: tighten discord model picker regressions 2026-03-22 16:56:41 +00:00
Peter Steinberger
279c0c621f test: harden integration provider regressions 2026-03-22 16:49:24 +00:00
Peter Steinberger
68170f99ac test: tighten discord monitor regression assertions 2026-03-22 16:49:16 +00:00
Peter Steinberger
42f23619e3 fix(hooks): harden workspace hook loading 2026-03-22 09:38:09 -07:00
Peter Steinberger
1ee9611079 fix(nostr): enforce inbound dm policy before decrypt 2026-03-22 09:37:40 -07:00
479 changed files with 15372 additions and 7034 deletions

View File

@@ -15,7 +15,7 @@ on:
workflow_dispatch:
inputs:
tag:
description: Existing release tag to backfill (for example v2026.3.13)
description: Existing release tag to backfill (for example v2026.3.22)
required: true
type: string

View File

@@ -3,8 +3,32 @@ name: Install Smoke
on:
push:
branches: [main]
paths:
- "Dockerfile"
- ".npmrc"
- "package.json"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"
- "scripts/install.sh"
- "scripts/test-install-sh-docker.sh"
- "scripts/docker/**"
- "extensions/*/package.json"
- ".github/workflows/install-smoke.yml"
- ".github/actions/setup-node-env/action.yml"
pull_request:
types: [opened, reopened, synchronize, ready_for_review, converted_to_draft]
paths:
- "Dockerfile"
- ".npmrc"
- "package.json"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"
- "scripts/install.sh"
- "scripts/test-install-sh-docker.sh"
- "scripts/docker/**"
- "extensions/*/package.json"
- ".github/workflows/install-smoke.yml"
- ".github/actions/setup-node-env/action.yml"
workflow_dispatch:
concurrency:
@@ -15,32 +39,12 @@ env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
docs-scope:
install-smoke:
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
runs-on: blacksmith-16vcpu-ubuntu-2404
outputs:
docs_only: ${{ steps.check.outputs.docs_only }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 1
fetch-tags: false
- name: Ensure docs-scope base commit
uses: ./.github/actions/ensure-base-commit
with:
base-sha: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
fetch-ref: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }}
- name: Detect docs-only changes
id: check
uses: ./.github/actions/detect-docs-changes
install-smoke:
needs: [docs-scope]
if: (github.event_name != 'pull_request' || !github.event.pull_request.draft) && needs.docs-scope.outputs.docs_only != 'true'
runs-on: blacksmith-16vcpu-ubuntu-2404
env:
DOCKER_BUILD_SUMMARY: "false"
DOCKER_BUILD_RECORD_UPLOAD: "false"
steps:
- name: Checkout CLI
uses: actions/checkout@v6
@@ -55,6 +59,8 @@ jobs:
with:
context: .
file: ./Dockerfile
build-args: |
OPENCLAW_DOCKER_APT_UPGRADE=0
tags: openclaw-dockerfile-smoke:local
load: true
push: false
@@ -73,6 +79,7 @@ jobs:
context: .
file: ./Dockerfile
build-args: |
OPENCLAW_DOCKER_APT_UPGRADE=0
OPENCLAW_EXTENSIONS=matrix
tags: openclaw-ext-smoke:local
load: true

View File

@@ -7,7 +7,7 @@ on:
workflow_dispatch:
inputs:
tag:
description: Release tag to publish (for example v2026.3.14, v2026.3.14-beta.1, or fallback v2026.3.14-1)
description: Release tag to publish (for example v2026.3.22, v2026.3.22-beta.1, or fallback v2026.3.22-1)
required: true
type: string

View File

@@ -10,6 +10,7 @@
- Tests: colocated `*.test.ts`.
- Docs: `docs/` (images, queue, Pi config). Built output lives in `dist/`.
- Nomenclature: use "plugin" / "plugins" in docs, UI, changelogs, and contributor guidance. `extensions/*` remains the internal directory/package path to avoid repo-wide churn from a rename.
- Bundled plugin naming: for repo-owned workspace plugins, keep the canonical plugin id aligned across `openclaw.plugin.json:id`, `extensions/<id>` by default, and package names anchored to the same id (`@openclaw/<id>` or approved suffix forms like `-provider`, `-plugin`, `-speech`, `-sandbox`). Keep `openclaw.install.npmSpec` equal to the package name and `openclaw.channel.id` equal to the plugin id when present. Exceptions must be explicit and covered by the repo invariant test.
- Plugins: live under `extensions/*` (workspace packages). Keep plugin-only deps in the extension `package.json`; do not add them to the root `package.json` unless core uses them.
- Plugins: install runs `npm install --omit=dev` in plugin dir; runtime deps must live in `dependencies`. Avoid `workspace:*` in `dependencies` (npm install breaks); put `openclaw` in `devDependencies` or `peerDependencies` instead (runtime resolves `openclaw/plugin-sdk` via jiti alias).
- Import boundaries: extension production code should treat `openclaw/plugin-sdk/*` plus local `api.ts` / `runtime-api.ts` barrels as the public surface. Do not import core `src/**`, `src/plugin-sdk-internal/**`, or another extension's `src/**` directly.
@@ -113,6 +114,7 @@
- Framework: Vitest with V8 coverage thresholds (70% lines/branches/functions/statements).
- Naming: match source names with `*.test.ts`; e2e in `*.e2e.test.ts`.
- Run `pnpm test` (or `pnpm test:coverage`) before pushing when you touch logic.
- Write tests to clean up timers, env, globals, mocks, sockets, temp dirs, and module state so `--isolate=false` stays green.
- Agents MUST NOT modify baseline, inventory, ignore, snapshot, or expected-failure files to silence failing checks without explicit approval in this chat.
- For targeted/local debugging, keep using the wrapper: `pnpm test -- <path-or-filter> [vitest args...]` (for example `pnpm test -- src/commands/onboard-search.test.ts -t "shows registered plugin providers"`); do not default to raw `pnpm vitest run ...` because it bypasses wrapper config/profile/pool routing.
- Do not set test workers above 16; tried already.

View File

@@ -6,6 +6,8 @@ Docs: https://docs.openclaw.ai
### Changes
- Breaking/Plugins: bare `openclaw plugins install <package>` now prefers ClawHub before npm for npm-safe names, and only falls back to npm when ClawHub does not have that package or version.
- ClawHub/install: add native `openclaw skills search|install|update` flows plus `openclaw plugins install clawhub:<package>` with tracked update metadata, gateway skill-install/update support for ClawHub-backed requests, and regression coverage/docs for the new source path.
- Models/Anthropic Vertex: add core `anthropic-vertex` provider support for Claude via Google Vertex AI, including GCP auth/discovery and main run-path routing. (#43356) Thanks @sallyom and @yossiovadia.
- Commands/btw: add `/btw` side questions for quick tool-less answers about the current session without changing future session context, with dismissible in-session TUI answers and explicit BTW replies on external channels. (#45444) Thanks @ngutman.
- Gateway/docs: clarify that empty URL input allowlists are treated as unset, document `allowUrl: false` as the deny-all switch, and add regression coverage for the normalization path.
@@ -65,17 +67,22 @@ Docs: https://docs.openclaw.ai
- Control UI/usage: improve usage overview styling, localization, and responsive chat/context-notice presentation, including safer theme color handling and unclipped usage-header menus. (#51951) Thanks @BunsDev.
- Agents: add per-agent thinking/reasoning/fast defaults and auto-revert disallowed model overrides to the agent's default selection. Thanks @xuanmingguo and @vincentkoc.
- Control UI/usage: drop the empty session-detail placeholder card so the usage view stays single-column until a real session detail panel is selected. (#52013) Thanks @BunsDev.
- Hooks/workspace: keep repo-local `<workspace>/hooks` disabled until explicitly enabled, block workspace hook name collisions from shadowing bundled/managed/plugin hooks, and treat `hooks.internal.load.extraDirs` as trusted managed hook sources.
- CLI/hooks: route hook-pack install and update through `openclaw plugins`, keep `openclaw hooks` focused on hook visibility and per-hook controls, and show plugin-managed hook details in CLI output.
### Fixes
- Nostr/security: enforce inbound DM policy before decrypt, route Nostr DMs through the standard reply pipeline, and add pre-crypto rate and size guards so unknown senders cannot bypass pairing or force unbounded crypto work. Thanks @kuranikaran.
- Agents/default timeout: raise the shared default agent timeout from `600s` to `48h` so long-running ACP and agent sessions do not fail unless you configure a shorter limit.
- Gateway/Linux: auto-detect nvm-managed Node TLS CA bundle needs before CLI startup and refresh installed services that are missing `NODE_EXTRA_CA_CERTS`. (#51146) Thanks @GodsBoy.
- Android/pairing: resolve portless secure setup URLs to `443` while preserving direct cleartext gateway defaults and explicit `:80` manual endpoints in onboarding. (#43540) Thanks @fmercurio.
- CLI/config: make `config set --strict-json` enforce real JSON, prefer `JSON.parse` with JSON5 fallback for machine-written cron/subagent stores, and relabel raw config surfaces as `JSON/JSON5` to match actual compatibility. Related: #48415, #43127, #14529, #21332. Thanks @adhitShet and @vincentkoc.
- CLI/Ollama onboarding: keep the interactive model picker for explicit `openclaw onboard --auth-choice ollama` runs so setup still selects a default model without reintroducing pre-picker auto-pulls. (#49249) Thanks @BruceMacD.
- Android/location: make current-location requests drop late callbacks after timeout instead of crashing with `Already resumed`. (#52318) Thanks @Kaneki-x.
- Plugins/bundler TDZ: fix `RESERVED_COMMANDS` temporal dead zone error that prevented device-pair, phone-control, and talk-voice plugins from registering when the bundler placed the commands module after call sites in the same output chunk. Thanks @BunsDev.
- Plugins/imports: fix stale googlechat runtime-api import paths and signal SDK circular re-exports broken by recent plugin-sdk refactors. Thanks @BunsDev.
- Telegram/setup: seed fresh setups with `channels.telegram.groups["*"].requireMention=true` so new bots stay mention-gated in groups unless you explicitly open them up. Thanks @vincentkoc.
- Security/exec safe bins: remove `jq` from the default safe-bin allowlist and fail closed on the `jq` `env` builtin when operators explicitly opt `jq` back in, so `jq -n env` cannot dump host secrets without an explicit trust path. Thanks @gladiator9797 for reporting.
- Google auth/Node 25: patch `gaxios` to use native fetch without injecting `globalThis.window`, while translating proxy and mTLS transport settings so Google Vertex and Google Chat auth keep working on Node 25. (#47914) Thanks @pdd-cli.
- Gateway/startup: load bundled channel plugins from compiled `dist/extensions` entries in built installs, so gateway boot no longer recompiles bundled extension TypeScript on every startup and WhatsApp-class cold starts drop back to seconds instead of tens of seconds or worse. (#47560) Thanks @ngutman.
- Agents/openai-responses: strip `prompt_cache_key` and `prompt_cache_retention` for non-OpenAI-compatible Responses endpoints while keeping them on direct OpenAI and Azure OpenAI paths, so third-party OpenAI-compatible providers no longer reject those requests with HTTP 400. (#49877) Thanks @ShaunTsai.
@@ -116,6 +123,7 @@ Docs: https://docs.openclaw.ai
- Doctor/extensions: keep Matrix DM `allowFrom` repairs on the canonical `dm.allowFrom` path and stop treating Zalouser group sender gating as if it fell back to `allowFrom`, so doctor warnings and `--fix` stay aligned with runtime access control. Thanks @vincentkoc.
- Doctor/refactor: centralize built-in channel doctor semantics in one static capability registry with conservative fallback behavior for unknown/external channels, so future extension changes stop depending on scattered shared string checks. Thanks @vincentkoc.
- Models/OpenRouter runtime capabilities: fetch uncatalogued OpenRouter model metadata on first use so newly added vision models keep image input instead of silently degrading to text-only, with top-level capability field fallbacks for `/api/v1/models`. (#45824) Thanks @DJjjjhao.
- Gateway/startup: prewarm the configured primary model before channel startup and retry one transient provider-runtime miss so the first Telegram or Discord message after boot no longer fails with `Unknown model: openai-codex/gpt-5.4`. Thanks @vincentkoc.
- Channels/plugins: keep shared interactive payloads merge-ready by fixing Slack custom callback routing and repeat-click dedupe, allowing interactive-only sends, and preserving ordered Discord shared text blocks. (#47715) Thanks @vincentkoc.
- Slack/interactive replies: preserve `channelData.slack.blocks` through live DM delivery and preview-finalized edits so Block Kit button and select directives render instead of falling back to raw text. (#45890) Thanks @vincentkoc.
- Feishu/actions: expand the runtime action surface with message read/edit, explicit thread replies, pinning, and operator-facing chat/member inspection so Feishu can operate more of the workspace directly. (#47968) Thanks @Takhoffman.
@@ -241,6 +249,7 @@ Docs: https://docs.openclaw.ai
- Android/theme: switch status bar icon contrast with the active system theme so Android light mode no longer leaves unreadable light icons over the app header. (#51098) Thanks @goweii.
- Discord/ACP: forward worker abort signals into ACP turns so timed-out Discord jobs cancel the running turn instead of silently leaving the bound ACP session working in the background.
- Gateway/openresponses: preserve assistant commentary and session continuity across hosted-tool `/v1/responses` turns, and emit streamed tool-call payloads before finalization so client tool loops stay resumable. (#52171) Thanks @CharZhou.
- Android/Talk: serialize `TalkModeManager` player teardown so rapid interrupt/restart cycles stop double-releasing or overlapping TTS playback. (#52310) Thanks @Kaneki-x.
### Breaking

View File

@@ -14,6 +14,7 @@
# Slim (bookworm-slim): docker build --build-arg OPENCLAW_VARIANT=slim .
ARG OPENCLAW_EXTENSIONS=""
ARG OPENCLAW_VARIANT=default
ARG OPENCLAW_DOCKER_APT_UPGRADE=1
ARG OPENCLAW_NODE_BOOKWORM_IMAGE="node:24-bookworm@sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"
ARG OPENCLAW_NODE_BOOKWORM_DIGEST="sha256:3a09aa6354567619221ef6c45a5051b671f953f0a1924d1f819ffb236e520e6b"
ARG OPENCLAW_NODE_BOOKWORM_SLIM_IMAGE="node:24-bookworm-slim@sha256:e8e2e91b1378f83c5b2dd15f0247f34110e2fe895f6ca7719dbb780f929368eb"
@@ -113,6 +114,7 @@ LABEL org.opencontainers.image.base.name="docker.io/library/node:24-bookworm-sli
# ── Stage 3: Runtime ────────────────────────────────────────────
FROM base-${OPENCLAW_VARIANT}
ARG OPENCLAW_VARIANT
ARG OPENCLAW_DOCKER_APT_UPGRADE
# OCI base-image metadata for downstream image consumers.
# If you change these annotations, also update:
@@ -129,10 +131,14 @@ WORKDIR /app
# Install system utilities present in bookworm but missing in bookworm-slim.
# On the full bookworm image these are already installed (apt-get is a no-op).
# Smoke workflows can opt out of distro upgrades to cut repeated CI time while
# keeping the default runtime image behavior unchanged.
RUN --mount=type=cache,id=openclaw-bookworm-apt-cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,id=openclaw-bookworm-apt-lists,target=/var/lib/apt,sharing=locked \
apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \
if [ "${OPENCLAW_DOCKER_APT_UPGRADE}" != "0" ]; then \
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends; \
fi && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
procps hostname curl git lsof openssl

View File

@@ -65,8 +65,8 @@ android {
applicationId = "ai.openclaw.app"
minSdk = 31
targetSdk = 36
versionCode = 2026032000
versionName = "2026.3.20"
versionCode = 2026032200
versionName = "2026.3.22"
ndk {
// Support all major ABIs — native libs are tiny (~47 KB per ABI)
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")

View File

@@ -12,8 +12,6 @@ import java.time.format.DateTimeFormatter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlinx.coroutines.suspendCancellableCoroutine
class LocationCaptureManager(private val context: Context) {
@@ -100,18 +98,15 @@ class LocationCaptureManager(private val context: Context) {
val resolved =
providers.firstOrNull { manager.isProviderEnabled(it) }
?: throw IllegalStateException("LOCATION_UNAVAILABLE: no providers available")
return withTimeout(timeoutMs.coerceAtLeast(1)) {
suspendCancellableCoroutine { cont ->
val location = withTimeout(timeoutMs.coerceAtLeast(1)) {
suspendCancellableCoroutine<Location?> { cont ->
val signal = CancellationSignal()
cont.invokeOnCancellation { signal.cancel() }
manager.getCurrentLocation(resolved, signal, context.mainExecutor) { location ->
if (location != null) {
cont.resume(location)
} else {
cont.resumeWithException(IllegalStateException("LOCATION_UNAVAILABLE: no fix"))
}
cont.resume(location) { _, _, _ -> }
}
}
}
return location ?: throw IllegalStateException("LOCATION_UNAVAILABLE: no fix")
}
}

View File

@@ -104,6 +104,7 @@ class TalkModeManager(
private val playbackGeneration = AtomicLong(0L)
private var ttsJob: Job? = null
private val playerLock = Any()
private var player: MediaPlayer? = null
@Volatile private var finalizeInFlight = false
private var listenWatchdogJob: Job? = null
@@ -763,7 +764,9 @@ class TalkModeManager(
try {
withContext(Dispatchers.IO) { tempFile.writeBytes(audioBytes) }
val player = MediaPlayer()
this.player = player
synchronized(playerLock) {
this.player = player
}
val finished = CompletableDeferred<Unit>()
player.setAudioAttributes(
AudioAttributes.Builder()
@@ -784,7 +787,7 @@ class TalkModeManager(
ensurePlaybackActive(playbackToken)
} finally {
try {
cleanupPlayer()
cleanupPlayer(player)
} catch (_: Throwable) {}
tempFile.delete()
}
@@ -821,7 +824,11 @@ class TalkModeManager(
return
}
if (resetInterrupt) {
val currentMs = player?.currentPosition?.toDouble() ?: 0.0
val currentMs = synchronized(playerLock) {
try {
player?.currentPosition?.toDouble() ?: 0.0
} catch (_: IllegalStateException) { 0.0 }
}
lastInterruptedAtSeconds = currentMs / 1000.0
}
cleanupPlayer()
@@ -864,10 +871,16 @@ class TalkModeManager(
audioFocusRequest = null
}
private fun cleanupPlayer() {
player?.stop()
player?.release()
player = null
private fun cleanupPlayer(expectedPlayer: MediaPlayer? = null) {
synchronized(playerLock) {
val p = player ?: return
if (expectedPlayer != null && p !== expectedPlayer) return
player = null
try {
p.stop()
} catch (_: IllegalStateException) {}
p.release()
}
}
private fun shouldInterrupt(transcript: String): Boolean {

View File

@@ -1,8 +1,8 @@
// Shared iOS version defaults.
// Generated overrides live in build/Version.xcconfig (git-ignored).
OPENCLAW_GATEWAY_VERSION = 2026.3.14
OPENCLAW_MARKETING_VERSION = 2026.3.14
OPENCLAW_BUILD_VERSION = 202603140
OPENCLAW_GATEWAY_VERSION = 2026.3.22
OPENCLAW_MARKETING_VERSION = 2026.3.22
OPENCLAW_BUILD_VERSION = 202603220
#include? "../build/Version.xcconfig"

View File

@@ -65,9 +65,9 @@ Release behavior:
- Beta release also switches the app to `OpenClawPushTransport=relay`, `OpenClawPushDistribution=official`, and `OpenClawPushAPNsEnvironment=production`.
- The beta flow does not modify `apps/ios/.local-signing.xcconfig` or `apps/ios/LocalSigning.xcconfig`.
- Root `package.json.version` is the only version source for iOS.
- A root version like `2026.3.13-beta.1` becomes:
- `CFBundleShortVersionString = 2026.3.13`
- `CFBundleVersion = next TestFlight build number for 2026.3.13`
- A root version like `2026.3.22-beta.1` becomes:
- `CFBundleShortVersionString = 2026.3.22`
- `CFBundleVersion = next TestFlight build number for 2026.3.22`
Required env for beta builds:

View File

@@ -99,7 +99,7 @@ def normalize_release_version(raw_value)
version = raw_value.to_s.strip.sub(/\Av/, "")
UI.user_error!("Missing root package.json version.") unless env_present?(version)
unless version.match?(/\A\d+\.\d+\.\d+(?:[.-]?beta[.-]\d+)?\z/i)
UI.user_error!("Invalid package.json version '#{raw_value}'. Expected 2026.3.13 or 2026.3.13-beta.1.")
UI.user_error!("Invalid package.json version '#{raw_value}'. Expected 2026.3.22 or 2026.3.22-beta.1.")
end
version

View File

@@ -783,7 +783,7 @@ extension AppState {
remoteToken: String,
remoteTokenDirty: Bool) -> [String: Any]
{
Self.updatedRemoteGatewayConfig(
self.updatedRemoteGatewayConfig(
current: current,
transport: transport,
remoteUrl: remoteUrl,
@@ -804,7 +804,7 @@ extension AppState {
remoteToken: String,
remoteTokenDirty: Bool) -> [String: Any]
{
Self.syncedGatewayRoot(
self.syncedGatewayRoot(
currentRoot: currentRoot,
connectionMode: connectionMode,
remoteTransport: remoteTransport,

View File

@@ -8,8 +8,8 @@ final class CanvasA2UIActionMessageHandler: NSObject, WKScriptMessageHandler {
static let messageName = "openclawCanvasA2UIAction"
static let allMessageNames = [messageName]
// Compatibility helper for debug/test shims. Runtime dispatch remains
// limited to in-app canvas schemes in `didReceive`.
/// Compatibility helper for debug/test shims. Runtime dispatch remains
/// limited to in-app canvas schemes in `didReceive`.
static func isLocalNetworkCanvasURL(_ url: URL) -> Bool {
guard let scheme = url.scheme?.lowercased(), scheme == "http" || scheme == "https" else {
return false

View File

@@ -57,8 +57,7 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
let allowedSchemesJSON = (
try? String(
data: JSONSerialization.data(withJSONObject: CanvasScheme.allSchemes),
encoding: .utf8)
) ?? "[]"
encoding: .utf8)) ?? "[]"
let bridgeScript = """
(() => {
try {

View File

@@ -17,10 +17,10 @@ extension CronJobEditor {
self.enabled = job.enabled
self.deleteAfterRun = job.deleteAfterRun ?? false
switch job.parsedSessionTarget {
case .predefined(let target):
case let .predefined(target):
self.sessionTarget = target
self.preservedSessionTargetRaw = nil
case .session(let id):
case let .session(id):
self.sessionTarget = .isolated
self.preservedSessionTargetRaw = "session:\(id)"
}
@@ -265,7 +265,10 @@ extension CronJobEditor {
}
var effectiveSessionTargetRaw: String {
if self.sessionTarget == .isolated, let preserved = self.preservedSessionTargetRaw?.trimmingCharacters(in: .whitespacesAndNewlines), !preserved.isEmpty {
if self.sessionTarget == .isolated,
let preserved = self.preservedSessionTargetRaw?.trimmingCharacters(in: .whitespacesAndNewlines),
!preserved.isEmpty
{
return preserved
}
return self.sessionTarget.rawValue

View File

@@ -16,10 +16,10 @@ enum CronCustomSessionTarget: Codable, Equatable {
var rawValue: String {
switch self {
case .predefined(let target):
return target.rawValue
case .session(let id):
return "session:\(id)"
case let .predefined(target):
target.rawValue
case let .session(id):
"session:\(id)"
}
}
@@ -328,10 +328,10 @@ struct CronJob: Identifiable, Codable, Equatable {
/// predefined enum.
var sessionTarget: CronSessionTarget {
switch self.parsedSessionTarget {
case .predefined(let target):
return target
case let .predefined(target):
target
case .session:
return .isolated
.isolated
}
}
@@ -342,20 +342,20 @@ struct CronJob: Identifiable, Codable, Equatable {
var transcriptSessionKey: String? {
switch self.parsedSessionTarget {
case .predefined(.main):
return nil
nil
case .predefined(.isolated), .predefined(.current):
return "cron:\(self.id)"
case .session(let id):
return id
"cron:\(self.id)"
case let .session(id):
id
}
}
var supportsAnnounceDelivery: Bool {
switch self.parsedSessionTarget {
case .predefined(.main):
return false
false
case .predefined(.isolated), .predefined(.current), .session:
return true
true
}
}

View File

@@ -89,11 +89,11 @@ final class ExecApprovalsGatewayPrompter {
private static func shouldAsk(security: ExecSecurity, ask: ExecAsk) -> Bool {
switch ask {
case .always:
return true
true
case .onMiss:
return security == .allowlist
security == .allowlist
case .off:
return false
false
}
}
@@ -113,21 +113,21 @@ final class ExecApprovalsGatewayPrompter {
let mode = AppStateStore.shared.connectionMode
let activeSession = WebChatManager.shared.activeSessionKey?.trimmingCharacters(in: .whitespacesAndNewlines)
let requestSession = request.request.sessionKey?.trimmingCharacters(in: .whitespacesAndNewlines)
// Read-only resolve to avoid disk writes on the MainActor
let approvals = ExecApprovalsStore.resolveReadOnly(agentId: request.request.agentId)
let security = approvals.agent.security
let ask = approvals.agent.ask
let shouldAsk = Self.shouldAsk(security: security, ask: ask)
let canPresent = shouldAsk && Self.shouldPresent(
mode: mode,
activeSession: activeSession,
requestSession: requestSession,
lastInputSeconds: Self.lastInputSeconds(),
thresholdSeconds: 120)
return PresentationDecision(
shouldAsk: shouldAsk,
canPresent: canPresent,

View File

@@ -147,7 +147,9 @@ actor MacNodeBrowserProxy {
}
if method != "GET", let body = params.body {
request.httpBody = try JSONSerialization.data(withJSONObject: body.foundationValue, options: [.fragmentsAllowed])
request.httpBody = try JSONSerialization.data(
withJSONObject: body.foundationValue,
options: [.fragmentsAllowed])
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
}

View File

@@ -337,7 +337,6 @@ extension OnboardingView {
self.remoteProbePreflightMessage == nil && self.remoteProbeState != .checking
}
@ViewBuilder
private func remoteConnectionSection() -> some View {
VStack(alignment: .leading, spacing: 10) {
HStack(alignment: .top, spacing: 12) {
@@ -503,17 +502,17 @@ extension OnboardingView {
{
switch issue {
case .tokenRequired:
return ("key.fill", .orange)
("key.fill", .orange)
case .tokenMismatch:
return ("exclamationmark.triangle.fill", .orange)
("exclamationmark.triangle.fill", .orange)
case .gatewayTokenNotConfigured:
return ("wrench.and.screwdriver.fill", .orange)
("wrench.and.screwdriver.fill", .orange)
case .setupCodeExpired:
return ("qrcode.viewfinder", .orange)
("qrcode.viewfinder", .orange)
case .passwordRequired:
return ("lock.slash.fill", .orange)
("lock.slash.fill", .orange)
case .pairingRequired:
return ("link.badge.plus", .orange)
("link.badge.plus", .orange)
}
}

View File

@@ -180,7 +180,7 @@ enum RemoteGatewayProbe {
}
do {
_ = try await GatewayConnection.shared.healthSnapshot(timeoutMs: 10_000)
_ = try await GatewayConnection.shared.healthSnapshot(timeoutMs: 10000)
let authSource = await GatewayConnection.shared.authSource()
return .ready(RemoteGatewayProbeSuccess(authSource: authSource))
} catch {

View File

@@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2026.3.14</string>
<string>2026.3.22</string>
<key>CFBundleVersion</key>
<string>202603140</string>
<string>202603220</string>
<key>CFBundleIconFile</key>
<string>OpenClaw</string>
<key>CFBundleURLTypes</key>

View File

@@ -23,8 +23,8 @@ enum TalkModeGatewayConfigParser {
defaultSilenceTimeoutMs: Int,
envVoice: String?,
sagVoice: String?,
envApiKey: String?
) -> TalkModeGatewayConfigState {
envApiKey: String?) -> TalkModeGatewayConfigState
{
let talk = snapshot.config?["talk"]?.dictionaryValue
let selection = TalkConfigParsing.selectProviderConfig(talk, defaultProvider: defaultProvider)
let activeProvider = selection?.provider ?? defaultProvider
@@ -81,8 +81,8 @@ enum TalkModeGatewayConfigParser {
defaultSilenceTimeoutMs: Int,
envVoice: String?,
sagVoice: String?,
envApiKey: String?
) -> TalkModeGatewayConfigState {
envApiKey: String?) -> TalkModeGatewayConfigState
{
let resolvedVoice =
(envVoice?.isEmpty == false ? envVoice : nil) ??
(sagVoice?.isEmpty == false ? sagVoice : nil)

View File

@@ -2780,54 +2780,6 @@ public struct SkillsBinsResult: Codable, Sendable {
}
}
public struct SkillsInstallParams: Codable, Sendable {
public let name: String
public let installid: String
public let timeoutms: Int?
public init(
name: String,
installid: String,
timeoutms: Int?)
{
self.name = name
self.installid = installid
self.timeoutms = timeoutms
}
private enum CodingKeys: String, CodingKey {
case name
case installid = "installId"
case timeoutms = "timeoutMs"
}
}
public struct SkillsUpdateParams: Codable, Sendable {
public let skillkey: String
public let enabled: Bool?
public let apikey: String?
public let env: [String: AnyCodable]?
public init(
skillkey: String,
enabled: Bool?,
apikey: String?,
env: [String: AnyCodable]?)
{
self.skillkey = skillkey
self.enabled = enabled
self.apikey = apikey
self.env = env
}
private enum CodingKeys: String, CodingKey {
case skillkey = "skillKey"
case enabled
case apikey = "apiKey"
case env
}
}
public struct CronJob: Codable, Sendable {
public let id: String
public let agentid: String?

View File

@@ -2780,54 +2780,6 @@ public struct SkillsBinsResult: Codable, Sendable {
}
}
public struct SkillsInstallParams: Codable, Sendable {
public let name: String
public let installid: String
public let timeoutms: Int?
public init(
name: String,
installid: String,
timeoutms: Int?)
{
self.name = name
self.installid = installid
self.timeoutms = timeoutms
}
private enum CodingKeys: String, CodingKey {
case name
case installid = "installId"
case timeoutms = "timeoutMs"
}
}
public struct SkillsUpdateParams: Codable, Sendable {
public let skillkey: String
public let enabled: Bool?
public let apikey: String?
public let env: [String: AnyCodable]?
public init(
skillkey: String,
enabled: Bool?,
apikey: String?,
env: [String: AnyCodable]?)
{
self.skillkey = skillkey
self.enabled = enabled
self.apikey = apikey
self.env = env
}
private enum CodingKeys: String, CodingKey {
case skillkey = "skillKey"
case enabled
case apikey = "apiKey"
case env
}
}
public struct CronJob: Codable, Sendable {
public let id: String
public let agentid: String?

View File

@@ -6869,6 +6869,16 @@
"tags": [],
"hasChildren": false
},
{
"path": "agents.list.*.tools.exec.strictInlineEval",
"kind": "core",
"type": "boolean",
"required": false,
"deprecated": false,
"sensitive": false,
"tags": [],
"hasChildren": false
},
{
"path": "agents.list.*.tools.exec.timeoutSec",
"kind": "core",
@@ -42146,6 +42156,46 @@
"tags": [],
"hasChildren": true
},
{
"path": "hooks.internal.installs.*.clawhubChannel",
"kind": "core",
"type": "string",
"required": false,
"deprecated": false,
"sensitive": false,
"tags": [],
"hasChildren": false
},
{
"path": "hooks.internal.installs.*.clawhubFamily",
"kind": "core",
"type": "string",
"required": false,
"deprecated": false,
"sensitive": false,
"tags": [],
"hasChildren": false
},
{
"path": "hooks.internal.installs.*.clawhubPackage",
"kind": "core",
"type": "string",
"required": false,
"deprecated": false,
"sensitive": false,
"tags": [],
"hasChildren": false
},
{
"path": "hooks.internal.installs.*.clawhubUrl",
"kind": "core",
"type": "string",
"required": false,
"deprecated": false,
"sensitive": false,
"tags": [],
"hasChildren": false
},
{
"path": "hooks.internal.installs.*.hooks",
"kind": "core",
@@ -57674,6 +57724,46 @@
"tags": [],
"hasChildren": true
},
{
"path": "plugins.installs.*.clawhubChannel",
"kind": "core",
"type": "string",
"required": false,
"deprecated": false,
"sensitive": false,
"tags": [],
"hasChildren": false
},
{
"path": "plugins.installs.*.clawhubFamily",
"kind": "core",
"type": "string",
"required": false,
"deprecated": false,
"sensitive": false,
"tags": [],
"hasChildren": false
},
{
"path": "plugins.installs.*.clawhubPackage",
"kind": "core",
"type": "string",
"required": false,
"deprecated": false,
"sensitive": false,
"tags": [],
"hasChildren": false
},
{
"path": "plugins.installs.*.clawhubUrl",
"kind": "core",
"type": "string",
"required": false,
"deprecated": false,
"sensitive": false,
"tags": [],
"hasChildren": false
},
{
"path": "plugins.installs.*.installedAt",
"kind": "core",
@@ -60430,6 +60520,20 @@
"help": "Execution security posture selector controlling sandbox/approval expectations for command execution. Keep strict security mode for untrusted prompts and relax only for trusted operator workflows.",
"hasChildren": false
},
{
"path": "tools.exec.strictInlineEval",
"kind": "core",
"type": "boolean",
"required": false,
"deprecated": false,
"sensitive": false,
"tags": [
"tools"
],
"label": "Require Inline-Eval Approval",
"help": "Require explicit approval for interpreter inline-eval forms such as `python -c`, `node -e`, `ruby -e`, or `osascript -e`. Prevents silent allowlist reuse and downgrades allow-always to ask-each-time for those forms.",
"hasChildren": false
},
{
"path": "tools.exec.timeoutSec",
"kind": "core",

View File

@@ -1,4 +1,4 @@
{"generatedBy":"scripts/generate-config-doc-baseline.ts","recordType":"meta","totalPaths":5566}
{"generatedBy":"scripts/generate-config-doc-baseline.ts","recordType":"meta","totalPaths":5576}
{"recordType":"path","path":"acp","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"ACP","help":"ACP runtime controls for enabling dispatch, selecting backends, constraining allowed agent targets, and tuning streamed turn projection behavior.","hasChildren":true}
{"recordType":"path","path":"acp.allowedAgents","kind":"core","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"ACP Allowed Agents","help":"Allowlist of ACP target agent ids permitted for ACP runtime sessions. Empty means no additional allowlist restriction.","hasChildren":true}
{"recordType":"path","path":"acp.allowedAgents.*","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
@@ -614,6 +614,7 @@
{"recordType":"path","path":"agents.list.*.tools.exec.safeBinTrustedDirs","kind":"core","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
{"recordType":"path","path":"agents.list.*.tools.exec.safeBinTrustedDirs.*","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"agents.list.*.tools.exec.security","kind":"core","type":"string","required":false,"enumValues":["deny","allowlist","full"],"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"agents.list.*.tools.exec.strictInlineEval","kind":"core","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"agents.list.*.tools.exec.timeoutSec","kind":"core","type":"integer","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"agents.list.*.tools.fs","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
{"recordType":"path","path":"agents.list.*.tools.fs.workspaceOnly","kind":"core","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
@@ -3756,6 +3757,10 @@
{"recordType":"path","path":"hooks.internal.handlers.*.module","kind":"core","type":"string","required":true,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Internal Hook Module","help":"Safe relative module path for the internal hook handler implementation loaded at runtime. Keep module files in reviewed directories and avoid dynamic path composition.","hasChildren":false}
{"recordType":"path","path":"hooks.internal.installs","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Internal Hook Install Records","help":"Install metadata for internal hook modules, including source and resolved artifacts for repeatable deployments. Use this as operational provenance and avoid manual drift edits.","hasChildren":true}
{"recordType":"path","path":"hooks.internal.installs.*","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
{"recordType":"path","path":"hooks.internal.installs.*.clawhubChannel","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"hooks.internal.installs.*.clawhubFamily","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"hooks.internal.installs.*.clawhubPackage","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"hooks.internal.installs.*.clawhubUrl","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"hooks.internal.installs.*.hooks","kind":"core","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
{"recordType":"path","path":"hooks.internal.installs.*.hooks.*","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"hooks.internal.installs.*.installedAt","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
@@ -4959,6 +4964,10 @@
{"recordType":"path","path":"plugins.entries.zalouser.subagent.allowModelOverride","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Plugin Subagent Model Override","help":"Explicitly allows this plugin to request provider/model overrides in background subagent runs. Keep false unless the plugin is trusted to steer model selection.","hasChildren":false}
{"recordType":"path","path":"plugins.installs","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Install Records","help":"CLI-managed install metadata (used by `openclaw plugins update` to locate install sources).","hasChildren":true}
{"recordType":"path","path":"plugins.installs.*","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
{"recordType":"path","path":"plugins.installs.*.clawhubChannel","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"plugins.installs.*.clawhubFamily","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"plugins.installs.*.clawhubPackage","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"plugins.installs.*.clawhubUrl","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"plugins.installs.*.installedAt","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Install Time","help":"ISO timestamp of last install/update.","hasChildren":false}
{"recordType":"path","path":"plugins.installs.*.installPath","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["storage"],"label":"Plugin Install Path","help":"Resolved install directory (usually ~/.openclaw/extensions/<id>).","hasChildren":false}
{"recordType":"path","path":"plugins.installs.*.integrity","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Resolved Integrity","help":"Resolved npm dist integrity hash for the fetched artifact (if reported by npm).","hasChildren":false}
@@ -5183,6 +5192,7 @@
{"recordType":"path","path":"tools.exec.safeBinTrustedDirs","kind":"core","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["storage","tools"],"label":"Exec Safe Bin Trusted Dirs","help":"Additional explicit directories trusted for safe-bin path checks (PATH entries are never auto-trusted).","hasChildren":true}
{"recordType":"path","path":"tools.exec.safeBinTrustedDirs.*","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"tools.exec.security","kind":"core","type":"string","required":false,"enumValues":["deny","allowlist","full"],"deprecated":false,"sensitive":false,"tags":["tools"],"label":"Exec Security","help":"Execution security posture selector controlling sandbox/approval expectations for command execution. Keep strict security mode for untrusted prompts and relax only for trusted operator workflows.","hasChildren":false}
{"recordType":"path","path":"tools.exec.strictInlineEval","kind":"core","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["tools"],"label":"Require Inline-Eval Approval","help":"Require explicit approval for interpreter inline-eval forms such as `python -c`, `node -e`, `ruby -e`, or `osascript -e`. Prevents silent allowlist reuse and downgrades allow-always to ask-each-time for those forms.","hasChildren":false}
{"recordType":"path","path":"tools.exec.timeoutSec","kind":"core","type":"integer","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
{"recordType":"path","path":"tools.fs","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
{"recordType":"path","path":"tools.fs.workspaceOnly","kind":"core","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["tools"],"label":"Workspace-only FS tools","help":"Restrict filesystem tools (read/write/edit/apply_patch) to the workspace directory (default: false).","hasChildren":false}

File diff suppressed because it is too large Load Diff

View File

@@ -4,37 +4,37 @@
{"declaration":"export function buildOpenAIImageGenerationProvider(): ImageGenerationProvider;","entrypoint":"index","exportName":"buildOpenAIImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":22,"sourcePath":"src/image-generation/providers/openai.ts"}
{"declaration":"export function delegateCompactionToRuntime(params: { sessionId: string; sessionKey?: string | undefined; sessionFile: string; tokenBudget?: number | undefined; force?: boolean | undefined; currentTokenCount?: number | undefined; compactionTarget?: \"budget\" | ... 1 more ... | undefined; customInstructions?: string | undefined; runtimeContext?: ContextEngineRuntimeContext | undefined; }): Promise<...>;","entrypoint":"index","exportName":"delegateCompactionToRuntime","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":16,"sourcePath":"src/context-engine/delegate.ts"}
{"declaration":"export function emptyPluginConfigSchema(): OpenClawPluginConfigSchema;","entrypoint":"index","exportName":"emptyPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":13,"sourcePath":"src/plugins/config-schema.ts"}
{"declaration":"export function onDiagnosticEvent(listener: (evt: DiagnosticEventPayload) => void): () => void;","entrypoint":"index","exportName":"onDiagnosticEvent","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":229,"sourcePath":"src/infra/diagnostic-events.ts"}
{"declaration":"export function onDiagnosticEvent(listener: (evt: DiagnosticEventPayload) => void): () => void;","entrypoint":"index","exportName":"onDiagnosticEvent","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":223,"sourcePath":"src/infra/diagnostic-events.ts"}
{"declaration":"export function registerContextEngine(id: string, factory: ContextEngineFactory): ContextEngineRegistrationResult;","entrypoint":"index","exportName":"registerContextEngine","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":377,"sourcePath":"src/context-engine/registry.ts"}
{"declaration":"export type AnyAgentTool = AnyAgentTool;","entrypoint":"index","exportName":"AnyAgentTool","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/agents/tools/common.ts"}
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"index","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":139,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"index","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAgentToolFactory = ChannelAgentToolFactory;","entrypoint":"index","exportName":"ChannelAgentToolFactory","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":21,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelCapabilities = ChannelCapabilities;","entrypoint":"index","exportName":"ChannelCapabilities","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":223,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelConfigSchema = ChannelConfigSchema;","entrypoint":"index","exportName":"ChannelConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":47,"sourcePath":"src/channels/plugins/types.plugin.ts"}
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"index","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"index","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":18,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAgentToolFactory = ChannelAgentToolFactory;","entrypoint":"index","exportName":"ChannelAgentToolFactory","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":23,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelCapabilities = ChannelCapabilities;","entrypoint":"index","exportName":"ChannelCapabilities","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":229,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelConfigSchema = ChannelConfigSchema;","entrypoint":"index","exportName":"ChannelConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":48,"sourcePath":"src/channels/plugins/types.plugin.ts"}
{"declaration":"export type ChannelConfiguredBindingConversationRef = ChannelConfiguredBindingConversationRef;","entrypoint":"index","exportName":"ChannelConfiguredBindingConversationRef","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":553,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelConfiguredBindingMatch = ChannelConfiguredBindingMatch;","entrypoint":"index","exportName":"ChannelConfiguredBindingMatch","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":558,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelConfiguredBindingProvider = ChannelConfiguredBindingProvider;","entrypoint":"index","exportName":"ChannelConfiguredBindingProvider","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":562,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelGatewayContext = ChannelGatewayContext<ResolvedAccount>;","entrypoint":"index","exportName":"ChannelGatewayContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":238,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelId = ChannelId;","entrypoint":"index","exportName":"ChannelId","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"index","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":506,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"index","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":473,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"index","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":515,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"index","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":481,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionName = \"send\" | \"broadcast\" | \"poll\" | \"poll-vote\" | \"react\" | \"reactions\" | \"read\" | \"edit\" | \"unsend\" | \"reply\" | \"sendWithEffect\" | \"renameGroup\" | \"setGroupIcon\" | \"addParticipant\" | \"removeParticipant\" | \"leaveGroup\" | \"sendAttachment\" | \"delete\" | \"pin\" | \"unpin\" | \"list-pins\" | \"permissions\" | \"thread-create\" | \"thread-list\" | \"thread-reply\" | \"search\" | \"sticker\" | \"sticker-search\" | \"member-info\" | \"role-info\" | \"emoji-list\" | \"emoji-upload\" | \"sticker-upload\" | \"role-add\" | \"role-remove\" | \"channel-info\" | \"channel-list\" | \"channel-create\" | \"channel-edit\" | \"channel-delete\" | \"channel-move\" | \"category-create\" | \"category-edit\" | \"category-delete\" | \"topic-create\" | \"topic-edit\" | \"voice-status\" | \"event-list\" | \"event-create\" | \"timeout\" | \"kick\" | \"ban\" | \"set-profile\" | \"set-presence\" | \"download-file\";","entrypoint":"index","exportName":"ChannelMessageActionName","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/channels/plugins/types.ts"}
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","entrypoint":"index","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/channels/plugins/types.plugin.ts"}
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","entrypoint":"index","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":55,"sourcePath":"src/channels/plugins/types.plugin.ts"}
{"declaration":"export type ChannelSetupAdapter = ChannelSetupAdapter;","entrypoint":"index","exportName":"ChannelSetupAdapter","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":56,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"index","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":60,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"index","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":63,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelSetupWizard = ChannelSetupWizard;","entrypoint":"index","exportName":"ChannelSetupWizard","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":247,"sourcePath":"src/channels/plugins/setup-wizard.ts"}
{"declaration":"export type ChannelSetupWizardAllowFromEntry = ChannelSetupWizardAllowFromEntry;","entrypoint":"index","exportName":"ChannelSetupWizardAllowFromEntry","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":154,"sourcePath":"src/channels/plugins/setup-wizard.ts"}
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"index","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":97,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"index","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":100,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"index","exportName":"ClawdbotConfig","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
{"declaration":"export type CompiledConfiguredBinding = CompiledConfiguredBinding;","entrypoint":"index","exportName":"CompiledConfiguredBinding","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":38,"sourcePath":"src/channels/plugins/binding-types.ts"}
{"declaration":"export type ConfiguredBindingConversation = ConversationRef;","entrypoint":"index","exportName":"ConfiguredBindingConversation","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/channels/plugins/binding-types.ts"}
{"declaration":"export type ConfiguredBindingResolution = ConfiguredBindingResolution;","entrypoint":"index","exportName":"ConfiguredBindingResolution","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":49,"sourcePath":"src/channels/plugins/binding-types.ts"}
{"declaration":"export type ContextEngineFactory = ContextEngineFactory;","entrypoint":"index","exportName":"ContextEngineFactory","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/context-engine/registry.ts"}
{"declaration":"export type ContextEngineFactory = ContextEngineFactory;","entrypoint":"index","exportName":"ContextEngineFactory","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":10,"sourcePath":"src/context-engine/registry.ts"}
{"declaration":"export type ContextEngineInfo = ContextEngineInfo;","entrypoint":"index","exportName":"ContextEngineInfo","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":46,"sourcePath":"src/context-engine/types.ts"}
{"declaration":"export type ContextEngineMaintenanceResult = TranscriptRewriteResult;","entrypoint":"index","exportName":"ContextEngineMaintenanceResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":84,"sourcePath":"src/context-engine/types.ts"}
{"declaration":"export type ContextEngineRuntimeContext = ContextEngineRuntimeContext;","entrypoint":"index","exportName":"ContextEngineRuntimeContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":86,"sourcePath":"src/context-engine/types.ts"}
{"declaration":"export type DiagnosticEventPayload = DiagnosticEventPayload;","entrypoint":"index","exportName":"DiagnosticEventPayload","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":150,"sourcePath":"src/infra/diagnostic-events.ts"}
{"declaration":"export type DiagnosticEventPayload = DiagnosticEventPayload;","entrypoint":"index","exportName":"DiagnosticEventPayload","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":152,"sourcePath":"src/infra/diagnostic-events.ts"}
{"declaration":"export type GeneratedImageAsset = GeneratedImageAsset;","entrypoint":"index","exportName":"GeneratedImageAsset","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/image-generation/types.ts"}
{"declaration":"export type HookEntry = HookEntry;","entrypoint":"index","exportName":"HookEntry","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":47,"sourcePath":"src/hooks/types.ts"}
{"declaration":"export type ImageGenerationProvider = ImageGenerationProvider;","entrypoint":"index","exportName":"ImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":66,"sourcePath":"src/image-generation/types.ts"}
@@ -42,21 +42,21 @@
{"declaration":"export type ImageGenerationResolution = ImageGenerationResolution;","entrypoint":"index","exportName":"ImageGenerationResolution","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/image-generation/types.ts"}
{"declaration":"export type ImageGenerationResult = ImageGenerationResult;","entrypoint":"index","exportName":"ImageGenerationResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":36,"sourcePath":"src/image-generation/types.ts"}
{"declaration":"export type ImageGenerationSourceImage = ImageGenerationSourceImage;","entrypoint":"index","exportName":"ImageGenerationSourceImage","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":14,"sourcePath":"src/image-generation/types.ts"}
{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"index","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":935,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"index","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":950,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"index","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"index","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1292,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"index","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":80,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"index","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":58,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"index","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/plugins/runtime/types.ts"}
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"index","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"index","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":130,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"index","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":284,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"index","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":1311,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"index","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":88,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"index","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":59,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"index","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/types.ts"}
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"index","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":155,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"index","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":140,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"index","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":295,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ReplyPayload = ReplyPayload;","entrypoint":"index","exportName":"ReplyPayload","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":76,"sourcePath":"src/auto-reply/types.ts"}
{"declaration":"export type RuntimeEnv = RuntimeEnv;","entrypoint":"index","exportName":"RuntimeEnv","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/runtime.ts"}
{"declaration":"export type RuntimeLogger = RuntimeLogger;","entrypoint":"index","exportName":"RuntimeLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":3,"sourcePath":"src/plugins/runtime/types-core.ts"}
{"declaration":"export type RuntimeLogger = RuntimeLogger;","entrypoint":"index","exportName":"RuntimeLogger","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/plugins/runtime/types-core.ts"}
{"declaration":"export type SecretInput = SecretInput;","entrypoint":"index","exportName":"SecretInput","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":16,"sourcePath":"src/config/types.secrets.ts"}
{"declaration":"export type SecretRef = SecretRef;","entrypoint":"index","exportName":"SecretRef","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":10,"sourcePath":"src/config/types.secrets.ts"}
{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"index","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":917,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"index","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":932,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type StatefulBindingTargetDescriptor = StatefulBindingTargetDescriptor;","entrypoint":"index","exportName":"StatefulBindingTargetDescriptor","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/channels/plugins/binding-types.ts"}
{"declaration":"export type StatefulBindingTargetDriver = StatefulBindingTargetDriver;","entrypoint":"index","exportName":"StatefulBindingTargetDriver","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":15,"sourcePath":"src/channels/plugins/stateful-target-drivers.ts"}
{"declaration":"export type StatefulBindingTargetReadyResult = StatefulBindingTargetReadyResult;","entrypoint":"index","exportName":"StatefulBindingTargetReadyResult","importSpecifier":"openclaw/plugin-sdk","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/channels/plugins/stateful-target-drivers.ts"}
@@ -98,8 +98,8 @@
{"declaration":"export type BasicAllowlistResolutionEntry = BasicAllowlistResolutionEntry;","entrypoint":"allow-from","exportName":"BasicAllowlistResolutionEntry","importSpecifier":"openclaw/plugin-sdk/allow-from","kind":"type","recordType":"export","sourceLine":129,"sourcePath":"src/plugin-sdk/allow-from.ts"}
{"declaration":"export type CompiledAllowlist = CompiledAllowlist;","entrypoint":"allow-from","exportName":"CompiledAllowlist","importSpecifier":"openclaw/plugin-sdk/allow-from","kind":"type","recordType":"export","sourceLine":19,"sourcePath":"src/channels/allowlist-match.ts"}
{"category":"channel","entrypoint":"channel-actions","importSpecifier":"openclaw/plugin-sdk/channel-actions","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/channel-actions.ts"}
{"declaration":"export function createMessageToolButtonsSchema(): TSchema;","entrypoint":"channel-actions","exportName":"createMessageToolButtonsSchema","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":10,"sourcePath":"src/plugin-sdk/channel-actions.ts"}
{"declaration":"export function createMessageToolCardSchema(): TSchema;","entrypoint":"channel-actions","exportName":"createMessageToolCardSchema","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":25,"sourcePath":"src/plugin-sdk/channel-actions.ts"}
{"declaration":"export function createMessageToolButtonsSchema(): TSchema;","entrypoint":"channel-actions","exportName":"createMessageToolButtonsSchema","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":11,"sourcePath":"src/plugin-sdk/channel-actions.ts"}
{"declaration":"export function createMessageToolCardSchema(): TSchema;","entrypoint":"channel-actions","exportName":"createMessageToolCardSchema","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":27,"sourcePath":"src/plugin-sdk/channel-actions.ts"}
{"declaration":"export function createUnionActionGate<TAccount, TKey extends string>(accounts: readonly TAccount[], createGate: (account: TAccount) => OptionalDefaultGate<TKey>): OptionalDefaultGate<TKey>;","entrypoint":"channel-actions","exportName":"createUnionActionGate","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":13,"sourcePath":"src/channels/plugins/actions/shared.ts"}
{"declaration":"export function listTokenSourcedAccounts<TAccount extends TokenSourcedAccount>(accounts: readonly TAccount[]): TAccount[];","entrypoint":"channel-actions","exportName":"listTokenSourcedAccounts","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":7,"sourcePath":"src/channels/plugins/actions/shared.ts"}
{"declaration":"export function resolveReactionMessageId(params: { args: Record<string, unknown>; toolContext?: ReactionToolContext | undefined; }): string | number | undefined;","entrypoint":"channel-actions","exportName":"resolveReactionMessageId","importSpecifier":"openclaw/plugin-sdk/channel-actions","kind":"function","recordType":"export","sourceLine":7,"sourcePath":"src/channels/plugins/actions/reaction-message-id.ts"}
@@ -113,32 +113,32 @@
{"declaration":"export const MarkdownConfigSchema: z.ZodOptional<z.ZodObject<{ tables: z.ZodOptional<z.ZodEnum<{ off: \"off\"; bullets: \"bullets\"; code: \"code\"; }>>; }, z.core.$strict>>;","entrypoint":"channel-config-schema","exportName":"MarkdownConfigSchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":371,"sourcePath":"src/config/zod-schema.core.ts"}
{"declaration":"export const ToolPolicySchema: z.ZodOptional<z.ZodObject<{ allow: z.ZodOptional<z.ZodArray<z.ZodString>>; alsoAllow: z.ZodOptional<z.ZodArray<z.ZodString>>; deny: z.ZodOptional<z.ZodArray<z.ZodString>>; }, z.core.$strict>>;","entrypoint":"channel-config-schema","exportName":"ToolPolicySchema","importSpecifier":"openclaw/plugin-sdk/channel-config-schema","kind":"const","recordType":"export","sourceLine":253,"sourcePath":"src/config/zod-schema.agent-runtime.ts"}
{"category":"channel","entrypoint":"channel-contract","importSpecifier":"openclaw/plugin-sdk/channel-contract","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/channel-contract.ts"}
{"declaration":"export type BaseProbeResult = BaseProbeResult<TError>;","entrypoint":"channel-contract","exportName":"BaseProbeResult","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":547,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type BaseTokenResolution = BaseTokenResolution;","entrypoint":"channel-contract","exportName":"BaseTokenResolution","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":553,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"channel-contract","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":139,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"channel-contract","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelGroupContext = ChannelGroupContext;","entrypoint":"channel-contract","exportName":"ChannelGroupContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":210,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"channel-contract","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":506,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-contract","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":473,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionDiscoveryContext = ChannelMessageActionDiscoveryContext;","entrypoint":"channel-contract","exportName":"ChannelMessageActionDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":29,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type BaseProbeResult = BaseProbeResult<TError>;","entrypoint":"channel-contract","exportName":"BaseProbeResult","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":557,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type BaseTokenResolution = BaseTokenResolution;","entrypoint":"channel-contract","exportName":"BaseTokenResolution","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":563,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"channel-contract","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"channel-contract","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":18,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelGroupContext = ChannelGroupContext;","entrypoint":"channel-contract","exportName":"ChannelGroupContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":215,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"channel-contract","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":515,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-contract","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":481,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionDiscoveryContext = ChannelMessageActionDiscoveryContext;","entrypoint":"channel-contract","exportName":"ChannelMessageActionDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":31,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionName = \"send\" | \"broadcast\" | \"poll\" | \"poll-vote\" | \"react\" | \"reactions\" | \"read\" | \"edit\" | \"unsend\" | \"reply\" | \"sendWithEffect\" | \"renameGroup\" | \"setGroupIcon\" | \"addParticipant\" | \"removeParticipant\" | \"leaveGroup\" | \"sendAttachment\" | \"delete\" | \"pin\" | \"unpin\" | \"list-pins\" | \"permissions\" | \"thread-create\" | \"thread-list\" | \"thread-reply\" | \"search\" | \"sticker\" | \"sticker-search\" | \"member-info\" | \"role-info\" | \"emoji-list\" | \"emoji-upload\" | \"sticker-upload\" | \"role-add\" | \"role-remove\" | \"channel-info\" | \"channel-list\" | \"channel-create\" | \"channel-edit\" | \"channel-delete\" | \"channel-move\" | \"category-create\" | \"category-edit\" | \"category-delete\" | \"topic-create\" | \"topic-edit\" | \"voice-status\" | \"event-list\" | \"event-create\" | \"timeout\" | \"kick\" | \"ban\" | \"set-profile\" | \"set-presence\" | \"download-file\";","entrypoint":"channel-contract","exportName":"ChannelMessageActionName","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/channels/plugins/types.ts"}
{"declaration":"export type ChannelMessageToolDiscovery = ChannelMessageToolDiscovery;","entrypoint":"channel-contract","exportName":"ChannelMessageToolDiscovery","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageToolSchemaContribution = ChannelMessageToolSchemaContribution;","entrypoint":"channel-contract","exportName":"ChannelMessageToolSchemaContribution","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":49,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"channel-contract","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":97,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelThreadingContext = ChannelThreadingContext;","entrypoint":"channel-contract","exportName":"ChannelThreadingContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":358,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelThreadingToolContext = ChannelThreadingToolContext;","entrypoint":"channel-contract","exportName":"ChannelThreadingToolContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":372,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageToolDiscovery = ChannelMessageToolDiscovery;","entrypoint":"channel-contract","exportName":"ChannelMessageToolDiscovery","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":56,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageToolSchemaContribution = ChannelMessageToolSchemaContribution;","entrypoint":"channel-contract","exportName":"ChannelMessageToolSchemaContribution","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":51,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"channel-contract","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":100,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelThreadingContext = ChannelThreadingContext;","entrypoint":"channel-contract","exportName":"ChannelThreadingContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":364,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelThreadingToolContext = ChannelThreadingToolContext;","entrypoint":"channel-contract","exportName":"ChannelThreadingToolContext","importSpecifier":"openclaw/plugin-sdk/channel-contract","kind":"type","recordType":"export","sourceLine":378,"sourcePath":"src/channels/plugins/types.core.ts"}
{"category":"channel","entrypoint":"channel-pairing","importSpecifier":"openclaw/plugin-sdk/channel-pairing","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
{"declaration":"export function createChannelPairingChallengeIssuer(params: { channel: ChannelId; upsertPairingRequest: (params: { id: string; meta?: PairingMeta | undefined; }) => Promise<{ code: string; created: boolean; }>; }): (challenge: Omit<...>) => Promise<...>;","entrypoint":"channel-pairing","exportName":"createChannelPairingChallengeIssuer","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":19,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
{"declaration":"export function createChannelPairingController(params: { core: PluginRuntime; channel: ChannelId; accountId: string; }): ChannelPairingController;","entrypoint":"channel-pairing","exportName":"createChannelPairingController","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":36,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
{"declaration":"export function createChannelPairingChallengeIssuer(params: { channel: ChannelId; upsertPairingRequest: (params: { id: string; meta?: PairingMeta | undefined; }) => Promise<{ code: string; created: boolean; }>; }): (challenge: Omit<...>) => Promise<...>;","entrypoint":"channel-pairing","exportName":"createChannelPairingChallengeIssuer","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":21,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
{"declaration":"export function createChannelPairingController(params: { core: PluginRuntime; channel: ChannelId; accountId: string; }): ChannelPairingController;","entrypoint":"channel-pairing","exportName":"createChannelPairingController","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":39,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
{"declaration":"export function createLoggedPairingApprovalNotifier(format: string | ((params: { cfg: OpenClawConfig; id: string; accountId?: string | undefined; runtime?: RuntimeEnv | undefined; }) => string), log?: (message: string) => void): (params: { ...; }) => Promise<...>;","entrypoint":"channel-pairing","exportName":"createLoggedPairingApprovalNotifier","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":12,"sourcePath":"src/channels/plugins/pairing-adapters.ts"}
{"declaration":"export function createPairingPrefixStripper(prefixRe: RegExp, map?: (entry: string) => string): (entry: string) => string;","entrypoint":"channel-pairing","exportName":"createPairingPrefixStripper","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":5,"sourcePath":"src/channels/plugins/pairing-adapters.ts"}
{"declaration":"export function createTextPairingAdapter(params: { idLabel: string; message: string; normalizeAllowEntry?: ((entry: string) => string) | undefined; notify: (params: { cfg: OpenClawConfig; id: string; accountId?: string | undefined; runtime?: RuntimeEnv | undefined; } & { ...; }) => void | Promise<...>; }): ChannelPairingAdapter;","entrypoint":"channel-pairing","exportName":"createTextPairingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"function","recordType":"export","sourceLine":21,"sourcePath":"src/channels/plugins/pairing-adapters.ts"}
{"declaration":"export type ChannelPairingController = ChannelPairingController;","entrypoint":"channel-pairing","exportName":"ChannelPairingController","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
{"declaration":"export type ChannelPairingController = ChannelPairingController;","entrypoint":"channel-pairing","exportName":"ChannelPairingController","importSpecifier":"openclaw/plugin-sdk/channel-pairing","kind":"type","recordType":"export","sourceLine":14,"sourcePath":"src/plugin-sdk/channel-pairing.ts"}
{"category":"channel","entrypoint":"channel-reply-pipeline","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/channel-reply-pipeline.ts"}
{"declaration":"export function createChannelReplyPipeline(params: { cfg: OpenClawConfig; agentId: string; channel?: string | undefined; accountId?: string | undefined; typing?: CreateTypingCallbacksParams | undefined; typingCallbacks?: TypingCallbacks | undefined; }): ChannelReplyPipeline;","entrypoint":"channel-reply-pipeline","exportName":"createChannelReplyPipeline","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"function","recordType":"export","sourceLine":20,"sourcePath":"src/plugin-sdk/channel-reply-pipeline.ts"}
{"declaration":"export type ChannelReplyPipeline = ChannelReplyPipeline;","entrypoint":"channel-reply-pipeline","exportName":"ChannelReplyPipeline","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":16,"sourcePath":"src/plugin-sdk/channel-reply-pipeline.ts"}
{"declaration":"export type CreateTypingCallbacksParams = CreateTypingCallbacksParams;","entrypoint":"channel-reply-pipeline","exportName":"CreateTypingCallbacksParams","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":11,"sourcePath":"src/channels/typing.ts"}
{"declaration":"export type ReplyPrefixContext = import(\"/Users/vincentkoc/GIT/_Perso/openclaw/.worktrees/pr-51877/src/auto-reply/reply/response-prefix-template\").ResponsePrefixContext;","entrypoint":"channel-reply-pipeline","exportName":"ReplyPrefixContext","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/plugin-sdk/channel-reply-pipeline.ts"}
{"declaration":"export type ReplyPrefixContext = import(\"src/auto-reply/reply/response-prefix-template\").ResponsePrefixContext;","entrypoint":"channel-reply-pipeline","exportName":"ReplyPrefixContext","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/plugin-sdk/channel-reply-pipeline.ts"}
{"declaration":"export type ReplyPrefixContextBundle = ReplyPrefixContextBundle;","entrypoint":"channel-reply-pipeline","exportName":"ReplyPrefixContextBundle","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/channels/reply-prefix.ts"}
{"declaration":"export type ReplyPrefixOptions = ReplyPrefixOptions;","entrypoint":"channel-reply-pipeline","exportName":"ReplyPrefixOptions","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":20,"sourcePath":"src/channels/reply-prefix.ts"}
{"declaration":"export type TypingCallbacks = TypingCallbacks;","entrypoint":"channel-reply-pipeline","exportName":"TypingCallbacks","importSpecifier":"openclaw/plugin-sdk/channel-reply-pipeline","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/channels/typing.ts"}
@@ -165,16 +165,16 @@
{"declaration":"export function waitUntilAbort(signal?: AbortSignal | undefined, onAbort?: (() => void | Promise<void>) | undefined): Promise<void>;","entrypoint":"channel-runtime","exportName":"waitUntilAbort","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":38,"sourcePath":"src/plugin-sdk/channel-lifecycle.ts"}
{"declaration":"export const CHANNEL_MESSAGE_ACTION_NAMES: readonly [\"send\", \"broadcast\", \"poll\", \"poll-vote\", \"react\", \"reactions\", \"read\", \"edit\", \"unsend\", \"reply\", \"sendWithEffect\", \"renameGroup\", \"setGroupIcon\", \"addParticipant\", \"removeParticipant\", \"leaveGroup\", \"sendAttachment\", \"delete\", \"pin\", \"unpin\", \"list-pins\", \"permissions\", \"thread-create\", \"thread-list\", \"thread-reply\", \"search\", \"sticker\", \"sticker-search\", \"member-info\", \"role-info\", \"emoji-list\", \"emoji-upload\", \"sticker-upload\", \"role-add\", \"role-remove\", \"channel-info\", \"channel-list\", \"channel-create\", \"channel-edit\", \"channel-delete\", \"channel-move\", \"category-create\", \"category-edit\", \"category-delete\", \"topic-create\", \"topic-edit\", \"voice-status\", \"event-list\", \"event-create\", \"timeout\", \"kick\", \"ban\", \"set-profile\", \"set-presence\", \"set-profile\", \"download-file\"];","entrypoint":"channel-runtime","exportName":"CHANNEL_MESSAGE_ACTION_NAMES","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"const","recordType":"export","sourceLine":1,"sourcePath":"src/channels/plugins/message-action-names.ts"}
{"declaration":"export const CHANNEL_MESSAGE_CAPABILITIES: readonly [\"interactive\", \"buttons\", \"cards\", \"components\", \"blocks\"];","entrypoint":"channel-runtime","exportName":"CHANNEL_MESSAGE_CAPABILITIES","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"const","recordType":"export","sourceLine":1,"sourcePath":"src/channels/plugins/message-capabilities.ts"}
{"declaration":"export type BaseProbeResult = BaseProbeResult<TError>;","entrypoint":"channel-runtime","exportName":"BaseProbeResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":547,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type BaseTokenResolution = BaseTokenResolution;","entrypoint":"channel-runtime","exportName":"BaseTokenResolution","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":553,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"channel-runtime","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":139,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAccountState = ChannelAccountState;","entrypoint":"channel-runtime","exportName":"ChannelAccountState","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":105,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAgentPromptAdapter = ChannelAgentPromptAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAgentPromptAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":455,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"channel-runtime","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAgentToolFactory = ChannelAgentToolFactory;","entrypoint":"channel-runtime","exportName":"ChannelAgentToolFactory","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":21,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type BaseProbeResult = BaseProbeResult<TError>;","entrypoint":"channel-runtime","exportName":"BaseProbeResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":557,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type BaseTokenResolution = BaseTokenResolution;","entrypoint":"channel-runtime","exportName":"BaseTokenResolution","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":563,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"channel-runtime","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAccountState = ChannelAccountState;","entrypoint":"channel-runtime","exportName":"ChannelAccountState","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":108,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAgentPromptAdapter = ChannelAgentPromptAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAgentPromptAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":462,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAgentTool = ChannelAgentTool;","entrypoint":"channel-runtime","exportName":"ChannelAgentTool","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":18,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAgentToolFactory = ChannelAgentToolFactory;","entrypoint":"channel-runtime","exportName":"ChannelAgentToolFactory","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":23,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAllowlistAdapter = ChannelAllowlistAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAllowlistAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":497,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelAuthAdapter = ChannelAuthAdapter;","entrypoint":"channel-runtime","exportName":"ChannelAuthAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":362,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelCapabilities = ChannelCapabilities;","entrypoint":"channel-runtime","exportName":"ChannelCapabilities","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":223,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelCapabilities = ChannelCapabilities;","entrypoint":"channel-runtime","exportName":"ChannelCapabilities","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":229,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelCapabilitiesDiagnostics = ChannelCapabilitiesDiagnostics;","entrypoint":"channel-runtime","exportName":"ChannelCapabilitiesDiagnostics","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":47,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelCapabilitiesDisplayLine = ChannelCapabilitiesDisplayLine;","entrypoint":"channel-runtime","exportName":"ChannelCapabilitiesDisplayLine","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":42,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelCapabilitiesDisplayTone = ChannelCapabilitiesDisplayTone;","entrypoint":"channel-runtime","exportName":"ChannelCapabilitiesDisplayTone","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":40,"sourcePath":"src/channels/plugins/types.adapters.ts"}
@@ -184,8 +184,8 @@
{"declaration":"export type ChannelConfiguredBindingMatch = ChannelConfiguredBindingMatch;","entrypoint":"channel-runtime","exportName":"ChannelConfiguredBindingMatch","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":558,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelConfiguredBindingProvider = ChannelConfiguredBindingProvider;","entrypoint":"channel-runtime","exportName":"ChannelConfiguredBindingProvider","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":562,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelDirectoryAdapter = ChannelDirectoryAdapter;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":406,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelDirectoryEntry = ChannelDirectoryEntry;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryEntry","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":461,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelDirectoryEntryKind = ChannelDirectoryEntryKind;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryEntryKind","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":459,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelDirectoryEntry = ChannelDirectoryEntry;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryEntry","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":468,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelDirectoryEntryKind = ChannelDirectoryEntryKind;","entrypoint":"channel-runtime","exportName":"ChannelDirectoryEntryKind","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":466,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelElevatedAdapter = ChannelElevatedAdapter;","entrypoint":"channel-runtime","exportName":"ChannelElevatedAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":437,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelExecApprovalAdapter = ChannelExecApprovalAdapter;","entrypoint":"channel-runtime","exportName":"ChannelExecApprovalAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":463,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelExecApprovalForwardTarget = ChannelExecApprovalForwardTarget;","entrypoint":"channel-runtime","exportName":"ChannelExecApprovalForwardTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/channels/plugins/types.adapters.ts"}
@@ -193,49 +193,49 @@
{"declaration":"export type ChannelGatewayAdapter = ChannelGatewayAdapter<ResolvedAccount>;","entrypoint":"channel-runtime","exportName":"ChannelGatewayAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":346,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelGatewayContext = ChannelGatewayContext<ResolvedAccount>;","entrypoint":"channel-runtime","exportName":"ChannelGatewayContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":238,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelGroupAdapter = ChannelGroupAdapter;","entrypoint":"channel-runtime","exportName":"ChannelGroupAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":122,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelGroupContext = ChannelGroupContext;","entrypoint":"channel-runtime","exportName":"ChannelGroupContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":210,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelGroupContext = ChannelGroupContext;","entrypoint":"channel-runtime","exportName":"ChannelGroupContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":215,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelHeartbeatAdapter = ChannelHeartbeatAdapter;","entrypoint":"channel-runtime","exportName":"ChannelHeartbeatAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":372,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelHeartbeatDeps = ChannelHeartbeatDeps;","entrypoint":"channel-runtime","exportName":"ChannelHeartbeatDeps","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":113,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelHeartbeatDeps = ChannelHeartbeatDeps;","entrypoint":"channel-runtime","exportName":"ChannelHeartbeatDeps","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":116,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelId = ChannelId;","entrypoint":"channel-runtime","exportName":"ChannelId","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelLifecycleAdapter = ChannelLifecycleAdapter;","entrypoint":"channel-runtime","exportName":"ChannelLifecycleAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":449,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelLoginWithQrStartResult = ChannelLoginWithQrStartResult;","entrypoint":"channel-runtime","exportName":"ChannelLoginWithQrStartResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":317,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelLoginWithQrWaitResult = ChannelLoginWithQrWaitResult;","entrypoint":"channel-runtime","exportName":"ChannelLoginWithQrWaitResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":322,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelLogoutContext = ChannelLogoutContext<ResolvedAccount>;","entrypoint":"channel-runtime","exportName":"ChannelLogoutContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":327,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelLogoutResult = ChannelLogoutResult;","entrypoint":"channel-runtime","exportName":"ChannelLogoutResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":311,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelLogSink = ChannelLogSink;","entrypoint":"channel-runtime","exportName":"ChannelLogSink","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":203,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMentionAdapter = ChannelMentionAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMentionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":253,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":506,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":473,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionDiscoveryContext = ChannelMessageActionDiscoveryContext;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":29,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelLogSink = ChannelLogSink;","entrypoint":"channel-runtime","exportName":"ChannelLogSink","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":208,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMentionAdapter = ChannelMentionAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMentionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":259,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionAdapter = ChannelMessageActionAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":515,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":481,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionDiscoveryContext = ChannelMessageActionDiscoveryContext;","entrypoint":"channel-runtime","exportName":"ChannelMessageActionDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":31,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageActionName = \"send\" | \"broadcast\" | \"poll\" | \"poll-vote\" | \"react\" | \"reactions\" | \"read\" | \"edit\" | \"unsend\" | \"reply\" | \"sendWithEffect\" | \"renameGroup\" | \"setGroupIcon\" | \"addParticipant\" | \"removeParticipant\" | \"leaveGroup\" | \"sendAttachment\" | \"delete\" | \"pin\" | \"unpin\" | \"list-pins\" | \"permissions\" | \"thread-create\" | \"thread-list\" | \"thread-reply\" | \"search\" | \"sticker\" | \"sticker-search\" | \"member-info\" | \"role-info\" | \"emoji-list\" | \"emoji-upload\" | \"sticker-upload\" | \"role-add\" | \"role-remove\" | \"channel-info\" | \"channel-list\" | \"channel-create\" | \"channel-edit\" | \"channel-delete\" | \"channel-move\" | \"category-create\" | \"category-edit\" | \"category-delete\" | \"topic-create\" | \"topic-edit\" | \"voice-status\" | \"event-list\" | \"event-create\" | \"timeout\" | \"kick\" | \"ban\" | \"set-profile\" | \"set-presence\" | \"download-file\";","entrypoint":"channel-runtime","exportName":"ChannelMessageActionName","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/channels/plugins/types.ts"}
{"declaration":"export type ChannelMessageCapability = \"interactive\" | \"buttons\" | \"cards\" | \"components\" | \"blocks\";","entrypoint":"channel-runtime","exportName":"ChannelMessageCapability","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/channels/plugins/message-capabilities.ts"}
{"declaration":"export type ChannelMessageToolDiscovery = ChannelMessageToolDiscovery;","entrypoint":"channel-runtime","exportName":"ChannelMessageToolDiscovery","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageToolSchemaContribution = ChannelMessageToolSchemaContribution;","entrypoint":"channel-runtime","exportName":"ChannelMessageToolSchemaContribution","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":49,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessagingAdapter = ChannelMessagingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMessagingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":387,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMeta = ChannelMeta;","entrypoint":"channel-runtime","exportName":"ChannelMeta","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":118,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageToolDiscovery = ChannelMessageToolDiscovery;","entrypoint":"channel-runtime","exportName":"ChannelMessageToolDiscovery","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":56,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessageToolSchemaContribution = ChannelMessageToolSchemaContribution;","entrypoint":"channel-runtime","exportName":"ChannelMessageToolSchemaContribution","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":51,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessagingAdapter = ChannelMessagingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelMessagingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":394,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMeta = ChannelMeta;","entrypoint":"channel-runtime","exportName":"ChannelMeta","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":122,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelOutboundAdapter = ChannelOutboundAdapter;","entrypoint":"channel-runtime","exportName":"ChannelOutboundAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":154,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelOutboundContext = ChannelOutboundContext;","entrypoint":"channel-runtime","exportName":"ChannelOutboundContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":128,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelOutboundTargetMode = ChannelOutboundTargetMode;","entrypoint":"channel-runtime","exportName":"ChannelOutboundTargetMode","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":15,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelPairingAdapter = ChannelPairingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelPairingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":335,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","entrypoint":"channel-runtime","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/channels/plugins/types.plugin.ts"}
{"declaration":"export type ChannelPollContext = ChannelPollContext;","entrypoint":"channel-runtime","exportName":"ChannelPollContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":536,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelPollResult = ChannelPollResult;","entrypoint":"channel-runtime","exportName":"ChannelPollResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":528,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","entrypoint":"channel-runtime","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":55,"sourcePath":"src/channels/plugins/types.plugin.ts"}
{"declaration":"export type ChannelPollContext = ChannelPollContext;","entrypoint":"channel-runtime","exportName":"ChannelPollContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":546,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelPollResult = ChannelPollResult;","entrypoint":"channel-runtime","exportName":"ChannelPollResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":537,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelResolveKind = ChannelResolveKind;","entrypoint":"channel-runtime","exportName":"ChannelResolveKind","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":417,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelResolverAdapter = ChannelResolverAdapter;","entrypoint":"channel-runtime","exportName":"ChannelResolverAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":427,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelResolveResult = ChannelResolveResult;","entrypoint":"channel-runtime","exportName":"ChannelResolveResult","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":419,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelSecurityAdapter = ChannelSecurityAdapter<ResolvedAccount>;","entrypoint":"channel-runtime","exportName":"ChannelSecurityAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":575,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelSecurityContext = ChannelSecurityContext<ResolvedAccount>;","entrypoint":"channel-runtime","exportName":"ChannelSecurityContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":247,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelSecurityDmPolicy = ChannelSecurityDmPolicy;","entrypoint":"channel-runtime","exportName":"ChannelSecurityDmPolicy","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":238,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelSecurityContext = ChannelSecurityContext<ResolvedAccount>;","entrypoint":"channel-runtime","exportName":"ChannelSecurityContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":253,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelSecurityDmPolicy = ChannelSecurityDmPolicy;","entrypoint":"channel-runtime","exportName":"ChannelSecurityDmPolicy","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":244,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelSetupAdapter = ChannelSetupAdapter;","entrypoint":"channel-runtime","exportName":"ChannelSetupAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":56,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"channel-runtime","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":60,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"channel-runtime","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":63,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelStatusAdapter = ChannelStatusAdapter<ResolvedAccount, Probe, Audit>;","entrypoint":"channel-runtime","exportName":"ChannelStatusAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":184,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"channel-runtime","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":97,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelStreamingAdapter = ChannelStreamingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelStreamingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":272,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelStructuredComponents = ChannelStructuredComponents;","entrypoint":"channel-runtime","exportName":"ChannelStructuredComponents","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":281,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelThreadingAdapter = ChannelThreadingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelThreadingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":315,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelThreadingContext = ChannelThreadingContext;","entrypoint":"channel-runtime","exportName":"ChannelThreadingContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":358,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelThreadingToolContext = ChannelThreadingToolContext;","entrypoint":"channel-runtime","exportName":"ChannelThreadingToolContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":372,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelToolSend = ChannelToolSend;","entrypoint":"channel-runtime","exportName":"ChannelToolSend","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":500,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelStatusIssue = ChannelStatusIssue;","entrypoint":"channel-runtime","exportName":"ChannelStatusIssue","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":100,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelStreamingAdapter = ChannelStreamingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelStreamingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":278,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelStructuredComponents = ChannelStructuredComponents;","entrypoint":"channel-runtime","exportName":"ChannelStructuredComponents","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":287,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelThreadingAdapter = ChannelThreadingAdapter;","entrypoint":"channel-runtime","exportName":"ChannelThreadingAdapter","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":321,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelThreadingContext = ChannelThreadingContext;","entrypoint":"channel-runtime","exportName":"ChannelThreadingContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":364,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelThreadingToolContext = ChannelThreadingToolContext;","entrypoint":"channel-runtime","exportName":"ChannelThreadingToolContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":378,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelToolSend = ChannelToolSend;","entrypoint":"channel-runtime","exportName":"ChannelToolSend","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":508,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChatType = ChatType;","entrypoint":"channel-runtime","exportName":"ChatType","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/channels/chat-type.ts"}
{"declaration":"export type CreateTypingCallbacksParams = CreateTypingCallbacksParams;","entrypoint":"channel-runtime","exportName":"CreateTypingCallbacksParams","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":11,"sourcePath":"src/channels/typing.ts"}
{"declaration":"export type NormalizedPollInput = NormalizedPollInput;","entrypoint":"channel-runtime","exportName":"NormalizedPollInput","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":17,"sourcePath":"src/polls.ts"}
@@ -245,7 +245,7 @@
{"declaration":"export type TypingCallbacks = TypingCallbacks;","entrypoint":"channel-runtime","exportName":"TypingCallbacks","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/channels/typing.ts"}
{"category":"channel","entrypoint":"channel-setup","importSpecifier":"openclaw/plugin-sdk/channel-setup","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/channel-setup.ts"}
{"declaration":"export function createOptionalChannelSetupAdapter(params: OptionalChannelSetupParams): ChannelSetupAdapter;","entrypoint":"channel-setup","exportName":"createOptionalChannelSetupAdapter","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":22,"sourcePath":"src/plugin-sdk/optional-channel-setup.ts"}
{"declaration":"export function createOptionalChannelSetupSurface(params: OptionalChannelSetupParams): OptionalChannelSetupSurface;","entrypoint":"channel-setup","exportName":"createOptionalChannelSetupSurface","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":37,"sourcePath":"src/plugin-sdk/channel-setup.ts"}
{"declaration":"export function createOptionalChannelSetupSurface(params: OptionalChannelSetupParams): OptionalChannelSetupSurface;","entrypoint":"channel-setup","exportName":"createOptionalChannelSetupSurface","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":40,"sourcePath":"src/plugin-sdk/channel-setup.ts"}
{"declaration":"export function createOptionalChannelSetupWizard(params: OptionalChannelSetupParams): ChannelSetupWizard;","entrypoint":"channel-setup","exportName":"createOptionalChannelSetupWizard","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":35,"sourcePath":"src/plugin-sdk/optional-channel-setup.ts"}
{"declaration":"export function createTopLevelChannelDmPolicy(params: { label: string; channel: string; policyKey: string; allowFromKey: string; getCurrent: (cfg: OpenClawConfig) => DmPolicy; promptAllowFrom?: ((params: { cfg: OpenClawConfig; prompter: WizardPrompter; accountId?: string | undefined; }) => Promise<...>) | undefined; getAllowFrom?: ((cfg: OpenClawConfig) => (string | number)[] | undefined) | undefined; }): ChannelSetupDmPolicy;","entrypoint":"channel-setup","exportName":"createTopLevelChannelDmPolicy","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":363,"sourcePath":"src/channels/plugins/setup-wizard-helpers.ts"}
{"declaration":"export function formatDocsLink(path: string, label?: string | undefined, opts?: { fallback?: string | undefined; force?: boolean | undefined; } | undefined): string;","entrypoint":"channel-setup","exportName":"formatDocsLink","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":5,"sourcePath":"src/terminal/links.ts"}
@@ -254,9 +254,9 @@
{"declaration":"export const DEFAULT_ACCOUNT_ID: \"default\";","entrypoint":"channel-setup","exportName":"DEFAULT_ACCOUNT_ID","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"const","recordType":"export","sourceLine":3,"sourcePath":"src/routing/account-id.ts"}
{"declaration":"export type ChannelSetupAdapter = ChannelSetupAdapter;","entrypoint":"channel-setup","exportName":"ChannelSetupAdapter","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":56,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type ChannelSetupDmPolicy = ChannelSetupDmPolicy;","entrypoint":"channel-setup","exportName":"ChannelSetupDmPolicy","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":93,"sourcePath":"src/channels/plugins/setup-wizard-types.ts"}
{"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"channel-setup","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":60,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelSetupInput = ChannelSetupInput;","entrypoint":"channel-setup","exportName":"ChannelSetupInput","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":63,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelSetupWizard = ChannelSetupWizard;","entrypoint":"channel-setup","exportName":"ChannelSetupWizard","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":247,"sourcePath":"src/channels/plugins/setup-wizard.ts"}
{"declaration":"export type OptionalChannelSetupSurface = OptionalChannelSetupSurface;","entrypoint":"channel-setup","exportName":"OptionalChannelSetupSurface","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":27,"sourcePath":"src/plugin-sdk/channel-setup.ts"}
{"declaration":"export type OptionalChannelSetupSurface = OptionalChannelSetupSurface;","entrypoint":"channel-setup","exportName":"OptionalChannelSetupSurface","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"type","recordType":"export","sourceLine":29,"sourcePath":"src/plugin-sdk/channel-setup.ts"}
{"category":"channel","entrypoint":"command-auth","importSpecifier":"openclaw/plugin-sdk/command-auth","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export function buildCommandsMessage(cfg?: OpenClawConfig | undefined, skillCommands?: SkillCommandSpec[] | undefined, options?: CommandsMessageOptions | undefined): string;","entrypoint":"command-auth","exportName":"buildCommandsMessage","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":847,"sourcePath":"src/auto-reply/status.ts"}
{"declaration":"export function buildCommandsMessagePaginated(cfg?: OpenClawConfig | undefined, skillCommands?: SkillCommandSpec[] | undefined, options?: CommandsMessageOptions | undefined): CommandsMessageResult;","entrypoint":"command-auth","exportName":"buildCommandsMessagePaginated","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":856,"sourcePath":"src/auto-reply/status.ts"}
@@ -265,6 +265,7 @@
{"declaration":"export function buildCommandTextFromArgs(command: ChatCommandDefinition, args?: CommandArgs | undefined): string;","entrypoint":"command-auth","exportName":"buildCommandTextFromArgs","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":291,"sourcePath":"src/auto-reply/commands-registry.ts"}
{"declaration":"export function buildHelpMessage(cfg?: OpenClawConfig | undefined): string;","entrypoint":"command-auth","exportName":"buildHelpMessage","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":727,"sourcePath":"src/auto-reply/status.ts"}
{"declaration":"export function buildModelsProviderData(cfg: OpenClawConfig, agentId?: string | undefined): Promise<ModelsProviderData>;","entrypoint":"command-auth","exportName":"buildModelsProviderData","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":37,"sourcePath":"src/auto-reply/reply/commands-models.ts"}
{"declaration":"export function createPreCryptoDirectDmAuthorizer(params: { resolveAccess: (senderId: string) => Promise<ResolvedInboundDirectDmAccess | Pick<ResolvedInboundDirectDmAccess, \"access\">>; issuePairingChallenge?: ((params: { ...; }) => Promise<...>) | undefined; onBlocked?: ((params: { ...; }) => void) | undefined; }): (input: { ...; }) => Promise<...>;","entrypoint":"command-auth","exportName":"createPreCryptoDirectDmAuthorizer","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":105,"sourcePath":"src/plugin-sdk/direct-dm.ts"}
{"declaration":"export function findCommandByNativeName(name: string, provider?: string | undefined): ChatCommandDefinition | undefined;","entrypoint":"command-auth","exportName":"findCommandByNativeName","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":187,"sourcePath":"src/auto-reply/commands-registry.ts"}
{"declaration":"export function formatModelsAvailableHeader(params: { provider: string; total: number; cfg: OpenClawConfig; agentDir?: string | undefined; sessionEntry?: SessionEntry | undefined; }): string;","entrypoint":"command-auth","exportName":"formatModelsAvailableHeader","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":204,"sourcePath":"src/auto-reply/reply/commands-models.ts"}
{"declaration":"export function getCommandDetection(_cfg?: OpenClawConfig | undefined): CommandDetection;","entrypoint":"command-auth","exportName":"getCommandDetection","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":440,"sourcePath":"src/auto-reply/commands-registry.ts"}
@@ -289,12 +290,13 @@
{"declaration":"export function resolveCommandAuthorization(params: { ctx: MsgContext; cfg: OpenClawConfig; commandAuthorized: boolean; }): CommandAuthorization;","entrypoint":"command-auth","exportName":"resolveCommandAuthorization","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":303,"sourcePath":"src/auto-reply/command-auth.ts"}
{"declaration":"export function resolveCommandAuthorizedFromAuthorizers(params: { useAccessGroups: boolean; authorizers: CommandAuthorizer[]; modeWhenAccessGroupsOff?: CommandGatingModeWhenAccessGroupsOff | undefined; }): boolean;","entrypoint":"command-auth","exportName":"resolveCommandAuthorizedFromAuthorizers","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":8,"sourcePath":"src/channels/command-gating.ts"}
{"declaration":"export function resolveControlCommandGate(params: { useAccessGroups: boolean; authorizers: CommandAuthorizer[]; allowTextCommands: boolean; hasControlCommand: boolean; modeWhenAccessGroupsOff?: CommandGatingModeWhenAccessGroupsOff | undefined; }): { ...; };","entrypoint":"command-auth","exportName":"resolveControlCommandGate","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":31,"sourcePath":"src/channels/command-gating.ts"}
{"declaration":"export function resolveDirectDmAuthorizationOutcome(params: { isGroup: boolean; dmPolicy: string; senderAllowedForCommands: boolean; }): \"disabled\" | \"unauthorized\" | \"allowed\";","entrypoint":"command-auth","exportName":"resolveDirectDmAuthorizationOutcome","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":114,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export function resolveDirectDmAuthorizationOutcome(params: { isGroup: boolean; dmPolicy: string; senderAllowedForCommands: boolean; }): \"disabled\" | \"unauthorized\" | \"allowed\";","entrypoint":"command-auth","exportName":"resolveDirectDmAuthorizationOutcome","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":120,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export function resolveDualTextControlCommandGate(params: { useAccessGroups: boolean; primaryConfigured: boolean; primaryAllowed: boolean; secondaryConfigured: boolean; secondaryAllowed: boolean; hasControlCommand: boolean; modeWhenAccessGroupsOff?: CommandGatingModeWhenAccessGroupsOff | undefined; }): { ...; };","entrypoint":"command-auth","exportName":"resolveDualTextControlCommandGate","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":47,"sourcePath":"src/channels/command-gating.ts"}
{"declaration":"export function resolveInboundDirectDmAccessWithRuntime(params: { cfg: OpenClawConfig; channel: ChannelId; accountId: string; dmPolicy?: string | null | undefined; allowFrom?: (string | number)[] | null | undefined; senderId: string; ... 4 more ...; readStoreAllowFrom?: ((provider: ChannelId, accountId: string) => Promise<...>) | undefined; }): Promise<...>;","entrypoint":"command-auth","exportName":"resolveInboundDirectDmAccessWithRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":35,"sourcePath":"src/plugin-sdk/direct-dm.ts"}
{"declaration":"export function resolveModelsCommandReply(params: { cfg: OpenClawConfig; commandBodyNormalized: string; surface?: string | undefined; currentModel?: string | undefined; agentId?: string | undefined; agentDir?: string | undefined; sessionEntry?: SessionEntry | undefined; }): Promise<...>;","entrypoint":"command-auth","exportName":"resolveModelsCommandReply","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":220,"sourcePath":"src/auto-reply/reply/commands-models.ts"}
{"declaration":"export function resolveNativeCommandSessionTargets(params: ResolveNativeCommandSessionTargetsParams): { sessionKey: string; commandTargetSessionKey: string; };","entrypoint":"command-auth","exportName":"resolveNativeCommandSessionTargets","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":10,"sourcePath":"src/channels/native-command-session-targets.ts"}
{"declaration":"export function resolveSenderCommandAuthorization(params: ResolveSenderCommandAuthorizationParams): Promise<{ shouldComputeAuth: boolean; effectiveAllowFrom: string[]; effectiveGroupAllowFrom: string[]; senderAllowedForCommands: boolean; commandAuthorized: boolean | undefined; }>;","entrypoint":"command-auth","exportName":"resolveSenderCommandAuthorization","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":143,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export function resolveSenderCommandAuthorizationWithRuntime(params: ResolveSenderCommandAuthorizationWithRuntimeParams): Promise<{ shouldComputeAuth: boolean; effectiveAllowFrom: string[]; effectiveGroupAllowFrom: string[]; senderAllowedForCommands: boolean; commandAuthorized: boolean | undefined; }>;","entrypoint":"command-auth","exportName":"resolveSenderCommandAuthorizationWithRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":132,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export function resolveSenderCommandAuthorization(params: ResolveSenderCommandAuthorizationParams): Promise<{ shouldComputeAuth: boolean; effectiveAllowFrom: string[]; effectiveGroupAllowFrom: string[]; senderAllowedForCommands: boolean; commandAuthorized: boolean | undefined; }>;","entrypoint":"command-auth","exportName":"resolveSenderCommandAuthorization","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":149,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export function resolveSenderCommandAuthorizationWithRuntime(params: ResolveSenderCommandAuthorizationWithRuntimeParams): Promise<{ shouldComputeAuth: boolean; effectiveAllowFrom: string[]; effectiveGroupAllowFrom: string[]; senderAllowedForCommands: boolean; commandAuthorized: boolean | undefined; }>;","entrypoint":"command-auth","exportName":"resolveSenderCommandAuthorizationWithRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":138,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export function resolveSkillCommandInvocation(params: { commandBodyNormalized: string; skillCommands: SkillCommandSpec[]; }): { command: SkillCommandSpec; args?: string | undefined; } | null;","entrypoint":"command-auth","exportName":"resolveSkillCommandInvocation","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":58,"sourcePath":"src/auto-reply/skill-commands-base.ts"}
{"declaration":"export function resolveStoredModelOverride(params: { sessionEntry?: SessionEntry | undefined; sessionStore?: Record<string, SessionEntry> | undefined; sessionKey?: string | undefined; parentSessionKey?: string | undefined; }): StoredModelOverride | null;","entrypoint":"command-auth","exportName":"resolveStoredModelOverride","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":156,"sourcePath":"src/auto-reply/reply/model-selection.ts"}
{"declaration":"export function resolveTextCommand(raw: string, cfg?: OpenClawConfig | undefined): { command: ChatCommandDefinition; args?: string | undefined; } | null;","entrypoint":"command-auth","exportName":"resolveTextCommand","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":494,"sourcePath":"src/auto-reply/commands-registry.ts"}
@@ -308,38 +310,40 @@
{"declaration":"export type CommandArgs = CommandArgs;","entrypoint":"command-auth","exportName":"CommandArgs","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":46,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
{"declaration":"export type CommandArgValues = CommandArgValues;","entrypoint":"command-auth","exportName":"CommandArgValues","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":44,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
{"declaration":"export type CommandAuthorization = CommandAuthorization;","entrypoint":"command-auth","exportName":"CommandAuthorization","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/auto-reply/command-auth.ts"}
{"declaration":"export type CommandAuthorizationRuntime = CommandAuthorizationRuntime;","entrypoint":"command-auth","exportName":"CommandAuthorizationRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":98,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export type CommandAuthorizationRuntime = CommandAuthorizationRuntime;","entrypoint":"command-auth","exportName":"CommandAuthorizationRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":104,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export type CommandAuthorizer = CommandAuthorizer;","entrypoint":"command-auth","exportName":"CommandAuthorizer","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/channels/command-gating.ts"}
{"declaration":"export type CommandDetection = CommandDetection;","entrypoint":"command-auth","exportName":"CommandDetection","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":78,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
{"declaration":"export type CommandGatingModeWhenAccessGroupsOff = CommandGatingModeWhenAccessGroupsOff;","entrypoint":"command-auth","exportName":"CommandGatingModeWhenAccessGroupsOff","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/channels/command-gating.ts"}
{"declaration":"export type CommandNormalizeOptions = CommandNormalizeOptions;","entrypoint":"command-auth","exportName":"CommandNormalizeOptions","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":74,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
{"declaration":"export type CommandScope = CommandScope;","entrypoint":"command-auth","exportName":"CommandScope","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":3,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
{"declaration":"export type DirectDmCommandAuthorizationRuntime = DirectDmCommandAuthorizationRuntime;","entrypoint":"command-auth","exportName":"DirectDmCommandAuthorizationRuntime","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/plugin-sdk/direct-dm.ts"}
{"declaration":"export type ModelsProviderData = ModelsProviderData;","entrypoint":"command-auth","exportName":"ModelsProviderData","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":27,"sourcePath":"src/auto-reply/reply/commands-models.ts"}
{"declaration":"export type NativeCommandSpec = NativeCommandSpec;","entrypoint":"command-auth","exportName":"NativeCommandSpec","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":67,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
{"declaration":"export type ResolvedCommandArgChoice = ResolvedCommandArgChoice;","entrypoint":"command-auth","exportName":"ResolvedCommandArgChoice","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":314,"sourcePath":"src/auto-reply/commands-registry.ts"}
{"declaration":"export type ResolvedInboundDirectDmAccess = ResolvedInboundDirectDmAccess;","entrypoint":"command-auth","exportName":"ResolvedInboundDirectDmAccess","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":22,"sourcePath":"src/plugin-sdk/direct-dm.ts"}
{"declaration":"export type ResolveNativeCommandSessionTargetsParams = ResolveNativeCommandSessionTargetsParams;","entrypoint":"command-auth","exportName":"ResolveNativeCommandSessionTargetsParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/channels/native-command-session-targets.ts"}
{"declaration":"export type ResolveSenderCommandAuthorizationParams = ResolveSenderCommandAuthorizationParams;","entrypoint":"command-auth","exportName":"ResolveSenderCommandAuthorizationParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":81,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export type ResolveSenderCommandAuthorizationWithRuntimeParams = ResolveSenderCommandAuthorizationWithRuntimeParams;","entrypoint":"command-auth","exportName":"ResolveSenderCommandAuthorizationWithRuntimeParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":106,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export type ResolveSenderCommandAuthorizationParams = ResolveSenderCommandAuthorizationParams;","entrypoint":"command-auth","exportName":"ResolveSenderCommandAuthorizationParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":87,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export type ResolveSenderCommandAuthorizationWithRuntimeParams = ResolveSenderCommandAuthorizationWithRuntimeParams;","entrypoint":"command-auth","exportName":"ResolveSenderCommandAuthorizationWithRuntimeParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":112,"sourcePath":"src/plugin-sdk/command-auth.ts"}
{"declaration":"export type ShouldHandleTextCommandsParams = ShouldHandleTextCommandsParams;","entrypoint":"command-auth","exportName":"ShouldHandleTextCommandsParams","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":83,"sourcePath":"src/auto-reply/commands-registry.types.ts"}
{"declaration":"export type StoredModelOverride = StoredModelOverride;","entrypoint":"command-auth","exportName":"StoredModelOverride","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"type","recordType":"export","sourceLine":123,"sourcePath":"src/auto-reply/reply/model-selection.ts"}
{"category":"core","entrypoint":"core","importSpecifier":"openclaw/plugin-sdk/core","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function applyAccountNameToChannelSection(params: { cfg: OpenClawConfig; channelKey: string; accountId: string; name?: string | undefined; alwaysUseAccounts?: boolean | undefined; }): OpenClawConfig;","entrypoint":"core","exportName":"applyAccountNameToChannelSection","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":33,"sourcePath":"src/channels/plugins/setup-helpers.ts"}
{"declaration":"export function buildAgentSessionKey(params: { agentId: string; channel: string; accountId?: string | null | undefined; peer?: RoutePeer | null | undefined; dmScope?: \"main\" | \"per-peer\" | \"per-channel-peer\" | \"per-account-channel-peer\" | undefined; identityLinks?: Record<...> | undefined; }): string;","entrypoint":"core","exportName":"buildAgentSessionKey","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":91,"sourcePath":"src/routing/resolve-route.ts"}
{"declaration":"export function buildChannelConfigSchema(schema: ZodType<unknown, unknown, $ZodTypeInternals<unknown, unknown>>): ChannelConfigSchema;","entrypoint":"core","exportName":"buildChannelConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":35,"sourcePath":"src/channels/plugins/config-schema.ts"}
{"declaration":"export function buildChannelOutboundSessionRoute(params: { cfg: OpenClawConfig; agentId: string; channel: string; accountId?: string | null | undefined; peer: { kind: \"direct\" | \"group\" | \"channel\"; id: string; }; chatType: \"direct\" | \"group\" | \"channel\"; from: string; to: string; threadId?: string | ... 1 more ... | undefined; }): ChannelOutboundSessionRoute;","entrypoint":"core","exportName":"buildChannelOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":155,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function buildChannelOutboundSessionRoute(params: { cfg: OpenClawConfig; agentId: string; channel: string; accountId?: string | null | undefined; peer: { kind: \"direct\" | \"group\" | \"channel\"; id: string; }; chatType: \"direct\" | \"group\" | \"channel\"; from: string; to: string; threadId?: string | ... 1 more ... | undefined; }): ChannelOutboundSessionRoute;","entrypoint":"core","exportName":"buildChannelOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":161,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function channelTargetSchema(options?: { description?: string | undefined; } | undefined): TString;","entrypoint":"core","exportName":"channelTargetSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":33,"sourcePath":"src/agents/schema/typebox.ts"}
{"declaration":"export function channelTargetsSchema(options?: { description?: string | undefined; } | undefined): TArray<TString>;","entrypoint":"core","exportName":"channelTargetsSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":39,"sourcePath":"src/agents/schema/typebox.ts"}
{"declaration":"export function clearAccountEntryFields<TAccountEntry extends object>(params: { accounts?: Record<string, TAccountEntry> | undefined; accountId: string; fields: string[]; isValueSet?: ((value: unknown) => boolean) | undefined; markClearedOnFieldPresence?: boolean | undefined; }): { ...; };","entrypoint":"core","exportName":"clearAccountEntryFields","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":122,"sourcePath":"src/channels/plugins/config-helpers.ts"}
{"declaration":"export function createChannelPluginBase<TResolvedAccount>(params: CreateChannelPluginBaseOptions<TResolvedAccount>): CreatedChannelPluginBase<TResolvedAccount>;","entrypoint":"core","exportName":"createChannelPluginBase","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":417,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function createChatChannelPlugin<TResolvedAccount extends { accountId?: string | null; }, Probe = unknown, Audit = unknown>(params: { base: ChatChannelPluginBase<TResolvedAccount, Probe, Audit>; security?: ChannelSecurityAdapter<TResolvedAccount> | ChatChannelSecurityOptions<...> | undefined; pairing?: ChannelPairingAdapter | ... 1 more ... | undefined; threading?: ChannelThreadingAdapter | ... 1 more ... | undefined; outbound?: ChannelOutboundAdapter | ... 1 more ... | undefined; }): ChannelPlugin<...>;","entrypoint":"core","exportName":"createChatChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":394,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function defineChannelPluginEntry<TPlugin extends ChannelPlugin>({ id, name, description, plugin, configSchema, setRuntime, registerFull, }: DefineChannelPluginEntryOptions<TPlugin>): DefinedPluginEntry;","entrypoint":"core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":231,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"core","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":79,"sourcePath":"src/plugin-sdk/plugin-entry.ts"}
{"declaration":"export function defineSetupPluginEntry<TPlugin>(plugin: TPlugin): { plugin: TPlugin; };","entrypoint":"core","exportName":"defineSetupPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":257,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function createChannelPluginBase<TResolvedAccount>(params: CreateChannelPluginBaseOptions<TResolvedAccount>): CreatedChannelPluginBase<TResolvedAccount>;","entrypoint":"core","exportName":"createChannelPluginBase","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":435,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function createChatChannelPlugin<TResolvedAccount extends { accountId?: string | null; }, Probe = unknown, Audit = unknown>(params: { base: ChatChannelPluginBase<TResolvedAccount, Probe, Audit>; security?: ChannelSecurityAdapter<TResolvedAccount> | ChatChannelSecurityOptions<...> | undefined; pairing?: ChannelPairingAdapter | ... 1 more ... | undefined; threading?: ChannelThreadingAdapter | ... 1 more ... | undefined; outbound?: ChannelOutboundAdapter | ... 1 more ... | undefined; }): ChannelPlugin<...>;","entrypoint":"core","exportName":"createChatChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":412,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function defineChannelPluginEntry<TPlugin extends ChannelPlugin>({ id, name, description, plugin, configSchema, setRuntime, registerFull, }: DefineChannelPluginEntryOptions<TPlugin>): DefinedPluginEntry;","entrypoint":"core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":244,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"core","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":88,"sourcePath":"src/plugin-sdk/plugin-entry.ts"}
{"declaration":"export function defineSetupPluginEntry<TPlugin>(plugin: TPlugin): { plugin: TPlugin; };","entrypoint":"core","exportName":"defineSetupPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":275,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function delegateCompactionToRuntime(params: { sessionId: string; sessionKey?: string | undefined; sessionFile: string; tokenBudget?: number | undefined; force?: boolean | undefined; currentTokenCount?: number | undefined; compactionTarget?: \"budget\" | ... 1 more ... | undefined; customInstructions?: string | undefined; runtimeContext?: ContextEngineRuntimeContext | undefined; }): Promise<...>;","entrypoint":"core","exportName":"delegateCompactionToRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":16,"sourcePath":"src/context-engine/delegate.ts"}
{"declaration":"export function deleteAccountFromConfigSection(params: { cfg: OpenClawConfig; sectionKey: string; accountId: string; clearBaseFields?: string[] | undefined; }): OpenClawConfig;","entrypoint":"core","exportName":"deleteAccountFromConfigSection","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":60,"sourcePath":"src/channels/plugins/config-helpers.ts"}
{"declaration":"export function emptyPluginConfigSchema(): OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"emptyPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":13,"sourcePath":"src/plugins/config-schema.ts"}
{"declaration":"export function formatPairingApproveHint(channelId: string): string;","entrypoint":"core","exportName":"formatPairingApproveHint","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":17,"sourcePath":"src/channels/plugins/helpers.ts"}
{"declaration":"export function getChatChannelMeta(id: \"telegram\" | \"whatsapp\" | \"discord\" | \"irc\" | \"googlechat\" | \"slack\" | \"signal\" | \"imessage\" | \"line\"): ChannelMeta;","entrypoint":"core","exportName":"getChatChannelMeta","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":142,"sourcePath":"src/channels/registry.ts"}
{"declaration":"export function getChatChannelMeta(id: \"telegram\" | \"whatsapp\" | \"discord\" | \"irc\" | \"googlechat\" | \"slack\" | \"signal\" | \"imessage\" | \"line\"): ChannelMeta;","entrypoint":"core","exportName":"getChatChannelMeta","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":158,"sourcePath":"src/channels/registry.ts"}
{"declaration":"export function isSecretRef(value: unknown): value is SecretRef;","entrypoint":"core","exportName":"isSecretRef","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":34,"sourcePath":"src/config/types.secrets.ts"}
{"declaration":"export function loadSecretFileSync(filePath: string, label: string, options?: SecretFileReadOptions): SecretFileReadResult;","entrypoint":"core","exportName":"loadSecretFileSync","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":29,"sourcePath":"src/infra/secret-file.ts"}
{"declaration":"export function migrateBaseNameToDefaultAccount(params: { cfg: OpenClawConfig; channelKey: string; alwaysUseAccounts?: boolean | undefined; }): OpenClawConfig;","entrypoint":"core","exportName":"migrateBaseNameToDefaultAccount","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":92,"sourcePath":"src/channels/plugins/setup-helpers.ts"}
@@ -354,113 +358,113 @@
{"declaration":"export function resolveThreadSessionKeys(params: { baseSessionKey: string; threadId?: string | null | undefined; parentSessionKey?: string | undefined; useSuffix?: boolean | undefined; normalizeThreadId?: ((threadId: string) => string) | undefined; }): { ...; };","entrypoint":"core","exportName":"resolveThreadSessionKeys","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":234,"sourcePath":"src/routing/session-key.ts"}
{"declaration":"export function setAccountEnabledInConfigSection(params: { cfg: OpenClawConfig; sectionKey: string; accountId: string; enabled: boolean; allowTopLevel?: boolean | undefined; }): OpenClawConfig;","entrypoint":"core","exportName":"setAccountEnabledInConfigSection","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":16,"sourcePath":"src/channels/plugins/config-helpers.ts"}
{"declaration":"export function stringEnum<T extends readonly string[]>(values: T, options?: StringEnumOptions<T>): TUnsafe<T[number]>;","entrypoint":"core","exportName":"stringEnum","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":15,"sourcePath":"src/agents/schema/typebox.ts"}
{"declaration":"export function stripChannelTargetPrefix(raw: string, ...providers: string[]): string;","entrypoint":"core","exportName":"stripChannelTargetPrefix","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":140,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function stripTargetKindPrefix(raw: string): string;","entrypoint":"core","exportName":"stripTargetKindPrefix","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":151,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function stripChannelTargetPrefix(raw: string, ...providers: string[]): string;","entrypoint":"core","exportName":"stripChannelTargetPrefix","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":141,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function stripTargetKindPrefix(raw: string): string;","entrypoint":"core","exportName":"stripTargetKindPrefix","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":153,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export function tryReadSecretFileSync(filePath: string | undefined, label: string, options?: SecretFileReadOptions): string | undefined;","entrypoint":"core","exportName":"tryReadSecretFileSync","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":130,"sourcePath":"src/infra/secret-file.ts"}
{"declaration":"export const DEFAULT_ACCOUNT_ID: \"default\";","entrypoint":"core","exportName":"DEFAULT_ACCOUNT_ID","importSpecifier":"openclaw/plugin-sdk/core","kind":"const","recordType":"export","sourceLine":3,"sourcePath":"src/routing/account-id.ts"}
{"declaration":"export const DEFAULT_SECRET_FILE_MAX_BYTES: number;","entrypoint":"core","exportName":"DEFAULT_SECRET_FILE_MAX_BYTES","importSpecifier":"openclaw/plugin-sdk/core","kind":"const","recordType":"export","sourceLine":5,"sourcePath":"src/infra/secret-file.ts"}
{"declaration":"export type AnyAgentTool = AnyAgentTool;","entrypoint":"core","exportName":"AnyAgentTool","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/agents/tools/common.ts"}
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"core","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":473,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessagingAdapter = ChannelMessagingAdapter;","entrypoint":"core","exportName":"ChannelMessagingAdapter","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":387,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelOutboundSessionRoute = ChannelOutboundSessionRoute;","entrypoint":"core","exportName":"ChannelOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":302,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelOutboundSessionRouteParams = { cfg: OpenClawConfig; agentId: string; accountId?: string | null; target: string; resolvedTarget?: { to: string; kind: import(\"/Users/vincentkoc/GIT/_Perso/openclaw/.worktrees/pr-51877/src/channels/plugins/types.core\").ChannelDirectoryEntryKind | \"channel\"; display?: string; source: \"normalized\" | \"directory\"; }; replyToId?: string | null; threadId?: string | number | null;};","entrypoint":"core","exportName":"ChannelOutboundSessionRouteParams","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":136,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","entrypoint":"core","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/channels/plugins/types.plugin.ts"}
{"declaration":"export type ChannelMessageActionContext = ChannelMessageActionContext;","entrypoint":"core","exportName":"ChannelMessageActionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":481,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelMessagingAdapter = ChannelMessagingAdapter;","entrypoint":"core","exportName":"ChannelMessagingAdapter","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":394,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelOutboundSessionRoute = ChannelOutboundSessionRoute;","entrypoint":"core","exportName":"ChannelOutboundSessionRoute","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":308,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelOutboundSessionRouteParams = { cfg: OpenClawConfig; agentId: string; accountId?: string | null; target: string; resolvedTarget?: { to: string; kind: import(\"src/channels/plugins/types.core\").ChannelDirectoryEntryKind | \"channel\"; display?: string; source: \"normalized\" | \"directory\"; }; replyToId?: string | null; threadId?: string | number | null;};","entrypoint":"core","exportName":"ChannelOutboundSessionRouteParams","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":136,"sourcePath":"src/plugin-sdk/core.ts"}
{"declaration":"export type ChannelPlugin = ChannelPlugin<ResolvedAccount, Probe, Audit>;","entrypoint":"core","exportName":"ChannelPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":55,"sourcePath":"src/channels/plugins/types.plugin.ts"}
{"declaration":"export type GatewayBindUrlResult = GatewayBindUrlResult;","entrypoint":"core","exportName":"GatewayBindUrlResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/shared/gateway-bind-url.ts"}
{"declaration":"export type GatewayRequestHandlerOptions = GatewayRequestHandlerOptions;","entrypoint":"core","exportName":"GatewayRequestHandlerOptions","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":111,"sourcePath":"src/gateway/server-methods/types.ts"}
{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"core","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":935,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"core","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":950,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"core","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1292,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1050,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":80,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1275,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"core","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1265,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"core","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1258,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"core","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":94,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"core","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":111,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":950,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"core","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1079,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"core","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":58,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"core","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/plugins/runtime/types.ts"}
{"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"core","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":560,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"core","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"core","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":435,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"core","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":222,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"core","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":206,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"core","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":130,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"core","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":488,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":504,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":513,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"core","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":476,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":243,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"core","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":266,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":537,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":576,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"core","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":416,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"core","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":547,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"core","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":327,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"core","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":363,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":318,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"core","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":449,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"core","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":342,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"core","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":403,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":301,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"core","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":384,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"core","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":284,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":525,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"core","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1311,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1065,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"core","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":88,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"core","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1293,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"core","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1282,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"core","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1274,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginToolContext = OpenClawPluginToolContext;","entrypoint":"core","exportName":"OpenClawPluginToolContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":103,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginToolFactory = OpenClawPluginToolFactory;","entrypoint":"core","exportName":"OpenClawPluginToolFactory","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":120,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"core","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":965,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"core","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1094,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"core","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":59,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"core","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/types.ts"}
{"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"core","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":571,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"core","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":155,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"core","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":446,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"core","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":233,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"core","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":217,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"core","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":140,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"core","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":499,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":515,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"core","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":524,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"core","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":487,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":254,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"core","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":277,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":548,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"core","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":587,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"core","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":427,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"core","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":558,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"core","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":338,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"core","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":374,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":329,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"core","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":460,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"core","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":353,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"core","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":414,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"core","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":312,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"core","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":395,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"core","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":295,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"core","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":536,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderUsageSnapshot = ProviderUsageSnapshot;","entrypoint":"core","exportName":"ProviderUsageSnapshot","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/infra/provider-usage.types.ts"}
{"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"core","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":466,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"core","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":477,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type RoutePeer = RoutePeer;","entrypoint":"core","exportName":"RoutePeer","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":21,"sourcePath":"src/routing/resolve-route.ts"}
{"declaration":"export type RoutePeerKind = ChatType;","entrypoint":"core","exportName":"RoutePeerKind","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":19,"sourcePath":"src/routing/resolve-route.ts"}
{"declaration":"export type SecretFileReadOptions = SecretFileReadOptions;","entrypoint":"core","exportName":"SecretFileReadOptions","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":7,"sourcePath":"src/infra/secret-file.ts"}
{"declaration":"export type SecretFileReadResult = SecretFileReadResult;","entrypoint":"core","exportName":"SecretFileReadResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":12,"sourcePath":"src/infra/secret-file.ts"}
{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"core","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":917,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"core","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":932,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type TailscaleStatusCommandResult = TailscaleStatusCommandResult;","entrypoint":"core","exportName":"TailscaleStatusCommandResult","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/shared/tailscale-status.ts"}
{"declaration":"export type TailscaleStatusCommandRunner = TailscaleStatusCommandRunner;","entrypoint":"core","exportName":"TailscaleStatusCommandRunner","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":6,"sourcePath":"src/shared/tailscale-status.ts"}
{"declaration":"export type UsageProviderId = UsageProviderId;","entrypoint":"core","exportName":"UsageProviderId","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":20,"sourcePath":"src/infra/provider-usage.types.ts"}
{"declaration":"export type UsageWindow = UsageWindow;","entrypoint":"core","exportName":"UsageWindow","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1,"sourcePath":"src/infra/provider-usage.types.ts"}
{"category":"core","entrypoint":"plugin-entry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/plugin-entry.ts"}
{"declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"plugin-entry","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export","sourceLine":79,"sourcePath":"src/plugin-sdk/plugin-entry.ts"}
{"declaration":"export function definePluginEntry({ id, name, description, kind, configSchema, register, }: DefinePluginEntryOptions): DefinedPluginEntry;","entrypoint":"plugin-entry","exportName":"definePluginEntry","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export","sourceLine":88,"sourcePath":"src/plugin-sdk/plugin-entry.ts"}
{"declaration":"export function emptyPluginConfigSchema(): OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"emptyPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"function","recordType":"export","sourceLine":13,"sourcePath":"src/plugins/config-schema.ts"}
{"declaration":"export type AnyAgentTool = AnyAgentTool;","entrypoint":"plugin-entry","exportName":"AnyAgentTool","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":9,"sourcePath":"src/agents/tools/common.ts"}
{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"plugin-entry","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":935,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type MediaUnderstandingProviderPlugin = MediaUnderstandingProvider;","entrypoint":"plugin-entry","exportName":"MediaUnderstandingProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":950,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"plugin-entry","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-entry","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1292,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1050,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":80,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1275,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"plugin-entry","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1265,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1258,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"plugin-entry","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":950,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"plugin-entry","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1079,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"plugin-entry","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":58,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":560,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":435,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"plugin-entry","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":222,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":206,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"plugin-entry","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":130,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"plugin-entry","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":488,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"plugin-entry","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":504,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"plugin-entry","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":513,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"plugin-entry","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":476,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":243,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"plugin-entry","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":266,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":537,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":576,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"plugin-entry","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":416,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":547,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"plugin-entry","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":327,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"plugin-entry","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":363,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":318,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":449,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":342,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"plugin-entry","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":403,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"plugin-entry","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":301,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":384,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"plugin-entry","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":284,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":525,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"plugin-entry","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":466,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"plugin-entry","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":917,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginApi = OpenClawPluginApi;","entrypoint":"plugin-entry","exportName":"OpenClawPluginApi","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1311,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1065,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginConfigSchema = OpenClawPluginConfigSchema;","entrypoint":"plugin-entry","exportName":"OpenClawPluginConfigSchema","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":88,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginDefinition = OpenClawPluginDefinition;","entrypoint":"plugin-entry","exportName":"OpenClawPluginDefinition","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1293,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"plugin-entry","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1282,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"plugin-entry","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1274,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginCommandContext = PluginCommandContext;","entrypoint":"plugin-entry","exportName":"PluginCommandContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":965,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"plugin-entry","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":1094,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type PluginLogger = PluginLogger;","entrypoint":"plugin-entry","exportName":"PluginLogger","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":59,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAugmentModelCatalogContext = ProviderAugmentModelCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderAugmentModelCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":571,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthContext = ProviderAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":155,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthDoctorHintContext = ProviderAuthDoctorHintContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthDoctorHintContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":446,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthMethod = ProviderAuthMethod;","entrypoint":"plugin-entry","exportName":"ProviderAuthMethod","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":233,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthMethodNonInteractiveContext = ProviderAuthMethodNonInteractiveContext;","entrypoint":"plugin-entry","exportName":"ProviderAuthMethodNonInteractiveContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":217,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderAuthResult = ProviderAuthResult;","entrypoint":"plugin-entry","exportName":"ProviderAuthResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":140,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderBuildMissingAuthMessageContext = ProviderBuildMissingAuthMessageContext;","entrypoint":"plugin-entry","exportName":"ProviderBuildMissingAuthMessageContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":499,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderBuiltInModelSuppressionContext = ProviderBuiltInModelSuppressionContext;","entrypoint":"plugin-entry","exportName":"ProviderBuiltInModelSuppressionContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":515,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderBuiltInModelSuppressionResult = ProviderBuiltInModelSuppressionResult;","entrypoint":"plugin-entry","exportName":"ProviderBuiltInModelSuppressionResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":524,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderCacheTtlEligibilityContext = ProviderCacheTtlEligibilityContext;","entrypoint":"plugin-entry","exportName":"ProviderCacheTtlEligibilityContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":487,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderCatalogContext = ProviderCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderCatalogContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":254,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderCatalogResult = ProviderCatalogResult;","entrypoint":"plugin-entry","exportName":"ProviderCatalogResult","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":277,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderDefaultThinkingPolicyContext = ProviderDefaultThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderDefaultThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":548,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderDiscoveryContext = ProviderCatalogContext;","entrypoint":"plugin-entry","exportName":"ProviderDiscoveryContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":587,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderFetchUsageSnapshotContext = ProviderFetchUsageSnapshotContext;","entrypoint":"plugin-entry","exportName":"ProviderFetchUsageSnapshotContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":427,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderModernModelPolicyContext = ProviderModernModelPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderModernModelPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":558,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderNormalizeResolvedModelContext = ProviderNormalizeResolvedModelContext;","entrypoint":"plugin-entry","exportName":"ProviderNormalizeResolvedModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":338,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPreparedRuntimeAuth = ProviderPreparedRuntimeAuth;","entrypoint":"plugin-entry","exportName":"ProviderPreparedRuntimeAuth","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":374,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPrepareDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":329,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPrepareExtraParamsContext = ProviderPrepareExtraParamsContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareExtraParamsContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":460,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderPrepareRuntimeAuthContext = ProviderPrepareRuntimeAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderPrepareRuntimeAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":353,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderResolvedUsageAuth = ProviderResolvedUsageAuth;","entrypoint":"plugin-entry","exportName":"ProviderResolvedUsageAuth","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":414,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderResolveDynamicModelContext = ProviderResolveDynamicModelContext;","entrypoint":"plugin-entry","exportName":"ProviderResolveDynamicModelContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":312,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderResolveUsageAuthContext = ProviderResolveUsageAuthContext;","entrypoint":"plugin-entry","exportName":"ProviderResolveUsageAuthContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":395,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderRuntimeModel = ProviderRuntimeModel;","entrypoint":"plugin-entry","exportName":"ProviderRuntimeModel","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":295,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderThinkingPolicyContext = ProviderThinkingPolicyContext;","entrypoint":"plugin-entry","exportName":"ProviderThinkingPolicyContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":536,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type ProviderWrapStreamFnContext = ProviderWrapStreamFnContext;","entrypoint":"plugin-entry","exportName":"ProviderWrapStreamFnContext","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":477,"sourcePath":"src/plugins/types.ts"}
{"declaration":"export type SpeechProviderPlugin = SpeechProviderPlugin;","entrypoint":"plugin-entry","exportName":"SpeechProviderPlugin","importSpecifier":"openclaw/plugin-sdk/plugin-entry","kind":"type","recordType":"export","sourceLine":932,"sourcePath":"src/plugins/types.ts"}
{"category":"provider","entrypoint":"provider-onboard","importSpecifier":"openclaw/plugin-sdk/provider-onboard","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/provider-onboard.ts"}
{"declaration":"export function applyAgentDefaultModelPrimary(cfg: OpenClawConfig, primary: string): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyAgentDefaultModelPrimary","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":76,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
{"declaration":"export function applyOnboardAuthAgentModelsAndProviders(cfg: OpenClawConfig, params: { agentModels: Record<string, AgentModelEntryConfig>; providers: Record<string, ModelProviderConfig>; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyOnboardAuthAgentModelsAndProviders","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":53,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
@@ -474,8 +478,8 @@
{"declaration":"export function withAgentModelAliases(existing: Record<string, AgentModelEntryConfig> | undefined, aliases: readonly AgentModelAliasEntry[]): Record<string, AgentModelEntryConfig>;","entrypoint":"provider-onboard","exportName":"withAgentModelAliases","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":38,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
{"declaration":"export type AgentModelAliasEntry = AgentModelAliasEntry;","entrypoint":"provider-onboard","exportName":"AgentModelAliasEntry","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":21,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
{"declaration":"export type ModelApi = \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\";","entrypoint":"provider-onboard","exportName":"ModelApi","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":15,"sourcePath":"src/config/types.models.ts"}
{"declaration":"export type ModelDefinitionConfig = ModelDefinitionConfig;","entrypoint":"provider-onboard","exportName":"ModelDefinitionConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":46,"sourcePath":"src/config/types.models.ts"}
{"declaration":"export type ModelProviderConfig = ModelProviderConfig;","entrypoint":"provider-onboard","exportName":"ModelProviderConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":64,"sourcePath":"src/config/types.models.ts"}
{"declaration":"export type ModelDefinitionConfig = ModelDefinitionConfig;","entrypoint":"provider-onboard","exportName":"ModelDefinitionConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":47,"sourcePath":"src/config/types.models.ts"}
{"declaration":"export type ModelProviderConfig = ModelProviderConfig;","entrypoint":"provider-onboard","exportName":"ModelProviderConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":65,"sourcePath":"src/config/types.models.ts"}
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"provider-onboard","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
{"category":"utilities","entrypoint":"reply-payload","importSpecifier":"openclaw/plugin-sdk/reply-payload","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/reply-payload.ts"}
{"declaration":"export function buildMediaPayload(mediaList: MediaPayloadInput[], opts?: { preserveMediaTypeCardinality?: boolean | undefined; } | undefined): MediaPayload;","entrypoint":"reply-payload","exportName":"buildMediaPayload","importSpecifier":"openclaw/plugin-sdk/reply-payload","kind":"function","recordType":"export","sourceLine":15,"sourcePath":"src/channels/plugins/media-payload.ts"}
@@ -505,25 +509,25 @@
{"declaration":"export type SendableOutboundReplyParts = SendableOutboundReplyParts;","entrypoint":"reply-payload","exportName":"SendableOutboundReplyParts","importSpecifier":"openclaw/plugin-sdk/reply-payload","kind":"type","recordType":"export","sourceLine":13,"sourcePath":"src/plugin-sdk/reply-payload.ts"}
{"category":"runtime","entrypoint":"runtime-store","importSpecifier":"openclaw/plugin-sdk/runtime-store","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/runtime-store.ts"}
{"declaration":"export function createPluginRuntimeStore<T>(errorMessage: string): { setRuntime: (next: T) => void; clearRuntime: () => void; tryGetRuntime: () => T | null; getRuntime: () => T; };","entrypoint":"runtime-store","exportName":"createPluginRuntimeStore","importSpecifier":"openclaw/plugin-sdk/runtime-store","kind":"function","recordType":"export","sourceLine":4,"sourcePath":"src/plugin-sdk/runtime-store.ts"}
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"runtime-store","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/runtime-store","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/plugins/runtime/types.ts"}
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"runtime-store","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/runtime-store","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/types.ts"}
{"category":"channel","entrypoint":"secret-input","importSpecifier":"openclaw/plugin-sdk/secret-input","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/secret-input.ts"}
{"declaration":"export function buildOptionalSecretInputSchema(): ZodOptional<ZodUnion<readonly [ZodString, ZodDiscriminatedUnion<[ZodObject<{ source: ZodLiteral<\"env\">; provider: ZodString; id: ZodString; }, $strip>, ZodObject<...>, ZodObject<...>], \"source\">]>>;","entrypoint":"secret-input","exportName":"buildOptionalSecretInputSchema","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":17,"sourcePath":"src/plugin-sdk/secret-input.ts"}
{"declaration":"export function buildSecretInputArraySchema(): ZodArray<ZodUnion<readonly [ZodString, ZodDiscriminatedUnion<[ZodObject<{ source: ZodLiteral<\"env\">; provider: ZodString; id: ZodString; }, $strip>, ZodObject<...>, ZodObject<...>], \"source\">]>>;","entrypoint":"secret-input","exportName":"buildSecretInputArraySchema","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":21,"sourcePath":"src/plugin-sdk/secret-input.ts"}
{"declaration":"export function buildOptionalSecretInputSchema(): ZodOptional<ZodUnion<readonly [ZodString, ZodDiscriminatedUnion<[ZodObject<{ source: ZodLiteral<\"env\">; provider: ZodString; id: ZodString; }, $strip>, ZodObject<...>, ZodObject<...>], \"source\">]>>;","entrypoint":"secret-input","exportName":"buildOptionalSecretInputSchema","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":18,"sourcePath":"src/plugin-sdk/secret-input.ts"}
{"declaration":"export function buildSecretInputArraySchema(): ZodArray<ZodUnion<readonly [ZodString, ZodDiscriminatedUnion<[ZodObject<{ source: ZodLiteral<\"env\">; provider: ZodString; id: ZodString; }, $strip>, ZodObject<...>, ZodObject<...>], \"source\">]>>;","entrypoint":"secret-input","exportName":"buildSecretInputArraySchema","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":23,"sourcePath":"src/plugin-sdk/secret-input.ts"}
{"declaration":"export function buildSecretInputSchema(): ZodUnion<readonly [ZodString, ZodDiscriminatedUnion<[ZodObject<{ source: ZodLiteral<\"env\">; provider: ZodString; id: ZodString; }, $strip>, ZodObject<...>, ZodObject<...>], \"source\">]>;","entrypoint":"secret-input","exportName":"buildSecretInputSchema","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":11,"sourcePath":"src/plugin-sdk/secret-input-schema.ts"}
{"declaration":"export function hasConfiguredSecretInput(value: unknown, defaults?: SecretDefaults | undefined): boolean;","entrypoint":"secret-input","exportName":"hasConfiguredSecretInput","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":106,"sourcePath":"src/config/types.secrets.ts"}
{"declaration":"export function normalizeResolvedSecretInputString(params: { value: unknown; refValue?: unknown; defaults?: SecretDefaults | undefined; path: string; }): string | undefined;","entrypoint":"secret-input","exportName":"normalizeResolvedSecretInputString","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":144,"sourcePath":"src/config/types.secrets.ts"}
{"declaration":"export function normalizeSecretInputString(value: unknown): string | undefined;","entrypoint":"secret-input","exportName":"normalizeSecretInputString","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"function","recordType":"export","sourceLine":113,"sourcePath":"src/config/types.secrets.ts"}
{"declaration":"export type SecretInput = SecretInput;","entrypoint":"secret-input","exportName":"SecretInput","importSpecifier":"openclaw/plugin-sdk/secret-input","kind":"type","recordType":"export","sourceLine":16,"sourcePath":"src/config/types.secrets.ts"}
{"category":"utilities","entrypoint":"testing","importSpecifier":"openclaw/plugin-sdk/testing","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/testing.ts"}
{"declaration":"export function createWindowsCmdShimFixture(params: { shimPath: string; scriptPath: string; shimLine: string; }): Promise<void>;","entrypoint":"testing","exportName":"createWindowsCmdShimFixture","importSpecifier":"openclaw/plugin-sdk/testing","kind":"function","recordType":"export","sourceLine":15,"sourcePath":"src/plugin-sdk/testing.ts"}
{"declaration":"export function installCommonResolveTargetErrorCases(params: { resolveTarget: ResolveTargetFn; implicitAllowFrom: string[]; }): void;","entrypoint":"testing","exportName":"installCommonResolveTargetErrorCases","importSpecifier":"openclaw/plugin-sdk/testing","kind":"function","recordType":"export","sourceLine":40,"sourcePath":"src/plugin-sdk/testing.ts"}
{"declaration":"export function createWindowsCmdShimFixture(params: { shimPath: string; scriptPath: string; shimLine: string; }): Promise<void>;","entrypoint":"testing","exportName":"createWindowsCmdShimFixture","importSpecifier":"openclaw/plugin-sdk/testing","kind":"function","recordType":"export","sourceLine":16,"sourcePath":"src/plugin-sdk/testing.ts"}
{"declaration":"export function installCommonResolveTargetErrorCases(params: { resolveTarget: ResolveTargetFn; implicitAllowFrom: string[]; }): void;","entrypoint":"testing","exportName":"installCommonResolveTargetErrorCases","importSpecifier":"openclaw/plugin-sdk/testing","kind":"function","recordType":"export","sourceLine":42,"sourcePath":"src/plugin-sdk/testing.ts"}
{"declaration":"export function removeAckReactionAfterReply(params: { removeAfterReply: boolean; ackReactionPromise: Promise<boolean> | null; ackReactionValue: string | null; remove: () => Promise<void>; onError?: ((err: unknown) => void) | undefined; }): void;","entrypoint":"testing","exportName":"removeAckReactionAfterReply","importSpecifier":"openclaw/plugin-sdk/testing","kind":"function","recordType":"export","sourceLine":81,"sourcePath":"src/channels/ack-reactions.ts"}
{"declaration":"export function shouldAckReaction(params: AckReactionGateParams): boolean;","entrypoint":"testing","exportName":"shouldAckReaction","importSpecifier":"openclaw/plugin-sdk/testing","kind":"function","recordType":"export","sourceLine":16,"sourcePath":"src/channels/ack-reactions.ts"}
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"testing","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":139,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelAccountSnapshot = ChannelAccountSnapshot;","entrypoint":"testing","exportName":"ChannelAccountSnapshot","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":144,"sourcePath":"src/channels/plugins/types.core.ts"}
{"declaration":"export type ChannelGatewayContext = ChannelGatewayContext<ResolvedAccount>;","entrypoint":"testing","exportName":"ChannelGatewayContext","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":238,"sourcePath":"src/channels/plugins/types.adapters.ts"}
{"declaration":"export type MockFn = MockFn<T>;","entrypoint":"testing","exportName":"MockFn","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":5,"sourcePath":"src/test-utils/vitest-mock-fn.ts"}
{"declaration":"export type OpenClawConfig = OpenClawConfig;","entrypoint":"testing","exportName":"OpenClawConfig","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":32,"sourcePath":"src/config/types.openclaw.ts"}
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"testing","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":53,"sourcePath":"src/plugins/runtime/types.ts"}
{"declaration":"export type PluginRuntime = PluginRuntime;","entrypoint":"testing","exportName":"PluginRuntime","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":54,"sourcePath":"src/plugins/runtime/types.ts"}
{"declaration":"export type RuntimeEnv = RuntimeEnv;","entrypoint":"testing","exportName":"RuntimeEnv","importSpecifier":"openclaw/plugin-sdk/testing","kind":"type","recordType":"export","sourceLine":4,"sourcePath":"src/runtime.ts"}
{"category":"channel","entrypoint":"webhook-ingress","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/webhook-ingress.ts"}
{"declaration":"export function applyBasicWebhookRequestGuards(params: { req: IncomingMessage; res: ServerResponse<IncomingMessage>; allowMethods?: readonly string[] | undefined; rateLimiter?: FixedWindowRateLimiter | undefined; rateLimitKey?: string | undefined; nowMs?: number | undefined; requireJsonContentType?: boolean | undefined; }): boolean;","entrypoint":"webhook-ingress","exportName":"applyBasicWebhookRequestGuards","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":148,"sourcePath":"src/plugin-sdk/webhook-request-guards.ts"}
@@ -533,15 +537,15 @@
{"declaration":"export function createWebhookAnomalyTracker(options?: { maxTrackedKeys?: number | undefined; ttlMs?: number | undefined; logEvery?: number | undefined; trackedStatusCodes?: readonly number[] | undefined; } | undefined): WebhookAnomalyTracker;","entrypoint":"webhook-ingress","exportName":"createWebhookAnomalyTracker","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":167,"sourcePath":"src/plugin-sdk/webhook-memory-guards.ts"}
{"declaration":"export function createWebhookInFlightLimiter(options?: { maxInFlightPerKey?: number | undefined; maxTrackedKeys?: number | undefined; } | undefined): WebhookInFlightLimiter;","entrypoint":"webhook-ingress","exportName":"createWebhookInFlightLimiter","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":91,"sourcePath":"src/plugin-sdk/webhook-request-guards.ts"}
{"declaration":"export function isJsonContentType(value: string | string[] | undefined): boolean;","entrypoint":"webhook-ingress","exportName":"isJsonContentType","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":138,"sourcePath":"src/plugin-sdk/webhook-request-guards.ts"}
{"declaration":"export function isRequestBodyLimitError(error: unknown, code?: RequestBodyLimitErrorCode | undefined): error is RequestBodyLimitError;","entrypoint":"webhook-ingress","exportName":"isRequestBodyLimitError","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":46,"sourcePath":"src/infra/http-body.ts"}
{"declaration":"export function isRequestBodyLimitError(error: unknown, code?: RequestBodyLimitErrorCode | undefined): error is RequestBodyLimitError;","entrypoint":"webhook-ingress","exportName":"isRequestBodyLimitError","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":47,"sourcePath":"src/infra/http-body.ts"}
{"declaration":"export function normalizeWebhookPath(raw: string): string;","entrypoint":"webhook-ingress","exportName":"normalizeWebhookPath","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":2,"sourcePath":"src/plugin-sdk/webhook-path.ts"}
{"declaration":"export function readJsonWebhookBodyOrReject(params: { req: IncomingMessage; res: ServerResponse<IncomingMessage>; maxBytes?: number | undefined; timeoutMs?: number | undefined; profile?: WebhookBodyReadProfile | undefined; emptyObjectOnEmpty?: boolean | undefined; invalidJsonMessage?: string | undefined; }): Promise<...>;","entrypoint":"webhook-ingress","exportName":"readJsonWebhookBodyOrReject","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":275,"sourcePath":"src/plugin-sdk/webhook-request-guards.ts"}
{"declaration":"export function readRequestBodyWithLimit(req: IncomingMessage, options: ReadRequestBodyOptions): Promise<string>;","entrypoint":"webhook-ingress","exportName":"readRequestBodyWithLimit","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":121,"sourcePath":"src/infra/http-body.ts"}
{"declaration":"export function readRequestBodyWithLimit(req: IncomingMessage, options: ReadRequestBodyOptions): Promise<string>;","entrypoint":"webhook-ingress","exportName":"readRequestBodyWithLimit","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":122,"sourcePath":"src/infra/http-body.ts"}
{"declaration":"export function readWebhookBodyOrReject(params: { req: IncomingMessage; res: ServerResponse<IncomingMessage>; maxBytes?: number | undefined; timeoutMs?: number | undefined; profile?: WebhookBodyReadProfile | undefined; invalidBodyMessage?: string | undefined; }): Promise<...>;","entrypoint":"webhook-ingress","exportName":"readWebhookBodyOrReject","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":240,"sourcePath":"src/plugin-sdk/webhook-request-guards.ts"}
{"declaration":"export function registerPluginHttpRoute(params: { path?: string | null | undefined; fallbackPath?: string | null | undefined; handler: PluginHttpRouteHandler; auth: OpenClawPluginHttpRouteAuth; ... 6 more ...; registry?: PluginRegistry | undefined; }): () => void;","entrypoint":"webhook-ingress","exportName":"registerPluginHttpRoute","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":12,"sourcePath":"src/plugins/http-registry.ts"}
{"declaration":"export function registerWebhookTarget<T extends { path: string; }>(targetsByPath: Map<string, T[]>, target: T, opts?: RegisterWebhookTargetOptions<T> | undefined): RegisteredWebhookTarget<T>;","entrypoint":"webhook-ingress","exportName":"registerWebhookTarget","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":61,"sourcePath":"src/plugin-sdk/webhook-targets.ts"}
{"declaration":"export function registerWebhookTargetWithPluginRoute<T extends { path: string; }>(params: { targetsByPath: Map<string, T[]>; target: T; route: RegisterWebhookPluginRouteOptions; onLastPathTargetRemoved?: ((params: { ...; }) => void) | undefined; }): RegisteredWebhookTarget<...>;","entrypoint":"webhook-ingress","exportName":"registerWebhookTargetWithPluginRoute","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":30,"sourcePath":"src/plugin-sdk/webhook-targets.ts"}
{"declaration":"export function requestBodyErrorToText(code: RequestBodyLimitErrorCode): string;","entrypoint":"webhook-ingress","exportName":"requestBodyErrorToText","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":59,"sourcePath":"src/infra/http-body.ts"}
{"declaration":"export function requestBodyErrorToText(code: RequestBodyLimitErrorCode): string;","entrypoint":"webhook-ingress","exportName":"requestBodyErrorToText","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":60,"sourcePath":"src/infra/http-body.ts"}
{"declaration":"export function resolveSingleWebhookTarget<T>(targets: readonly T[], isMatch: (target: T) => boolean): WebhookTargetMatchResult<T>;","entrypoint":"webhook-ingress","exportName":"resolveSingleWebhookTarget","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":193,"sourcePath":"src/plugin-sdk/webhook-targets.ts"}
{"declaration":"export function resolveSingleWebhookTargetAsync<T>(targets: readonly T[], isMatch: (target: T) => Promise<boolean>): Promise<WebhookTargetMatchResult<T>>;","entrypoint":"webhook-ingress","exportName":"resolveSingleWebhookTargetAsync","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":212,"sourcePath":"src/plugin-sdk/webhook-targets.ts"}
{"declaration":"export function resolveWebhookPath(params: { webhookPath?: string | undefined; webhookUrl?: string | undefined; defaultPath?: string | null | undefined; }): string | null;","entrypoint":"webhook-ingress","exportName":"resolveWebhookPath","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":15,"sourcePath":"src/plugin-sdk/webhook-path.ts"}

View File

@@ -8,7 +8,7 @@ title: "Hooks"
# Hooks
Hooks provide an extensible event-driven system for automating actions in response to agent commands and events. Hooks are automatically discovered from directories and can be managed via CLI commands, similar to how skills work in OpenClaw.
Hooks provide an extensible event-driven system for automating actions in response to agent commands and events. Hooks are automatically discovered from directories and can be inspected with `openclaw hooks`, while hook-pack installation and updates now go through `openclaw plugins`.
## Getting Oriented
@@ -17,7 +17,7 @@ Hooks are small scripts that run when something happens. There are two kinds:
- **Hooks** (this page): run inside the Gateway when agent events fire, like `/new`, `/reset`, `/stop`, or lifecycle events.
- **Webhooks**: external HTTP webhooks that let other systems trigger work in OpenClaw. See [Webhook Hooks](/automation/webhook) or use `openclaw webhooks` for Gmail helper commands.
Hooks can also be bundled inside plugins; see [Plugin hooks](/plugins/architecture#provider-runtime-hooks).
Hooks can also be bundled inside plugins; see [Plugin hooks](/plugins/architecture#provider-runtime-hooks). `openclaw hooks list` shows both standalone hooks and plugin-managed hooks.
Common uses:
@@ -26,7 +26,7 @@ Common uses:
- Trigger follow-up automation when a session starts or ends
- Write files into the agent workspace or call external APIs when events fire
If you can write a small TypeScript function, you can write a hook. Hooks are discovered automatically, and you enable or disable them via the CLI.
If you can write a small TypeScript function, you can write a hook. Managed and bundled hooks are trusted local code. Workspace hooks are discovered automatically, but OpenClaw keeps them disabled until you explicitly enable them via the CLI or config.
## Overview
@@ -76,13 +76,20 @@ openclaw hooks info session-memory
During onboarding (`openclaw onboard`), you'll be prompted to enable recommended hooks. The wizard automatically discovers eligible hooks and presents them for selection.
### Trust Boundary
Hooks run inside the Gateway process. Treat bundled hooks, managed hooks, and `hooks.internal.load.extraDirs` as trusted local code. Workspace hooks under `<workspace>/hooks/` are repo-local code, so OpenClaw requires an explicit enable step before loading them.
## Hook Discovery
Hooks are automatically discovered from three directories (in order of precedence):
Hooks are automatically discovered from these directories:
1. **Workspace hooks**: `<workspace>/hooks/` (per-agent, highest precedence)
1. **Workspace hooks**: `<workspace>/hooks/` (per-agent, disabled by default until explicitly enabled)
2. **Managed hooks**: `~/.openclaw/hooks/` (user-installed, shared across workspaces)
3. **Bundled hooks**: `<openclaw>/dist/hooks/bundled/` (shipped with OpenClaw)
3. **Extra hook directories**: `hooks.internal.load.extraDirs` (operator-configured shared hook folders)
4. **Bundled hooks**: `<openclaw>/dist/hooks/bundled/` (shipped with OpenClaw)
Workspace hooks can add new hook names for a repo, but they cannot override bundled, managed, or plugin-provided hooks with the same name.
Managed hook directories can be either a **single hook** or a **hook pack** (package directory).
@@ -100,7 +107,7 @@ Hook packs are standard npm packages that export one or more hooks via `openclaw
`package.json`. Install them with:
```bash
openclaw hooks install <path-or-spec>
openclaw plugins install <path-or-spec>
```
Npm specs are registry-only (package name + optional exact version or dist-tag).
@@ -127,7 +134,7 @@ Hook packs can ship dependencies; they will be installed under `~/.openclaw/hook
Each `openclaw.hooks` entry must stay inside the package directory after symlink
resolution; entries that escape are rejected.
Security note: `openclaw hooks install` installs dependencies with `npm install --ignore-scripts`
Security note: `openclaw plugins install` installs hook-pack dependencies with `npm install --ignore-scripts`
(no lifecycle scripts). Keep hook pack dependency trees "pure JS/TS" and avoid packages that rely
on `postinstall` builds.
@@ -294,11 +301,13 @@ Message events include rich context about the message:
to?: string,
provider?: string,
surface?: string,
threadId?: string,
threadId?: string | number,
senderId?: string,
senderName?: string,
senderUsername?: string,
senderE164?: string,
guildId?: string, // Discord guild / server ID
channelName?: string, // Channel name (e.g., Discord channel name)
}
}
@@ -318,22 +327,42 @@ Message events include rich context about the message:
// message:transcribed context
{
from?: string, // Sender identifier
to?: string, // Recipient identifier
body?: string, // Raw inbound body before enrichment
bodyForAgent?: string, // Enriched body visible to the agent
transcript: string, // Audio transcript text
timestamp?: number, // Unix timestamp when received
channelId: string, // Channel (e.g., "telegram", "whatsapp")
conversationId?: string,
messageId?: string,
senderId?: string, // Sender user ID
senderName?: string, // Sender display name
senderUsername?: string,
provider?: string, // Provider name
surface?: string, // Surface name
mediaPath?: string, // Path to the media file that was transcribed
mediaType?: string, // MIME type of the media
}
// message:preprocessed context
{
from?: string, // Sender identifier
to?: string, // Recipient identifier
body?: string, // Raw inbound body
bodyForAgent?: string, // Final enriched body after media/link understanding
transcript?: string, // Transcript when audio was present
timestamp?: number, // Unix timestamp when received
channelId: string, // Channel (e.g., "telegram", "whatsapp")
conversationId?: string,
messageId?: string,
senderId?: string, // Sender user ID
senderName?: string, // Sender display name
senderUsername?: string,
provider?: string, // Provider name
surface?: string, // Surface name
mediaPath?: string, // Path to the media file
mediaType?: string, // MIME type of the media
isGroup?: boolean,
groupId?: string,
}
@@ -594,6 +623,11 @@ Saves session context to memory when you issue `/new`.
- **Session Key**: agent:main:main
- **Session ID**: abc123def456
- **Source**: telegram
## Conversation Summary
user: Can you help me design the API?
assistant: Sure! Let's start with the endpoints...
```
**Filename examples**:

View File

@@ -582,6 +582,7 @@ Default slash command settings:
OpenClaw can stream draft replies by sending a temporary message and editing it as text arrives.
- `channels.discord.streaming` controls preview streaming (`off` | `partial` | `block` | `progress`, default: `off`).
- Default stays `off` because Discord preview edits can hit rate limits quickly, especially when multiple bots or gateways share the same account or guild traffic.
- `progress` is accepted for cross-channel consistency and maps to `partial` on Discord.
- `channels.discord.streamMode` is a legacy alias and is auto-migrated.
- `partial` edits a single preview message as tokens arrive.

View File

@@ -130,6 +130,12 @@ Notes:
- **open**: public inbound DMs (requires `allowFrom: ["*"]`).
- **disabled**: ignore inbound DMs.
Enforcement notes:
- Sender policy is checked before signature verification and NIP-04 decryption.
- Pairing replies are sent without processing the original DM body.
- Inbound DMs are rate-limited and oversized payloads are dropped before decrypt.
### Allowlist example
```json5
@@ -234,6 +240,7 @@ docker run -p 7777:7777 ghcr.io/hoytech/strfry
- Never commit private keys.
- Use environment variables for keys.
- Consider `allowlist` for production bots.
- Pairing and allowlist policy is enforced before decrypt, so unknown senders cannot force full crypto work.
## Limitations (MVP)

View File

@@ -36,7 +36,7 @@ openclaw pairing list telegram
openclaw pairing approve telegram <CODE>
```
Supported channels: `telegram`, `whatsapp`, `signal`, `imessage`, `discord`, `slack`, `feishu`.
Supported channels: `telegram`, `whatsapp`, `signal`, `imessage`, `discord`, `slack`, `feishu`, `nostr`.
### Where the state lives

View File

@@ -36,6 +36,7 @@ Jobs are ordered so cheap checks fail before expensive ones run:
3. Pushes to `main`: `build-artifacts` + `release-check` + Bun compat + `compat-node22`
Scope logic lives in `scripts/ci-changed-scope.mjs` and is covered by unit tests in `src/scripts/ci-changed-scope.test.ts`.
The same shared scope module also drives the separate `install-smoke` workflow through a narrower `changed-smoke` gate, so Docker/install smoke only runs for install, packaging, and container-relevant changes.
## Runners

View File

@@ -2,7 +2,7 @@
summary: "CLI reference for `openclaw hooks` (agent hooks)"
read_when:
- You want to manage agent hooks
- You want to install or update hooks
- You want to inspect hook availability or enable workspace hooks
title: "hooks"
---
@@ -21,7 +21,7 @@ Related:
openclaw hooks list
```
List all discovered hooks from workspace, managed, and bundled directories.
List all discovered hooks from workspace, managed, extra, and bundled directories.
**Options:**
@@ -127,8 +127,7 @@ openclaw hooks enable <name>
Enable a specific hook by adding it to your config (`~/.openclaw/config.json`).
**Note:** Hooks managed by plugins show `plugin:<id>` in `openclaw hooks list` and
cant be enabled/disabled here. Enable/disable the plugin instead.
**Note:** Workspace hooks are disabled by default until enabled here or in config. Hooks managed by plugins show `plugin:<id>` in `openclaw hooks list` and cant be enabled/disabled here. Enable/disable the plugin instead.
**Arguments:**
@@ -152,6 +151,9 @@ openclaw hooks enable session-memory
- Updates `hooks.internal.entries.<name>.enabled = true` in your config
- Saves config to disk
If the hook came from `<workspace>/hooks/`, this opt-in step is required before
the Gateway will load it.
**After enabling:**
- Restart the gateway so hooks reload (menu bar app restart on macOS, or restart your gateway process in dev).
@@ -184,14 +186,17 @@ openclaw hooks disable command-logger
- Restart the gateway so hooks reload
## Install Hooks
## Install Hook Packs
```bash
openclaw hooks install <path-or-spec>
openclaw hooks install <npm-spec> --pin
openclaw plugins install <path-or-spec>
openclaw plugins install <npm-spec> --pin
```
Install a hook pack from a local folder/archive or npm.
Install hook packs through the unified plugins installer.
`openclaw hooks install` still works as a compatibility alias, but it prints a
deprecation warning and forwards to `openclaw plugins install`.
Npm specs are **registry-only** (package name + optional **exact version** or
**dist-tag**). Git/URL/file specs and semver ranges are rejected. Dependency
@@ -218,26 +223,32 @@ prerelease tag such as `@beta`/`@rc` or an exact prerelease version.
```bash
# Local directory
openclaw hooks install ./my-hook-pack
openclaw plugins install ./my-hook-pack
# Local archive
openclaw hooks install ./my-hook-pack.zip
openclaw plugins install ./my-hook-pack.zip
# NPM package
openclaw hooks install @openclaw/my-hook-pack
openclaw plugins install @openclaw/my-hook-pack
# Link a local directory without copying
openclaw hooks install -l ./my-hook-pack
openclaw plugins install -l ./my-hook-pack
```
## Update Hooks
Linked hook packs are treated as managed hooks from an operator-configured
directory, not as workspace hooks.
## Update Hook Packs
```bash
openclaw hooks update <id>
openclaw hooks update --all
openclaw plugins update <id>
openclaw plugins update --all
```
Update installed hook packs (npm installs only).
Update tracked npm-based hook packs through the unified plugins updater.
`openclaw hooks update` still works as a compatibility alias, but it prints a
deprecation warning and forwards to `openclaw plugins update`.
**Options:**

View File

@@ -485,6 +485,9 @@ List and inspect available skills plus readiness info.
Subcommands:
- `skills search [query...]`: search ClawHub skills.
- `skills install <slug>`: install a skill from ClawHub into the active workspace.
- `skills update <slug|--all>`: update tracked ClawHub skills.
- `skills list`: list skills (default when no subcommand).
- `skills info <name>`: show details for one skill.
- `skills check`: summary of ready vs missing requirements.
@@ -495,7 +498,7 @@ Options:
- `--json`: output JSON (no styling).
- `-v`, `--verbose`: include missing requirements detail.
Tip: use `npx clawhub` to search, install, and sync skills.
Tip: use `openclaw skills search`, `openclaw skills install`, and `openclaw skills update` for ClawHub-backed skills.
### `pairing`

View File

@@ -8,7 +8,7 @@ title: "plugins"
# `openclaw plugins`
Manage Gateway plugins/extensions and compatible bundles.
Manage Gateway plugins/extensions, hook packs, and compatible bundles.
Related:
@@ -48,12 +48,17 @@ capabilities.
```bash
openclaw plugins install <path-or-spec>
openclaw plugins install <npm-spec> --pin
openclaw plugins install clawhub:<package>
openclaw plugins install <plugin>@<marketplace>
openclaw plugins install <plugin> --marketplace <marketplace>
```
Security note: treat plugin installs like running code. Prefer pinned versions.
`plugins install` is also the install surface for hook packs that expose
`openclaw.hooks` in `package.json`. Use `openclaw hooks` for filtered hook
visibility and per-hook enablement, not package installation.
Npm specs are **registry-only** (package name + optional **exact version** or
**dist-tag**). Git/URL/file specs and semver ranges are rejected. Dependency
installs run with `--ignore-scripts` for safety.
@@ -71,6 +76,25 @@ Supported archives: `.zip`, `.tgz`, `.tar.gz`, `.tar`.
Claude marketplace installs are also supported.
ClawHub installs use an explicit `clawhub:<package>` locator:
```bash
openclaw plugins install clawhub:openclaw-codex-app-server
openclaw plugins install clawhub:openclaw-codex-app-server@1.2.3
```
OpenClaw now also prefers ClawHub for bare npm-safe plugin specs. It only falls
back to npm if ClawHub does not have that package or version:
```bash
openclaw plugins install openclaw-codex-app-server
```
OpenClaw downloads the package archive from ClawHub, checks the advertised
plugin API / minimum gateway compatibility, then installs it through the normal
archive path. Recorded installs keep their ClawHub source metadata for later
updates.
Use `plugin@marketplace` shorthand when the marketplace name exists in Claude's
local registry cache at `~/.claude/plugins/known_marketplaces.json`:
@@ -144,8 +168,8 @@ openclaw plugins update <id-or-npm-spec> --dry-run
openclaw plugins update @openclaw/voice-call@beta
```
Updates apply to tracked installs in `plugins.installs`, currently npm and
marketplace installs.
Updates apply to tracked installs in `plugins.installs` and tracked hook-pack
installs in `hooks.internal.installs`.
When you pass a plugin id, OpenClaw reuses the recorded install spec for that
plugin. That means previously stored dist-tags such as `@beta` and exact pinned

View File

@@ -1,14 +1,15 @@
---
summary: "CLI reference for `openclaw skills` (list/info/check) and skill eligibility"
summary: "CLI reference for `openclaw skills` (search/install/update/list/info/check)"
read_when:
- You want to see which skills are available and ready to run
- You want to search, install, or update skills from ClawHub
- You want to debug missing binaries/env/config for skills
title: "skills"
---
# `openclaw skills`
Inspect skills (bundled + workspace + managed overrides) and see whats eligible vs missing requirements.
Inspect local skills and install/update skills from ClawHub.
Related:
@@ -19,8 +20,17 @@ Related:
## Commands
```bash
openclaw skills search "calendar"
openclaw skills install <slug>
openclaw skills install <slug> --version <version>
openclaw skills update <slug>
openclaw skills update --all
openclaw skills list
openclaw skills list --eligible
openclaw skills info <name>
openclaw skills check
```
`search`/`install`/`update` use ClawHub directly and install into the active
workspace `skills/` directory. `list`/`info`/`check` still inspect the local
skills visible to the current workspace and config.

View File

@@ -1044,7 +1044,8 @@
"pages": [
"plugins/building-plugins",
"plugins/sdk-channel-plugins",
"plugins/sdk-provider-plugins"
"plugins/sdk-provider-plugins",
"plugins/sdk-migration"
]
},
{
@@ -1055,7 +1056,6 @@
"plugins/sdk-runtime",
"plugins/sdk-setup",
"plugins/sdk-testing",
"plugins/sdk-migration",
"plugins/manifest",
"plugins/architecture"
]

View File

@@ -179,7 +179,7 @@ WhatsApp runs through the gateway's web channel (Baileys Web). It starts automat
historyLimit: 50,
replyToMode: "first", // off | first | all
linkPreview: true,
streaming: "partial", // off | partial | block | progress (default: off)
streaming: "partial", // off | partial | block | progress (default: off; opt in explicitly to avoid preview-edit rate limits)
actions: { reactions: true, sendMessage: true },
reactionNotifications: "own", // off | own | all
mediaMaxMb: 100,

View File

@@ -259,6 +259,7 @@ High-signal `checkId` values you will most likely see in real deployments (not e
| `tools.exec.auto_allow_skills_enabled` | warn | Exec approvals trust skill bins implicitly | `~/.openclaw/exec-approvals.json` | no |
| `tools.exec.allowlist_interpreter_without_strict_inline_eval` | warn | Interpreter allowlists permit inline eval without forced reapproval | `tools.exec.strictInlineEval`, `agents.list[].tools.exec.strictInlineEval`, exec approvals allowlist | no |
| `tools.exec.safe_bins_interpreter_unprofiled` | warn | Interpreter/runtime bins in `safeBins` without explicit profiles broaden exec risk | `tools.exec.safeBins`, `tools.exec.safeBinProfiles`, `agents.list[].tools.exec.*` | no |
| `tools.exec.safe_bins_broad_behavior` | warn | Broad-behavior tools in `safeBins` weaken the low-risk stdin-filter trust model | `tools.exec.safeBins`, `agents.list[].tools.exec.safeBins` | no |
| `skills.workspace.symlink_escape` | warn | Workspace `skills/**/SKILL.md` resolves outside workspace root (symlink-chain drift) | workspace `skills/**` filesystem state | no |
| `security.exposure.open_channels_with_exec` | warn/critical | Shared/public rooms can reach exec-enabled agents | `channels.*.dmPolicy`, `channels.*.groupPolicy`, `tools.exec.*`, `agents.list[].tools.exec.*` | no |
| `security.exposure.open_groups_with_elevated` | critical | Open groups + elevated tools create high-impact prompt-injection paths | `channels.*.groupPolicy`, `tools.elevated.*` | no |

View File

@@ -992,18 +992,16 @@ Quick answers plus deeper troubleshooting for real-world setups (local dev, VPS,
</Accordion>
<Accordion title="How do I install skills on Linux?">
Use **ClawHub** (CLI) or drop skills into your workspace. The macOS Skills UI isn't available on Linux.
Use native `openclaw skills` commands or drop skills into your workspace. The macOS Skills UI isn't available on Linux.
Browse skills at [https://clawhub.com](https://clawhub.com).
Install the ClawHub CLI (pick one package manager):
```bash
npm i -g clawhub
openclaw skills search "calendar"
openclaw skills install <skill-slug>
openclaw skills update --all
```
```bash
pnpm add -g clawhub
```
Install the separate `clawhub` CLI only if you want to publish or sync your own skills.
</Accordion>
@@ -1075,11 +1073,11 @@ Quick answers plus deeper troubleshooting for real-world setups (local dev, VPS,
Install skills:
```bash
clawhub install <skill-slug>
clawhub update --all
openclaw skills install <skill-slug>
openclaw skills update --all
```
ClawHub installs into `./skills` under your current directory (or falls back to your configured OpenClaw workspace); OpenClaw treats that as `<workspace>/skills` on the next session. For shared skills across agents, place them in `~/.openclaw/skills/<name>/SKILL.md`. Some skills expect binaries installed via Homebrew; on Linux that means Linuxbrew (see the Homebrew Linux FAQ entry above). See [Skills](/tools/skills) and [ClawHub](/tools/clawhub).
Native installs land in the active workspace `skills/` directory. For shared skills across agents, place them in `~/.openclaw/skills/<name>/SKILL.md`. Some skills expect binaries installed via Homebrew; on Linux that means Linuxbrew (see the Homebrew Linux FAQ entry above). See [Skills](/tools/skills) and [ClawHub](/tools/clawhub).
</Accordion>

View File

@@ -54,7 +54,9 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
- Should be fast and stable
- Scheduler note:
- `pnpm test` now keeps a small checked-in behavioral manifest for true pool/isolation overrides and a separate timing snapshot for the slowest unit files.
- Shared unit coverage stays on, but the wrapper peels the heaviest measured files into dedicated lanes instead of relying on a growing hand-maintained exclusion list.
- Shared unit coverage now defaults to `threads`, while the manifest keeps the measured fork-only exceptions and heavy singleton lanes explicit.
- The extension suite (`vitest.extensions.config.ts`) also now defaults to `threads`; the March 22, 2026 direct full-suite control run passed clean without extension-specific fork exceptions.
- The wrapper peels the heaviest measured files into dedicated lanes instead of relying on a growing hand-maintained exclusion list.
- Refresh the timing snapshot with `pnpm test:perf:update-timings` after major suite shape changes.
- Embedded runner note:
- When you change message-tool discovery inputs or compaction runtime context,
@@ -68,9 +70,13 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
through the real `run.ts` / `compact.ts` paths; helper-only tests are not a
sufficient substitute for those integration paths.
- Pool note:
- OpenClaw uses Vitest `vmForks` on Node 22, 23, and 24 for faster unit shards.
- On Node 25+, OpenClaw automatically falls back to regular `forks` until the repo is re-validated there.
- Override manually with `OPENCLAW_TEST_VM_FORKS=0` (force `forks`) or `OPENCLAW_TEST_VM_FORKS=1` (force `vmForks`).
- Base Vitest config still defaults to `forks`.
- Unit wrapper lanes default to `threads`, with explicit manifest fork/vmFork exceptions.
- Extension scoped config defaults to `threads`.
- `pnpm test` also defaults to `--isolate=false` at the wrapper level for faster file startup.
- Opt back into Vitest file isolation with `OPENCLAW_TEST_ISOLATE=1 pnpm test`.
- `OPENCLAW_TEST_NO_ISOLATE=0` or `OPENCLAW_TEST_NO_ISOLATE=false` also force isolated runs.
- `OPENCLAW_TEST_VM_FORKS=1` remains an opt-in experiment on Node 22, 23, and 24 only.
### E2E (gateway smoke)
@@ -78,8 +84,8 @@ Think of the suites as “increasing realism” (and increasing flakiness/cost):
- Config: `vitest.e2e.config.ts`
- Files: `src/**/*.e2e.test.ts`, `test/**/*.e2e.test.ts`
- Runtime defaults:
- Uses Vitest `vmForks` for faster file startup.
- Uses adaptive workers (CI: 2-4, local: 4-8).
- Uses Vitest `forks` for deterministic cross-file isolation.
- Uses adaptive workers (CI: up to 2, local: 1 by default).
- Runs in silent mode by default to reduce console I/O overhead.
- Useful overrides:
- `OPENCLAW_E2E_WORKERS=<n>` to force worker count (capped at 16).

View File

@@ -48,7 +48,7 @@ update **without** changing your persisted channel:
```bash
# Install a specific version
openclaw update --tag 2026.3.14
openclaw update --tag 2026.3.22
# Install from the beta dist-tag (one-off, does not persist)
openclaw update --tag beta
@@ -57,7 +57,7 @@ openclaw update --tag beta
openclaw update --tag main
# Install a specific npm package spec
openclaw update --tag openclaw@2026.3.12
openclaw update --tag openclaw@2026.3.22
```
Notes:
@@ -75,7 +75,7 @@ Preview what `openclaw update` would do without making changes:
```bash
openclaw update --dry-run
openclaw update --channel beta --dry-run
openclaw update --tag 2026.3.14 --dry-run
openclaw update --tag 2026.3.22 --dry-run
openclaw update --dry-run --json
```

View File

@@ -13,8 +13,10 @@ read_when:
Plugins extend OpenClaw with new capabilities: channels, model providers, speech,
image generation, web search, agent tools, or any combination.
You do not need to add your plugin to the OpenClaw repository. Publish on npm
and users install with `openclaw plugins install <npm-spec>`.
You do not need to add your plugin to the OpenClaw repository. Publish to
[ClawHub](/tools/clawhub) or npm and users install with
`openclaw plugins install <package-name>`. OpenClaw tries ClawHub first and
falls back to npm automatically.
## Prerequisites
@@ -105,13 +107,14 @@ and provider plugins have dedicated guides linked above.
<Step title="Test and publish">
**External plugins:**
**External plugins:** publish to [ClawHub](/tools/clawhub) or npm, then install:
```bash
npm publish
openclaw plugins install @myorg/openclaw-my-plugin
```
OpenClaw checks ClawHub first, then falls back to npm.
**In-repo plugins:** place under `extensions/` — automatically discovered.
```bash

View File

@@ -10,12 +10,15 @@ title: "Community Plugins"
Community plugins are third-party packages that extend OpenClaw with new
channels, tools, providers, or other capabilities. They are built and maintained
by the community, published on npm, and installable with a single command.
by the community, published on [ClawHub](/tools/clawhub) or npm, and
installable with a single command.
```bash
openclaw plugins install <npm-spec>
openclaw plugins install <package-name>
```
OpenClaw checks ClawHub first and falls back to npm automatically.
## Listed plugins
### Codex App Server Bridge
@@ -99,8 +102,9 @@ openclaw plugins install @wecom/wecom-openclaw-plugin
We welcome community plugins that are useful, documented, and safe to operate.
<Steps>
<Step title="Publish to npm">
Your plugin must be installable via `openclaw plugins install \<npm-spec\>`.
<Step title="Publish to ClawHub or npm">
Your plugin must be installable via `openclaw plugins install \<package-name\>`.
Publish to [ClawHub](/tools/clawhub) (preferred) or npm.
See [Building Plugins](/plugins/building-plugins) for the full guide.
</Step>
@@ -125,12 +129,12 @@ We welcome community plugins that are useful, documented, and safe to operate.
## Quality bar
| Requirement | Why |
| -------------------- | --------------------------------------------- |
| Published on npm | Users need `openclaw plugins install` to work |
| Public GitHub repo | Source review, issue tracking, transparency |
| Setup and usage docs | Users need to know how to configure it |
| Active maintenance | Recent updates or responsive issue handling |
| Requirement | Why |
| --------------------------- | --------------------------------------------- |
| Published on ClawHub or npm | Users need `openclaw plugins install` to work |
| Public GitHub repo | Source review, issue tracking, transparency |
| Setup and usage docs | Users need to know how to configure it |
| Active maintenance | Recent updates or responsive issue handling |
Low-effort wrappers, unclear ownership, or unmaintained packages may be declined.

View File

@@ -35,7 +35,28 @@ See the full plugin system guide: [Plugins](/tools/plugin).
For the native capability model and current external-compatibility guidance:
[Capability model](/plugins/architecture#public-capability-model).
## Required fields
## What this file does
`openclaw.plugin.json` is the metadata OpenClaw reads before it loads your
plugin code.
Use it for:
- plugin identity
- config validation
- auth and onboarding metadata that should be available without booting plugin
runtime
- config UI hints
Do not use it for:
- registering runtime behavior
- declaring code entrypoints
- npm install metadata
Those belong in your plugin code and `package.json`.
## Minimal example
```json
{
@@ -48,45 +69,18 @@ For the native capability model and current external-compatibility guidance:
}
```
Required keys:
- `id` (string): canonical plugin id.
- `configSchema` (object): JSON Schema for plugin config (inline).
Optional keys:
- `kind` (string): plugin kind (examples: `"memory"`, `"context-engine"`).
- `channels` (array): channel ids registered by this plugin (channel capability; example: `["matrix"]`).
- `providers` (array): provider ids registered by this plugin (text inference capability).
- `providerAuthEnvVars` (object): auth env vars keyed by provider id. Use this
when OpenClaw should resolve provider credentials from env without loading
plugin runtime first.
- `providerAuthChoices` (array): cheap onboarding/auth-choice metadata keyed by
provider + auth method. Use this when OpenClaw should show a provider in
auth-choice pickers, preferred-provider resolution, and CLI help without
loading plugin runtime first.
- `skills` (array): skill directories to load (relative to the plugin root).
- `name` (string): display name for the plugin.
- `description` (string): short plugin summary.
- `uiHints` (object): config field labels/placeholders/sensitive flags for UI rendering.
- `version` (string): plugin version (informational).
### `providerAuthChoices` shape
Each entry can declare:
- `provider`: provider id
- `method`: auth method id
- `choiceId`: stable onboarding/auth-choice id
- `choiceLabel` / `choiceHint`: picker label + short hint
- `groupId` / `groupLabel` / `groupHint`: grouped onboarding bucket metadata
- `optionKey` / `cliFlag` / `cliOption` / `cliDescription`: optional one-flag
CLI wiring for simple auth flows such as API keys
Example:
## Rich example
```json
{
"id": "openrouter",
"name": "OpenRouter",
"description": "OpenRouter provider plugin",
"version": "1.0.0",
"providers": ["openrouter"],
"providerAuthEnvVars": {
"openrouter": ["OPENROUTER_API_KEY"]
},
"providerAuthChoices": [
{
"provider": "openrouter",
@@ -98,12 +92,110 @@ Example:
"optionKey": "openrouterApiKey",
"cliFlag": "--openrouter-api-key",
"cliOption": "--openrouter-api-key <key>",
"cliDescription": "OpenRouter API key"
"cliDescription": "OpenRouter API key",
"onboardingScopes": ["text-inference"]
}
]
],
"uiHints": {
"apiKey": {
"label": "API key",
"placeholder": "sk-or-v1-...",
"sensitive": true
}
},
"configSchema": {
"type": "object",
"additionalProperties": false,
"properties": {
"apiKey": {
"type": "string"
}
}
}
}
```
## Top-level field reference
| Field | Required | Type | What it means |
| --------------------- | -------- | -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `id` | Yes | `string` | Canonical plugin id. This is the id used in `plugins.entries.<id>`. |
| `configSchema` | Yes | `object` | Inline JSON Schema for this plugin's config. |
| `enabledByDefault` | No | `true` | Marks a bundled plugin as enabled by default. Omit it, or set any non-`true` value, to leave the plugin disabled by default. |
| `kind` | No | `"memory"` \| `"context-engine"` | Declares an exclusive plugin kind used by `plugins.slots.*`. |
| `channels` | No | `string[]` | Channel ids owned by this plugin. Used for discovery and config validation. |
| `providers` | No | `string[]` | Provider ids owned by this plugin. |
| `providerAuthEnvVars` | No | `Record<string, string[]>` | Cheap provider-auth env metadata that OpenClaw can inspect without loading plugin code. |
| `providerAuthChoices` | No | `object[]` | Cheap auth-choice metadata for onboarding pickers, preferred-provider resolution, and simple CLI flag wiring. |
| `skills` | No | `string[]` | Skill directories to load, relative to the plugin root. |
| `name` | No | `string` | Human-readable plugin name. |
| `description` | No | `string` | Short summary shown in plugin surfaces. |
| `version` | No | `string` | Informational plugin version. |
| `uiHints` | No | `Record<string, object>` | UI labels, placeholders, and sensitivity hints for config fields. |
## providerAuthChoices reference
Each `providerAuthChoices` entry describes one onboarding or auth choice.
OpenClaw reads this before provider runtime loads.
| Field | Required | Type | What it means |
| ------------------ | -------- | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `provider` | Yes | `string` | Provider id this choice belongs to. |
| `method` | Yes | `string` | Auth method id to dispatch to. |
| `choiceId` | Yes | `string` | Stable auth-choice id used by onboarding and CLI flows. |
| `choiceLabel` | No | `string` | User-facing label. If omitted, OpenClaw falls back to `choiceId`. |
| `choiceHint` | No | `string` | Short helper text for the picker. |
| `groupId` | No | `string` | Optional group id for grouping related choices. |
| `groupLabel` | No | `string` | User-facing label for that group. |
| `groupHint` | No | `string` | Short helper text for the group. |
| `optionKey` | No | `string` | Internal option key for simple one-flag auth flows. |
| `cliFlag` | No | `string` | CLI flag name, such as `--openrouter-api-key`. |
| `cliOption` | No | `string` | Full CLI option shape, such as `--openrouter-api-key <key>`. |
| `cliDescription` | No | `string` | Description used in CLI help. |
| `onboardingScopes` | No | `Array<"text-inference" \| "image-generation">` | Which onboarding surfaces this choice should appear in. If omitted, it defaults to `["text-inference"]`. |
## uiHints reference
`uiHints` is a map from config field names to small rendering hints.
```json
{
"uiHints": {
"apiKey": {
"label": "API key",
"help": "Used for OpenRouter requests",
"placeholder": "sk-or-v1-...",
"sensitive": true
}
}
}
```
Each field hint can include:
| Field | Type | What it means |
| ------------- | ---------- | --------------------------------------- |
| `label` | `string` | User-facing field label. |
| `help` | `string` | Short helper text. |
| `tags` | `string[]` | Optional UI tags. |
| `advanced` | `boolean` | Marks the field as advanced. |
| `sensitive` | `boolean` | Marks the field as secret or sensitive. |
| `placeholder` | `string` | Placeholder text for form inputs. |
## Manifest versus package.json
The two files serve different jobs:
| File | Use it for |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------ |
| `openclaw.plugin.json` | Discovery, config validation, auth-choice metadata, and UI hints that must exist before plugin code runs |
| `package.json` | npm metadata, dependency installation, and the `openclaw` block used for entrypoints and setup or catalog metadata |
If you are unsure where a piece of metadata belongs, use this rule:
- if OpenClaw must know it before loading plugin code, put it in `openclaw.plugin.json`
- if it is about packaging, entry files, or npm install behavior, put it in `package.json`
## JSON Schema requirements
- **Every plugin must ship a JSON Schema**, even if it accepts no config.
@@ -128,6 +220,8 @@ See [Configuration reference](/configuration) for the full `plugins.*` schema.
- The manifest is **required for native OpenClaw plugins**, including local filesystem loads.
- Runtime still loads the plugin module separately; the manifest is only for
discovery + validation.
- Only documented manifest fields are read by the manifest loader. Avoid adding
custom top-level keys here.
- `providerAuthEnvVars` is the cheap metadata path for auth probes, env-marker
validation, and similar provider-auth surfaces that should not boot plugin
runtime just to inspect env names.
@@ -140,6 +234,8 @@ See [Configuration reference](/configuration) for the full `plugins.*` schema.
- `kind: "memory"` is selected by `plugins.slots.memory`.
- `kind: "context-engine"` is selected by `plugins.slots.contextEngine`
(default: built-in `legacy`).
- `channels`, `providers`, and `skills` can be omitted when a plugin does not
need them.
- If your plugin depends on native modules, document the build steps and any
package-manager allowlist requirements (for example, pnpm `allow-build-scripts`
- `pnpm rebuild <package>`).

View File

@@ -43,7 +43,7 @@ export default definePluginEntry({
});
```
### Options
### Channel entry options
| Field | Type | Required | Default |
| -------------- | ---------------------------------------------------------------- | -------- | ------------------- |

View File

@@ -1,6 +1,6 @@
---
title: "Plugin SDK Migration"
sidebarTitle: "SDK Migration"
sidebarTitle: "Migrate to SDK"
summary: "Migrate from the legacy backwards-compatibility layer to the modern plugin SDK"
read_when:
- You see the OPENCLAW_PLUGIN_SDK_COMPAT_DEPRECATED warning

View File

@@ -294,13 +294,20 @@ const setupSurface = createOptionalChannelSetupSurface({
## Publishing and installing
**External plugins:**
**External plugins:** publish to [ClawHub](/tools/clawhub) or npm, then install:
```bash
npm publish
openclaw plugins install @myorg/openclaw-my-plugin
```
OpenClaw tries ClawHub first and falls back to npm automatically. You can also
force a specific source:
```bash
openclaw plugins install clawhub:@myorg/openclaw-my-plugin # ClawHub only
openclaw plugins install npm:@myorg/openclaw-my-plugin # npm only
```
**In-repo plugins:** place under `extensions/` and they are automatically
discovered during build.
@@ -308,13 +315,13 @@ discovered during build.
```bash
openclaw plugins search <query>
openclaw plugins install <npm-spec>
openclaw plugins install <package-name>
```
<Info>
`openclaw plugins install` runs `npm install --ignore-scripts` (no lifecycle
scripts). Keep plugin dependency trees pure JS/TS and avoid packages that
require `postinstall` builds.
For npm-sourced installs, `openclaw plugins install` runs
`npm install --ignore-scripts` (no lifecycle scripts). Keep plugin dependency
trees pure JS/TS and avoid packages that require `postinstall` builds.
</Info>
## Related

View File

@@ -13,6 +13,8 @@ title: "Tests"
- `pnpm test:coverage`: Runs the unit suite with V8 coverage (via `vitest.unit.config.ts`). Global thresholds are 70% lines/branches/functions/statements. Coverage excludes integration-heavy entrypoints (CLI wiring, gateway/telegram bridges, webchat static server) to keep the target focused on unit-testable logic.
- `pnpm test` on Node 22, 23, and 24 uses Vitest `vmForks` by default for local runs with enough memory. CI stays on `forks` unless explicitly overridden. Node 25+ falls back to `forks` until re-validated. You can force behavior with `OPENCLAW_TEST_VM_FORKS=0|1`.
- `pnpm test`: runs the full wrapper. It keeps only a small behavioral override manifest in git, then uses a checked-in timing snapshot to peel the heaviest measured unit files into dedicated lanes.
- Unit files default to `threads` in the wrapper; keep fork-only or singleton exceptions documented in `test/fixtures/test-parallel.behavior.json`.
- `pnpm test:extensions` now defaults to `threads` via `vitest.extensions.config.ts`; the March 22, 2026 direct full-suite control run passed clean without extension-specific fork exceptions.
- Files marked `singletonIsolated` no longer spawn one fresh Vitest process each by default. The wrapper batches them into dedicated `forks` lanes with `maxWorkers=1`, which preserves isolation from `unit-fast` while cutting process startup overhead. Tune lane count with `OPENCLAW_TEST_SINGLETON_ISOLATED_LANES=<n>`.
- `pnpm test:channels`: runs channel-heavy suites.
- `pnpm test:extensions`: runs extension/plugin suites.

View File

@@ -192,6 +192,11 @@ MEDIA:https://example.com/screenshot.png
OpenClaw extracts these and sends them as media alongside the text.
For local paths, the default allowlist is intentionally narrow: the OpenClaw temp
root, the media cache, agent workspace paths, and sandbox-generated files. If you
need broader local-file attachment roots, configure an explicit channel/plugin
allowlist instead of relying on arbitrary host paths.
## Operations checklist
```bash

View File

@@ -528,7 +528,7 @@ Then verify backend health:
### acpx command and version configuration
By default, the acpx plugin (published as `@openclaw/acpx`) uses the plugin-local pinned binary:
By default, the bundled acpx backend plugin (`acpx`) uses the plugin-local pinned binary:
1. Command defaults to `extensions/acpx/node_modules/.bin/acpx`.
2. Expected version defaults to the extension pin.

View File

@@ -1,5 +1,5 @@
---
summary: "ClawHub guide: public skills registry + CLI workflows"
summary: "ClawHub guide: public registry, native OpenClaw install flows, and ClawHub CLI workflows"
read_when:
- Introducing ClawHub to new users
- Installing, searching, or publishing skills
@@ -9,10 +9,41 @@ title: "ClawHub"
# ClawHub
ClawHub is the **public skill registry for OpenClaw**. It is a free service: all skills are public, open, and visible to everyone for sharing and reuse. A skill is just a folder with a `SKILL.md` file (plus supporting text files). You can browse skills in the web app or use the CLI to search, install, update, and publish skills.
ClawHub is the public registry for **OpenClaw skills and plugins**.
- Use native `openclaw` commands to search/install/update skills and install
plugins from ClawHub.
- Use the separate `clawhub` CLI when you need registry auth, publish, delete,
undelete, or sync workflows.
Site: [clawhub.ai](https://clawhub.ai)
## Native OpenClaw flows
Skills:
```bash
openclaw skills search "calendar"
openclaw skills install <skill-slug>
openclaw skills update --all
```
Plugins:
```bash
openclaw plugins install clawhub:<package>
openclaw plugins update --all
```
Bare npm-safe plugin specs are also tried against ClawHub before npm:
```bash
openclaw plugins install openclaw-codex-app-server
```
Native `openclaw` commands install into your active workspace and persist source
metadata so later `update` calls can stay on ClawHub.
## What ClawHub is
- A public registry for OpenClaw skills.
@@ -45,16 +76,17 @@ If you want to add new capabilities to your OpenClaw agent, ClawHub is the easie
## Quick start (non-technical)
1. Install the CLI (see next section).
2. Search for something you need:
- `clawhub search "calendar"`
3. Install a skill:
- `clawhub install <skill-slug>`
4. Start a new OpenClaw session so it picks up the new skill.
1. Search for something you need:
- `openclaw skills search "calendar"`
2. Install a skill:
- `openclaw skills install <skill-slug>`
3. Start a new OpenClaw session so it picks up the new skill.
4. If you want to publish or manage registry auth, install the separate
`clawhub` CLI too.
## Install the CLI
## Install the ClawHub CLI
Pick one:
You only need this for registry-authenticated workflows such as publish/sync:
```bash
npm i -g clawhub
@@ -66,7 +98,16 @@ pnpm add -g clawhub
## How it fits into OpenClaw
By default, the CLI installs skills into `./skills` under your current working directory. If an OpenClaw workspace is configured, `clawhub` falls back to that workspace unless you override `--workdir` (or `CLAWHUB_WORKDIR`). OpenClaw loads workspace skills from `<workspace>/skills` and will pick them up in the **next** session. If you already use `~/.openclaw/skills` or bundled skills, workspace skills take precedence.
Native `openclaw skills install` installs into the active workspace `skills/`
directory. `openclaw plugins install clawhub:...` records a normal managed
plugin install plus ClawHub source metadata for updates.
The separate `clawhub` CLI also installs skills into `./skills` under your
current working directory. If an OpenClaw workspace is configured, `clawhub`
falls back to that workspace unless you override `--workdir` (or
`CLAWHUB_WORKDIR`). OpenClaw loads workspace skills from `<workspace>/skills`
and will pick them up in the **next** session. If you already use
`~/.openclaw/skills` or bundled skills, workspace skills take precedence.
For more detail on how skills are loaded, shared, and gated, see
[Skills](/tools/skills).

View File

@@ -160,7 +160,7 @@ Important trust notes:
## Safe bins (stdin-only)
`tools.exec.safeBins` defines a small list of **stdin-only** binaries (for example `jq`)
`tools.exec.safeBins` defines a small list of **stdin-only** binaries (for example `cut`)
that can run in allowlist mode **without** explicit allowlist entries. Safe bins reject
positional file args and path-like tokens, so they can only operate on the incoming stream.
Treat this as a narrow fast-path for stream filters, not a general trust list.
@@ -215,7 +215,13 @@ etc.) so inner executables are persisted instead of multiplexer binaries. If a w
multiplexer cannot be safely unwrapped, no allowlist entry is persisted automatically.
If you allowlist interpreters like `python3` or `node`, prefer `tools.exec.strictInlineEval=true` so inline eval still requires an explicit approval.
Default safe bins: `jq`, `cut`, `uniq`, `head`, `tail`, `tr`, `wc`.
Default safe bins:
[//]: # "SAFE_BIN_DEFAULTS:START"
`cut`, `uniq`, `head`, `tail`, `tr`, `wc`
[//]: # "SAFE_BIN_DEFAULTS:END"
`grep` and `sort` are not in the default list. If you opt in, keep explicit allowlist entries for
their non-stdin workflows.
@@ -229,7 +235,7 @@ rejected so file operands cannot be smuggled as ambiguous positionals.
| Goal | Auto-allow narrow stdin filters | Explicitly trust specific executables |
| Match type | Executable name + safe-bin argv policy | Resolved executable path glob pattern |
| Argument scope | Restricted by safe-bin profile and literal-token rules | Path match only; arguments are otherwise your responsibility |
| Typical examples | `jq`, `head`, `tail`, `wc` | `python3`, `node`, `ffmpeg`, custom CLIs |
| Typical examples | `head`, `tail`, `tr`, `wc` | `jq`, `python3`, `node`, `ffmpeg`, custom CLIs |
| Best use | Low-risk text transforms in pipelines | Any tool with broader behavior or side effects |
Configuration location:
@@ -261,6 +267,10 @@ Custom profile example:
}
```
If you explicitly opt `jq` into `safeBins`, OpenClaw still rejects the `env` builtin in safe-bin
mode so `jq -n env` cannot dump the host process environment without an explicit allowlist path
or approval prompt.
## Control UI editing
Use the **Control UI → Nodes → Exec approvals** card to edit defaults, peragent

View File

@@ -144,6 +144,7 @@ Use the two controls for different jobs:
Do not treat `safeBins` as a generic allowlist, and do not add interpreter/runtime binaries (for example `python3`, `node`, `ruby`, `bash`). If you need those, use explicit allowlist entries and keep approval prompts enabled.
`openclaw security audit` warns when interpreter/runtime `safeBins` entries are missing explicit profiles, and `openclaw doctor --fix` can scaffold missing custom `safeBinProfiles` entries.
`openclaw security audit` and `openclaw doctor` also warn when you explicitly add broad-behavior bins such as `jq` back into `safeBins`.
If you explicitly allowlist interpreters, enable `tools.exec.strictInlineEval` so inline code-eval forms still require a fresh approval.
For full policy details and examples, see [Exec approvals](/tools/exec-approvals#safe-bins-stdin-only) and [Safe bins versus allowlist](/tools/exec-approvals#safe-bins-versus-allowlist).

View File

@@ -193,7 +193,8 @@ openclaw plugins inspect <id> --json # machine-readable
openclaw plugins status # operational summary
openclaw plugins doctor # diagnostics
openclaw plugins install <npm-spec> # install from npm
openclaw plugins install <package> # install (ClawHub first, then npm)
openclaw plugins install clawhub:<pkg> # install from ClawHub only
openclaw plugins install <path> # install from local path
openclaw plugins install -l <path> # link (no copy) for dev
openclaw plugins update <id> # update one plugin

View File

@@ -50,21 +50,24 @@ tool surface those skills teach.
## ClawHub (install + sync)
ClawHub is the public skills registry for OpenClaw. Browse at
[https://clawhub.com](https://clawhub.com). Use it to discover, install, update, and back up skills.
[https://clawhub.com](https://clawhub.com). Use native `openclaw skills`
commands to discover/install/update skills, or the separate `clawhub` CLI when
you need publish/sync workflows.
Full guide: [ClawHub](/tools/clawhub).
Common flows:
- Install a skill into your workspace:
- `clawhub install <skill-slug>`
- `openclaw skills install <skill-slug>`
- Update all installed skills:
- `clawhub update --all`
- `openclaw skills update --all`
- Sync (scan + publish updates):
- `clawhub sync --all`
By default, `clawhub` installs into `./skills` under your current working
directory (or falls back to the configured OpenClaw workspace). OpenClaw picks
that up as `<workspace>/skills` on the next session.
Native `openclaw skills install` installs into the active workspace `skills/`
directory. The separate `clawhub` CLI also installs into `./skills` under your
current working directory (or falls back to the configured OpenClaw workspace).
OpenClaw picks that up as `<workspace>/skills` on the next session.
## Security notes

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/acpx",
"version": "2026.3.14",
"version": "2026.3.22",
"description": "OpenClaw ACP runtime backend via acpx",
"type": "module",
"dependencies": {

View File

@@ -109,7 +109,7 @@ Do not default to subagent runtime for these requests.
## ACPX install and version policy (direct acpx path)
For this repo, direct `acpx` calls must follow the same pinned policy as the `@openclaw/acpx` extension.
For this repo, direct `acpx` calls must follow the same pinned policy as the `@openclaw/acpx` extension package.
1. Prefer plugin-local binary, not global PATH:
- `./extensions/acpx/node_modules/.bin/acpx`

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/amazon-bedrock-provider",
"version": "2026.3.14",
"version": "2026.3.22",
"private": true,
"description": "OpenClaw Amazon Bedrock provider plugin",
"type": "module",

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/anthropic-provider",
"version": "2026.3.14",
"version": "2026.3.22",
"private": true,
"description": "OpenClaw Anthropic provider plugin",
"type": "module",

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/bluebubbles",
"version": "2026.3.14",
"version": "2026.3.22",
"description": "OpenClaw BlueBubbles channel plugin",
"type": "module",
"dependencies": {
@@ -10,7 +10,7 @@
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
"openclaw": ">=2026.3.22"
},
"peerDependenciesMeta": {
"openclaw": {
@@ -43,7 +43,7 @@
"npmSpec": "@openclaw/bluebubbles",
"localPath": "extensions/bluebubbles",
"defaultChoice": "npm",
"minHostVersion": ">=2026.3.14"
"minHostVersion": ">=2026.3.22"
},
"release": {
"publishToNpm": true

View File

@@ -1,5 +1,8 @@
import { createAccountListHelpers } from "openclaw/plugin-sdk/account-helpers";
import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
import {
createAccountListHelpers,
normalizeAccountId,
resolveMergedAccountConfig,
} from "openclaw/plugin-sdk/account-resolution";
import type { OpenClawConfig } from "openclaw/plugin-sdk/core";
import { hasConfiguredSecretInput, normalizeSecretInputString } from "./secret-input.js";
import { normalizeBlueBubblesServerUrl, type BlueBubblesAccountConfig } from "./types.js";
@@ -19,29 +22,19 @@ const {
} = createAccountListHelpers("bluebubbles");
export { listBlueBubblesAccountIds, resolveDefaultBlueBubblesAccountId };
function resolveAccountConfig(
cfg: OpenClawConfig,
accountId: string,
): BlueBubblesAccountConfig | undefined {
const accounts = cfg.channels?.bluebubbles?.accounts;
if (!accounts || typeof accounts !== "object") {
return undefined;
}
return accounts[accountId] as BlueBubblesAccountConfig | undefined;
}
function mergeBlueBubblesAccountConfig(
cfg: OpenClawConfig,
accountId: string,
): BlueBubblesAccountConfig {
const base = (cfg.channels?.bluebubbles ?? {}) as BlueBubblesAccountConfig & {
accounts?: unknown;
defaultAccount?: unknown;
};
const { accounts: _ignored, defaultAccount: _ignoredDefaultAccount, ...rest } = base;
const account = resolveAccountConfig(cfg, accountId) ?? {};
const chunkMode = account.chunkMode ?? rest.chunkMode ?? "length";
return { ...rest, ...account, chunkMode };
const merged = resolveMergedAccountConfig<BlueBubblesAccountConfig>({
channelConfig: cfg.channels?.bluebubbles as BlueBubblesAccountConfig | undefined,
accounts: cfg.channels?.bluebubbles?.accounts as
| Record<string, Partial<BlueBubblesAccountConfig>>
| undefined,
accountId,
omitKeys: ["defaultAccount"],
});
return { ...merged, chunkMode: merged.chunkMode ?? "length" };
}
export function resolveBlueBubblesAccount(params: {

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/brave-plugin",
"version": "2026.3.14",
"version": "2026.3.22",
"private": true,
"description": "OpenClaw Brave plugin",
"type": "module",

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/byteplus-provider",
"version": "2026.3.14",
"version": "2026.3.22",
"private": true,
"description": "OpenClaw BytePlus provider plugin",
"type": "module",

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/chutes-provider",
"version": "2026.3.14",
"version": "2026.3.22",
"private": true,
"description": "OpenClaw Chutes.ai provider plugin",
"type": "module",

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/cloudflare-ai-gateway-provider",
"version": "2026.3.14",
"version": "2026.3.22",
"private": true,
"description": "OpenClaw Cloudflare AI Gateway provider plugin",
"type": "module",

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/copilot-proxy",
"version": "2026.3.14",
"version": "2026.3.22",
"private": true,
"description": "OpenClaw Copilot Proxy provider plugin",
"type": "module",

View File

@@ -84,8 +84,17 @@ function registerPairCommand(params?: {
},
}),
);
expect(command).toBeTruthy();
return command!;
if (!command) {
throw new Error("device-pair plugin did not register its /pair command");
}
return command;
}
function requireText(result: { text?: unknown } | null | undefined): string {
if (typeof result?.text !== "string") {
throw new Error("pair command did not return a text response");
}
return result.text;
}
function createChannelRuntime(
@@ -135,15 +144,16 @@ describe("device-pair /pair qr", () => {
it("returns an inline QR image for webchat surfaces", async () => {
const command = registerPairCommand();
const result = await command?.handler(createCommandContext({ channel: "webchat" }));
const result = await command.handler(createCommandContext({ channel: "webchat" }));
const text = requireText(result);
expect(pluginApiMocks.renderQrPngBase64).toHaveBeenCalledTimes(1);
expect(result?.text).toContain("Scan this QR code with the OpenClaw iOS app:");
expect(result?.text).toContain("![OpenClaw pairing QR](data:image/png;base64,ZmFrZXBuZw==)");
expect(result?.text).toContain("- Security: single-use bootstrap token");
expect(result?.text).toContain("**Important:** Run `/pair cleanup` after pairing finishes.");
expect(result?.text).toContain("If this QR code leaks, run `/pair cleanup` immediately.");
expect(result?.text).not.toContain("```");
expect(text).toContain("Scan this QR code with the OpenClaw iOS app:");
expect(text).toContain("![OpenClaw pairing QR](data:image/png;base64,ZmFrZXBuZw==)");
expect(text).toContain("- Security: single-use bootstrap token");
expect(text).toContain("**Important:** Run `/pair cleanup` after pairing finishes.");
expect(text).toContain("If this QR code leaks, run `/pair cleanup` immediately.");
expect(text).not.toContain("```");
});
it("reissues the bootstrap token if webchat QR rendering fails before falling back", async () => {
@@ -159,16 +169,17 @@ describe("device-pair /pair qr", () => {
pluginApiMocks.renderQrPngBase64.mockRejectedValueOnce(new Error("render failed"));
const command = registerPairCommand();
const result = await command?.handler(createCommandContext({ channel: "webchat" }));
const result = await command.handler(createCommandContext({ channel: "webchat" }));
const text = requireText(result);
expect(pluginApiMocks.revokeDeviceBootstrapToken).toHaveBeenCalledWith({
token: "first-token",
});
expect(pluginApiMocks.issueDeviceBootstrapToken).toHaveBeenCalledTimes(2);
expect(result?.text).toContain(
expect(text).toContain(
"QR image delivery is not available on this channel right now, so I generated a pasteable setup code instead.",
);
expect(result?.text).toContain("Pairing setup code generated.");
expect(text).toContain("Pairing setup code generated.");
});
it.each([
@@ -273,7 +284,8 @@ describe("device-pair /pair qr", () => {
runtime: createChannelRuntime(testCase.runtimeKey, testCase.sendKey, sendMessage),
});
const result = await command?.handler(createCommandContext(testCase.ctx));
const result = await command.handler(createCommandContext(testCase.ctx));
const text = requireText(result);
expect(sendMessage).toHaveBeenCalledTimes(1);
const [target, caption, opts] = sendMessage.mock.calls[0] as [
@@ -293,9 +305,9 @@ describe("device-pair /pair qr", () => {
expect(opts.mediaLocalRoots).toEqual([path.dirname(opts.mediaUrl!)]);
expect(opts).toMatchObject(testCase.expectedOpts);
expect(sentPng).toBe("fakepng");
await expect(fs.access(opts.mediaUrl!)).rejects.toBeTruthy();
expect(result?.text).toContain("QR code sent above.");
expect(result?.text).toContain("IMPORTANT: Run /pair cleanup after pairing finishes.");
await expect(fs.access(opts.mediaUrl!)).rejects.toThrow();
expect(text).toContain("QR code sent above.");
expect(text).toContain("IMPORTANT: Run /pair cleanup after pairing finishes.");
});
it("reissues the bootstrap token after QR delivery failure before falling back", async () => {
@@ -314,34 +326,36 @@ describe("device-pair /pair qr", () => {
runtime: createChannelRuntime("discord", "sendMessageDiscord", sendMessage),
});
const result = await command?.handler(
const result = await command.handler(
createCommandContext({
channel: "discord",
senderId: "123",
}),
);
const text = requireText(result);
expect(pluginApiMocks.revokeDeviceBootstrapToken).toHaveBeenCalledWith({
token: "first-token",
});
expect(pluginApiMocks.issueDeviceBootstrapToken).toHaveBeenCalledTimes(2);
expect(result?.text).toContain("Pairing setup code generated.");
expect(result?.text).toContain("If this code leaks or you are done, run /pair cleanup");
expect(text).toContain("Pairing setup code generated.");
expect(text).toContain("If this code leaks or you are done, run /pair cleanup");
});
it("falls back to the setup code instead of ASCII when the channel cannot send media", async () => {
const command = registerPairCommand();
const result = await command?.handler(
const result = await command.handler(
createCommandContext({
channel: "msteams",
senderId: "8:orgid:123",
}),
);
const text = requireText(result);
expect(result?.text).toContain("QR image delivery is not available on this channel");
expect(result?.text).toContain("Setup code:");
expect(result?.text).toContain("IMPORTANT: After pairing finishes, run /pair cleanup.");
expect(result?.text).not.toContain("```");
expect(text).toContain("QR image delivery is not available on this channel");
expect(text).toContain("Setup code:");
expect(text).toContain("IMPORTANT: After pairing finishes, run /pair cleanup.");
expect(text).not.toContain("```");
});
it("supports invalidating unused setup codes", async () => {

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/diagnostics-otel",
"version": "2026.3.14",
"version": "2026.3.22",
"description": "OpenClaw diagnostics OpenTelemetry exporter",
"type": "module",
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/diffs",
"version": "2026.3.14",
"version": "2026.3.22",
"private": true,
"description": "OpenClaw diff viewer plugin",
"type": "module",

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/discord",
"version": "2026.3.14",
"version": "2026.3.22",
"description": "OpenClaw Discord channel plugin",
"type": "module",
"dependencies": {
@@ -14,7 +14,7 @@
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
"openclaw": ">=2026.3.22"
},
"peerDependenciesMeta": {
"openclaw": {
@@ -40,7 +40,7 @@
"npmSpec": "@openclaw/discord",
"localPath": "extensions/discord",
"defaultChoice": "npm",
"minHostVersion": ">=2026.3.14"
"minHostVersion": ">=2026.3.22"
},
"bundle": {
"stageRuntimeDependencies": true

View File

@@ -1,6 +1,7 @@
import {
createAccountActionGate,
createAccountListHelpers,
resolveMergedAccountConfig,
} from "openclaw/plugin-sdk/account-helpers";
import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
import { resolveAccountEntry } from "openclaw/plugin-sdk/routing";
@@ -31,11 +32,13 @@ export function mergeDiscordAccountConfig(
cfg: OpenClawConfig,
accountId: string,
): DiscordAccountConfig {
const { accounts: _ignored, ...base } = (cfg.channels?.discord ?? {}) as DiscordAccountConfig & {
accounts?: unknown;
};
const account = resolveDiscordAccountConfig(cfg, accountId) ?? {};
return { ...base, ...account };
return resolveMergedAccountConfig<DiscordAccountConfig>({
channelConfig: cfg.channels?.discord as DiscordAccountConfig | undefined,
accounts: cfg.channels?.discord?.accounts as
| Record<string, Partial<DiscordAccountConfig>>
| undefined,
accountId,
});
}
export function createDiscordActionGate(params: {

View File

@@ -1,19 +1,10 @@
import { resolveGlobalMap } from "openclaw/plugin-sdk/text-runtime";
import type { DiscordComponentEntry, DiscordModalEntry } from "./components.js";
const DEFAULT_COMPONENT_TTL_MS = 30 * 60 * 1000;
const DISCORD_COMPONENT_ENTRIES_KEY = Symbol.for("openclaw.discord.componentEntries");
const DISCORD_MODAL_ENTRIES_KEY = Symbol.for("openclaw.discord.modalEntries");
function resolveGlobalMap<TKey, TValue>(key: symbol): Map<TKey, TValue> {
const globalStore = globalThis as Record<PropertyKey, unknown>;
if (globalStore[key] instanceof Map) {
return globalStore[key] as Map<TKey, TValue>;
}
const created = new Map<TKey, TValue>();
globalStore[key] = created;
return created;
}
const componentEntries = resolveGlobalMap<string, DiscordComponentEntry>(
DISCORD_COMPONENT_ENTRIES_KEY,
);
@@ -33,6 +24,42 @@ function normalizeEntryTimestamps<T extends { createdAt?: number; expiresAt?: nu
return { ...entry, createdAt, expiresAt };
}
function registerEntries<
T extends { id: string; messageId?: string; createdAt?: number; expiresAt?: number },
>(
entries: T[],
store: Map<string, T>,
params: { now: number; ttlMs: number; messageId?: string },
): void {
for (const entry of entries) {
const normalized = normalizeEntryTimestamps(
{ ...entry, messageId: params.messageId ?? entry.messageId },
params.now,
params.ttlMs,
);
store.set(entry.id, normalized);
}
}
function resolveEntry<T extends { expiresAt?: number }>(
store: Map<string, T>,
params: { id: string; consume?: boolean },
): T | null {
const entry = store.get(params.id);
if (!entry) {
return null;
}
const now = Date.now();
if (isExpired(entry, now)) {
store.delete(params.id);
return null;
}
if (params.consume !== false) {
store.delete(params.id);
}
return entry;
}
export function registerDiscordComponentEntries(params: {
entries: DiscordComponentEntry[];
modals: DiscordModalEntry[];
@@ -41,60 +68,22 @@ export function registerDiscordComponentEntries(params: {
}): void {
const now = Date.now();
const ttlMs = params.ttlMs ?? DEFAULT_COMPONENT_TTL_MS;
for (const entry of params.entries) {
const normalized = normalizeEntryTimestamps(
{ ...entry, messageId: params.messageId ?? entry.messageId },
now,
ttlMs,
);
componentEntries.set(entry.id, normalized);
}
for (const modal of params.modals) {
const normalized = normalizeEntryTimestamps(
{ ...modal, messageId: params.messageId ?? modal.messageId },
now,
ttlMs,
);
modalEntries.set(modal.id, normalized);
}
registerEntries(params.entries, componentEntries, { now, ttlMs, messageId: params.messageId });
registerEntries(params.modals, modalEntries, { now, ttlMs, messageId: params.messageId });
}
export function resolveDiscordComponentEntry(params: {
id: string;
consume?: boolean;
}): DiscordComponentEntry | null {
const entry = componentEntries.get(params.id);
if (!entry) {
return null;
}
const now = Date.now();
if (isExpired(entry, now)) {
componentEntries.delete(params.id);
return null;
}
if (params.consume !== false) {
componentEntries.delete(params.id);
}
return entry;
return resolveEntry(componentEntries, params);
}
export function resolveDiscordModalEntry(params: {
id: string;
consume?: boolean;
}): DiscordModalEntry | null {
const entry = modalEntries.get(params.id);
if (!entry) {
return null;
}
const now = Date.now();
if (isExpired(entry, now)) {
modalEntries.delete(params.id);
return null;
}
if (params.consume !== false) {
modalEntries.delete(params.id);
}
return entry;
return resolveEntry(modalEntries, params);
}
export function clearDiscordComponentEntries(): void {

View File

@@ -108,9 +108,10 @@ describe("waitForDiscordGatewayStop", () => {
},
});
expect(forceStop).toBeDefined();
forceStop?.(new Error("reconnect watchdog timeout"));
if (!forceStop) {
throw new Error("registerForceStop did not expose a stopper callback");
}
forceStop(new Error("reconnect watchdog timeout"));
await expect(promise).rejects.toThrow("reconnect watchdog timeout");
expect(disconnect).toHaveBeenCalledTimes(1);

View File

@@ -43,10 +43,12 @@ function expectExhaustedDecision(params: { failureCounts: Record<string, number>
now,
});
expect(decision).toBeTruthy();
expect(decision?.state).toBe("exhausted");
expect(decision?.presence.status).toBe("dnd");
expect(decision?.presence.activities[0]?.state).toBe("token exhausted");
if (!decision) {
throw new Error("expected an exhausted auto-presence decision");
}
expect(decision.state).toBe("exhausted");
expect(decision.presence.status).toBe("dnd");
expect(decision.presence.activities[0]?.state).toBe("token exhausted");
}
describe("discord auto presence", () => {
@@ -87,8 +89,10 @@ describe("discord auto presence", () => {
controller.runNow();
expect(updatePresence).toHaveBeenCalledTimes(2);
expect(updatePresence.mock.calls[0]?.[0]?.status).toBe("dnd");
expect(updatePresence.mock.calls[1]?.[0]?.status).toBe("online");
expect(updatePresence.mock.calls).toEqual([
[expect.objectContaining({ status: "dnd" })],
[expect.objectContaining({ status: "online" })],
]);
});
it("re-applies presence on refresh even when signature is unchanged", () => {
@@ -119,8 +123,10 @@ describe("discord auto presence", () => {
controller.refresh();
expect(updatePresence).toHaveBeenCalledTimes(2);
expect(updatePresence.mock.calls[0]?.[0]?.status).toBe("online");
expect(updatePresence.mock.calls[1]?.[0]?.status).toBe("online");
expect(updatePresence.mock.calls).toEqual([
[expect.objectContaining({ status: "online" })],
[expect.objectContaining({ status: "online" })],
]);
});
it("does nothing when auto presence is disabled", () => {

View File

@@ -537,6 +537,12 @@ describe("processDiscordMessage draft streaming", () => {
expectSinglePreviewEdit();
});
it("keeps preview streaming off by default when streaming is unset", async () => {
await runSingleChunkFinalScenario({ maxLinesPerMessage: 5 });
expect(editMessageDiscord).not.toHaveBeenCalled();
expect(deliverDiscordReply).toHaveBeenCalledTimes(1);
});
it("falls back to standard send when final needs multiple chunks", async () => {
await runSingleChunkFinalScenario({ streamMode: "partial", maxLinesPerMessage: 1 });

View File

@@ -60,6 +60,13 @@ function renderRecentsViewRows(
return extractContainerRows(payload.components);
}
function requireValue<T>(value: T | null | undefined, message: string): T {
if (value == null) {
throw new Error(message);
}
return value;
}
describe("loadDiscordModelPickerData", () => {
it("reuses buildModelsProviderData as source of truth with agent scope", async () => {
const expected = createModelsProviderData({ openai: ["gpt-4o"] });
@@ -293,19 +300,23 @@ describe("model paging", () => {
);
const data = createModelsProviderData({ openai: models });
const page1 = getDiscordModelPickerModelPage({ data, provider: "openai", page: 1 });
const page2 = getDiscordModelPickerModelPage({ data, provider: "openai", page: 2 });
const page1 = requireValue(
getDiscordModelPickerModelPage({ data, provider: "openai", page: 1 }),
"expected first model page for openai",
);
const page2 = requireValue(
getDiscordModelPickerModelPage({ data, provider: "openai", page: 2 }),
"expected second model page for openai",
);
expect(page1).not.toBeNull();
expect(page2).not.toBeNull();
expect(page1?.items).toHaveLength(DISCORD_MODEL_PICKER_MODEL_PAGE_SIZE);
expect(page1?.items[0]).toBe("model-01");
expect(page1?.hasNext).toBe(true);
expect(page1.items).toHaveLength(DISCORD_MODEL_PICKER_MODEL_PAGE_SIZE);
expect(page1.items[0]).toBe("model-01");
expect(page1.hasNext).toBe(true);
expect(page2?.items).toHaveLength(4);
expect(page2?.page).toBe(2);
expect(page2?.hasPrev).toBe(true);
expect(page2?.hasNext).toBe(false);
expect(page2.items).toHaveLength(4);
expect(page2.page).toBe(2);
expect(page2.hasPrev).toBe(true);
expect(page2.hasNext).toBe(false);
});
it("returns null for unknown provider", () => {
@@ -316,8 +327,11 @@ describe("model paging", () => {
it("caps custom model page size at Discord select-option max", () => {
const data = createModelsProviderData({ openai: ["gpt-4o", "gpt-4.1"] });
const page = getDiscordModelPickerModelPage({ data, provider: "openai", pageSize: 999 });
expect(page?.pageSize).toBe(DISCORD_MODEL_PICKER_MODEL_PAGE_SIZE);
const page = requireValue(
getDiscordModelPickerModelPage({ data, provider: "openai", pageSize: 999 }),
"expected model page when provider exists",
);
expect(page.pageSize).toBe(DISCORD_MODEL_PICKER_MODEL_PAGE_SIZE);
});
});
@@ -344,7 +358,11 @@ describe("Discord model picker rendering", () => {
};
expect(payload.content).toBeUndefined();
expect(payload.components?.[0]?.type).toBe(ComponentType.Container);
const firstComponent = requireValue(
payload.components?.[0],
"provider view should render a container component",
);
expect(firstComponent.type).toBe(ComponentType.Container);
const rows = extractContainerRows(payload.components);
expect(rows.length).toBeGreaterThan(0);
@@ -412,7 +430,11 @@ describe("Discord model picker rendering", () => {
};
expect(payload.content).toContain("Model Picker");
expect(payload.components?.[0]?.type).toBe(ComponentType.ActionRow);
const firstComponent = requireValue(
payload.components?.[0],
"classic provider view should render an action row",
);
expect(firstComponent.type).toBe(ComponentType.ActionRow);
});
it("preserves the stored model suffix spacing in Discord current-model text", () => {
@@ -461,22 +483,24 @@ describe("Discord model picker rendering", () => {
const providerSelect = rows[0]?.components?.find(
(component) => component.type === Number(ComponentType.StringSelect),
);
expect(providerSelect).toBeTruthy();
expect(providerSelect?.options?.length).toBe(2);
expect(providerSelect?.options?.find((option) => option.value === "openai")?.default).toBe(
true,
);
const parsedProviderState = parseDiscordModelPickerCustomId(providerSelect?.custom_id ?? "");
if (!providerSelect) {
throw new Error("models view did not render a provider select");
}
expect(providerSelect.options?.length).toBe(2);
expect(providerSelect.options?.find((option) => option.value === "openai")?.default).toBe(true);
const parsedProviderState = parseDiscordModelPickerCustomId(providerSelect.custom_id ?? "");
expect(parsedProviderState?.action).toBe("provider");
const modelSelect = rows[1]?.components?.find(
(component) => component.type === Number(ComponentType.StringSelect),
);
expect(modelSelect).toBeTruthy();
expect(modelSelect?.options?.length).toBe(3);
expect(modelSelect?.options?.find((option) => option.value === "o3")?.default).toBe(true);
if (!modelSelect) {
throw new Error("models view did not render a model select");
}
expect(modelSelect.options?.length).toBe(3);
expect(modelSelect.options?.find((option) => option.value === "o3")?.default).toBe(true);
const parsedModelSelectState = parseDiscordModelPickerCustomId(modelSelect?.custom_id ?? "");
const parsedModelSelectState = parseDiscordModelPickerCustomId(modelSelect.custom_id ?? "");
expect(parsedModelSelectState?.action).toBe("model");
expect(parsedModelSelectState?.provider).toBe("openai");
@@ -514,13 +538,19 @@ describe("Discord model picker rendering", () => {
const rows = extractContainerRows(payload.components);
expect(rows).toHaveLength(1);
const backButton = rows[0]?.components?.[0];
expect(backButton?.type).toBe(ComponentType.Button);
const backButton = requireValue(
rows[0]?.components?.[0],
"models view should render a back button row",
);
expect(backButton.type).toBe(ComponentType.Button);
const state = parseDiscordModelPickerCustomId(backButton?.custom_id ?? "");
expect(state?.action).toBe("back");
expect(state?.view).toBe("providers");
expect(state?.page).toBe(3);
const state = requireValue(
parseDiscordModelPickerCustomId(backButton.custom_id ?? ""),
"back button custom id should parse",
);
expect(state.action).toBe("back");
expect(state.view).toBe("providers");
expect(state.page).toBe(3);
});
it("shows Recents button when quickModels are provided", () => {
@@ -543,9 +573,12 @@ describe("Discord model picker rendering", () => {
const buttons = buttonRow?.components ?? [];
expect(buttons).toHaveLength(4);
const favoritesState = parseDiscordModelPickerCustomId(buttons[2]?.custom_id ?? "");
expect(favoritesState?.action).toBe("recents");
expect(favoritesState?.view).toBe("recents");
const favoritesState = requireValue(
parseDiscordModelPickerCustomId(buttons[2]?.custom_id ?? ""),
"recents button custom id should parse",
);
expect(favoritesState.action).toBe("recents");
expect(favoritesState.view).toBe("recents");
});
it("omits Recents button when no quickModels", () => {
@@ -592,28 +625,52 @@ describe("Discord model picker recents view", () => {
expect(rows).toHaveLength(4);
// First row: default model button (slot 1).
const defaultBtn = rows[0]?.components?.[0];
expect(defaultBtn?.type).toBe(ComponentType.Button);
const defaultState = parseDiscordModelPickerCustomId(defaultBtn?.custom_id ?? "");
expect(defaultState?.action).toBe("submit");
expect(defaultState?.view).toBe("recents");
expect(defaultState?.recentSlot).toBe(1);
const defaultBtn = requireValue(
rows[0]?.components?.[0],
"recents view should render a default model button",
);
expect(defaultBtn.type).toBe(ComponentType.Button);
const defaultState = requireValue(
parseDiscordModelPickerCustomId(defaultBtn.custom_id ?? ""),
"default recents button custom id should parse",
);
expect(defaultState.action).toBe("submit");
expect(defaultState.view).toBe("recents");
expect(defaultState.recentSlot).toBe(1);
// Second row: first recent (slot 2).
const recentBtn1 = rows[1]?.components?.[0];
const recentState1 = parseDiscordModelPickerCustomId(recentBtn1?.custom_id ?? "");
expect(recentState1?.recentSlot).toBe(2);
const recentBtn1 = requireValue(
rows[1]?.components?.[0],
"recents view should render first recent button",
);
const recentState1 = requireValue(
parseDiscordModelPickerCustomId(recentBtn1.custom_id ?? ""),
"first recent custom id should parse",
);
expect(recentState1.recentSlot).toBe(2);
// Third row: second recent (slot 3).
const recentBtn2 = rows[2]?.components?.[0];
const recentState2 = parseDiscordModelPickerCustomId(recentBtn2?.custom_id ?? "");
expect(recentState2?.recentSlot).toBe(3);
const recentBtn2 = requireValue(
rows[2]?.components?.[0],
"recents view should render second recent button",
);
const recentState2 = requireValue(
parseDiscordModelPickerCustomId(recentBtn2.custom_id ?? ""),
"second recent custom id should parse",
);
expect(recentState2.recentSlot).toBe(3);
// Fourth row (after divider): Back button.
const backBtn = rows[3]?.components?.[0];
const backState = parseDiscordModelPickerCustomId(backBtn?.custom_id ?? "");
expect(backState?.action).toBe("back");
expect(backState?.view).toBe("models");
const backBtn = requireValue(
rows[3]?.components?.[0],
"recents view should render a back button",
);
const backState = requireValue(
parseDiscordModelPickerCustomId(backBtn.custom_id ?? ""),
"recents back button custom id should parse",
);
expect(backState.action).toBe("back");
expect(backState.view).toBe("models");
});
it("includes (default) suffix on default model button label", () => {
@@ -628,8 +685,11 @@ describe("Discord model picker recents view", () => {
quickModels: ["openai/gpt-4o"],
currentModel: "openai/gpt-4o",
});
const defaultBtn = rows[0]?.components?.[0] as { label?: string };
expect(defaultBtn?.label).toContain("(default)");
const defaultBtn = requireValue(
rows[0]?.components?.[0] as { label?: string } | undefined,
"recents default row should include a button",
);
expect(defaultBtn.label).toContain("(default)");
});
it("deduplicates recents that match the default model", () => {
@@ -648,11 +708,17 @@ describe("Discord model picker recents view", () => {
// 1 default + 1 deduped recent + 1 back = 3 rows (openai/gpt-4o not shown twice)
expect(rows).toHaveLength(3);
const defaultBtn = rows[0]?.components?.[0] as { label?: string };
expect(defaultBtn?.label).toContain("openai/gpt-4o");
expect(defaultBtn?.label).toContain("(default)");
const defaultBtn = requireValue(
rows[0]?.components?.[0] as { label?: string } | undefined,
"deduped recents should keep the default button",
);
expect(defaultBtn.label).toContain("openai/gpt-4o");
expect(defaultBtn.label).toContain("(default)");
const recentBtn = rows[1]?.components?.[0] as { label?: string };
expect(recentBtn?.label).toContain("anthropic/claude-sonnet-4-5");
const recentBtn = requireValue(
rows[1]?.components?.[0] as { label?: string } | undefined,
"deduped recents should keep the non-default recent button",
);
expect(recentBtn.label).toContain("anthropic/claude-sonnet-4-5");
});
});

View File

@@ -203,7 +203,9 @@ describe("agent components", () => {
const pairingText = String(reply.mock.calls[0]?.[0]?.content ?? "");
expect(pairingText).toContain("Pairing code:");
const code = pairingText.match(/Pairing code:\s*([A-Z2-9]{8})/)?.[1];
expect(code).toBeDefined();
if (!code) {
throw new Error(`pairing reply did not include an 8-character pairing code: ${pairingText}`);
}
expect(pairingText).toContain(`openclaw pairing approve discord ${code}`);
expect(peekSystemEvents(dmSessionKey)).toEqual([]);
expect(readAllowFromStoreMock).toHaveBeenCalledWith("discord", "default");

View File

@@ -200,7 +200,9 @@ function expectDispatchedModelSelection(params: {
expect(dispatchCall.ctx?.CommandBody).toBe(`/model ${params.model}`);
expect(dispatchCall.ctx?.CommandArgs?.values?.model).toBe(params.model);
if (params.requireTargetSessionKey) {
expect(dispatchCall.ctx?.CommandTargetSessionKey).toBeDefined();
if (!dispatchCall.ctx?.CommandTargetSessionKey) {
throw new Error("model selection dispatch did not include a target session key");
}
}
}
@@ -372,8 +374,12 @@ describe("Discord model picker interactions", () => {
expect(interaction.update).toHaveBeenCalledTimes(1);
const updatePayload = interaction.update.mock.calls[0]?.[0];
expect(updatePayload).toBeDefined();
expect(updatePayload.components).toBeDefined();
if (!updatePayload) {
throw new Error("recents button did not emit an update payload");
}
const updateText = JSON.stringify(updatePayload);
expect(updateText).toContain("gpt-4o");
expect(updateText).toContain("claude-sonnet-4-5");
});
it("clicking recents model button applies model through /model pipeline", async () => {

View File

@@ -1,4 +1,4 @@
import { describe, expect, it } from "vitest";
import { describe, expect, it, vi } from "vitest";
import { listNativeCommandSpecs } from "../../../../src/auto-reply/commands-registry.js";
import type { OpenClawConfig, loadConfig } from "../../../../src/config/config.js";
import { createDiscordNativeCommand } from "./native-command.js";
@@ -33,6 +33,17 @@ function findOption(
return command.options?.find((entry) => entry.name === name);
}
function requireOption(
command: ReturnType<typeof createDiscordNativeCommand>,
name: string,
): CommandOption {
const option = findOption(command, name);
if (!option) {
throw new Error(`missing command option: ${name}`);
}
return option;
}
function readAutocomplete(option: CommandOption | undefined): unknown {
if (!option || typeof option !== "object") {
return undefined;
@@ -49,21 +60,39 @@ function readChoices(option: CommandOption | undefined): unknown[] | undefined {
}
describe("createDiscordNativeCommand option wiring", () => {
it("uses autocomplete for /acp action so inline action values are accepted", () => {
it("uses autocomplete for /acp action so inline action values are accepted", async () => {
const command = createNativeCommand("acp");
const action = findOption(command, "action");
const action = requireOption(command, "action");
const autocomplete = readAutocomplete(action);
if (typeof autocomplete !== "function") {
throw new Error("acp action option did not wire autocomplete");
}
const respond = vi.fn(async (_choices: unknown[]) => undefined);
expect(action).toBeDefined();
expect(typeof readAutocomplete(action)).toBe("function");
expect(readChoices(action)).toBeUndefined();
await autocomplete({
options: {
getFocused: () => ({ value: "st" }),
},
respond,
} as never);
expect(respond).toHaveBeenCalledWith([
{ name: "steer", value: "steer" },
{ name: "status", value: "status" },
{ name: "install", value: "install" },
]);
});
it("keeps static choices for non-acp string action arguments", () => {
const command = createNativeCommand("voice");
const action = findOption(command, "action");
const action = requireOption(command, "action");
const choices = readChoices(action);
expect(action).toBeDefined();
expect(readAutocomplete(action)).toBeUndefined();
expect(readChoices(action)?.length).toBeGreaterThan(0);
expect(choices).toEqual(
expect.arrayContaining([
expect.objectContaining({ name: expect.any(String), value: expect.any(String) }),
]),
);
});
});

View File

@@ -1,10 +1,8 @@
import { ChannelType } from "discord-api-types/v10";
import { beforeEach, describe, expect, it, vi } from "vitest";
import type { NativeCommandSpec } from "../../../../src/auto-reply/commands-registry.js";
import * as dispatcherModule from "../../../../src/auto-reply/reply/provider-dispatcher.js";
import { setDefaultChannelPluginRegistryForTests } from "../../../../src/commands/channel-test-helpers.js";
import type { OpenClawConfig } from "../../../../src/config/config.js";
import * as pluginCommandsModule from "../../../../src/plugins/commands.js";
import { clearPluginCommands, registerPluginCommand } from "../../../../src/plugins/commands.js";
import {
createMockCommandInteraction,
@@ -20,6 +18,11 @@ const ensureConfiguredBindingRouteReadyMock = vi.hoisted(() =>
ok: true,
})),
);
const runtimeModuleMocks = vi.hoisted(() => ({
matchPluginCommand: vi.fn(),
executePluginCommand: vi.fn(),
dispatchReplyWithDispatcher: vi.fn(),
}));
vi.mock("openclaw/plugin-sdk/conversation-runtime", async (importOriginal) => {
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/conversation-runtime")>();
@@ -32,6 +35,24 @@ vi.mock("openclaw/plugin-sdk/conversation-runtime", async (importOriginal) => {
};
});
vi.mock("openclaw/plugin-sdk/plugin-runtime", async (importOriginal) => {
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/plugin-runtime")>();
return {
...actual,
matchPluginCommand: (...args: unknown[]) => runtimeModuleMocks.matchPluginCommand(...args),
executePluginCommand: (...args: unknown[]) => runtimeModuleMocks.executePluginCommand(...args),
};
});
vi.mock("openclaw/plugin-sdk/reply-runtime", async (importOriginal) => {
const actual = await importOriginal<typeof import("openclaw/plugin-sdk/reply-runtime")>();
return {
...actual,
dispatchReplyWithDispatcher: (...args: unknown[]) =>
runtimeModuleMocks.dispatchReplyWithDispatcher(...args),
};
});
function createInteraction(params?: {
channelType?: ChannelType;
channelId?: string;
@@ -61,6 +82,7 @@ function createConfig(): OpenClawConfig {
}
async function loadCreateDiscordNativeCommand() {
vi.resetModules();
return (await import("./native-command.js")).createDiscordNativeCommand;
}
@@ -123,9 +145,7 @@ async function expectPairCommandReply(params: {
cfg: params.cfg,
name: params.commandName,
});
const dispatchSpy = vi
.spyOn(dispatcherModule, "dispatchReplyWithDispatcher")
.mockResolvedValue({} as never);
const dispatchSpy = runtimeModuleMocks.dispatchReplyWithDispatcher;
await (command as { run: (interaction: unknown) => Promise<void> }).run(
Object.assign(params.interaction, {
@@ -152,7 +172,7 @@ async function createStatusCommand(cfg: OpenClawConfig) {
}
function createDispatchSpy() {
return vi.spyOn(dispatcherModule, "dispatchReplyWithDispatcher").mockResolvedValue({
return runtimeModuleMocks.dispatchReplyWithDispatcher.mockResolvedValue({
counts: {
final: 1,
block: 0,
@@ -169,8 +189,11 @@ function expectBoundSessionDispatch(
const dispatchCall = dispatchSpy.mock.calls[0]?.[0] as {
ctx?: { SessionKey?: string; CommandTargetSessionKey?: string };
};
expect(dispatchCall.ctx?.SessionKey).toMatch(expectedPattern);
expect(dispatchCall.ctx?.CommandTargetSessionKey).toMatch(expectedPattern);
if (!dispatchCall.ctx?.SessionKey || !dispatchCall.ctx.CommandTargetSessionKey) {
throw new Error("native command dispatch did not include bound session context");
}
expect(dispatchCall.ctx.SessionKey).toMatch(expectedPattern);
expect(dispatchCall.ctx.CommandTargetSessionKey).toMatch(expectedPattern);
expect(ensureConfiguredBindingRouteReadyMock).toHaveBeenCalledTimes(1);
}
@@ -179,10 +202,9 @@ async function expectBoundStatusCommandDispatch(params: {
interaction: MockCommandInteraction;
expectedPattern: RegExp;
}) {
const command = await createStatusCommand(params.cfg);
vi.spyOn(pluginCommandsModule, "matchPluginCommand").mockReturnValue(null);
runtimeModuleMocks.matchPluginCommand.mockReturnValue(null);
const dispatchSpy = createDispatchSpy();
const command = await createStatusCommand(params.cfg);
await (command as { run: (interaction: unknown) => Promise<void> }).run(
params.interaction as unknown,
@@ -192,7 +214,7 @@ async function expectBoundStatusCommandDispatch(params: {
}
describe("Discord native plugin command dispatch", () => {
beforeEach(() => {
beforeEach(async () => {
vi.clearAllMocks();
clearPluginCommands();
setDefaultChannelPluginRegistryForTests();
@@ -200,6 +222,25 @@ describe("Discord native plugin command dispatch", () => {
ensureConfiguredBindingRouteReadyMock.mockResolvedValue({
ok: true,
});
const actualPluginRuntime = await vi.importActual<
typeof import("openclaw/plugin-sdk/plugin-runtime")
>("openclaw/plugin-sdk/plugin-runtime");
runtimeModuleMocks.matchPluginCommand.mockReset();
runtimeModuleMocks.matchPluginCommand.mockImplementation(
actualPluginRuntime.matchPluginCommand,
);
runtimeModuleMocks.executePluginCommand.mockReset();
runtimeModuleMocks.executePluginCommand.mockImplementation(
actualPluginRuntime.executePluginCommand,
);
runtimeModuleMocks.dispatchReplyWithDispatcher.mockReset();
runtimeModuleMocks.dispatchReplyWithDispatcher.mockResolvedValue({
counts: {
final: 1,
block: 0,
tool: 0,
},
} as never);
});
it("executes plugin commands from the real registry through the native Discord command path", async () => {
@@ -274,10 +315,10 @@ describe("Discord native plugin command dispatch", () => {
}),
).toEqual({ ok: true });
const executeSpy = vi.spyOn(pluginCommandsModule, "executePluginCommand");
const dispatchSpy = vi
.spyOn(dispatcherModule, "dispatchReplyWithDispatcher")
.mockResolvedValue({} as never);
const executeSpy = runtimeModuleMocks.executePluginCommand;
const dispatchSpy = runtimeModuleMocks.dispatchReplyWithDispatcher.mockResolvedValue(
{} as never,
);
await (command as { run: (interaction: unknown) => Promise<void> }).run(interaction as unknown);
@@ -298,7 +339,6 @@ describe("Discord native plugin command dispatch", () => {
description: "List cron jobs",
acceptsArgs: false,
};
const command = await createNativeCommand(cfg, commandSpec);
const interaction = createInteraction();
const pluginMatch = {
command: {
@@ -311,15 +351,14 @@ describe("Discord native plugin command dispatch", () => {
args: undefined,
};
vi.spyOn(pluginCommandsModule, "matchPluginCommand").mockReturnValue(
pluginMatch as ReturnType<typeof pluginCommandsModule.matchPluginCommand>,
runtimeModuleMocks.matchPluginCommand.mockReturnValue(pluginMatch as never);
const executeSpy = runtimeModuleMocks.executePluginCommand.mockResolvedValue({
text: "direct plugin output",
});
const dispatchSpy = runtimeModuleMocks.dispatchReplyWithDispatcher.mockResolvedValue(
{} as never,
);
const executeSpy = vi
.spyOn(pluginCommandsModule, "executePluginCommand")
.mockResolvedValue({ text: "direct plugin output" });
const dispatchSpy = vi
.spyOn(dispatcherModule, "dispatchReplyWithDispatcher")
.mockResolvedValue({} as never);
const command = await createNativeCommand(cfg, commandSpec);
await (command as { run: (interaction: unknown) => Promise<void> }).run(interaction as unknown);
@@ -407,7 +446,6 @@ describe("Discord native plugin command dispatch", () => {
},
},
} as OpenClawConfig;
const command = await createStatusCommand(cfg);
const interaction = createInteraction({
channelType: ChannelType.GuildText,
channelId,
@@ -415,8 +453,9 @@ describe("Discord native plugin command dispatch", () => {
guildName: "Ops",
});
vi.spyOn(pluginCommandsModule, "matchPluginCommand").mockReturnValue(null);
runtimeModuleMocks.matchPluginCommand.mockReturnValue(null);
const dispatchSpy = createDispatchSpy();
const command = await createStatusCommand(cfg);
await (command as { run: (interaction: unknown) => Promise<void> }).run(interaction as unknown);
@@ -497,19 +536,18 @@ describe("Discord native plugin command dispatch", () => {
guildId,
guildName: "Ops",
});
ensureConfiguredBindingRouteReadyMock.mockResolvedValue({
ok: false,
error: "acpx exited with code 1",
});
runtimeModuleMocks.matchPluginCommand.mockReturnValue(null);
const dispatchSpy = createDispatchSpy();
const command = await createNativeCommand(cfg, {
name: "new",
description: "Start a new session.",
acceptsArgs: true,
});
ensureConfiguredBindingRouteReadyMock.mockResolvedValue({
ok: false,
error: "acpx exited with code 1",
});
vi.spyOn(pluginCommandsModule, "matchPluginCommand").mockReturnValue(null);
const dispatchSpy = createDispatchSpy();
await (command as { run: (interaction: unknown) => Promise<void> }).run(interaction as unknown);
expect(dispatchSpy).toHaveBeenCalledTimes(1);

View File

@@ -220,12 +220,14 @@ describe("runDiscordGatewayLifecycle", () => {
const patch = (call[0] ?? {}) as Record<string, unknown>;
return patch.connected === true;
});
expect(connectedCall).toBeDefined();
expect(connectedCall![0]).toMatchObject({
if (!connectedCall) {
throw new Error("connected status update was not emitted");
}
expect(connectedCall[0]).toMatchObject({
connected: true,
lastDisconnect: null,
});
expect(connectedCall![0].lastConnectedAt).toBeTypeOf("number");
expect(connectedCall[0].lastConnectedAt).toBeTypeOf("number");
});
it("forces a fresh reconnect when startup never reaches READY, then recovers", async () => {
@@ -409,10 +411,12 @@ describe("runDiscordGatewayLifecycle", () => {
expect(gateway.connect).toHaveBeenNthCalledWith(1, true);
expect(gateway.connect).toHaveBeenNthCalledWith(2, true);
expect(gateway.connect).toHaveBeenNthCalledWith(3, false);
expect(gateway.state).toBeDefined();
expect(gateway.state?.sessionId).toBeNull();
expect(gateway.state?.resumeGatewayUrl).toBeNull();
expect(gateway.state?.sequence).toBeNull();
if (!gateway.state) {
throw new Error("gateway state was not initialized");
}
expect(gateway.state.sessionId).toBeNull();
expect(gateway.state.resumeGatewayUrl).toBeNull();
expect(gateway.state.sequence).toBeNull();
expect(gateway.sequence).toBeNull();
} finally {
vi.useRealTimers();
@@ -554,7 +558,7 @@ describe("runDiscordGatewayLifecycle", () => {
// onAbort should have pushed connected: false
const connectedFalse = statusUpdates.find((s) => s.connected === false);
expect(connectedFalse).toBeDefined();
expect(connectedFalse).toEqual(expect.objectContaining({ connected: false }));
// No connected: true should appear — the isConnected check must be
// guarded by !lifecycleStopping to avoid contradicting the abort.

View File

@@ -110,8 +110,10 @@ describe("monitorDiscordProvider", () => {
| [ReconcileStartupParams]
| undefined;
const reconcileParams = firstCall?.[0];
expect(typeof reconcileParams?.healthProbe).toBe("function");
return reconcileParams?.healthProbe as NonNullable<ReconcileStartupParams["healthProbe"]>;
if (!reconcileParams?.healthProbe) {
throw new Error("healthProbe was not wired into ACP startup reconciliation");
}
return reconcileParams.healthProbe as NonNullable<ReconcileStartupParams["healthProbe"]>;
};
beforeEach(() => {
@@ -319,8 +321,10 @@ describe("monitorDiscordProvider", () => {
const firstCall = getAcpSessionStatusMock.mock.calls[0]?.[0] as
| { signal?: AbortSignal }
| undefined;
expect(firstCall?.signal).toBeDefined();
expect(firstCall?.signal?.aborted).toBe(true);
if (!firstCall?.signal) {
throw new Error("ACP status check did not receive an abort signal");
}
expect(firstCall.signal.aborted).toBe(true);
} finally {
vi.useRealTimers();
}
@@ -387,8 +391,7 @@ describe("monitorDiscordProvider", () => {
});
const eventQueue = getConstructedEventQueue();
expect(eventQueue).toBeDefined();
expect(eventQueue?.listenerTimeout).toBe(120_000);
expect(eventQueue).toEqual({ listenerTimeout: 120_000 });
});
it("forwards custom eventQueue config from discord config to Carbon Client", async () => {
@@ -575,11 +578,8 @@ describe("monitorDiscordProvider", () => {
setStatus,
});
const connectedTrue = setStatus.mock.calls.find((call) => call[0]?.connected === true);
const connectedFalse = setStatus.mock.calls.find((call) => call[0]?.connected === false);
expect(connectedTrue).toBeDefined();
expect(connectedFalse).toBeDefined();
expect(setStatus.mock.calls).toContainEqual([expect.objectContaining({ connected: true })]);
expect(setStatus.mock.calls).toContainEqual([expect.objectContaining({ connected: false })]);
});
it("logs Discord startup phases and early gateway debug events", async () => {

View File

@@ -211,7 +211,11 @@ describe("deliverDiscordReply", () => {
textLimit: 2000,
});
expect(sendMessageDiscordMock.mock.calls[0]?.[2]?.cfg).toBe(cfg);
expect(sendMessageDiscordMock).toHaveBeenCalledWith(
"channel:101",
"cfg path",
expect.objectContaining({ cfg }),
);
});
it("uses replyToId only for the first chunk when replyToMode is first", async () => {
@@ -231,8 +235,18 @@ describe("deliverDiscordReply", () => {
});
expect(sendMessageDiscordMock).toHaveBeenCalledTimes(2);
expect(sendMessageDiscordMock.mock.calls[0]?.[2]?.replyTo).toBe("reply-1");
expect(sendMessageDiscordMock.mock.calls[1]?.[2]?.replyTo).toBeUndefined();
expect(sendMessageDiscordMock.mock.calls).toEqual([
expect.arrayContaining([
"channel:789",
"12345",
expect.objectContaining({ replyTo: "reply-1" }),
]),
expect.arrayContaining([
"channel:789",
"67890",
expect.not.objectContaining({ replyTo: expect.anything() }),
]),
]);
});
it("does not consume replyToId for replyToMode=first on whitespace-only payloads", async () => {

View File

@@ -222,6 +222,17 @@ describe("thread binding lifecycle", () => {
});
};
const requireBinding = (
manager: ReturnType<typeof createThreadBindingManager>,
threadId: string,
) => {
const binding = manager.getByThreadId(threadId);
if (!binding) {
throw new Error(`missing thread binding: ${threadId}`);
}
return binding;
};
it("includes idle and max-age details in intro text", () => {
const intro = resolveThreadBindingIntroText({
agentId: "main",
@@ -328,7 +339,12 @@ describe("thread binding lifecycle", () => {
await vi.advanceTimersByTimeAsync(120_000);
await __testing.runThreadBindingSweepForAccount("default");
expect(manager.getByThreadId("thread-1")).toBeDefined();
expect(requireBinding(manager, "thread-1")).toMatchObject({
threadId: "thread-1",
targetSessionKey: "agent:main:subagent:child",
webhookId: "wh-1",
webhookToken: "tok-1",
});
expect(hoisted.sendWebhookMessageDiscord).not.toHaveBeenCalled();
} finally {
vi.useRealTimers();
@@ -474,7 +490,11 @@ describe("thread binding lifecycle", () => {
await vi.advanceTimersByTimeAsync(240_000);
await __testing.runThreadBindingSweepForAccount("default");
expect(manager.getByThreadId("thread-1")).toBeDefined();
expect(requireBinding(manager, "thread-1")).toMatchObject({
threadId: "thread-1",
targetSessionKey: "agent:main:subagent:child",
idleTimeoutMs: 0,
});
} finally {
vi.useRealTimers();
}
@@ -534,7 +554,10 @@ describe("thread binding lifecycle", () => {
await vi.advanceTimersByTimeAsync(120_000);
await __testing.runThreadBindingSweepForAccount("default");
expect(manager.getByThreadId("thread-2")).toBeDefined();
expect(requireBinding(manager, "thread-2")).toMatchObject({
threadId: "thread-2",
targetSessionKey: "agent:main:subagent:second",
});
expect(hoisted.sendMessageDiscord).not.toHaveBeenCalled();
} finally {
vi.useRealTimers();
@@ -565,12 +588,11 @@ describe("thread binding lifecycle", () => {
const touched = manager.touchThread({ threadId: "thread-1", persist: false });
expect(touched).not.toBeNull();
const record = manager.getByThreadId("thread-1");
expect(record).toBeDefined();
expect(record?.lastActivityAt).toBe(new Date("2026-02-20T00:00:30.000Z").getTime());
const record = requireBinding(manager, "thread-1");
expect(record.lastActivityAt).toBe(new Date("2026-02-20T00:00:30.000Z").getTime());
expect(
resolveThreadBindingInactivityExpiresAt({
record: record!,
record,
defaultIdleTimeoutMs: manager.getIdleTimeoutMs(),
}),
).toBe(new Date("2026-02-20T00:01:30.000Z").getTime());
@@ -618,12 +640,11 @@ describe("thread binding lifecycle", () => {
maxAgeMs: 0,
});
const record = reloaded.getByThreadId("thread-1");
expect(record).toBeDefined();
expect(record?.lastActivityAt).toBe(touchedAt);
const record = requireBinding(reloaded, "thread-1");
expect(record.lastActivityAt).toBe(touchedAt);
expect(
resolveThreadBindingInactivityExpiresAt({
record: record!,
record,
defaultIdleTimeoutMs: reloaded.getIdleTimeoutMs(),
}),
).toBe(new Date("2026-02-20T00:01:30.000Z").getTime());
@@ -1069,9 +1090,17 @@ describe("thread binding lifecycle", () => {
expect(result.checked).toBe(2);
expect(result.removed).toBe(1);
expect(result.staleSessionKeys).toContain("agent:codex:acp:stale");
expect(manager.getByThreadId("thread-acp-healthy")).toBeDefined();
expect(requireBinding(manager, "thread-acp-healthy")).toMatchObject({
threadId: "thread-acp-healthy",
targetKind: "acp",
targetSessionKey: "agent:codex:acp:healthy",
});
expect(manager.getByThreadId("thread-acp-stale")).toBeUndefined();
expect(manager.getByThreadId("thread-subagent")).toBeDefined();
expect(requireBinding(manager, "thread-subagent")).toMatchObject({
threadId: "thread-subagent",
targetKind: "subagent",
targetSessionKey: "agent:main:subagent:child",
});
expect(hoisted.sendMessageDiscord).not.toHaveBeenCalled();
expect(hoisted.sendWebhookMessageDiscord).not.toHaveBeenCalled();
});
@@ -1113,7 +1142,11 @@ describe("thread binding lifecycle", () => {
expect(result.checked).toBe(1);
expect(result.removed).toBe(0);
expect(result.staleSessionKeys).toEqual([]);
expect(manager.getByThreadId("thread-acp-uncertain")).toBeDefined();
expect(requireBinding(manager, "thread-acp-uncertain")).toMatchObject({
threadId: "thread-acp-uncertain",
targetKind: "acp",
targetSessionKey: "agent:codex:acp:uncertain",
});
});
it("does not reconcile plugin-owned direct bindings as stale ACP sessions", async () => {
@@ -1242,7 +1275,11 @@ describe("thread binding lifecycle", () => {
expect(result.checked).toBe(1);
expect(result.removed).toBe(0);
expect(result.staleSessionKeys).toEqual([]);
expect(manager.getByThreadId("thread-acp-running-uncertain")).toBeDefined();
expect(requireBinding(manager, "thread-acp-running-uncertain")).toMatchObject({
threadId: "thread-acp-running-uncertain",
targetKind: "acp",
targetSessionKey: "agent:codex:acp:running-uncertain",
});
});
it("keeps ACP bindings in stored error state when no explicit stale probe verdict exists", async () => {
@@ -1285,7 +1322,11 @@ describe("thread binding lifecycle", () => {
expect(result.checked).toBe(1);
expect(result.removed).toBe(0);
expect(result.staleSessionKeys).toEqual([]);
expect(manager.getByThreadId("thread-acp-error")).toBeDefined();
expect(requireBinding(manager, "thread-acp-error")).toMatchObject({
threadId: "thread-acp-error",
targetKind: "acp",
targetSessionKey: "agent:codex:acp:error",
});
});
it("starts ACP health probes in parallel during startup reconciliation", async () => {
@@ -1493,29 +1534,33 @@ describe("thread binding lifecycle", () => {
});
const active = manager.getByThreadId("thread-legacy-active");
expect(active).toBeDefined();
expect(active?.idleTimeoutMs).toBe(0);
expect(active?.maxAgeMs).toBe(expiresAt - boundAt);
if (!active) {
throw new Error("missing migrated legacy active thread binding");
}
expect(active.idleTimeoutMs).toBe(0);
expect(active.maxAgeMs).toBe(expiresAt - boundAt);
expect(
resolveThreadBindingMaxAgeExpiresAt({
record: active!,
record: active,
defaultMaxAgeMs: manager.getMaxAgeMs(),
}),
).toBe(expiresAt);
expect(
resolveThreadBindingInactivityExpiresAt({
record: active!,
record: active,
defaultIdleTimeoutMs: manager.getIdleTimeoutMs(),
}),
).toBeUndefined();
const disabled = manager.getByThreadId("thread-legacy-disabled");
expect(disabled).toBeDefined();
expect(disabled?.idleTimeoutMs).toBe(0);
expect(disabled?.maxAgeMs).toBe(0);
if (!disabled) {
throw new Error("missing migrated legacy disabled thread binding");
}
expect(disabled.idleTimeoutMs).toBe(0);
expect(disabled.maxAgeMs).toBe(0);
expect(
resolveThreadBindingMaxAgeExpiresAt({
record: disabled!,
record: disabled,
defaultMaxAgeMs: manager.getMaxAgeMs(),
}),
).toBeUndefined();

View File

@@ -3,6 +3,7 @@ import path from "node:path";
import { loadJsonFile, saveJsonFile } from "openclaw/plugin-sdk/json-store";
import { normalizeAccountId, resolveAgentIdFromSessionKey } from "openclaw/plugin-sdk/routing";
import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
import { resolveGlobalSingleton } from "openclaw/plugin-sdk/text-runtime";
import {
DEFAULT_THREAD_BINDING_IDLE_TIMEOUT_MS,
DEFAULT_THREAD_BINDING_MAX_AGE_MS,
@@ -29,7 +30,7 @@ type ThreadBindingsGlobalState = {
// Plugin hooks can load this module via Jiti while core imports it via ESM.
// Store mutable state on globalThis so both loader paths share one registry.
const THREAD_BINDINGS_STATE_KEY = "__openclawDiscordThreadBindingsState";
const THREAD_BINDINGS_STATE_KEY = Symbol.for("openclaw.discordThreadBindingsState");
function createThreadBindingsGlobalState(): ThreadBindingsGlobalState {
return {
@@ -52,13 +53,10 @@ function createThreadBindingsGlobalState(): ThreadBindingsGlobalState {
}
function resolveThreadBindingsGlobalState(): ThreadBindingsGlobalState {
const runtimeGlobal = globalThis as typeof globalThis & {
[THREAD_BINDINGS_STATE_KEY]?: ThreadBindingsGlobalState;
};
if (!runtimeGlobal[THREAD_BINDINGS_STATE_KEY]) {
runtimeGlobal[THREAD_BINDINGS_STATE_KEY] = createThreadBindingsGlobalState();
}
return runtimeGlobal[THREAD_BINDINGS_STATE_KEY];
return resolveGlobalSingleton<ThreadBindingsGlobalState>(
THREAD_BINDINGS_STATE_KEY,
createThreadBindingsGlobalState,
);
}
const THREAD_BINDINGS_STATE = resolveThreadBindingsGlobalState();

View File

@@ -54,6 +54,9 @@ describe("resolveDiscordThreadStarter", () => {
() => undefined,
);
expect(result?.text).toBe("starter content");
if (!result) {
throw new Error("starter content should have produced a resolved starter payload");
}
expect(result.text).toBe("starter content");
});
});

View File

@@ -0,0 +1,65 @@
import { describe, expect, it } from "vitest";
import {
inspectDiscordSetupAccount,
listDiscordSetupAccountIds,
resolveDiscordSetupAccountConfig,
} from "./setup-account-state.js";
describe("discord setup account state", () => {
it("lists normalized setup account ids plus the implicit default account", () => {
expect(
listDiscordSetupAccountIds({
channels: {
discord: {
accounts: {
Work: { token: "work-token" },
alerts: { token: "alerts-token" },
},
},
},
}),
).toEqual(["alerts", "default", "work"]);
});
it("resolves setup account config when account key casing differs from normalized id", () => {
const resolved = resolveDiscordSetupAccountConfig({
cfg: {
channels: {
discord: {
allowFrom: ["top"],
accounts: {
Work: { name: "Work", allowFrom: ["acct"] },
},
},
},
},
accountId: "work",
});
expect(resolved.accountId).toBe("work");
expect(resolved.config.name).toBe("Work");
expect(resolved.config.allowFrom).toEqual(["acct"]);
});
it("treats explicit blank account tokens as missing without falling back", () => {
const inspected = inspectDiscordSetupAccount({
cfg: {
channels: {
discord: {
token: "top-level-token",
accounts: {
work: { token: "" },
},
},
},
},
accountId: "work",
});
expect(inspected.accountId).toBe("work");
expect(inspected.token).toBe("");
expect(inspected.tokenSource).toBe("none");
expect(inspected.tokenStatus).toBe("missing");
expect(inspected.configured).toBe(false);
});
});

View File

@@ -1,9 +1,11 @@
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
import { listCombinedAccountIds } from "openclaw/plugin-sdk/account-resolution";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import {
hasConfiguredSecretInput,
normalizeSecretInputString,
} from "openclaw/plugin-sdk/secret-input";
import { mergeDiscordAccountConfig, resolveDiscordAccountConfig } from "./accounts.js";
import type { DiscordAccountConfig } from "./runtime-api.js";
import { resolveDiscordToken } from "./token.js";
@@ -17,23 +19,6 @@ export type InspectedDiscordSetupAccount = {
config: DiscordAccountConfig;
};
function resolveDiscordAccountEntry(
cfg: OpenClawConfig,
accountId: string,
): DiscordAccountConfig | undefined {
const accounts = cfg.channels?.discord?.accounts;
if (!accounts || typeof accounts !== "object" || Array.isArray(accounts)) {
return undefined;
}
const normalized = normalizeAccountId(accountId);
const direct = accounts[normalized];
if (direct) {
return direct;
}
const matchKey = Object.keys(accounts).find((key) => normalizeAccountId(key) === normalized);
return matchKey ? accounts[matchKey] : undefined;
}
function inspectConfiguredToken(value: unknown): {
token: string;
tokenSource: "config";
@@ -59,13 +44,13 @@ function inspectConfiguredToken(value: unknown): {
export function listDiscordSetupAccountIds(cfg: OpenClawConfig): string[] {
const accounts = cfg.channels?.discord?.accounts;
const ids =
accounts && typeof accounts === "object" && !Array.isArray(accounts)
? Object.keys(accounts)
.map((accountId) => normalizeAccountId(accountId))
.filter(Boolean)
: [];
return [...new Set([DEFAULT_ACCOUNT_ID, ...ids])];
return listCombinedAccountIds({
configuredAccountIds:
accounts && typeof accounts === "object" && !Array.isArray(accounts)
? Object.keys(accounts).map((accountId) => normalizeAccountId(accountId))
: [],
implicitAccountId: DEFAULT_ACCOUNT_ID,
});
}
export function resolveDefaultDiscordSetupAccountId(cfg: OpenClawConfig): string {
@@ -77,16 +62,9 @@ export function resolveDiscordSetupAccountConfig(params: {
accountId?: string | null;
}): { accountId: string; config: DiscordAccountConfig } {
const accountId = normalizeAccountId(params.accountId ?? DEFAULT_ACCOUNT_ID);
const { accounts: _ignored, ...base } = (params.cfg.channels?.discord ??
{}) as DiscordAccountConfig & {
accounts?: unknown;
};
return {
accountId,
config: {
...base,
...(resolveDiscordAccountEntry(params.cfg, accountId) ?? {}),
},
config: mergeDiscordAccountConfig(params.cfg, accountId),
};
}
@@ -96,7 +74,7 @@ export function inspectDiscordSetupAccount(params: {
}): InspectedDiscordSetupAccount {
const { accountId, config } = resolveDiscordSetupAccountConfig(params);
const enabled = params.cfg.channels?.discord?.enabled !== false && config.enabled !== false;
const accountConfig = resolveDiscordAccountEntry(params.cfg, accountId);
const accountConfig = resolveDiscordAccountConfig(params.cfg, accountId);
const hasAccountToken = Boolean(
accountConfig &&
Object.prototype.hasOwnProperty.call(accountConfig as Record<string, unknown>, "token"),

View File

@@ -1,6 +1,7 @@
import type { BaseTokenResolution } from "openclaw/plugin-sdk/channel-contract";
import type { OpenClawConfig } from "openclaw/plugin-sdk/config-runtime";
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/routing";
import { resolveAccountEntry } from "openclaw/plugin-sdk/routing";
import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
export type DiscordTokenSource = "env" | "config" | "none";
@@ -23,19 +24,7 @@ export function resolveDiscordToken(
): DiscordTokenResolution {
const accountId = normalizeAccountId(opts.accountId);
const discordCfg = cfg?.channels?.discord;
const resolveAccountCfg = (id: string) => {
const accounts = discordCfg?.accounts;
if (!accounts || typeof accounts !== "object" || Array.isArray(accounts)) {
return undefined;
}
const direct = accounts[id];
if (direct) {
return direct;
}
const matchKey = Object.keys(accounts).find((key) => normalizeAccountId(key) === id);
return matchKey ? accounts[matchKey] : undefined;
};
const accountCfg = resolveAccountCfg(accountId);
const accountCfg = resolveAccountEntry(discordCfg?.accounts, accountId);
const hasAccountToken = Boolean(
accountCfg &&
Object.prototype.hasOwnProperty.call(accountCfg as Record<string, unknown>, "token"),

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/elevenlabs-speech",
"version": "2026.3.14",
"version": "2026.3.22",
"private": true,
"description": "OpenClaw ElevenLabs speech plugin",
"type": "module",

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/fal-provider",
"version": "2026.3.14",
"version": "2026.3.22",
"private": true,
"description": "OpenClaw fal provider plugin",
"type": "module",

View File

@@ -7,9 +7,14 @@ const registerFeishuWikiToolsMock = vi.hoisted(() => vi.fn());
const registerFeishuDriveToolsMock = vi.hoisted(() => vi.fn());
const registerFeishuPermToolsMock = vi.hoisted(() => vi.fn());
const registerFeishuBitableToolsMock = vi.hoisted(() => vi.fn());
const feishuPluginMock = vi.hoisted(() => ({ id: "feishu-test-plugin" }));
const setFeishuRuntimeMock = vi.hoisted(() => vi.fn());
const registerFeishuSubagentHooksMock = vi.hoisted(() => vi.fn());
vi.mock("./src/channel.js", () => ({
feishuPlugin: feishuPluginMock,
}));
vi.mock("./src/docx.js", () => ({
registerFeishuDocTools: registerFeishuDocToolsMock,
}));
@@ -58,6 +63,7 @@ describe("feishu plugin register", () => {
expect(setFeishuRuntimeMock).toHaveBeenCalledWith(api.runtime);
expect(registerChannel).toHaveBeenCalledTimes(1);
expect(registerChannel).toHaveBeenCalledWith({ plugin: feishuPluginMock });
expect(registerFeishuSubagentHooksMock).toHaveBeenCalledWith(api);
expect(registerFeishuDocToolsMock).toHaveBeenCalledWith(api);
expect(registerFeishuChatToolsMock).toHaveBeenCalledWith(api);

View File

@@ -1,6 +1,6 @@
{
"name": "@openclaw/feishu",
"version": "2026.3.14",
"version": "2026.3.22",
"description": "OpenClaw Feishu/Lark channel plugin (community maintained by @m1heng)",
"type": "module",
"dependencies": {
@@ -13,7 +13,7 @@
"openclaw": "workspace:*"
},
"peerDependencies": {
"openclaw": ">=2026.3.14"
"openclaw": ">=2026.3.22"
},
"peerDependenciesMeta": {
"openclaw": {
@@ -42,7 +42,7 @@
"npmSpec": "@openclaw/feishu",
"localPath": "extensions/feishu",
"defaultChoice": "npm",
"minHostVersion": ">=2026.3.14"
"minHostVersion": ">=2026.3.22"
},
"bundle": {
"stageRuntimeDependencies": true

View File

@@ -1,4 +1,10 @@
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
import {
DEFAULT_ACCOUNT_ID,
createAccountListHelpers,
normalizeAccountId,
normalizeOptionalAccountId,
resolveMergedAccountConfig,
} from "openclaw/plugin-sdk/account-resolution";
import type { ClawdbotConfig } from "../runtime-api.js";
import { normalizeResolvedSecretInputString, normalizeSecretInputString } from "./secret-input.js";
import type {
@@ -9,29 +15,15 @@ import type {
ResolvedFeishuAccount,
} from "./types.js";
/**
* List all configured account IDs from the accounts field.
*/
function listConfiguredAccountIds(cfg: ClawdbotConfig): string[] {
const accounts = (cfg.channels?.feishu as FeishuConfig)?.accounts;
if (!accounts || typeof accounts !== "object") {
return [];
}
return Object.keys(accounts).filter(Boolean);
}
const {
listConfiguredAccountIds,
listAccountIds: listFeishuAccountIds,
resolveDefaultAccountId,
} = createAccountListHelpers("feishu", {
allowUnlistedDefaultAccount: true,
});
/**
* List all Feishu account IDs.
* If no accounts are configured, returns [DEFAULT_ACCOUNT_ID] for backward compatibility.
*/
export function listFeishuAccountIds(cfg: ClawdbotConfig): string[] {
const ids = listConfiguredAccountIds(cfg);
if (ids.length === 0) {
// Backward compatibility: no accounts configured, use default
return [DEFAULT_ACCOUNT_ID];
}
return [...ids].toSorted((a, b) => a.localeCompare(b));
}
export { listFeishuAccountIds };
/**
* Resolve the default account selection and its source.
@@ -40,8 +32,9 @@ export function resolveDefaultFeishuAccountSelection(cfg: ClawdbotConfig): {
accountId: string;
source: FeishuDefaultAccountSelectionSource;
} {
const preferredRaw = (cfg.channels?.feishu as FeishuConfig | undefined)?.defaultAccount?.trim();
const preferred = preferredRaw ? normalizeAccountId(preferredRaw) : undefined;
const preferred = normalizeOptionalAccountId(
(cfg.channels?.feishu as FeishuConfig | undefined)?.defaultAccount,
);
if (preferred) {
return {
accountId: preferred,
@@ -65,21 +58,7 @@ export function resolveDefaultFeishuAccountSelection(cfg: ClawdbotConfig): {
* Resolve the default account ID.
*/
export function resolveDefaultFeishuAccountId(cfg: ClawdbotConfig): string {
return resolveDefaultFeishuAccountSelection(cfg).accountId;
}
/**
* Get the raw account-specific config.
*/
function resolveAccountConfig(
cfg: ClawdbotConfig,
accountId: string,
): FeishuAccountConfig | undefined {
const accounts = (cfg.channels?.feishu as FeishuConfig)?.accounts;
if (!accounts || typeof accounts !== "object") {
return undefined;
}
return accounts[accountId];
return resolveDefaultAccountId(cfg);
}
/**
@@ -88,15 +67,12 @@ function resolveAccountConfig(
*/
function mergeFeishuAccountConfig(cfg: ClawdbotConfig, accountId: string): FeishuConfig {
const feishuCfg = cfg.channels?.feishu as FeishuConfig | undefined;
// Extract base config (exclude accounts field to avoid recursion)
const { accounts: _ignored, defaultAccount: _ignoredDefaultAccount, ...base } = feishuCfg ?? {};
// Get account-specific overrides
const account = resolveAccountConfig(cfg, accountId) ?? {};
// Merge: account config overrides base config
return { ...base, ...account } as FeishuConfig;
return resolveMergedAccountConfig<FeishuConfig>({
channelConfig: feishuCfg,
accounts: feishuCfg?.accounts as Record<string, Partial<FeishuConfig>> | undefined,
accountId,
omitKeys: ["defaultAccount"],
});
}
/**

View File

@@ -5,6 +5,17 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
const createFeishuClientMock = vi.hoisted(() => vi.fn());
const fetchRemoteMediaMock = vi.hoisted(() => vi.fn());
const convertMock = vi.fn();
const documentCreateMock = vi.fn();
const blockListMock = vi.fn();
const blockChildrenCreateMock = vi.fn();
const blockChildrenGetMock = vi.fn();
const blockChildrenBatchDeleteMock = vi.fn();
const blockDescendantCreateMock = vi.fn();
const driveUploadAllMock = vi.fn();
const permissionMemberCreateMock = vi.fn();
const blockPatchMock = vi.fn();
const scopeListMock = vi.fn();
vi.mock("./client.js", () => ({
createFeishuClient: createFeishuClientMock,
@@ -23,18 +34,6 @@ vi.mock("./runtime.js", () => ({
import { registerFeishuDocTools } from "./docx.js";
describe("feishu_doc image fetch hardening", () => {
const convertMock = vi.hoisted(() => vi.fn());
const documentCreateMock = vi.hoisted(() => vi.fn());
const blockListMock = vi.hoisted(() => vi.fn());
const blockChildrenCreateMock = vi.hoisted(() => vi.fn());
const blockChildrenGetMock = vi.hoisted(() => vi.fn());
const blockChildrenBatchDeleteMock = vi.hoisted(() => vi.fn());
const blockDescendantCreateMock = vi.hoisted(() => vi.fn());
const driveUploadAllMock = vi.hoisted(() => vi.fn());
const permissionMemberCreateMock = vi.hoisted(() => vi.fn());
const blockPatchMock = vi.hoisted(() => vi.fn());
const scopeListMock = vi.hoisted(() => vi.fn());
beforeEach(() => {
vi.clearAllMocks();

View File

@@ -52,16 +52,15 @@ type FeishuThreadBindingsState = {
};
const FEISHU_THREAD_BINDINGS_STATE_KEY = Symbol.for("openclaw.feishuThreadBindingsState");
let state: FeishuThreadBindingsState | undefined;
const state = resolveGlobalSingleton<FeishuThreadBindingsState>(
FEISHU_THREAD_BINDINGS_STATE_KEY,
() => ({
managersByAccountId: new Map(),
bindingsByAccountConversation: new Map(),
}),
);
function getState(): FeishuThreadBindingsState {
state ??= resolveGlobalSingleton<FeishuThreadBindingsState>(
FEISHU_THREAD_BINDINGS_STATE_KEY,
() => ({
managersByAccountId: new Map(),
bindingsByAccountConversation: new Map(),
}),
);
return state;
}

View File

@@ -24,7 +24,9 @@ describe("firecrawl plugin", () => {
expect(result.finalUrl).toBe("https://example.com/final");
expect(result.status).toBe(200);
expect(result.extractor).toBe("firecrawl");
expect(typeof result.text).toBe("string");
expect(String(result.text)).toContain("Hello");
expect(String(result.text)).toContain("World");
expect(result.truncated).toBe(false);
});
it("extracts search items from flexible Firecrawl payload shapes", () => {

Some files were not shown because too many files have changed in this diff Show More