mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-08 23:14:17 +08:00
Compare commits
6 Commits
codex/plug
...
docs/plugi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
984a83dd22 | ||
|
|
b89f9a9a7c | ||
|
|
1f4e4028ef | ||
|
|
0cd6e6df6f | ||
|
|
1db4cfd9c8 | ||
|
|
0a8caa6d8b |
@@ -16,30 +16,12 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
|
||||
- Pass `--json` for machine-readable summaries.
|
||||
- Per-phase logs land under `/tmp/openclaw-parallels-*`.
|
||||
- Do not run local and gateway agent turns in parallel on the same fresh workspace or session.
|
||||
- For `prlctl exec`, pass the VM name before `--current-user` (`prlctl exec "$VM" --current-user ...`), not the other way around.
|
||||
|
||||
## npm install then update
|
||||
|
||||
- Preferred entrypoint: `pnpm test:parallels:npm-update`
|
||||
- Flow: fresh snapshot -> install npm package baseline -> smoke -> install current main tgz on the same guest -> smoke again.
|
||||
- Same-guest update verification should set the default model explicitly to `openai/gpt-5.4` before the agent turn and use a fresh explicit `--session-id` so old session model state does not leak into the check.
|
||||
- The aggregate npm-update wrapper must resolve the Linux VM with the same Ubuntu fallback policy as `parallels-linux-smoke.sh` before both fresh and update lanes. On Peter's current host, missing `Ubuntu 24.04.3 ARM64` should fall back to `Ubuntu 25.10`.
|
||||
- On Windows same-guest update checks, restart the gateway after the npm upgrade before `gateway status` / `agent`; in-place global npm updates can otherwise leave stale hashed `dist/*` module imports alive in the running service.
|
||||
- For Windows same-guest update checks, prefer the done-file/log-drain PowerShell runner pattern over one long-lived `prlctl exec ... powershell -EncodedCommand ...` transport. The guest can finish successfully while the outer `prlctl exec` still hangs.
|
||||
- Linux same-guest update verification should also export `HOME=/root`, pass `OPENAI_API_KEY` via `prlctl exec ... /usr/bin/env`, and use `openclaw agent --local`; the fresh Linux baseline does not rely on persisted gateway credentials.
|
||||
|
||||
## CLI invocation footgun
|
||||
|
||||
- The Parallels smoke shell scripts should tolerate a literal bare `--` arg so `pnpm test:parallels:* -- --json` and similar forwarded invocations work without needing to call `bash scripts/e2e/...` directly.
|
||||
|
||||
## macOS flow
|
||||
|
||||
- Preferred entrypoint: `pnpm test:parallels:macos`
|
||||
- Default to the snapshot closest to `macOS 26.3.1 latest`.
|
||||
- On Peter's Tahoe VM, `fresh-latest-march-2026` can hang in `prlctl snapshot-switch`; if restore times out there, rerun with `--snapshot-hint 'macOS 26.3.1 latest'` before blaming auth or the harness.
|
||||
- The macOS smoke should include a dashboard load phase after gateway health: resolve the tokenized URL with `openclaw dashboard --no-open`, verify the served HTML contains the Control UI title/root shell, then open Safari and require an established localhost TCP connection from Safari to the gateway port.
|
||||
- Target the snapshot closest to `macOS 26.3.1 fresh`.
|
||||
- `prlctl exec` is fine for deterministic repo commands, but use the guest Terminal or `prlctl enter` when installer parity or shell-sensitive behavior matters.
|
||||
- Multi-word `openclaw agent --message ...` checks should go through a guest shell wrapper (`guest_current_user_sh` / `guest_current_user_cli` or `/bin/sh -lc ...`), not raw `prlctl exec ... node openclaw.mjs ...`, or the message can be split into extra argv tokens and Commander reports `too many arguments for 'agent'`.
|
||||
- On the fresh Tahoe snapshot, `brew` exists but `node` may be missing from PATH in noninteractive exec. Use `/opt/homebrew/bin/node` when needed.
|
||||
- Fresh host-served tgz installs should install as guest root with `HOME=/var/root`, then run onboarding as the desktop user via `prlctl exec --current-user`.
|
||||
- Root-installed tgz smoke can log plugin blocks for world-writable `extensions/*`; do not treat that as an onboarding or gateway failure unless plugin loading is the task.
|
||||
@@ -51,23 +33,17 @@ Use this skill for Parallels guest workflows and smoke interpretation. Do not lo
|
||||
- Always use `prlctl exec --current-user`; plain `prlctl exec` lands in `NT AUTHORITY\\SYSTEM`.
|
||||
- Prefer explicit `npm.cmd` and `openclaw.cmd`.
|
||||
- Use PowerShell only as the transport with `-ExecutionPolicy Bypass`, then call the `.cmd` shims from inside it.
|
||||
- Multi-word `openclaw agent --message ...` checks should call `& $openclaw ...` inside PowerShell, not `Start-Process ... -ArgumentList` against `openclaw.cmd`, or Commander can see split argv and throw `too many arguments for 'agent'`.
|
||||
- Windows installer/tgz phases now retry once after guest-ready recheck; keep new Windows smoke steps idempotent so a transport-flake retry is safe.
|
||||
- Windows global `npm install -g` phases can stay quiet for a minute or more even when healthy; inspect the phase log before calling it hung, and only treat it as a regression once the retry wrapper or timeout trips.
|
||||
- Keep onboarding and status output ASCII-clean in logs; fancy punctuation becomes mojibake in current capture paths.
|
||||
- If you hit an older run with `rc=255` plus an empty `fresh.install-main.log` or `upgrade.install-main.log`, treat it as a likely `prlctl exec` transport drop after guest start-up, not immediate proof of an npm/package failure.
|
||||
|
||||
## Linux flow
|
||||
|
||||
- Preferred entrypoint: `pnpm test:parallels:linux`
|
||||
- Use the snapshot closest to fresh `Ubuntu 24.04.3 ARM64`.
|
||||
- If that exact VM is missing on the host, fall back to the closest Ubuntu guest with a fresh poweroff snapshot. On Peter's host today, that is `Ubuntu 25.10`.
|
||||
- Use plain `prlctl exec`; `--current-user` is not the right transport on this snapshot.
|
||||
- Fresh snapshots may be missing `curl`, and `apt-get update` can fail on clock skew. Bootstrap with `apt-get -o Acquire::Check-Date=false update` and install `curl ca-certificates`.
|
||||
- Fresh `main` tgz smoke still needs the latest-release installer first because the snapshot has no Node or npm before bootstrap.
|
||||
- This snapshot does not have a usable `systemd --user` session; managed daemon install is unsupported.
|
||||
- `prlctl exec` reaps detached Linux child processes on this snapshot, so detached background gateway runs are not trustworthy smoke signals.
|
||||
- Treat `gateway=skipped-no-detached-linux-gateway` plus `daemon=systemd-user-unavailable` as baseline on that Linux lane, not a regression.
|
||||
|
||||
## Discord roundtrip
|
||||
|
||||
|
||||
@@ -11,9 +11,7 @@ Use this skill for release and publish-time workflow. Keep ordinary development
|
||||
|
||||
- Do not change version numbers without explicit operator approval.
|
||||
- Ask permission before any npm publish or release step.
|
||||
- This skill should be sufficient to drive the normal release flow end-to-end.
|
||||
- Use the private maintainer release docs for credentials, recovery steps, and mac signing/notary specifics, and use `docs/reference/RELEASING.md` for public policy.
|
||||
- Core `openclaw` publish is manual `workflow_dispatch`; creating or pushing a tag does not publish by itself.
|
||||
- Use the private maintainer release docs for the actual runbook and `docs/reference/RELEASING.md` for public policy.
|
||||
|
||||
## Keep release channel naming aligned
|
||||
|
||||
@@ -33,19 +31,8 @@ Use this skill for release and publish-time workflow. Keep ordinary development
|
||||
- `apps/macos/Sources/OpenClaw/Resources/Info.plist`
|
||||
- `docs/install/updating.md`
|
||||
- Peekaboo Xcode project and plist version fields
|
||||
- Before creating a release tag, make every version location above match the version encoded by that tag.
|
||||
- For fallback correction tags like `vYYYY.M.D-N`, the repo version locations still stay at `YYYY.M.D`.
|
||||
- “Bump version everywhere” means all version locations above except `appcast.xml`.
|
||||
- Release signing and notary credentials live outside the repo in the private maintainer docs.
|
||||
- Every OpenClaw release ships the npm package and macOS app together.
|
||||
- The production Sparkle feed lives at `https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml`, and the canonical published file is `appcast.xml` on `main` in the `openclaw` repo.
|
||||
- That shared production Sparkle feed is stable-only. Beta mac releases may
|
||||
upload assets to the GitHub prerelease, but they must not replace the shared
|
||||
`appcast.xml` unless a separate beta feed exists.
|
||||
- For fallback correction tags like `vYYYY.M.D-N`, the repo version still stays
|
||||
at `YYYY.M.D`, but the mac release must use a strictly higher numeric
|
||||
`APP_BUILD` / Sparkle build than the original release so existing installs
|
||||
see it as newer.
|
||||
|
||||
## Build changelog-backed release notes
|
||||
|
||||
@@ -72,166 +59,16 @@ pnpm test:install:smoke
|
||||
For a non-root smoke path:
|
||||
|
||||
```bash
|
||||
OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smoke
|
||||
OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smoke
|
||||
```
|
||||
|
||||
After npm publish, run:
|
||||
|
||||
```bash
|
||||
node --import tsx scripts/openclaw-npm-postpublish-verify.ts <published-version>
|
||||
```
|
||||
|
||||
- This verifies the published registry install path in a fresh temp prefix.
|
||||
- For stable correction releases like `YYYY.M.D-N`, it also verifies the
|
||||
upgrade path from `YYYY.M.D` to `YYYY.M.D-N` so a correction publish cannot
|
||||
silently leave existing global installs on the old base stable payload.
|
||||
|
||||
## Check all relevant release builds
|
||||
|
||||
- Always validate the OpenClaw npm release path before creating the tag.
|
||||
- Default release checks:
|
||||
- `pnpm check`
|
||||
- `pnpm build`
|
||||
- `node --import tsx scripts/release-check.ts`
|
||||
- `pnpm release:check`
|
||||
- `OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT=1 pnpm test:install:smoke`
|
||||
- Check all release-related build surfaces touched by the release, not only the npm package.
|
||||
- Include mac release readiness in preflight by running the public validation
|
||||
workflow in `openclaw/openclaw` and the real mac preflight in
|
||||
`openclaw/releases-private` for every release.
|
||||
- Treat the `appcast.xml` update on `main` as part of mac release readiness, not an optional follow-up.
|
||||
- The workflows remain tag-based. The agent is responsible for making sure
|
||||
preflight runs complete successfully before any publish run starts.
|
||||
- Any fix after preflight means a new commit. Delete and recreate the tag and
|
||||
matching GitHub release from the fixed commit, then rerun preflight from
|
||||
scratch before publishing.
|
||||
- For stable mac releases, generate the signed `appcast.xml` before uploading
|
||||
public release assets so the updater feed cannot lag the published binaries.
|
||||
- Serialize stable appcast-producing runs across tags so two releases do not
|
||||
generate replacement `appcast.xml` files from the same stale seed.
|
||||
- For stable releases, confirm the latest beta already passed the broader release workflows before cutting stable.
|
||||
- If any required build, packaging step, or release workflow is red, do not say the release is ready.
|
||||
|
||||
## Use the right auth flow
|
||||
|
||||
- OpenClaw publish uses GitHub trusted publishing.
|
||||
- The publish run must be started manually with `workflow_dispatch`.
|
||||
- The npm workflow and the private mac publish workflow accept
|
||||
`preflight_only=true` to run validation/build/package steps without uploading
|
||||
public release assets.
|
||||
- The private mac workflow also accepts `smoke_test_only=true` for branch-safe
|
||||
workflow smoke tests that use ad-hoc signing, skip notarization, skip shared
|
||||
appcast generation, and do not prove release readiness.
|
||||
- `preflight_only=true` on the npm workflow is also the right way to validate an
|
||||
existing tag after publish; it should keep running the build checks even when
|
||||
the npm version is already published.
|
||||
- Validation-only runs may be dispatched from a branch when you are testing a
|
||||
workflow change before merge.
|
||||
- `.github/workflows/macos-release.yml` in `openclaw/openclaw` is now a
|
||||
public validation-only handoff. It validates the tag/release state and points
|
||||
operators to the private repo; it does not build or publish macOS artifacts.
|
||||
- Real mac preflight and real mac publish both use
|
||||
`openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml`.
|
||||
- The private mac workflow runs on GitHub's xlarge macOS runner and uses a
|
||||
SwiftPM cache because the Swift build/test/package path is CPU-heavy.
|
||||
- Private mac preflight uploads notarized build artifacts as workflow artifacts
|
||||
instead of uploading public GitHub release assets.
|
||||
- Private smoke-test runs upload ad-hoc, non-notarized build artifacts as
|
||||
workflow artifacts and intentionally skip stable `appcast.xml` generation.
|
||||
- npm preflight, public mac validation, and private mac preflight must all pass
|
||||
before any real publish run starts.
|
||||
- Real publish runs must be dispatched from `main`; branch-dispatched publish
|
||||
attempts should fail before the protected environment is reached.
|
||||
- The release workflows stay tag-based; rely on the documented release sequence
|
||||
rather than workflow-level SHA pinning.
|
||||
- The `npm-release` environment must be approved by `@openclaw/openclaw-release-managers` before publish continues.
|
||||
- Mac publish uses
|
||||
`openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml` for
|
||||
build, signing, notarization, packaged mac artifact generation, and
|
||||
stable-feed `appcast.xml` artifact generation.
|
||||
- Real private mac publish uploads the packaged `.zip`, `.dmg`, and
|
||||
`.dSYM.zip` assets to the existing GitHub release in `openclaw/openclaw`
|
||||
automatically when `OPENCLAW_PUBLIC_REPO_RELEASE_TOKEN` is present in the
|
||||
private repo `mac-release` environment.
|
||||
- For stable releases, the agent must also download the signed
|
||||
`macos-appcast-<tag>` artifact from the successful private mac workflow and
|
||||
then update `appcast.xml` on `main`.
|
||||
- For beta mac releases, do not update the shared production `appcast.xml`
|
||||
unless a separate beta Sparkle feed exists.
|
||||
- The private repo targets a dedicated `mac-release` environment. If the GitHub
|
||||
plan does not yet support required reviewers there, do not assume the
|
||||
environment alone is the approval boundary; rely on private repo access and
|
||||
CODEOWNERS until those settings can be enabled.
|
||||
- Do not use `NPM_TOKEN` or the plugin OTP flow for OpenClaw releases.
|
||||
- Core `openclaw` publish uses GitHub trusted publishing.
|
||||
- Do not use `NPM_TOKEN` or the plugin OTP flow for core releases.
|
||||
- `@openclaw/*` plugin publishes use a separate maintainer-only flow.
|
||||
- Only publish plugins that already exist on npm; bundled disk-tree-only plugins stay unpublished.
|
||||
|
||||
## Fallback local mac publish
|
||||
|
||||
- Keep the original local macOS publish workflow available as a fallback in case
|
||||
CI/CD mac publishing is unavailable or broken.
|
||||
- Preserve the existing maintainer workflow Peter uses: run it on a real Mac
|
||||
with local signing, notary, and Sparkle credentials already configured.
|
||||
- Follow the private maintainer macOS runbook for the local steps:
|
||||
`scripts/package-mac-dist.sh` to build, sign, notarize, and package the app;
|
||||
manual GitHub release asset upload; then `scripts/make_appcast.sh` plus the
|
||||
`appcast.xml` commit to `main`.
|
||||
- `scripts/package-mac-dist.sh` now fails closed for release builds if the
|
||||
bundled app comes out with a debug bundle id, an empty Sparkle feed URL, or a
|
||||
`CFBundleVersion` below the canonical Sparkle build floor for that short
|
||||
version. For correction tags, set a higher explicit `APP_BUILD`.
|
||||
- `scripts/make_appcast.sh` first uses `generate_appcast` from `PATH`, then
|
||||
falls back to the SwiftPM Sparkle tool output under `apps/macos/.build`.
|
||||
- For stable tags, the local fallback may update the shared production
|
||||
`appcast.xml`.
|
||||
- For beta tags, the local fallback still publishes the mac assets but must not
|
||||
update the shared production `appcast.xml` unless a separate beta feed exists.
|
||||
- Treat the local workflow as fallback only. Prefer the CI/CD publish workflow
|
||||
when it is working.
|
||||
- After any stable mac publish, verify all of the following before you call the
|
||||
release finished:
|
||||
- the GitHub release has `.zip`, `.dmg`, and `.dSYM.zip` assets
|
||||
- `appcast.xml` on `main` points at the new stable zip
|
||||
- the packaged app reports the expected short version and a numeric
|
||||
`CFBundleVersion` at or above the canonical Sparkle build floor
|
||||
|
||||
## Run the release sequence
|
||||
|
||||
1. Confirm the operator explicitly wants to cut a release.
|
||||
2. Choose the exact target version and git tag.
|
||||
3. Make every repo version location match that tag before creating it.
|
||||
4. Update `CHANGELOG.md` and assemble the matching GitHub release notes.
|
||||
5. Run the full preflight for all relevant release builds, including mac readiness.
|
||||
6. Confirm the target npm version is not already published.
|
||||
7. Create and push the git tag.
|
||||
8. Create or refresh the matching GitHub release.
|
||||
9. Start `.github/workflows/openclaw-npm-release.yml` with `preflight_only=true`
|
||||
and wait for it to pass.
|
||||
10. Start `.github/workflows/macos-release.yml` in `openclaw/openclaw` and wait
|
||||
for the public validation-only run to pass.
|
||||
11. Start
|
||||
`openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml`
|
||||
with `preflight_only=true` and wait for it to pass.
|
||||
12. If any preflight or validation run fails, fix the issue on a new commit,
|
||||
delete the tag and matching GitHub release, recreate them from the fixed
|
||||
commit, and rerun all relevant preflights from scratch before continuing.
|
||||
Never reuse old preflight results after the commit changes.
|
||||
13. Start `.github/workflows/openclaw-npm-release.yml` with the same tag for
|
||||
the real publish.
|
||||
14. Wait for `npm-release` approval from `@openclaw/openclaw-release-managers`.
|
||||
15. Start
|
||||
`openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml`
|
||||
for the real publish and wait for success.
|
||||
16. Verify the successful real private mac run uploaded the `.zip`, `.dmg`,
|
||||
and `.dSYM.zip` artifacts to the existing GitHub release in
|
||||
`openclaw/openclaw`.
|
||||
17. For stable releases, download `macos-appcast-<tag>` from the successful
|
||||
private mac run, update `appcast.xml` on `main`, and verify the feed.
|
||||
18. For beta releases, publish the mac assets but expect no shared production
|
||||
`appcast.xml` artifact and do not update the shared production feed unless a
|
||||
separate beta feed exists.
|
||||
19. After publish, verify npm and the attached release artifacts.
|
||||
|
||||
## GHSA advisory work
|
||||
|
||||
- Use `openclaw-ghsa-maintainer` for GHSA advisory inspection, patch/publish flow, private-fork validation, and GHSA API-specific publish checks.
|
||||
|
||||
14
.github/actions/ensure-base-commit/action.yml
vendored
14
.github/actions/ensure-base-commit/action.yml
vendored
@@ -23,16 +23,6 @@ runs:
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! [[ "$BASE_SHA" =~ ^[0-9a-fA-F]{7,40}$ ]]; then
|
||||
echo "::error title=ensure-base-commit invalid base sha::Refusing invalid base SHA: $BASE_SHA"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if ! git check-ref-format --branch "$FETCH_REF" >/dev/null 2>&1; then
|
||||
echo "::error title=ensure-base-commit invalid fetch ref::Refusing invalid fetch ref: $FETCH_REF"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if git rev-parse --verify "$BASE_SHA^{commit}" >/dev/null 2>&1; then
|
||||
echo "Base commit already present: $BASE_SHA"
|
||||
exit 0
|
||||
@@ -40,7 +30,7 @@ runs:
|
||||
|
||||
for deepen_by in 25 100 300; do
|
||||
echo "Base commit missing; deepening $FETCH_REF by $deepen_by."
|
||||
if ! git fetch --no-tags --deepen="$deepen_by" origin -- "$FETCH_REF"; then
|
||||
if ! git fetch --no-tags --deepen="$deepen_by" origin "$FETCH_REF"; then
|
||||
echo "::warning title=ensure-base-commit fetch failed::Failed to deepen $FETCH_REF by $deepen_by while looking for $BASE_SHA"
|
||||
fi
|
||||
if git rev-parse --verify "$BASE_SHA^{commit}" >/dev/null 2>&1; then
|
||||
@@ -50,7 +40,7 @@ runs:
|
||||
done
|
||||
|
||||
echo "Base commit still missing; fetching full history for $FETCH_REF."
|
||||
if ! git fetch --no-tags origin -- "$FETCH_REF"; then
|
||||
if ! git fetch --no-tags origin "$FETCH_REF"; then
|
||||
echo "::warning title=ensure-base-commit fetch failed::Failed to fetch full history for $FETCH_REF while looking for $BASE_SHA"
|
||||
fi
|
||||
if git rev-parse --verify "$BASE_SHA^{commit}" >/dev/null 2>&1; then
|
||||
|
||||
8
.github/labeler.yml
vendored
8
.github/labeler.yml
vendored
@@ -229,10 +229,6 @@
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "extensions/device-pair/**"
|
||||
"extensions: duckduckgo":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "extensions/duckduckgo/**"
|
||||
"extensions: acpx":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
@@ -241,10 +237,6 @@
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "extensions/byteplus/**"
|
||||
"extensions: deepseek":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "extensions/deepseek/**"
|
||||
"extensions: anthropic":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
|
||||
26
.github/pull_request_template.md
vendored
26
.github/pull_request_template.md
vendored
@@ -31,32 +31,6 @@ Describe the problem and fix in 2–5 bullets:
|
||||
|
||||
- Closes #
|
||||
- Related #
|
||||
- [ ] This PR fixes a bug or regression
|
||||
|
||||
## Root Cause / Regression History (if applicable)
|
||||
|
||||
For bug fixes or regressions, explain why this happened, not just what changed. Otherwise write `N/A`. If the cause is unclear, write `Unknown`.
|
||||
|
||||
- Root cause:
|
||||
- Missing detection / guardrail:
|
||||
- Prior context (`git blame`, prior PR, issue, or refactor if known):
|
||||
- Why this regressed now:
|
||||
- If unknown, what was ruled out:
|
||||
|
||||
## Regression Test Plan (if applicable)
|
||||
|
||||
For bug fixes or regressions, name the smallest reliable test coverage that should have caught this. Otherwise write `N/A`.
|
||||
|
||||
- Coverage level that should have caught this:
|
||||
- [ ] Unit test
|
||||
- [ ] Seam / integration test
|
||||
- [ ] End-to-end test
|
||||
- [ ] Existing coverage already sufficient
|
||||
- Target test or file:
|
||||
- Scenario the test should lock in:
|
||||
- Why this is the smallest reliable guardrail:
|
||||
- Existing test that already covers this (if any):
|
||||
- If no new test is added, why not:
|
||||
|
||||
## User-visible / Behavior Changes
|
||||
|
||||
|
||||
4
.github/workflows/auto-response.yml
vendored
4
.github/workflows/auto-response.yml
vendored
@@ -11,10 +11,6 @@ on:
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref || github.run_id }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request_target' }}
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
|
||||
72
.github/workflows/ci-bun.yml
vendored
72
.github/workflows/ci-bun.yml
vendored
@@ -1,72 +0,0 @@
|
||||
name: CI Bun
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
concurrency:
|
||||
group: ci-bun-push-${{ github.run_id }}
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
build-bun-artifacts:
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Build A2UI bundle
|
||||
run: pnpm canvas:a2ui:bundle
|
||||
|
||||
- name: Upload A2UI bundle artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: canvas-a2ui-bundle
|
||||
path: src/canvas-host/a2ui/
|
||||
|
||||
bun-checks:
|
||||
needs: [build-bun-artifacts]
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- shard_index: 1
|
||||
shard_count: 2
|
||||
command: OPENCLAW_TEST_ISOLATE=1 bunx vitest run --config vitest.unit.config.ts --shard 1/2
|
||||
- shard_index: 2
|
||||
shard_count: 2
|
||||
command: OPENCLAW_TEST_ISOLATE=1 bunx vitest run --config vitest.unit.config.ts --shard 2/2
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "true"
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Download A2UI bundle artifact
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: canvas-a2ui-bundle
|
||||
path: src/canvas-host/a2ui/
|
||||
|
||||
- name: Run Bun test shard
|
||||
run: ${{ matrix.command }}
|
||||
667
.github/workflows/ci.yml
vendored
667
.github/workflows/ci.yml
vendored
@@ -6,61 +6,68 @@ on:
|
||||
pull_request:
|
||||
types: [opened, reopened, synchronize, ready_for_review, converted_to_draft]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.event_name == 'pull_request' && format('{0}-{1}', github.workflow, github.event.pull_request.number) || format('{0}-{1}', github.workflow, github.run_id) }}
|
||||
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
jobs:
|
||||
# Scope: establish the fast global truth for this revision before the
|
||||
# expensive platform and platform-specific lanes fan out.
|
||||
# Detect docs-only changes to skip heavy jobs (test, build, Windows, macOS, Android).
|
||||
# Keep this job focused on routing decisions so the rest of CI can fan out sooner.
|
||||
# Fail-safe: if detection steps are skipped, downstream outputs fall back to
|
||||
# conservative defaults that keep heavy lanes enabled.
|
||||
scope:
|
||||
# Lint and format always run. Fail-safe: if detection fails, run everything.
|
||||
docs-scope:
|
||||
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
outputs:
|
||||
docs_only: ${{ steps.docs_scope.outputs.docs_only }}
|
||||
docs_changed: ${{ steps.docs_scope.outputs.docs_changed }}
|
||||
run_node: ${{ steps.changed_scope.outputs.run_node || 'false' }}
|
||||
run_macos: ${{ steps.changed_scope.outputs.run_macos || 'false' }}
|
||||
run_android: ${{ steps.changed_scope.outputs.run_android || 'false' }}
|
||||
run_skills_python: ${{ steps.changed_scope.outputs.run_skills_python || 'false' }}
|
||||
run_windows: ${{ steps.changed_scope.outputs.run_windows || 'false' }}
|
||||
has_changed_extensions: ${{ steps.changed_extensions.outputs.has_changed_extensions || 'false' }}
|
||||
changed_extensions_matrix: ${{ steps.changed_extensions.outputs.changed_extensions_matrix || '{"include":[]}' }}
|
||||
docs_only: ${{ steps.check.outputs.docs_only }}
|
||||
docs_changed: ${{ steps.check.outputs.docs_changed }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Ensure preflight base commit
|
||||
- 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: docs_scope
|
||||
id: check
|
||||
uses: ./.github/actions/detect-docs-changes
|
||||
|
||||
# Detect which heavy areas are touched so CI can skip unrelated expensive jobs.
|
||||
# Fail-safe: if skipped, downstream lanes run.
|
||||
# Detect which heavy areas are touched so CI can skip unrelated expensive jobs.
|
||||
# Fail-safe: if detection fails, downstream jobs run.
|
||||
changed-scope:
|
||||
needs: [docs-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
outputs:
|
||||
run_node: ${{ steps.scope.outputs.run_node }}
|
||||
run_macos: ${{ steps.scope.outputs.run_macos }}
|
||||
run_android: ${{ steps.scope.outputs.run_android }}
|
||||
run_skills_python: ${{ steps.scope.outputs.run_skills_python }}
|
||||
run_windows: ${{ steps.scope.outputs.run_windows }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
submodules: false
|
||||
|
||||
- name: Ensure changed-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 changed scopes
|
||||
id: changed_scope
|
||||
if: steps.docs_scope.outputs.docs_only != 'true'
|
||||
id: scope
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
@@ -73,8 +80,28 @@ jobs:
|
||||
|
||||
node scripts/ci-changed-scope.mjs --base "$BASE" --head HEAD
|
||||
|
||||
changed-extensions:
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
outputs:
|
||||
has_changed_extensions: ${{ steps.changed.outputs.has_changed_extensions }}
|
||||
changed_extensions_matrix: ${{ steps.changed.outputs.changed_extensions_matrix }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
submodules: false
|
||||
|
||||
- name: Ensure changed-extensions 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: Setup Node environment
|
||||
if: steps.docs_scope.outputs.docs_only != 'true'
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
@@ -82,138 +109,30 @@ jobs:
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Detect changed extensions
|
||||
id: changed_extensions
|
||||
if: steps.docs_scope.outputs.docs_only != 'true' && steps.changed_scope.outputs.run_node == 'true'
|
||||
id: changed
|
||||
env:
|
||||
BASE_SHA: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
|
||||
BASE_REF: ${{ github.event_name == 'push' && github.ref_name || github.event.pull_request.base.ref }}
|
||||
run: |
|
||||
node --input-type=module <<'EOF'
|
||||
import { appendFileSync } from "node:fs";
|
||||
import { listChangedExtensionIds } from "./scripts/test-extension.mjs";
|
||||
|
||||
const extensionIds = listChangedExtensionIds({
|
||||
base: process.env.BASE_SHA,
|
||||
head: "HEAD",
|
||||
fallbackBaseRef: process.env.BASE_REF,
|
||||
unavailableBaseBehavior: "all",
|
||||
});
|
||||
const extensionIds = listChangedExtensionIds({ base: process.env.BASE_SHA, head: "HEAD" });
|
||||
const matrix = JSON.stringify({ include: extensionIds.map((extension) => ({ extension })) });
|
||||
|
||||
appendFileSync(process.env.GITHUB_OUTPUT, `has_changed_extensions=${extensionIds.length > 0}\n`, "utf8");
|
||||
appendFileSync(process.env.GITHUB_OUTPUT, `changed_extensions_matrix=${matrix}\n`, "utf8");
|
||||
EOF
|
||||
|
||||
# Run the fast security/SCM checks in parallel with scope detection so the
|
||||
# main Node jobs do not have to wait for Python/pre-commit setup.
|
||||
security-fast:
|
||||
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
PRE_COMMIT_CACHE_KEY_SUFFIX: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.sha }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Ensure security 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: Prepare trusted pre-commit config
|
||||
if: github.event_name == 'pull_request'
|
||||
env:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
trusted_config="$RUNNER_TEMP/pre-commit-base.yaml"
|
||||
git show "${BASE_SHA}:.pre-commit-config.yaml" > "$trusted_config"
|
||||
echo "PRE_COMMIT_CONFIG_PATH=$trusted_config" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
install-deps: "false"
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Setup Python
|
||||
id: setup-python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
cache: "pip"
|
||||
cache-dependency-path: |
|
||||
pyproject.toml
|
||||
.pre-commit-config.yaml
|
||||
.github/workflows/ci.yml
|
||||
|
||||
- name: Restore pre-commit cache
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: pre-commit-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}-${{ env.PRE_COMMIT_CACHE_KEY_SUFFIX }}
|
||||
restore-keys: |
|
||||
pre-commit-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}-
|
||||
|
||||
- name: Install pre-commit
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install pre-commit==4.2.0
|
||||
|
||||
- name: Detect committed private keys
|
||||
run: pre-commit run --config "${PRE_COMMIT_CONFIG_PATH:-.pre-commit-config.yaml}" --all-files detect-private-key
|
||||
|
||||
- name: Audit changed GitHub workflows with zizmor
|
||||
env:
|
||||
BASE_SHA: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ -z "${BASE_SHA:-}" ] || [ "${BASE_SHA}" = "0000000000000000000000000000000000000000" ]; then
|
||||
echo "No usable base SHA detected; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null; then
|
||||
echo "Base SHA ${BASE_SHA} is unavailable; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mapfile -t workflow_files < <(
|
||||
git diff --name-only "${BASE_SHA}" HEAD -- '.github/workflows/*.yml' '.github/workflows/*.yaml'
|
||||
)
|
||||
if [ "${#workflow_files[@]}" -eq 0 ]; then
|
||||
echo "No workflow changes detected; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf 'Auditing workflow files:\n%s\n' "${workflow_files[@]}"
|
||||
pre-commit run --config "${PRE_COMMIT_CONFIG_PATH:-.pre-commit-config.yaml}" zizmor --files "${workflow_files[@]}"
|
||||
|
||||
- name: Audit production dependencies
|
||||
run: pre-commit run --config "${PRE_COMMIT_CONFIG_PATH:-.pre-commit-config.yaml}" --all-files pnpm-audit-prod
|
||||
|
||||
# Fanout: downstream lanes branch from preflight outputs instead of waiting
|
||||
# on unrelated Linux checks.
|
||||
# Build dist once for Node-relevant changes and share it with downstream jobs.
|
||||
build-artifacts:
|
||||
needs: [scope]
|
||||
if: needs.scope.outputs.docs_only != 'true' && needs.scope.outputs.run_node == 'true'
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: github.event_name == 'push' && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Ensure secrets base commit (PR fast path)
|
||||
@@ -232,9 +151,6 @@ jobs:
|
||||
- name: Build dist
|
||||
run: pnpm build
|
||||
|
||||
- name: Build Control UI
|
||||
run: pnpm ui:build
|
||||
|
||||
- name: Upload dist artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
@@ -242,25 +158,15 @@ jobs:
|
||||
path: dist/
|
||||
retention-days: 1
|
||||
|
||||
- name: Upload A2UI bundle artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: canvas-a2ui-bundle
|
||||
path: src/canvas-host/a2ui/
|
||||
include-hidden-files: true
|
||||
retention-days: 1
|
||||
|
||||
# Validate npm pack contents after build (only on push to main, not PRs).
|
||||
release-check:
|
||||
needs: [scope, build-artifacts]
|
||||
if: github.event_name == 'push' && needs.scope.outputs.docs_only != 'true'
|
||||
needs: [docs-scope, build-artifacts]
|
||||
if: github.event_name == 'push' && needs.docs-scope.outputs.docs_only != 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
@@ -278,90 +184,45 @@ jobs:
|
||||
- name: Check release contents
|
||||
run: pnpm release:check
|
||||
|
||||
checks-fast:
|
||||
needs: [scope]
|
||||
if: always() && needs.scope.outputs.docs_only != 'true' && needs.scope.outputs.run_node == 'true'
|
||||
checks:
|
||||
needs: [docs-scope, changed-scope, build-artifacts]
|
||||
if: always() && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true' && (github.event_name != 'push' || needs.build-artifacts.result == 'success')
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 1
|
||||
shard_count: 2
|
||||
command: pnpm canvas:a2ui:bundle && pnpm test
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 2
|
||||
shard_count: 2
|
||||
command: pnpm canvas:a2ui:bundle && pnpm test
|
||||
- runtime: node
|
||||
task: extensions
|
||||
command: pnpm test:extensions
|
||||
- runtime: node
|
||||
task: contracts-protocol
|
||||
command: |
|
||||
pnpm test:contracts
|
||||
pnpm protocol:check
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Run ${{ matrix.task }} (${{ matrix.runtime }})
|
||||
run: ${{ matrix.command }}
|
||||
|
||||
checks:
|
||||
needs: [scope, build-artifacts]
|
||||
if: always() && needs.scope.outputs.docs_only != 'true' && needs.scope.outputs.run_node == 'true' && needs.build-artifacts.result == 'success'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 1
|
||||
shard_count: 4
|
||||
command: pnpm test
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 2
|
||||
shard_count: 4
|
||||
command: pnpm test
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 3
|
||||
shard_count: 4
|
||||
command: pnpm test
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 4
|
||||
shard_count: 4
|
||||
command: pnpm test
|
||||
- runtime: node
|
||||
task: channels
|
||||
shard_index: 1
|
||||
shard_count: 3
|
||||
command: pnpm test:channels
|
||||
- runtime: node
|
||||
task: channels
|
||||
shard_index: 2
|
||||
shard_count: 3
|
||||
command: pnpm test:channels
|
||||
task: contracts
|
||||
command: pnpm test:contracts
|
||||
- runtime: node
|
||||
task: channels
|
||||
shard_index: 3
|
||||
shard_count: 3
|
||||
command: pnpm test:channels
|
||||
task: protocol
|
||||
command: pnpm protocol:check
|
||||
- runtime: bun
|
||||
task: test
|
||||
command: pnpm canvas:a2ui:bundle && bunx vitest run --config vitest.unit.config.ts
|
||||
- runtime: node
|
||||
task: compat-node22
|
||||
node_version: "22.x"
|
||||
cache_key_suffix: "node22"
|
||||
command: |
|
||||
pnpm build
|
||||
pnpm ui:build
|
||||
node openclaw.mjs --help
|
||||
node openclaw.mjs status --json --timeout 1
|
||||
pnpm test:build:singleton
|
||||
@@ -369,27 +230,26 @@ jobs:
|
||||
node --import tsx scripts/release-check.ts
|
||||
steps:
|
||||
- name: Skip compatibility lanes on pull requests
|
||||
if: github.event_name == 'pull_request' && matrix.task == 'compat-node22'
|
||||
if: github.event_name == 'pull_request' && (matrix.runtime == 'bun' || matrix.task == 'compat-node22')
|
||||
run: echo "Skipping push-only lane on pull requests."
|
||||
|
||||
- name: Checkout
|
||||
if: github.event_name != 'pull_request' || matrix.task != 'compat-node22'
|
||||
if: github.event_name != 'pull_request' || (matrix.runtime != 'bun' && matrix.task != 'compat-node22')
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
if: github.event_name != 'pull_request' || matrix.task != 'compat-node22'
|
||||
if: github.event_name != 'pull_request' || (matrix.runtime != 'bun' && matrix.task != 'compat-node22')
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
node-version: "${{ matrix.node_version || '24.x' }}"
|
||||
cache-key-suffix: "${{ matrix.cache_key_suffix || 'node24' }}"
|
||||
install-bun: "false"
|
||||
install-bun: "${{ matrix.runtime == 'bun' }}"
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Configure Node test resources
|
||||
if: (github.event_name != 'pull_request' || matrix.task != 'compat-node22') && matrix.runtime == 'node' && (matrix.task == 'test' || matrix.task == 'channels' || matrix.task == 'compat-node22')
|
||||
if: (github.event_name != 'pull_request' || (matrix.runtime != 'bun' && matrix.task != 'compat-node22')) && matrix.runtime == 'node' && (matrix.task == 'test' || matrix.task == 'compat-node22')
|
||||
env:
|
||||
SHARD_COUNT: ${{ matrix.shard_count || '' }}
|
||||
SHARD_INDEX: ${{ matrix.shard_index || '' }}
|
||||
@@ -398,47 +258,38 @@ jobs:
|
||||
# Default heap limits have been too low on Linux CI (V8 OOM near 4GB).
|
||||
echo "OPENCLAW_TEST_WORKERS=2" >> "$GITHUB_ENV"
|
||||
echo "OPENCLAW_TEST_MAX_OLD_SPACE_SIZE_MB=6144" >> "$GITHUB_ENV"
|
||||
if [ "${{ matrix.task }}" = "channels" ]; then
|
||||
echo "OPENCLAW_TEST_WORKERS=1" >> "$GITHUB_ENV"
|
||||
echo "OPENCLAW_TEST_ISOLATE=1" >> "$GITHUB_ENV"
|
||||
fi
|
||||
if [ -n "$SHARD_COUNT" ] && [ -n "$SHARD_INDEX" ]; then
|
||||
echo "OPENCLAW_TEST_SHARDS=$SHARD_COUNT" >> "$GITHUB_ENV"
|
||||
echo "OPENCLAW_TEST_SHARD_INDEX=$SHARD_INDEX" >> "$GITHUB_ENV"
|
||||
fi
|
||||
|
||||
- name: Download dist artifact
|
||||
if: matrix.task == 'test'
|
||||
if: github.event_name == 'push' && matrix.task == 'test'
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: dist-build
|
||||
path: dist/
|
||||
|
||||
- name: Download A2UI bundle artifact
|
||||
if: matrix.task == 'test' || matrix.task == 'channels'
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: canvas-a2ui-bundle
|
||||
path: src/canvas-host/a2ui/
|
||||
- name: Build dist
|
||||
if: github.event_name != 'push' && matrix.task == 'test' && matrix.runtime == 'node'
|
||||
run: pnpm build
|
||||
|
||||
- name: Run ${{ matrix.task }} (${{ matrix.runtime }})
|
||||
if: github.event_name != 'pull_request' || matrix.task != 'compat-node22'
|
||||
if: github.event_name != 'pull_request' || (matrix.runtime != 'bun' && matrix.task != 'compat-node22')
|
||||
run: ${{ matrix.command }}
|
||||
|
||||
extension-fast:
|
||||
name: "extension-fast"
|
||||
needs: [scope]
|
||||
if: needs.scope.outputs.docs_only != 'true' && needs.scope.outputs.run_node == 'true' && needs.scope.outputs.has_changed_extensions == 'true'
|
||||
needs: [docs-scope, changed-scope, changed-extensions]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true' && needs.changed-extensions.outputs.has_changed_extensions == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.scope.outputs.changed_extensions_matrix) }}
|
||||
matrix: ${{ fromJson(needs.changed-extensions.outputs.changed_extensions_matrix) }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
@@ -455,15 +306,13 @@ jobs:
|
||||
# Types, lint, and format check.
|
||||
check:
|
||||
name: "check"
|
||||
needs: [scope]
|
||||
if: always() && (github.event_name != 'pull_request' || !github.event.pull_request.draft) && needs.scope.outputs.docs_only != 'true'
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
@@ -480,15 +329,13 @@ jobs:
|
||||
|
||||
check-additional:
|
||||
name: "check-additional"
|
||||
needs: [scope]
|
||||
if: always() && (github.event_name != 'pull_request' || !github.event.pull_request.draft) && needs.scope.outputs.docs_only != 'true'
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
@@ -579,15 +426,13 @@ jobs:
|
||||
|
||||
build-smoke:
|
||||
name: "build-smoke"
|
||||
needs: [scope, build-artifacts]
|
||||
if: always() && needs.scope.outputs.docs_only != 'true' && needs.scope.outputs.run_node == 'true' && (github.event_name != 'push' || needs.build-artifacts.result == 'success')
|
||||
needs: [docs-scope, changed-scope, build-artifacts]
|
||||
if: always() && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_node == 'true' && (github.event_name != 'push' || needs.build-artifacts.result == 'success')
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
@@ -621,15 +466,13 @@ jobs:
|
||||
|
||||
# Validate docs (format, lint, broken links) only when docs files changed.
|
||||
check-docs:
|
||||
needs: [scope]
|
||||
if: needs.scope.outputs.docs_changed == 'true'
|
||||
needs: [docs-scope]
|
||||
if: needs.docs-scope.outputs.docs_changed == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
@@ -642,15 +485,13 @@ jobs:
|
||||
run: pnpm check:docs
|
||||
|
||||
skills-python:
|
||||
needs: [scope]
|
||||
if: needs.scope.outputs.docs_only != 'true' && (github.event_name == 'push' || needs.scope.outputs.run_skills_python == 'true')
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && (github.event_name == 'push' || needs.changed-scope.outputs.run_skills_python == 'true')
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Python
|
||||
@@ -669,11 +510,88 @@ jobs:
|
||||
- name: Test skill Python scripts
|
||||
run: python -m pytest -q skills
|
||||
|
||||
secrets:
|
||||
if: github.event_name != 'pull_request' || !github.event.pull_request.draft
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Ensure secrets 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: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
install-bun: "false"
|
||||
use-sticky-disk: "false"
|
||||
install-deps: "false"
|
||||
|
||||
- name: Setup Python
|
||||
id: setup-python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.12"
|
||||
cache: "pip"
|
||||
cache-dependency-path: |
|
||||
pyproject.toml
|
||||
.pre-commit-config.yaml
|
||||
.github/workflows/ci.yml
|
||||
|
||||
- name: Restore pre-commit cache
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: pre-commit-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
|
||||
- name: Install pre-commit
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python -m pip install pre-commit
|
||||
|
||||
- name: Detect committed private keys
|
||||
run: pre-commit run --all-files detect-private-key
|
||||
|
||||
- name: Audit changed GitHub workflows with zizmor
|
||||
env:
|
||||
BASE_SHA: ${{ github.event_name == 'push' && github.event.before || github.event.pull_request.base.sha }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ -z "${BASE_SHA:-}" ] || [ "${BASE_SHA}" = "0000000000000000000000000000000000000000" ]; then
|
||||
echo "No usable base SHA detected; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null; then
|
||||
echo "Base SHA ${BASE_SHA} is unavailable; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mapfile -t workflow_files < <(
|
||||
git diff --name-only "${BASE_SHA}" HEAD -- '.github/workflows/*.yml' '.github/workflows/*.yaml'
|
||||
)
|
||||
if [ "${#workflow_files[@]}" -eq 0 ]; then
|
||||
echo "No workflow changes detected; skipping zizmor."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
printf 'Auditing workflow files:\n%s\n' "${workflow_files[@]}"
|
||||
pre-commit run zizmor --files "${workflow_files[@]}"
|
||||
|
||||
- name: Audit production dependencies
|
||||
run: pre-commit run --all-files pnpm-audit-prod
|
||||
|
||||
checks-windows:
|
||||
needs: [scope, build-artifacts]
|
||||
if: always() && needs.scope.outputs.docs_only != 'true' && needs.scope.outputs.run_windows == 'true' && needs.build-artifacts.result == 'success'
|
||||
needs: [docs-scope, changed-scope, build-artifacts]
|
||||
if: always() && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_windows == 'true' && (github.event_name != 'push' || needs.build-artifacts.result == 'success')
|
||||
runs-on: blacksmith-32vcpu-windows-2025
|
||||
timeout-minutes: 20
|
||||
timeout-minutes: 45
|
||||
env:
|
||||
NODE_OPTIONS: --max-old-space-size=6144
|
||||
# Keep total concurrency predictable on the 32 vCPU runner.
|
||||
@@ -689,53 +607,37 @@ jobs:
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 1
|
||||
shard_count: 9
|
||||
shard_count: 6
|
||||
command: pnpm test
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 2
|
||||
shard_count: 9
|
||||
shard_count: 6
|
||||
command: pnpm test
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 3
|
||||
shard_count: 9
|
||||
shard_count: 6
|
||||
command: pnpm test
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 4
|
||||
shard_count: 9
|
||||
shard_count: 6
|
||||
command: pnpm test
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 5
|
||||
shard_count: 9
|
||||
shard_count: 6
|
||||
command: pnpm test
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 6
|
||||
shard_count: 9
|
||||
command: pnpm test
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 7
|
||||
shard_count: 9
|
||||
command: pnpm test
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 8
|
||||
shard_count: 9
|
||||
command: pnpm test
|
||||
- runtime: node
|
||||
task: test
|
||||
shard_index: 9
|
||||
shard_count: 9
|
||||
shard_count: 6
|
||||
command: pnpm test
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Try to exclude workspace from Windows Defender (best-effort)
|
||||
@@ -803,19 +705,20 @@ jobs:
|
||||
echo "OPENCLAW_TEST_SHARDS=${{ matrix.shard_count }}" >> "$GITHUB_ENV"
|
||||
echo "OPENCLAW_TEST_SHARD_INDEX=${{ matrix.shard_index }}" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Download dist artifact
|
||||
- name: Build A2UI bundle (Windows)
|
||||
if: matrix.task == 'test'
|
||||
run: pnpm canvas:a2ui:bundle
|
||||
|
||||
- name: Download dist artifact
|
||||
if: github.event_name == 'push' && matrix.task == 'test'
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: dist-build
|
||||
path: dist/
|
||||
|
||||
- name: Download A2UI bundle artifact
|
||||
if: matrix.task == 'test'
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: canvas-a2ui-bundle
|
||||
path: src/canvas-host/a2ui/
|
||||
- name: Build dist (Windows)
|
||||
if: github.event_name != 'push' && matrix.task == 'test'
|
||||
run: pnpm build
|
||||
|
||||
- name: Run ${{ matrix.task }} (${{ matrix.runtime }})
|
||||
run: ${{ matrix.command }}
|
||||
@@ -825,15 +728,13 @@ jobs:
|
||||
# running 4 separate jobs per PR (as before) starved the queue. One job
|
||||
# per PR allows 5 PRs to run macOS checks simultaneously.
|
||||
macos:
|
||||
needs: [scope]
|
||||
if: github.event_name == 'pull_request' && needs.scope.outputs.docs_only != 'true' && needs.scope.outputs.run_macos == 'true'
|
||||
needs: [docs-scope, changed-scope, check]
|
||||
if: github.event_name == 'pull_request' && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_macos == 'true'
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Node environment
|
||||
@@ -902,11 +803,170 @@ jobs:
|
||||
done
|
||||
exit 1
|
||||
|
||||
ios:
|
||||
if: false # ignore iOS in CI for now
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Select Xcode 26.1
|
||||
run: |
|
||||
sudo xcode-select -s /Applications/Xcode_26.1.app
|
||||
xcodebuild -version
|
||||
|
||||
- name: Install XcodeGen
|
||||
run: brew install xcodegen
|
||||
|
||||
- name: Install SwiftLint / SwiftFormat
|
||||
run: brew install swiftlint swiftformat
|
||||
|
||||
- name: Show toolchain
|
||||
run: |
|
||||
sw_vers
|
||||
xcodebuild -version
|
||||
swift --version
|
||||
|
||||
- name: Generate iOS project
|
||||
run: |
|
||||
cd apps/ios
|
||||
xcodegen generate
|
||||
|
||||
- name: iOS tests
|
||||
run: |
|
||||
set -euo pipefail
|
||||
RESULT_BUNDLE_PATH="$RUNNER_TEMP/Clawdis-iOS.xcresult"
|
||||
DEST_ID="$(
|
||||
python3 - <<'PY'
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
def sh(args: list[str]) -> str:
|
||||
return subprocess.check_output(args, text=True).strip()
|
||||
|
||||
# Prefer an already-created iPhone simulator if it exists.
|
||||
devices = json.loads(sh(["xcrun", "simctl", "list", "devices", "-j"]))
|
||||
candidates: list[tuple[str, str]] = []
|
||||
for runtime, devs in (devices.get("devices") or {}).items():
|
||||
for dev in devs or []:
|
||||
if not dev.get("isAvailable"):
|
||||
continue
|
||||
name = str(dev.get("name") or "")
|
||||
udid = str(dev.get("udid") or "")
|
||||
if not udid or not name.startswith("iPhone"):
|
||||
continue
|
||||
candidates.append((name, udid))
|
||||
|
||||
candidates.sort(key=lambda it: (0 if "iPhone 16" in it[0] else 1, it[0]))
|
||||
if candidates:
|
||||
print(candidates[0][1])
|
||||
sys.exit(0)
|
||||
|
||||
# Otherwise, create one from the newest available iOS runtime.
|
||||
runtimes = json.loads(sh(["xcrun", "simctl", "list", "runtimes", "-j"])).get("runtimes") or []
|
||||
ios = [rt for rt in runtimes if rt.get("platform") == "iOS" and rt.get("isAvailable")]
|
||||
if not ios:
|
||||
print("No available iOS runtimes found.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
def version_key(rt: dict) -> tuple[int, ...]:
|
||||
parts: list[int] = []
|
||||
for p in str(rt.get("version") or "0").split("."):
|
||||
try:
|
||||
parts.append(int(p))
|
||||
except ValueError:
|
||||
parts.append(0)
|
||||
return tuple(parts)
|
||||
|
||||
ios.sort(key=version_key, reverse=True)
|
||||
runtime = ios[0]
|
||||
runtime_id = str(runtime.get("identifier") or "")
|
||||
if not runtime_id:
|
||||
print("Missing iOS runtime identifier.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
supported = runtime.get("supportedDeviceTypes") or []
|
||||
iphones = [dt for dt in supported if dt.get("productFamily") == "iPhone"]
|
||||
if not iphones:
|
||||
print("No iPhone device types for iOS runtime.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
iphones.sort(
|
||||
key=lambda dt: (
|
||||
0 if "iPhone 16" in str(dt.get("name") or "") else 1,
|
||||
str(dt.get("name") or ""),
|
||||
)
|
||||
)
|
||||
device_type_id = str(iphones[0].get("identifier") or "")
|
||||
if not device_type_id:
|
||||
print("Missing iPhone device type identifier.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
sim_name = f"CI iPhone {uuid.uuid4().hex[:8]}"
|
||||
udid = sh(["xcrun", "simctl", "create", sim_name, device_type_id, runtime_id])
|
||||
if not udid:
|
||||
print("Failed to create iPhone simulator.", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
print(udid)
|
||||
PY
|
||||
)"
|
||||
echo "Using iOS Simulator id: $DEST_ID"
|
||||
xcodebuild test \
|
||||
-project apps/ios/Clawdis.xcodeproj \
|
||||
-scheme Clawdis \
|
||||
-destination "platform=iOS Simulator,id=$DEST_ID" \
|
||||
-resultBundlePath "$RESULT_BUNDLE_PATH" \
|
||||
-enableCodeCoverage YES
|
||||
|
||||
- name: iOS coverage summary
|
||||
run: |
|
||||
set -euo pipefail
|
||||
RESULT_BUNDLE_PATH="$RUNNER_TEMP/Clawdis-iOS.xcresult"
|
||||
xcrun xccov view --report --only-targets "$RESULT_BUNDLE_PATH"
|
||||
|
||||
- name: iOS coverage gate (43%)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
RESULT_BUNDLE_PATH="$RUNNER_TEMP/Clawdis-iOS.xcresult"
|
||||
RESULT_BUNDLE_PATH="$RESULT_BUNDLE_PATH" python3 - <<'PY'
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
target_name = "Clawdis.app"
|
||||
minimum = 0.43
|
||||
|
||||
report = json.loads(
|
||||
subprocess.check_output(
|
||||
["xcrun", "xccov", "view", "--report", "--json", os.environ["RESULT_BUNDLE_PATH"]],
|
||||
text=True,
|
||||
)
|
||||
)
|
||||
|
||||
target_coverage = None
|
||||
for target in report.get("targets", []):
|
||||
if target.get("name") == target_name:
|
||||
target_coverage = float(target["lineCoverage"])
|
||||
break
|
||||
|
||||
if target_coverage is None:
|
||||
print(f"Could not find coverage for target: {target_name}")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"{target_name} line coverage: {target_coverage * 100:.2f}% (min {minimum * 100:.2f}%)")
|
||||
if target_coverage + 1e-12 < minimum:
|
||||
sys.exit(1)
|
||||
PY
|
||||
|
||||
android:
|
||||
needs: [scope]
|
||||
if: needs.scope.outputs.docs_only != 'true' && needs.scope.outputs.run_android == 'true'
|
||||
needs: [docs-scope, changed-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true' && needs.changed-scope.outputs.run_android == 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
timeout-minutes: 20
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -923,7 +983,6 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
persist-credentials: false
|
||||
submodules: false
|
||||
|
||||
- name: Setup Java
|
||||
@@ -953,7 +1012,7 @@ jobs:
|
||||
echo "$ANDROID_SDK_ROOT/platform-tools" >> "$GITHUB_PATH"
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@0723195856401067f7a2779048b490ace7a47d7c # v5
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
with:
|
||||
gradle-version: 8.11.1
|
||||
|
||||
|
||||
4
.github/workflows/docker-release.yml
vendored
4
.github/workflows/docker-release.yml
vendored
@@ -15,12 +15,12 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: Existing release tag to backfill (for example v2026.3.22)
|
||||
description: Existing release tag to backfill (for example v2026.3.13)
|
||||
required: true
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.event_name == 'workflow_dispatch' && format('docker-release-manual-{0}', inputs.tag) || format('docker-release-push-{0}', github.run_id) }}
|
||||
group: docker-release-${{ github.workflow }}-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
|
||||
61
.github/workflows/install-smoke.yml
vendored
61
.github/workflows/install-smoke.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.event_name == 'pull_request' && format('{0}-{1}', github.workflow, github.event.pull_request.number) || format('{0}-{1}', github.workflow, github.run_id) }}
|
||||
group: install-smoke-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
env:
|
||||
@@ -37,46 +37,10 @@ jobs:
|
||||
id: check
|
||||
uses: ./.github/actions/detect-docs-changes
|
||||
|
||||
changed-smoke:
|
||||
needs: [docs-scope]
|
||||
if: needs.docs-scope.outputs.docs_only != 'true'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
outputs:
|
||||
run_changed_smoke: ${{ steps.scope.outputs.run_changed_smoke }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 1
|
||||
fetch-tags: false
|
||||
|
||||
- name: Ensure changed-smoke 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 changed smoke scope
|
||||
id: scope
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
if [ "${{ github.event_name }}" = "push" ]; then
|
||||
BASE="${{ github.event.before }}"
|
||||
else
|
||||
BASE="${{ github.event.pull_request.base.sha }}"
|
||||
fi
|
||||
|
||||
node scripts/ci-changed-scope.mjs --base "$BASE" --head HEAD
|
||||
|
||||
install-smoke:
|
||||
needs: [docs-scope, changed-smoke]
|
||||
if: (github.event_name != 'pull_request' || !github.event.pull_request.draft) && needs.docs-scope.outputs.docs_only != 'true' && needs.changed-smoke.outputs.run_changed_smoke == 'true'
|
||||
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
|
||||
@@ -91,8 +55,6 @@ jobs:
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
build-args: |
|
||||
OPENCLAW_DOCKER_APT_UPGRADE=0
|
||||
tags: openclaw-dockerfile-smoke:local
|
||||
load: true
|
||||
push: false
|
||||
@@ -111,7 +73,6 @@ jobs:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
build-args: |
|
||||
OPENCLAW_DOCKER_APT_UPGRADE=0
|
||||
OPENCLAW_EXTENSIONS=matrix
|
||||
tags: openclaw-ext-smoke:local
|
||||
load: true
|
||||
@@ -186,12 +147,12 @@ jobs:
|
||||
|
||||
- name: Run installer docker tests
|
||||
env:
|
||||
OPENCLAW_INSTALL_URL: https://openclaw.ai/install.sh
|
||||
OPENCLAW_INSTALL_CLI_URL: https://openclaw.ai/install-cli.sh
|
||||
OPENCLAW_NO_ONBOARD: "1"
|
||||
OPENCLAW_INSTALL_SMOKE_SKIP_CLI: "1"
|
||||
OPENCLAW_INSTALL_SMOKE_SKIP_IMAGE_BUILD: "1"
|
||||
OPENCLAW_INSTALL_NONROOT_SKIP_IMAGE_BUILD: ${{ github.event_name == 'pull_request' && '0' || '1' }}
|
||||
OPENCLAW_INSTALL_SMOKE_SKIP_NONROOT: ${{ github.event_name == 'pull_request' && '1' || '0' }}
|
||||
OPENCLAW_INSTALL_SMOKE_SKIP_PREVIOUS: "1"
|
||||
CLAWDBOT_INSTALL_URL: https://openclaw.ai/install.sh
|
||||
CLAWDBOT_INSTALL_CLI_URL: https://openclaw.ai/install-cli.sh
|
||||
CLAWDBOT_NO_ONBOARD: "1"
|
||||
CLAWDBOT_INSTALL_SMOKE_SKIP_CLI: "1"
|
||||
CLAWDBOT_INSTALL_SMOKE_SKIP_IMAGE_BUILD: "1"
|
||||
CLAWDBOT_INSTALL_NONROOT_SKIP_IMAGE_BUILD: ${{ github.event_name == 'pull_request' && '0' || '1' }}
|
||||
CLAWDBOT_INSTALL_SMOKE_SKIP_NONROOT: ${{ github.event_name == 'pull_request' && '1' || '0' }}
|
||||
CLAWDBOT_INSTALL_SMOKE_SKIP_PREVIOUS: "1"
|
||||
run: bash scripts/test-install-sh-docker.sh
|
||||
|
||||
4
.github/workflows/labeler.yml
vendored
4
.github/workflows/labeler.yml
vendored
@@ -19,10 +19,6 @@ on:
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref || github.run_id }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request_target' }}
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
|
||||
86
.github/workflows/macos-release.yml
vendored
86
.github/workflows/macos-release.yml
vendored
@@ -1,86 +0,0 @@
|
||||
name: macOS Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: Existing release tag to validate for macOS release handoff (for example v2026.3.22 or v2026.3.22-beta.1)
|
||||
required: true
|
||||
type: string
|
||||
preflight_only:
|
||||
description: Retained for operator compatibility; this public workflow is validation-only
|
||||
required: true
|
||||
default: true
|
||||
type: boolean
|
||||
|
||||
concurrency:
|
||||
group: macos-release-${{ inputs.tag }}
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
||||
NODE_VERSION: "24.x"
|
||||
PNPM_VERSION: "10.23.0"
|
||||
|
||||
jobs:
|
||||
validate_macos_release_request:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Validate tag input format
|
||||
env:
|
||||
RELEASE_TAG: ${{ inputs.tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-beta\.[1-9][0-9]*)|(-[1-9][0-9]*))?$ ]]; then
|
||||
echo "Invalid release tag format: ${RELEASE_TAG}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Checkout selected tag
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: refs/tags/${{ inputs.tag }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node environment
|
||||
uses: ./.github/actions/setup-node-env
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
pnpm-version: ${{ env.PNPM_VERSION }}
|
||||
install-bun: "false"
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Ensure matching GitHub release exists
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
RELEASE_TAG: ${{ inputs.tag }}
|
||||
run: gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null
|
||||
|
||||
- name: Validate release tag and package metadata
|
||||
env:
|
||||
RELEASE_TAG: ${{ inputs.tag }}
|
||||
RELEASE_MAIN_REF: origin/main
|
||||
run: |
|
||||
set -euo pipefail
|
||||
RELEASE_SHA=$(git rev-parse HEAD)
|
||||
export RELEASE_SHA RELEASE_TAG RELEASE_MAIN_REF
|
||||
git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main
|
||||
pnpm release:openclaw:npm:check
|
||||
|
||||
- name: Summarize next step
|
||||
env:
|
||||
RELEASE_TAG: ${{ inputs.tag }}
|
||||
run: |
|
||||
{
|
||||
echo "## Public macOS validation only"
|
||||
echo
|
||||
echo "This workflow no longer builds, signs, notarizes, or uploads macOS assets."
|
||||
echo
|
||||
echo "Next step:"
|
||||
echo "- Run \`openclaw/releases-private/.github/workflows/openclaw-macos-publish.yml\` with tag \`${RELEASE_TAG}\`."
|
||||
echo "- Use \`preflight_only=true\` there for the full private mac preflight."
|
||||
echo "- For the real publish path, the private run uploads the packaged \`.zip\`, \`.dmg\`, and \`.dSYM.zip\` files to the existing GitHub release in \`openclaw/openclaw\` automatically."
|
||||
echo "- For stable releases, also download \`macos-appcast-${RELEASE_TAG}\` from the successful private run and commit \`appcast.xml\` back to \`main\` in \`openclaw/openclaw\`."
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
128
.github/workflows/openclaw-npm-release.yml
vendored
128
.github/workflows/openclaw-npm-release.yml
vendored
@@ -1,17 +1,15 @@
|
||||
name: OpenClaw NPM Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: Release tag to publish (for example v2026.3.22, v2026.3.22-beta.1, or fallback v2026.3.22-1)
|
||||
description: Release tag to publish (for example v2026.3.14, v2026.3.14-beta.1, or fallback v2026.3.14-1)
|
||||
required: true
|
||||
type: string
|
||||
preflight_only:
|
||||
description: Run validation/build only and skip the gated publish job
|
||||
required: true
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
concurrency:
|
||||
group: openclaw-npm-release-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
|
||||
@@ -23,25 +21,15 @@ env:
|
||||
PNPM_VERSION: "10.23.0"
|
||||
|
||||
jobs:
|
||||
preflight_openclaw_npm:
|
||||
preview_openclaw_npm:
|
||||
if: github.event_name == 'push'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Validate tag input format
|
||||
env:
|
||||
RELEASE_TAG: ${{ inputs.tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*((-beta\.[1-9][0-9]*)|(-[1-9][0-9]*))?$ ]]; then
|
||||
echo "Invalid release tag format: ${RELEASE_TAG}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: refs/tags/${{ inputs.tag }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node environment
|
||||
@@ -52,13 +40,39 @@ jobs:
|
||||
install-bun: "false"
|
||||
use-sticky-disk: "false"
|
||||
|
||||
- name: Validate release tag and package metadata
|
||||
- name: Print release plan
|
||||
env:
|
||||
RELEASE_TAG: ${{ inputs.tag }}
|
||||
RELEASE_MAIN_REF: origin/main
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
RELEASE_SHA=$(git rev-parse HEAD)
|
||||
PACKAGE_VERSION=$(node -p "require('./package.json').version")
|
||||
if [[ "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*-[1-9][0-9]*$ ]]; then
|
||||
TAG_KIND="fallback correction"
|
||||
else
|
||||
TAG_KIND="standard"
|
||||
fi
|
||||
echo "Release plan for ${RELEASE_TAG}:"
|
||||
echo "Resolved release SHA: ${RELEASE_SHA}"
|
||||
echo "Resolved package version: ${PACKAGE_VERSION}"
|
||||
echo "Resolved tag kind: ${TAG_KIND}"
|
||||
if [[ "${TAG_KIND}" == "fallback correction" ]]; then
|
||||
echo "Correction tag note: npm version remains ${PACKAGE_VERSION}"
|
||||
fi
|
||||
echo "Would run: git fetch --no-tags origin +refs/heads/main:refs/remotes/origin/main"
|
||||
echo "Would run with env: RELEASE_SHA=${RELEASE_SHA} RELEASE_TAG=${RELEASE_TAG} RELEASE_MAIN_REF=origin/main pnpm release:openclaw:npm:check"
|
||||
echo "Would run: npm view openclaw@${PACKAGE_VERSION} version"
|
||||
echo "Would run: pnpm check"
|
||||
echo "Would run: pnpm build"
|
||||
echo "Would run: pnpm release:check"
|
||||
|
||||
- name: Validate release tag and package metadata
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
RELEASE_MAIN_REF: origin/main
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
RELEASE_SHA=$(git rev-parse HEAD)
|
||||
export RELEASE_SHA RELEASE_TAG RELEASE_MAIN_REF
|
||||
# Fetch the full main ref so merge-base ancestry checks keep working
|
||||
# for older tagged commits that are still contained in main.
|
||||
@@ -67,51 +81,52 @@ jobs:
|
||||
|
||||
- name: Ensure version is not already published
|
||||
env:
|
||||
PREFLIGHT_ONLY: ${{ inputs.preflight_only }}
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
set -euxo pipefail
|
||||
PACKAGE_VERSION=$(node -p "require('./package.json').version")
|
||||
IS_CORRECTION_TAG=0
|
||||
if [[ "${RELEASE_TAG}" =~ ^v[0-9]{4}\.[1-9][0-9]*\.[1-9][0-9]*-[1-9][0-9]*$ ]]; then
|
||||
IS_CORRECTION_TAG=1
|
||||
fi
|
||||
|
||||
if npm view "openclaw@${PACKAGE_VERSION}" version >/dev/null 2>&1; then
|
||||
if [[ "${PREFLIGHT_ONLY}" == "true" ]]; then
|
||||
echo "openclaw@${PACKAGE_VERSION} is already published on npm; continuing because preflight_only=true."
|
||||
if [[ "${IS_CORRECTION_TAG}" == "1" ]]; then
|
||||
echo "openclaw@${PACKAGE_VERSION} is already published on npm."
|
||||
echo "Correction tag ${RELEASE_TAG} is allowed as a fallback release tag, so preview will continue without treating this as an error."
|
||||
exit 0
|
||||
fi
|
||||
echo "openclaw@${PACKAGE_VERSION} is already published on npm."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Publishing openclaw@${PACKAGE_VERSION}"
|
||||
|
||||
- name: Check
|
||||
run: pnpm check
|
||||
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
|
||||
- name: Verify release contents
|
||||
run: pnpm release:check
|
||||
|
||||
validate_publish_dispatch_ref:
|
||||
if: ${{ !inputs.preflight_only }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Require main workflow ref for publish
|
||||
env:
|
||||
WORKFLOW_REF: ${{ github.ref }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ "${WORKFLOW_REF}" != "refs/heads/main" ]]; then
|
||||
echo "Real publish runs must be dispatched from main. Use preflight_only=true for branch validation."
|
||||
exit 1
|
||||
if [[ "${IS_CORRECTION_TAG}" == "1" ]]; then
|
||||
echo "Previewing fallback correction tag ${RELEASE_TAG} for npm version openclaw@${PACKAGE_VERSION}"
|
||||
else
|
||||
echo "Previewing openclaw@${PACKAGE_VERSION}"
|
||||
fi
|
||||
|
||||
- name: Check
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
pnpm check
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
pnpm build
|
||||
|
||||
- name: Verify release contents
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
pnpm release:check
|
||||
|
||||
- name: Preview publish command
|
||||
run: bash scripts/openclaw-npm-publish.sh --dry-run
|
||||
|
||||
publish_openclaw_npm:
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
# npm trusted publishing + provenance requires a GitHub-hosted runner.
|
||||
needs: [preflight_openclaw_npm, validate_publish_dispatch_ref]
|
||||
if: ${{ !inputs.preflight_only }}
|
||||
runs-on: ubuntu-latest
|
||||
environment: npm-release
|
||||
permissions:
|
||||
@@ -167,5 +182,14 @@ jobs:
|
||||
|
||||
echo "Publishing openclaw@${PACKAGE_VERSION}"
|
||||
|
||||
- name: Check
|
||||
run: pnpm check
|
||||
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
|
||||
- name: Verify release contents
|
||||
run: pnpm release:check
|
||||
|
||||
- name: Publish
|
||||
run: bash scripts/openclaw-npm-publish.sh --publish
|
||||
|
||||
2
.github/workflows/sandbox-common-smoke.yml
vendored
2
.github/workflows/sandbox-common-smoke.yml
vendored
@@ -15,7 +15,7 @@ on:
|
||||
- scripts/sandbox-common-setup.sh
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
group: sandbox-common-smoke-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
env:
|
||||
|
||||
5
.github/workflows/workflow-sanity.yml
vendored
5
.github/workflows/workflow-sanity.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
group: workflow-sanity-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
env:
|
||||
@@ -72,9 +72,6 @@ jobs:
|
||||
- name: Disallow direct inputs interpolation in composite run blocks
|
||||
run: python3 scripts/check-composite-action-input-interpolation.py
|
||||
|
||||
- name: Disallow tracked merge conflict markers
|
||||
run: node scripts/check-no-conflict-markers.mjs
|
||||
|
||||
generated-doc-baselines:
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
runs-on: blacksmith-16vcpu-ubuntu-2404
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
- Tests: colocated `*.test.ts`.
|
||||
- Docs: `docs/` (images, queue, Pi config). Built output lives in `dist/`.
|
||||
- Nomenclature: use "plugin" / "plugins" in docs, UI, changelogs, and contributor guidance. `extensions/*` remains the internal directory/package path to avoid repo-wide churn from a rename.
|
||||
- Bundled plugin naming: for repo-owned workspace plugins, keep the canonical plugin id aligned across `openclaw.plugin.json:id`, `extensions/<id>` by default, and package names anchored to the same id (`@openclaw/<id>` or approved suffix forms like `-provider`, `-plugin`, `-speech`, `-sandbox`, `-media-understanding`). Keep `openclaw.install.npmSpec` equal to the package name and `openclaw.channel.id` equal to the plugin id when present. Exceptions must be explicit and covered by the repo invariant test.
|
||||
- Plugins: live under `extensions/*` (workspace packages). Keep plugin-only deps in the extension `package.json`; do not add them to the root `package.json` unless core uses them.
|
||||
- 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.
|
||||
@@ -29,7 +28,7 @@
|
||||
- For docs, UI copy, and picker lists, order services/providers alphabetically unless the section is explicitly describing runtime behavior (for example auto-detection or execution order).
|
||||
- Section cross-references: use anchors on root-relative paths (example: `[Hooks](/configuration#hooks)`).
|
||||
- Doc headings and anchors: avoid em dashes and apostrophes in headings because they break Mintlify anchor links.
|
||||
- When the user asks for links, reply with full `https://docs.openclaw.ai/...` URLs (not root-relative).
|
||||
- When Peter asks for links, reply with full `https://docs.openclaw.ai/...` URLs (not root-relative).
|
||||
- When you touch docs, end the reply with the `https://docs.openclaw.ai/...` URLs you referenced.
|
||||
- README (GitHub): keep absolute docs URLs (`https://docs.openclaw.ai/...`) so links work on GitHub.
|
||||
- Docs content must be generic: no personal device names/hostnames/paths; use placeholders like `user@gateway-host` and “gateway host”.
|
||||
@@ -113,15 +112,13 @@
|
||||
|
||||
- Framework: Vitest with V8 coverage thresholds (70% lines/branches/functions/statements).
|
||||
- Naming: match source names with `*.test.ts`; e2e in `*.e2e.test.ts`.
|
||||
- When tests need example Anthropic/OpenAI model constants, prefer `sonnet-4.6` and `gpt-5.4`; update older Anthropic/GPT examples when you touch those tests.
|
||||
- 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.
|
||||
- Do not reintroduce Vitest VM pools by default without fresh green evidence on current `main`; keep CI on `forks`.
|
||||
- Do not switch CI `pnpm test` lanes back to Vitest `vmForks` by default without fresh green evidence on current `main`; keep CI on `forks` unless explicitly re-validated.
|
||||
- If local Vitest runs cause memory pressure (common on non-Mac-Studio hosts), use `OPENCLAW_TEST_PROFILE=low OPENCLAW_TEST_SERIAL_GATEWAY=1 pnpm test` for land/gate runs.
|
||||
- Live tests (real keys): `OPENCLAW_LIVE_TEST=1 pnpm test:live` (OpenClaw-only) or `LIVE=1 pnpm test:live` (includes provider live tests). Docker: `pnpm test:docker:live-models`, `pnpm test:docker:live-gateway`. Onboarding Docker E2E: `pnpm test:docker:onboard`.
|
||||
- Live tests (real keys): `CLAWDBOT_LIVE_TEST=1 pnpm test:live` (OpenClaw-only) or `LIVE=1 pnpm test:live` (includes provider live tests). Docker: `pnpm test:docker:live-models`, `pnpm test:docker:live-gateway`. Onboarding Docker E2E: `pnpm test:docker:onboard`.
|
||||
- Full kit + what’s covered: `docs/help/testing.md`.
|
||||
- Changelog: user-facing changes only; no internal/meta notes (version alignment, appcast reminders, release process).
|
||||
- Changelog placement: in the active version block, append new entries to the end of the target section (`### Changes` or `### Fixes`); do not insert new entries at the top of a section.
|
||||
|
||||
490
CHANGELOG.md
490
CHANGELOG.md
@@ -4,347 +4,103 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Breaking
|
||||
|
||||
### Changes
|
||||
|
||||
### Fixes
|
||||
|
||||
## 2026.3.24-beta.1
|
||||
|
||||
### Breaking
|
||||
|
||||
### Changes
|
||||
|
||||
- Gateway/OpenAI compatibility: add `/v1/models` and `/v1/embeddings`, and forward explicit model overrides through `/v1/chat/completions` and `/v1/responses` for broader client and RAG compatibility. Thanks @vincentkoc.
|
||||
- Agents/tools: make `/tools` show the tools the current agent can actually use right now, add a compact default view with an optional detailed mode, and add a live “Available Right Now” section in the Control UI so it is easier to see what will work before you ask.
|
||||
- Microsoft Teams: migrate to the official Teams SDK and add AI-agent UX best practices including streaming 1:1 replies, welcome cards with prompt starters, feedback/reflection, informative status updates, typing indicators, and native AI labeling. (#51808)
|
||||
- Microsoft Teams: add message edit and delete support for sent messages, including in-thread fallbacks when no explicit target is provided. (#49925)
|
||||
- Skills/install metadata: add one-click install recipes to bundled skills (coding-agent, gh-issues, openai-whisper-api, session-logs, tmux, trello, weather) so the CLI and Control UI can offer dependency installation when requirements are missing. (#53411) Thanks @BunsDev.
|
||||
- Control UI/skills: add status-filter tabs (All / Ready / Needs Setup / Disabled) with counts, replace inline skill cards with a click-to-detail dialog showing requirements, toggle switch, install action, API key entry, source metadata, and homepage link. (#53411) Thanks @BunsDev.
|
||||
- Slack/interactive replies: restore rich reply parity for direct deliveries, auto-render simple trailing `Options:` lines as buttons/selects, improve Slack interactive setup defaults, and isolate reply controls from plugin interactive handlers. (#53389) Thanks @vincentkoc.
|
||||
- CLI/containers: add `--container` and `OPENCLAW_CONTAINER` to run `openclaw` commands inside a running Docker or Podman OpenClaw container. (#52651) Thanks @sallyom.
|
||||
- Discord/auto threads: add optional `autoThreadName: "generated"` naming so new auto-created threads can be renamed asynchronously with concise LLM-generated titles while keeping the existing message-based naming as the default. (#43366) Thanks @davidguttman.
|
||||
- Plugins/hooks: add `before_dispatch` with canonical inbound metadata and route handled replies through the normal final-delivery path, preserving TTS and routed delivery semantics. (#50444) Thanks @gfzhx.
|
||||
- Control UI/agents: convert agent workspace file rows to expandable `<details>` with lazy-loaded inline markdown preview, and add comprehensive `.sidebar-markdown` styles for headings, lists, code blocks, tables, blockquotes, and details/summary elements. (#53411) Thanks @BunsDev.
|
||||
- Control UI/markdown preview: restyle the agent workspace file preview dialog with a frosted backdrop, sized panel, and styled header, and integrate `@create-markdown/preview` v2 system theme for rich markdown rendering (headings, tables, code blocks, callouts, blockquotes) that auto-adapts to the app's light/dark design tokens. (#53411) Thanks @BunsDev.
|
||||
- macOS app/config: replace horizontal pill-based subsection navigation with a collapsible tree sidebar using disclosure chevrons and indented subsection rows. (#53411) Thanks @BunsDev.
|
||||
- CLI/skills: soften missing-requirements label from "missing" to "needs setup" and surface API key setup guidance (where to get a key, CLI save command, storage path) in `openclaw skills info` output. (#53411) Thanks @BunsDev.
|
||||
- macOS app/skills: add "Get your key" homepage link and storage-path hint to the API key editor dialog, and show the config path in save confirmation messages. (#53411) Thanks @BunsDev.
|
||||
- Control UI/agents: add a "Not set" placeholder to the default agent model selector dropdown. (#53411) Thanks @BunsDev.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Security/sandbox media dispatch: close the `mediaUrl`/`fileUrl` alias bypass so outbound tool and message actions cannot escape media-root restrictions. (#54034)
|
||||
- Gateway/restart sentinel: wake the interrupted agent session via heartbeat after restart instead of only sending a best-effort restart note, retry outbound delivery once on transient failure, and preserve explicit thread/topic routing through the wake path so replies land in the correct Telegram topic or Slack thread. (#53940) Thanks @VACInc.
|
||||
- Docker/setup: avoid the pre-start `openclaw-cli` shared-network namespace loop by routing setup-time onboard/config writes through `openclaw-gateway`, so fresh Docker installs stop failing before the gateway comes up. (#53385) Thanks @amsminn.
|
||||
- Gateway/channels: keep channel startup sequential while isolating per-channel boot failures, so one broken channel no longer blocks later channels from starting. (#54215) Thanks @JonathanJing.
|
||||
- Embedded runs/secrets: stop unresolved `SecretRef` config from crashing embedded agent runs by falling back to the resolved runtime snapshot when needed. Fixes #45838.
|
||||
- WhatsApp/groups: track recent gateway-sent message IDs and suppress only matching group echoes, preserving owner `/status`, `/new`, and `/activation` commands from linked-account `fromMe` traffic. (#53624) Thanks @w-sss.
|
||||
- WhatsApp/reply-to-bot detection: restore implicit group reply detection by unwrapping `botInvokeMessage` payloads and reading `selfLid` from `creds.json`, so reply-based mentions reach the bot again in linked-account group chats.
|
||||
- Telegram/forum topics: recover `#General` topic `1` routing when Telegram omits forum metadata, including native commands, interactive callbacks, inbound message context, and fallback error replies. (#53699) thanks @huntharo
|
||||
- Discord/gateway supervision: centralize gateway error handling behind a lifetime-owned supervisor so early, active, and late-teardown Carbon gateway errors stay classified consistently and stop surfacing as process-killing teardown crashes.
|
||||
- Discord/timeouts: send a visible timeout reply when the inbound Discord worker times out before a final reply starts, including created auto-thread targets and queued-run ordering. (#53823) Thanks @Kimbo7870.
|
||||
- ACP/direct chats: always deliver a terminal ACP result when final TTS does not yield audio, even if block text already streamed earlier, and skip redundant empty-text final synthesis. (#53692) Thanks @w-sss.
|
||||
- Telegram/outbound errors: preserve actionable 403 membership/block/kick details and treat `bot not a member` as a permanent delivery failure so Telegram sends stop retrying doomed chats. (#53635) Thanks @w-sss.
|
||||
- Telegram/photos: preflight Telegram photo dimension and aspect-ratio rules, and fall back to document sends when image metadata is invalid or unavailable so photo uploads stop failing with `PHOTO_INVALID_DIMENSIONS`. (#52545) Thanks @hnshah.
|
||||
- Slack/runtime defaults: trim Slack DM reply overhead, restore Codex auto transport, and tighten Slack/web-search runtime defaults around DM preview threading, cache scoping, warning dedupe, and explicit web-search opt-in. (#53957) Thanks @vincentkoc.
|
||||
- Doctor/image generation: seed migrated legacy Nano Banana Google provider config with the `/v1beta` API root and an empty model list so `openclaw doctor --fix` completes and the migrated native Google image path keeps hitting the correct endpoint. (#53757) Thanks @mahopan.
|
||||
- Models/google: normalize bare Google Generative AI API roots for custom provider names, and keep built-in Google model-id rewrites working when `api` is declared only on individual models, so custom Google lanes and older configs stop missing `/v1beta` or preview-id normalization. (#44969) Thanks @Kathie-yu.
|
||||
- Feishu/startup: treat unresolved `SecretRef` app credentials as not configured during account resolution so CLI startup and read-only Feishu config surfaces stop crashing before runtime-backed secret resolution is available. (#53675) Thanks @hpt.
|
||||
- Feishu/groups: when `groupPolicy` is `open`, stop implicitly requiring @mentions for unset `requireMention`, so image, file, audio, and other non-text group messages reach the bot unless operators explicitly keep mention gating on. (#54058) Thanks @byungsker.
|
||||
- Feishu/startup: keep `requireMention` enforcement strict when bot identity startup probes fail, raise the startup bot-info timeout to 30s, and add cancellable background identity recovery so mention-gated groups recover without noisy fallback. (#43788) Thanks @lefarcen.
|
||||
- Feishu/MSTeams message tool: keep provider-native `card` payloads optional in merged tool schemas so media-only sends stop failing validation before channel runtime dispatch. (#53715) Thanks @lndyzwdxhs.
|
||||
- Feishu/docx block ordering: preserve the document tree order from `docx.document.convert` when inserting blocks, fixing heading/paragraph/list misordering in newly written Feishu documents. (#40524) Thanks @TaoXieSZ.
|
||||
- Telegram/native commands: run native slash-command execution against the resolved runtime snapshot so DM commands still reply when fresh config reads surface unresolved SecretRefs. (#53179) Thanks @nimbleenigma.
|
||||
- Gateway/ports: parse Docker Compose-style `OPENCLAW_GATEWAY_PORT` host publish values correctly without reviving the legacy `CLAWDBOT_GATEWAY_PORT` override. (#44083) Thanks @bebule.
|
||||
- Plugins/memory-lancedb: bootstrap the env-configured HTTP/HTTPS proxy dispatcher before OpenAI embeddings requests so memory capture and recall work in proxy-required environments again. (#54119) Thanks @neeravmakwana.
|
||||
- Runtime/build: stabilize long-lived lazy `dist` runtime entry paths and harden bundled plugin npm staging so local rebuilds stop breaking on missing hashed chunks or broken shell `npm` shims. (#53855) Thanks @vincentkoc.
|
||||
- Security/skills: validate skill installer metadata against strict regex allowlists per package manager, sanitize skill metadata for terminal output, add URL protocol allowlisting in markdown preview and skill homepage links, warn on non-bundled skill install sources, and remove unsafe `file://` workspace links. (#53471) Thanks @BunsDev.
|
||||
- Memory/builtin sqlite: cut redundant sync and status query churn by snapshotting file state once per source, reusing sync statements, and consolidating status aggregation reads, which reduces builtin memory overhead on sync/status/doctor-style paths. Thanks @vincentkoc.
|
||||
- TUI/chat: preserve pending user messages when a slow local run emits an empty final event, but still defer and flush the needed history reload after the newer active run finishes so silent/tool-only runs do not stay incomplete. (#53130) Thanks @joelnishanth.
|
||||
- DeepSeek/pricing: replace the zero-cost DeepSeek catalog rates with the current DeepSeek V3.2 pricing so usage totals stop showing `$0.00` for DeepSeek sessions. (#54143) Thanks @arkyu2077.
|
||||
- CLI/logging: make pretty log timestamps always include an explicit timezone offset in default UTC and `--local-time` modes, so incident triage no longer mixes ambiguous clock displays. (#38904) Thanks @sahilsatralkar.
|
||||
- Browser/default detection: recognize macOS LaunchServices Edge bundle ids so default Chromium detection stops falling back to Chrome when Edge is the system default. (#48561) Thanks @zoherghadyali.
|
||||
- CLI/Telegram topics: route `message thread create` through Telegram `topic-create` with the required topic `name` field so Telegram forum topic creation works from the CLI again. (#54336) Thanks @andyliu.
|
||||
- Telegram/pairing: render pairing codes and approval commands as Telegram-only code blocks while keeping shared pairing replies plain text for other channels. (#52784) Thanks @sumukhj1219.
|
||||
- Agents/cron: suppress the default heartbeat system prompt for cron-triggered embedded runs even when they target non-cron session keys, so cron tasks stop reading `HEARTBEAT.md` and polluting unrelated threads. (#53152) Thanks @Protocol-zero-0.
|
||||
- Agents/cron: mark best-effort announce runs as not delivered when any payload fails, and log those partial delivery failures instead of silently reporting success. (#42535) Thanks @MoerAI.
|
||||
- Plugins: enforce terminal hook decision semantics for tool/message guards (#54241) Thanks @joshavant.
|
||||
- Marketplace/agents: correct the ClawHub skill URL in agent docs and stream marketplace archive downloads to disk so installs avoid excess memory use and fail cleanly on empty responses. (#54160) Thanks @QuinnH496.
|
||||
- Discord/config types: add missing `autoArchiveDuration` to `DiscordGuildChannelConfig` so TypeScript config definitions match the existing schema and runtime support. (#43427) Thanks @davidguttman.
|
||||
- Docs/IRC: fix five `json55` code-fence typos in the IRC channel examples so Mintlify applies JSON5 syntax highlighting correctly. (#50842) Thanks @Hollychou924.
|
||||
|
||||
## 2026.3.23
|
||||
|
||||
### Breaking
|
||||
|
||||
### Changes
|
||||
|
||||
- ModelStudio/Qwen: add standard (pay-as-you-go) DashScope endpoints for China and global Qwen API keys alongside the existing Coding Plan endpoints, and relabel the provider group to `Qwen (Alibaba Cloud Model Studio)`. (#43878)
|
||||
- UI/clarity: consolidate button primitives (`btn--icon`, `btn--ghost`, `btn--xs`), refine the Knot theme to a black-and-red palette with WCAG 2.1 AA contrast, add config icons for Diagnostics/CLI/Secrets/ACP/MCP sections, replace the roundness slider with discrete stops, and improve accessibility with aria-labels across usage filters. (#53272) Thanks @BunsDev.
|
||||
- CSP/Control UI: compute SHA-256 hashes for inline `<script>` blocks in the served `index.html` and include them in the `script-src` CSP directive, keeping inline scripts blocked by default while allowing explicitly hashed bootstrap code. (#53307) Thanks @BunsDev.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Plugins/bundled runtimes: ship bundled plugin runtime sidecars like WhatsApp `light-runtime-api.js`, Matrix `runtime-api.js`, and other plugin runtime entry files in the npm package again, so global installs stop failing on missing bundled plugin runtime surfaces.
|
||||
- CLI/channel auth: auto-select the single configured login-capable channel for `channels login`/`logout`, harden channel ids against prototype-chain and control-character abuse, and fall back cleanly to catalog-backed channel installs, so channel auth works again for single-channel setups and on-demand channel installs. (#53254) Thanks @BunsDev.
|
||||
- Auth/OpenAI tokens: stop live gateway auth-profile writes from reverting freshly saved credentials back to stale in-memory values, and make `models auth paste-token` write to the resolved agent store, so Configure, Onboard, and token-paste flows stop snapping back to expired OpenAI tokens. Fixes #53207. Related to #45516.
|
||||
- Control UI/auth: preserve operator scopes through the device-auth bypass path, ignore cached under-scoped operator tokens, and show a clear `operator.read` fallback message when a connection really lacks read scope, so operator sessions stop failing or blanking on read-backed pages. (#53110) Thanks @BunsDev.
|
||||
- Plugins/ClawHub: resolve plugin API compatibility against the active runtime version at install time, and add regression coverage for current `>=2026.3.22` ClawHub package checks so installs no longer fail behind the stale `1.2.0` constant. (#53157) Thanks @futhgar.
|
||||
- Plugins/uninstall: accept installed `clawhub:` specs and versionless ClawHub package names as uninstall targets, so `openclaw plugins uninstall clawhub:<package>` works again even when the recorded install was pinned to a version.
|
||||
- Browser/Chrome MCP: wait for existing-session browser tabs to become usable after attach instead of treating the initial Chrome MCP handshake as ready, which reduces user-profile timeouts and repeated consent churn on macOS Chrome attach flows. Fixes #52930. Thanks @vincentkoc.
|
||||
- Browser/CDP: reuse an already-running loopback browser after a short initial reachability miss instead of immediately falling back to relaunch detection, which fixes second-run browser start/open regressions on slower headless Linux setups. Fixes #53004. Thanks @vincentkoc.
|
||||
- Agents/web_search: use the active runtime `web_search` provider instead of stale/default selection, so agent turns keep hitting the provider you actually configured. Fixes #53020. Thanks @jzakirov.
|
||||
- Mistral/models: lower bundled Mistral max-token defaults to safe output budgets and teach `openclaw doctor --fix` to repair old persisted Mistral provider configs that still carry context-sized output limits, avoiding deterministic Mistral 422 rejects on fresh and existing setups. Fixes #52599. Thanks @vincentkoc.
|
||||
- ClawHub/macOS auth: honor macOS auth config and XDG auth paths for saved ClawHub credentials, so `openclaw skills ...` and gateway skill browsing keep using the signed-in auth state instead of silently falling back to unauthenticated mode. Fixes #53034.
|
||||
- ClawHub/macOS: read the local ClawHub login from the macOS Application Support path and still honor XDG config on macOS, so skill browsing uses the logged-in token on both default and XDG-style setups. Fixes #52949. Thanks @scoootscooob.
|
||||
- ClawHub/skills: resolve the local ClawHub auth token for gateway skill browsing and switch browse-all requests to search so ClawControl stops falling into unauthenticated 429s and empty authenticated skill lists. Fixes #52949. Thanks @vincentkoc.
|
||||
- Config/warnings: suppress the confusing “newer OpenClaw” warning when a config written by a same-base correction release like `2026.3.23-2` is read by `2026.3.23`, while still warning for truly newer or incompatible versions.
|
||||
- CLI/cron: make `openclaw cron add|edit --at ... --tz <iana>` honor the requested local wall-clock time for offset-less one-shot datetimes, including DST boundaries, and keep `--tz` rejected for `--every`. (#53224) Thanks @RolfHegr.
|
||||
- Commands/auth: stop slash-command authorization from crashing or dropping valid allowlists when channel `allowFrom` resolution hits unresolved SecretRef-backed accounts, and fail closed only for the affected provider inference path. (#52791) Thanks @Lukavyi.
|
||||
- Agents/failover: classify generic `api_error` payloads as retryable only when they include transient failure signals, so MiniMax-style backend failures still trigger model fallback without misclassifying billing, auth, or format/context errors. (#49611) Thanks @ayushozha.
|
||||
- LINE/runtime-api: pre-export overlapping runtime symbols before the `line-runtime` star export so jiti no longer throws `TypeError: Cannot redefine property` on startup. (#53221) Thanks @Drickon.
|
||||
- Telegram/threading: populate `currentThreadTs` in the threading tool-context fallback for Telegram DM topics so thread-aware tools still receive the active topic context when the main thread metadata is missing. (#52217)
|
||||
- Diagnostics/cache trace: strip credential fields from cache-trace JSONL output while preserving non-sensitive diagnostic fields and image redaction metadata.
|
||||
- Docs/Feishu: replace `botName` with `name` in the channel config examples so the docs match the strict account schema for per-account display names. (#52753) Thanks @haroldfabla2-hue.
|
||||
- Doctor/plugins: make `openclaw doctor --fix` remove stale `plugins.allow` and `plugins.entries` refs left behind after plugin removal. Thanks @sallyom
|
||||
- Agents/replay: canonicalize malformed assistant transcript content before session-history sanitization so legacy or corrupted assistant turns stop crashing Pi replay and subagent recovery paths.
|
||||
- ClawHub/skills: keep updating already-tracked legacy Unicode slugs after the ASCII-only slug hardening, so older installs do not get stuck behind `Invalid skill slug` errors during `openclaw skills update`. (#53206) Thanks @drobison00.
|
||||
- Infra/exec trust: preserve shell-multiplexer wrapper binaries for policy checks without breaking approved-command reconstruction, so BusyBox/ToyBox allowlist and audit flows bind to the real wrapper while execution plans stay coherent. (#53134) Thanks @vincentkoc.
|
||||
- Plugins/message tool: make Discord `components` and Slack `blocks` optional again, and route Feishu `message(..., media=...)` sends through the outbound media path, so pin/unpin/react flows stop failing schema validation and Feishu file/image attachments actually send. Fixes #52970 and #52962. Thanks @vincentkoc.
|
||||
- Gateway/model pricing: stop `openrouter/auto` pricing refresh from recursing indefinitely during bootstrap, so OpenRouter auto routes can populate cached pricing and `usage.cost` again. Fixes #53035. Thanks @vincentkoc.
|
||||
- Models/OpenAI Codex OAuth: bootstrap the env-configured HTTP/HTTPS proxy dispatcher on the stored-credential refresh path before token renewal runs, so expired Codex OAuth profiles can refresh successfully in proxy-required environments instead of locking users out after the first token expiry.
|
||||
- Models/OpenAI Codex OAuth and Plugins/MiniMax OAuth: ensure env-configured HTTP/HTTPS proxy dispatchers are initialized before OAuth preflight and token exchange requests so proxy-required environments can complete MiniMax and OpenAI Codex sign-in flows again. (#52228; fixes #51619, #51569) Thanks @openperf.
|
||||
- Plugins/memory-lancedb: bootstrap LanceDB into plugin runtime state on first use when the bundled npm install does not already have it, so `plugins.slots.memory="memory-lancedb"` works again after global npm installs without moving LanceDB into OpenClaw core dependencies. Fixes #26100.
|
||||
- Config/plugins: treat stale unknown `plugins.allow` ids as warnings instead of fatal config errors, so recovery commands like `plugins install`, `doctor --fix`, and `status` still run when a plugin is missing locally. Fixes #52992. Thanks @vincentkoc.
|
||||
- Doctor/WhatsApp: stop auto-enable from appending built-in channel ids like `whatsapp` to `plugins.allow`, so `openclaw doctor --fix` no longer writes schema-invalid plugin allowlist entries when repairing built-in channels. Fixes #52931. Thanks @vincentkoc.
|
||||
- Telegram/auto-reply: preserve same-chat inbound debounce order without stranding stale busy-session followups, and keep same-key overflow turns ordered when tracked debounce keys are saturated. (#52998) Thanks @osolmaz.
|
||||
- Telegram/message tool: add `asDocument` as a user-facing alias for `forceDocument` on image and GIF sends, while preserving explicit `forceDocument` precedence when both flags are present. (#52461) Thanks @bakhtiersizhaev.
|
||||
- Discord/commands: return an explicit unauthorized reply for privileged native slash commands instead of falling through to Discord's misleading generic completion when auth gates reject the sender. Fixes #53041. Thanks @scoootscooob.
|
||||
- Channels/catalog: let external channel catalogs override shipped fallback metadata and honor overridden npm specs during channel setup, so custom channel catalogs no longer fall back to bundled packages when a channel id matches. (#52988)
|
||||
- Voice-call/Plivo: stabilize Plivo v2 replay keys so webhook retries and replay protection stop colliding on valid follow-up deliveries.
|
||||
- Agents/skills: prefer the active resolved runtime snapshot for embedded skill config and env injection, so `skills.entries.<skill>.apiKey` SecretRefs resolve correctly during embedded startup instead of failing on raw source config. Fixes #53098. Thanks @vincentkoc.
|
||||
- Agents/subagents: recheck timed-out worker waits against the latest runtime snapshot before sending completion events, so fast-finishing workers stop being reported as timed out when they actually succeeded. Fixes #53106. Thanks @vincentkoc.
|
||||
- Agents/Anthropic: preserve latest assistant thinking and redacted-thinking block ordering during transcript image sanitization so follow-up turns do not trip Anthropic's unmodified-thinking validation. (#52961) Thanks @vincentkoc.
|
||||
- Plugins/DeepSeek: refactor the bundled DeepSeek provider onto the shared single-provider plugin entry, move its coverage into the extension test lane, and keep bundled auth env-var metadata on the generated manifest path. (#48762) Thanks @07akioni.
|
||||
- Plugins/Matrix: avoid duplicate `resolveMatrixAccountStringValues` runtime-api exports under Jiti so bundled Matrix installs no longer crash at startup with `Cannot redefine property: resolveMatrixAccountStringValues`. Fixes #52909 and #52891. Thanks @vincentkoc.
|
||||
- Security/exec approvals: keep shell-wrapper positional-argv allowlist matching on real direct carriers only by rejecting single-quoted `$0`/`$n` tokens, disallowing newline-separated `exec`, and still accepting `exec --` carrier forms. Thanks @vincentkoc.
|
||||
- Gateway/probe: stop successful gateway handshakes from timing out as unreachable while post-connect detail RPCs are still loading, so slow devices report a reachable RPC failure instead of a false negative dead gateway. Fixes #52927. Thanks @vincentkoc.
|
||||
- Gateway/supervision: stop lock conflicts from crash-looping under launchd and systemd by keeping the duplicate process in a retry wait instead of exiting as a failure while another healthy gateway still owns the lock. Fixes #52922. Thanks @vincentkoc.
|
||||
- Gateway/auth: require auth for canvas routes and admin scope for agent session reset, so anonymous canvas access and non-admin reset requests fail closed.
|
||||
- Release/install: keep previously released bundled plugins and Control UI assets in published openclaw npm installs, and fail release checks when those shipped artifacts are missing. Thanks @vincentkoc.
|
||||
- WhatsApp/outbound sends: keep the active Web listener on a direct process-global symbol so split runtime chunks keep sharing the connected Baileys session and `openclaw message send --channel whatsapp` stops failing after connect. Fixes #52574. Thanks @MonkeyLeeT.
|
||||
- Agents/process: fail loud when `send-keys` tries cursor-sensitive keys before a background PTY reports its cursor mode, so startup races no longer silently send the wrong arrow/Home/End sequences. (#51490) Thanks @liuy.
|
||||
|
||||
## 2026.3.22
|
||||
|
||||
### Breaking
|
||||
|
||||
- Plugins/install: 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. Docs: https://docs.openclaw.ai/tools/clawhub
|
||||
- Browser/Chrome MCP: remove the legacy Chrome extension relay path, bundled extension assets, `driver: "extension"`, and `browser.relayBindHost`. Run `openclaw doctor --fix` to migrate host-local browser config to `existing-session` / `user`; Docker, headless, sandbox, and remote browser flows still use raw CDP. Docs: https://docs.openclaw.ai/gateway/doctor and https://docs.openclaw.ai/tools/browser (#47893) Thanks @vincentkoc.
|
||||
- Tools/image generation: standardize the stock image create/edit path on the core `image_generate` tool. The old `nano-banana-pro` docs/examples are gone; if you previously copied that sample-skill config, switch to `agents.defaults.imageGenerationModel` for built-in image generation or install a separate third-party skill explicitly.
|
||||
- Skills/image generation: remove the bundled `nano-banana-pro` skill wrapper. Use `agents.defaults.imageGenerationModel.primary: "google/gemini-3-pro-image-preview"` for the native Nano Banana-style path instead.
|
||||
- Plugins/SDK: the new public plugin SDK surface is `openclaw/plugin-sdk/*`; `openclaw/extension-api` is removed with no compatibility shim. Bundled plugins must use injected runtime for host-side operations (for example `api.runtime.agent.runEmbeddedPiAgent`) and any remaining direct imports must come from narrow `openclaw/plugin-sdk/*` subpaths instead of the monolithic SDK root. Docs: https://docs.openclaw.ai/plugins/sdk-migration and https://docs.openclaw.ai/plugins/sdk-overview
|
||||
- Plugins/message discovery: require `ChannelMessageActionAdapter.describeMessageTool(...)` for shared `message` tool discovery. The legacy `listActions`, `getCapabilities`, and `getToolSchema` adapter methods are removed. Plugin authors should migrate message discovery to `describeMessageTool(...)` and keep channel-specific action runtime code inside the owning plugin package. Thanks @gumadeiras.
|
||||
- Plugins/Matrix: add a new Matrix plugin backed by the official `matrix-js-sdk`. If you are upgrading from the previous public Matrix plugin, follow the migration guide: https://docs.openclaw.ai/install/migrating-matrix Thanks @gumadeiras.
|
||||
- Config/env: remove legacy `CLAWDBOT_*` and `MOLTBOT_*` compatibility env names across runtime, installers, and test tooling. Use the matching `OPENCLAW_*` env names instead.
|
||||
- Config/state: remove legacy `.moltbot` state-dir and `moltbot.json` auto-detection/migration fallback. If you still keep state under `~/.moltbot`, move it to `~/.openclaw` or set `OPENCLAW_STATE_DIR` / `OPENCLAW_CONFIG_PATH` explicitly. Docs: https://docs.openclaw.ai/install/migrating and https://docs.openclaw.ai/start/getting-started
|
||||
- Exec/env sandbox: block build-tool JVM injection (`MAVEN_OPTS`, `SBT_OPTS`, `GRADLE_OPTS`, `ANT_OPTS`), glibc tunable exploitation (`GLIBC_TUNABLES`), and .NET dependency resolution hijack (`DOTNET_ADDITIONAL_DEPS`) from the host exec environment, and restrict Gradle init script redirect (`GRADLE_USER_HOME`) as an override-only block so user-configured Gradle homes still propagate. (#49702)
|
||||
- Discord/commands: switch native command deployment to Carbon reconcile by default so Discord restarts stop churning slash commands through OpenClaw’s local deploy path. (#46597) Thanks @huntharo and @thewilloftheshadow.
|
||||
- Security/exec approvals: treat `time` as a transparent dispatch wrapper during allowlist evaluation and allow-always persistence so approved `time ...` commands bind the inner executable instead of the wrapper path. Thanks @YLChen-007 for reporting.
|
||||
- Voice-call/webhooks: reject missing provider signature headers before body reads, drop the pre-auth body budget to `64 KB` / `5s`, and cap concurrent pre-auth requests per source IP so unauthenticated callers cannot force the old `1 MB` / `30s` buffering path. Thanks @SEORY0 for reporting.
|
||||
- Plugins/Matrix: stop mention-gated or otherwise dropped room chatter from refreshing focused thread bindings before the message is actually routed, so idle ACP and session bindings can still expire normally in mention-required rooms. Thanks @vincentkoc, @dinakars777 and @mvanhorn.
|
||||
- Plugins/Matrix: durably dedupe inbound room events across gateway restarts so previously handled Matrix messages are not replayed as new, while preserving clean-restart backlog delivery for unseen events. (#50922) thanks @gumadeiras
|
||||
- Agents/media replies: migrate the remaining browser, canvas, and nodes snapshot outputs onto `details.media` so generated media keeps attaching to assistant replies after the collect-then-attach refactor. (#51731) Thanks @christianklotz.
|
||||
- Android/contacts search: escape literal `%` and `_` in contact-name queries so searches like `100%` or `_id` no longer match unrelated contacts through SQL `LIKE` wildcards. (#41891) Thanks @Kaneki-x.
|
||||
- Gateway/usage: include reset and deleted archived session transcripts in usage totals, session discovery, and archived-only session detail fallback so the Usage view no longer undercounts rotated sessions. (#43215) Thanks @rcrick.
|
||||
|
||||
### Changes
|
||||
|
||||
- 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.
|
||||
- Plugins/marketplaces: add Claude marketplace registry resolution, `plugin@marketplace` installs, marketplace listing, and update support, plus Docker E2E coverage for local and official marketplace flows. (#48058) Thanks @vincentkoc.
|
||||
- Commands/plugins: add owner-gated `/plugins` and `/plugin` chat commands for plugin list/show and enable/disable flows, alongside explicit `commands.plugins` config gating. Thanks @vincentkoc.
|
||||
- Install/update: allow package-manager installs from GitHub `main` via `openclaw update --tag main`, installer `--version main`, or direct npm/pnpm git specs. (#47630) Thanks @vincentkoc.
|
||||
- Plugins/bundles: add compatible Codex, Claude, and Cursor bundle discovery/install support, map bundle skills into OpenClaw skills, and apply Claude bundle `settings.json` defaults to embedded Pi with shell overrides sanitized.
|
||||
- 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.
|
||||
- Models/OpenAI: switch the default OpenAI setup model to `openai/gpt-5.4`, keep Codex on `openai-codex/gpt-5.4`, and centralize OpenAI chat, image, TTS, transcription, and embedding defaults in one shared module so future default-model updates stay low-churn. Thanks @vincentkoc.
|
||||
- Agents: add per-agent thinking/reasoning/fast defaults and auto-revert disallowed model overrides to the agent's default selection. Thanks @xuanmingguo and @vincentkoc.
|
||||
- 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.
|
||||
- Sandbox/runtime: add pluggable sandbox backends, ship an OpenShell backend with `mirror` and `remote` workspace modes, and make sandbox list/recreate/prune backend-aware instead of Docker-only.
|
||||
- Sandbox/SSH: add a core SSH sandbox backend with secret-backed key, certificate, and known_hosts inputs, move shared remote exec/filesystem tooling into core, and keep OpenShell focused on sandbox lifecycle plus optional `mirror` mode.
|
||||
- Browser/existing-session: support `browser.profiles.<name>.userDataDir` so Chrome DevTools MCP can attach to Brave, Edge, and other Chromium-based browsers through their own user data directories. (#48170) Thanks @velvet-shark.
|
||||
- Plugins/bundles: make enabled bundle MCP servers expose runnable tools in embedded Pi, and default relative bundle MCP launches to the bundle root so marketplace bundles like Context7 work through Pi instead of stopping at config import.
|
||||
- Plugins/providers: move OpenRouter, GitHub Copilot, and OpenAI Codex provider/runtime logic into bundled plugins, including dynamic model fallback, runtime auth exchange, stream wrappers, capability hints, and cache-TTL policy.
|
||||
- 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.
|
||||
- Plugins/Chutes: add a bundled Chutes provider with plugin-owned OAuth/API-key auth, dynamic model discovery, and default-on extension wiring. (#41416) Thanks @Veightor.
|
||||
- Web tools/Exa: add Exa as a bundled web-search plugin with Exa-native date filters, search-mode selection, and optional content extraction under `plugins.entries.exa.config.webSearch.*`. Thanks @V-Gutierrez and @vincentkoc.
|
||||
- Web tools/Tavily: add Tavily as a bundled web-search provider with dedicated `tavily_search` and `tavily_extract` tools, using canonical plugin-owned config under `plugins.entries.tavily.config.webSearch.*`. (#49200) thanks @lakshyaag-tavily.
|
||||
- Web tools/Firecrawl: add Firecrawl as an `onboard`/configure search provider via a bundled plugin, expose explicit `firecrawl_search` and `firecrawl_scrape` tools, and align core `web_fetch` fallback behavior with Firecrawl base-URL/env fallback plus guarded endpoint fetches.
|
||||
- Models/OpenAI: add native forward-compat support for `gpt-5.4-mini` and `gpt-5.4-nano` in the OpenAI provider catalog, runtime resolution, and reasoning capability gates. Thanks @vincentkoc.
|
||||
- Control UI/chat: add an expand-to-canvas button on assistant chat bubbles and in-app session navigation from Sessions and Cron views. Thanks @BunsDev.
|
||||
- Control UI/appearance: unify theme border radii across Claw, Knot, and Dash, and add a Roundness slider to the Appearance settings so users can adjust corner radius from sharp to fully rounded. Thanks @BunsDev.
|
||||
- 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.
|
||||
- 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.
|
||||
- Plugins/bundles: add compatible Codex, Claude, and Cursor bundle discovery/install support, map bundle skills into OpenClaw skills, and apply Claude bundle `settings.json` defaults to embedded Pi with shell overrides sanitized.
|
||||
- Plugins/providers: move OpenRouter, GitHub Copilot, and OpenAI Codex provider/runtime logic into bundled plugins, including dynamic model fallback, runtime auth exchange, stream wrappers, capability hints, and cache-TTL policy.
|
||||
- Plugins/agent integrations: broaden the plugin surface for app-server integrations with channel-aware commands, interactive callbacks, inbound claims, and Discord/Telegram conversation binding support. (#45318) Thanks @huntharo and @vincentkoc.
|
||||
- Install/update: allow package-manager installs from GitHub `main` via `openclaw update --tag main`, installer `--version main`, or direct npm/pnpm git specs. (#47630) Thanks @vincentkoc.
|
||||
- Gateway/health monitor: add configurable stale-event thresholds and restart limits, plus per-channel and per-account `healthMonitor.enabled` overrides, while keeping the existing global disable path on `gateway.channelHealthCheckMinutes=0`. (#42107) Thanks @rstar327.
|
||||
- Android/mobile: add a system-aware dark theme across onboarding and post-onboarding screens so the app follows the device theme through setup, chat, and voice flows. (#46249) Thanks @sibbl.
|
||||
- Android/Talk: move Talk speech synthesis behind gateway `talk.speak`, keep Talk secrets on the gateway, and switch Android playback to final-response audio instead of device-local ElevenLabs streaming. (#50849)
|
||||
- Android/nodes: add `callLog.search` plus shared Call Log permission wiring so Android nodes can search recent call history through the gateway. (#44073) Thanks @lixuankai.
|
||||
- Android/nodes: add `sms.search` plus shared SMS permission wiring so Android nodes can search device text messages through the gateway. (#48299) Thanks @lixuankai.
|
||||
- Telegram/apiRoot: add per-account custom Bot API endpoint support across send, probe, setup, doctor repair, and inbound media download paths so proxied or self-hosted Telegram deployments work end to end. (#48842) Thanks @Cypherm.
|
||||
- Telegram/topics: auto-rename DM forum topics on first message with LLM-generated labels, with per-account and per-DM `autoTopicLabel` overrides. (#51502) Thanks @Lukavyi.
|
||||
- Telegram/actions: add `topic-edit` for forum-topic renames and icon updates while sharing the same Telegram topic-edit transport used by the plugin runtime. (#47798) Thanks @obviyus.
|
||||
- Telegram/error replies: add a default-off `channels.telegram.silentErrorReplies` setting so bot error replies can be delivered silently across regular replies, native commands, and fallback sends. (#19776) Thanks @ImLukeF.
|
||||
- Feishu/cards: add structured interactive approval and quick-action launcher cards, preserve callback user and conversation context through routing, and keep legacy card-action fallback behavior so common actions can run without typing raw commands. (#47873) Thanks @Takhoffman.
|
||||
- Feishu/ACP: add current-conversation ACP and subagent session binding for supported DMs and topic conversations, including completion delivery back to the originating Feishu conversation. (#46819) Thanks @Takhoffman.
|
||||
- Plugins/marketplaces: add Claude marketplace registry resolution, `plugin@marketplace` installs, marketplace listing, and update support, plus Docker E2E coverage for local and official marketplace flows. (#48058) Thanks @vincentkoc.
|
||||
- Commands/plugins: add owner-gated `/plugins` and `/plugin` chat commands for plugin list/show and enable/disable flows, alongside explicit `commands.plugins` config gating. Thanks @vincentkoc.
|
||||
- Feishu/cards: add structured interactive approval and quick-action launcher cards, preserve callback user and conversation context through routing, and keep legacy card-action fallback behavior so common actions can run without typing raw commands. (#47873) Thanks @Takhoffman.
|
||||
- Feishu/streaming: add `onReasoningStream` and `onReasoningEnd` support to streaming cards, so `/reasoning stream` renders thinking tokens as markdown blockquotes in the same card — matching the Telegram channel's reasoning lane behavior. (#46029) Thanks @day253.
|
||||
- Feishu/cards: add identity-aware structured card headers and note footers for Feishu replies and direct sends, while keeping that presentation wired through the shared outbound identity path. (#29938) Thanks @nszhsl.
|
||||
- Plugins/Matrix: add `allowBots` room policy so configured Matrix bot accounts can talk to each other, with optional mention-only gating. Thanks @gumadeiras.
|
||||
- Plugins/Matrix: add per-account `allowPrivateNetwork` opt-in for private/internal homeservers, while keeping public cleartext homeservers blocked. Thanks @gumadeiras.
|
||||
- Plugins/MiniMax: add MiniMax-M2.7 and MiniMax-M2.7-highspeed models and update the default model from M2.5 to M2.7. (#49691) Thanks @liyuan97.
|
||||
- MiniMax/fast mode: map shared `/fast` and `params.fastMode` to MiniMax `-highspeed` models for M2.1, M2.5, and M2.7 API-key and OAuth runs. Thanks @vincentkoc.
|
||||
- Models/MiniMax defaults: raise bundled MiniMax M2.5/M2.7 context-window, max-token, and pricing metadata to the higher defaults shipped by the current upstream Pi SDK. Thanks @vincentkoc.
|
||||
- Models/MiniMax: add bundled `MiniMax-M2`, `MiniMax-M2.1`, and `MiniMax-M2.1-highspeed` catalog entries so OpenClaw's provider metadata and OAuth aliases stay aligned with the current upstream Pi SDK. Thanks @vincentkoc.
|
||||
- Android/nodes: add `callLog.search` plus shared Call Log permission wiring so Android nodes can search recent call history through the gateway. (#44073) Thanks @lixuankai.
|
||||
- Android/nodes: add `sms.search` plus shared SMS permission wiring so Android nodes can search device text messages through the gateway. (#48299) Thanks @lixuankai.
|
||||
- Plugins/MiniMax: merge the bundled MiniMax API and MiniMax OAuth plugin surfaces into a single default-on `minimax` plugin, while keeping legacy `minimax-portal-auth` config ids aliased for compatibility.
|
||||
- Agents/Pi compatibility: align OpenClaw's bundled MiniMax runtime behavior with the current upstream Pi 0.61.1 release so embedded runs stay in sync with the latest published Pi SDK semantics. Thanks @vincentkoc.
|
||||
- Models/GitHub Copilot: allow forward-compat dynamic model ids without code updates, while preserving configured provider and per-model overrides for those synthetic models. (#51325) Thanks @fuller-stack-dev.
|
||||
- xAI/models: sync the bundled Grok catalog to current Pi-backed IDs, limits, and pricing metadata, while keeping older Grok fast and 4.20 aliases resolving cleanly at runtime. Thanks @vincentkoc.
|
||||
- xAI/fast mode: map shared `/fast` and `params.fastMode` to the current xAI Grok fast model family so direct Grok runs can opt into the faster Pi-backed variants. Thanks @vincentkoc.
|
||||
- CLI/config: expand `config set` with SecretRef and provider builder modes, JSON/batch assignment support, and `--dry-run` validation with structured JSON output. (#49296) Thanks @joshavant.
|
||||
- Z.AI/models: sync the bundled GLM catalog to current Pi metadata, including newer 4.5/4.6 model families, updated multimodal entries, and current pricing and token limits. Thanks @vincentkoc.
|
||||
- Mistral/models: sync the bundled default Mistral metadata to current Pi pricing so the built-in default no longer advertises zero-cost usage. Thanks @vincentkoc.
|
||||
- Plugins/Xiaomi: switch the bundled Xiaomi provider to the `/v1` OpenAI-compatible endpoint and add MiMo V2 Pro plus MiMo V2 Omni to the built-in catalog. (#49214) thanks @DJjjjhao.
|
||||
- Agents/compaction: notify users when followup auto-compaction starts and finishes, keeping those notices out of TTS and preserving reply threading for the real assistant reply. (#38805) Thanks @zidongdesign.
|
||||
- Memory/plugins: let the active memory plugin register its own system-prompt section while preserving cache-clear and snapshot-load prompt isolation. (#40126) Thanks @jarimustonen.
|
||||
- Gateway/health monitor: add configurable stale-event thresholds and restart limits, plus per-channel and per-account `healthMonitor.enabled` overrides, while keeping the existing global disable path on `gateway.channelHealthCheckMinutes=0`. (#42107) Thanks @rstar327.
|
||||
- Plugins/agent integrations: broaden the plugin surface for app-server integrations with channel-aware commands, interactive callbacks, inbound claims, and Discord/Telegram conversation binding support. (#45318) Thanks @huntharo and @vincentkoc.
|
||||
- Plugins/binding: add `onConversationBindingResolved(...)` so plugins can react immediately after bind approvals or denies without blocking channel interaction acknowledgements. (#48678) Thanks @huntharo.
|
||||
- Plugins/context engines: expose `delegateCompactionToRuntime(...)` on the public plugin SDK, refactor the legacy engine to use the shared helper, and clarify `ownsCompaction` delegation semantics for non-owning engines. (#49061) Thanks @jalehman.
|
||||
- Plugins/context engines: pass the embedded runner `modelId` into context-engine `assemble()` so plugins can adapt context formatting per model. (#47437) thanks @jscianna.
|
||||
- Plugins/context engines: add transcript maintenance rewrites for context engines, preserve active-branch transcript metadata during rewrites, and harden overflow-recovery truncation to rewrite sessions under the normal session write lock. (#51191) Thanks @jalehman.
|
||||
- Skills/prompt budget: preserve all registered skills via a compact catalog fallback before dropping entries when the full prompt format exceeds `maxSkillsPromptChars`. (#47553) Thanks @snese.
|
||||
- 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.
|
||||
- Security/plugins: reject remote marketplace manifest entries that expand installation outside the cloned marketplace repo, including external git/GitHub sources, HTTP archives, and absolute paths.
|
||||
- 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.
|
||||
- secrets: harden read-only SecretRef command paths and diagnostics. (#47794) Thanks @joshavant.
|
||||
- Scope message SecretRef resolution and harden doctor/status paths. (#48728) Thanks @joshavant.
|
||||
- Build/memory tools: emit `dist/cli/memory-cli.js` as a stable core entry so runtime `memory_search` loading no longer depends on hashed `memory-cli-*` bundle names. (#51759) Thanks @oliviareid-svg.
|
||||
- Plugins/testing: add a public `openclaw/plugin-sdk/testing` surface for plugin-author test helpers, and move bundled-extension-only test bridges out of `extensions/` into private repo test helpers.
|
||||
- Agents/steering docs: update embedded Pi steering docs and runner comments for the current upstream behavior, where queued steering is injected after the active assistant turn finishes its tool calls instead of skipping the remaining tools mid-turn. Thanks @vincentkoc.
|
||||
- Telegram/actions: add `topic-edit` for forum-topic renames and icon updates while sharing the same Telegram topic-edit transport used by the plugin runtime. (#47798) Thanks @obviyus.
|
||||
- Telegram/error replies: add a default-off `channels.telegram.silentErrorReplies` setting so bot error replies can be delivered silently across regular replies, native commands, and fallback sends. (#19776) Thanks @ImLukeF.
|
||||
- Doctor/refactor: start splitting doctor provider checks into `src/commands/doctor/providers/*` by extracting Telegram first-run and group allowlist warnings into a provider-specific module, keeping the current setup guidance and warning behavior intact. Thanks @vincentkoc.
|
||||
- Refactor/channels: remove the legacy channel shim directories and point channel-specific imports directly at the extension-owned implementations. (#45967) Thanks @scoootscooob.
|
||||
- Docs/Zalo: clarify the Marketplace-bot support matrix and config guidance so the Zalo channel docs match current Bot Creator behavior more closely. (#47552) Thanks @No898.
|
||||
- secrets: harden read-only SecretRef command paths and diagnostics. (#47794) Thanks @joshavant.
|
||||
- Browser/existing-session: support `browser.profiles.<name>.userDataDir` so Chrome DevTools MCP can attach to Brave, Edge, and other Chromium-based browsers through their own user data directories. (#48170) Thanks @velvet-shark.
|
||||
- Skills/prompt budget: preserve all registered skills via a compact catalog fallback before dropping entries when the full prompt format exceeds `maxSkillsPromptChars`. (#47553) Thanks @snese.
|
||||
- Models/OpenAI: add native forward-compat support for `gpt-5.4-mini` and `gpt-5.4-nano` in the OpenAI provider catalog, runtime resolution, and reasoning capability gates. Thanks @vincentkoc.
|
||||
- Plugins/bundles: make enabled bundle MCP servers expose runnable tools in embedded Pi, and default relative bundle MCP launches to the bundle root so marketplace bundles like Context7 work through Pi instead of stopping at config import.
|
||||
- Scope message SecretRef resolution and harden doctor/status paths. (#48728) Thanks @joshavant.
|
||||
- Plugins/testing: add a public `openclaw/plugin-sdk/testing` surface for plugin-author test helpers, and move bundled-extension-only test bridges out of `extensions/` into private repo test helpers.
|
||||
- Plugins/Chutes: add a bundled Chutes provider with plugin-owned OAuth/API-key auth, dynamic model discovery, and default-on extension wiring. (#41416) Thanks @Veightor.
|
||||
- Plugins/binding: add `onConversationBindingResolved(...)` so plugins can react immediately after bind approvals or denies without blocking channel interaction acknowledgements. (#48678) Thanks @huntharo.
|
||||
- CLI/config: expand `config set` with SecretRef and provider builder modes, JSON/batch assignment support, and `--dry-run` validation with structured JSON output. (#49296) Thanks @joshavant.
|
||||
- Control UI/appearance: unify theme border radii across Claw, Knot, and Dash, and add a Roundness slider to the Appearance settings so users can adjust corner radius from sharp to fully rounded. Thanks @BunsDev.
|
||||
- Control UI/chat: add an expand-to-canvas button on assistant chat bubbles and in-app session navigation from Sessions and Cron views. Thanks @BunsDev.
|
||||
- Plugins/context engines: expose `delegateCompactionToRuntime(...)` on the public plugin SDK, refactor the legacy engine to use the shared helper, and clarify `ownsCompaction` delegation semantics for non-owning engines. (#49061) Thanks @jalehman.
|
||||
- Plugins/MiniMax: add MiniMax-M2.7 and MiniMax-M2.7-highspeed models and update the default model from M2.5 to M2.7. (#49691) Thanks @liyuan97.
|
||||
- Plugins/Xiaomi: switch the bundled Xiaomi provider to the `/v1` OpenAI-compatible endpoint and add MiMo V2 Pro plus MiMo V2 Omni to the built-in catalog. (#49214) thanks @DJjjjhao.
|
||||
- Android/Talk: move Talk speech synthesis behind gateway `talk.speak`, keep Talk secrets on the gateway, and switch Android playback to final-response audio instead of device-local ElevenLabs streaming. (#50849)
|
||||
- Plugins/Matrix: add `allowBots` room policy so configured Matrix bot accounts can talk to each other, with optional mention-only gating. Thanks @gumadeiras.
|
||||
- Plugins/Matrix: add per-account `allowPrivateNetwork` opt-in for private/internal homeservers, while keeping public cleartext homeservers blocked. Thanks @gumadeiras.
|
||||
- Web tools/Tavily: add Tavily as a bundled web-search provider with dedicated `tavily_search` and `tavily_extract` tools, using canonical plugin-owned config under `plugins.entries.tavily.config.webSearch.*`. (#49200) thanks @lakshyaag-tavily.
|
||||
- Docs/plugins: add the community DingTalk plugin listing to the docs catalog. (#29913) Thanks @sliverp.
|
||||
- Docs/plugins: add the community QQbot plugin listing to the docs catalog. (#29898) Thanks @sliverp.
|
||||
- Plugins/context engines: pass the embedded runner `modelId` into context-engine `assemble()` so plugins can adapt context formatting per model. (#47437) thanks @jscianna.
|
||||
- Plugins/context engines: add transcript maintenance rewrites for context engines, preserve active-branch transcript metadata during rewrites, and harden overflow-recovery truncation to rewrite sessions under the normal session write lock. (#51191) Thanks @jalehman.
|
||||
- Telegram/apiRoot: add per-account custom Bot API endpoint support across send, probe, setup, doctor repair, and inbound media download paths so proxied or self-hosted Telegram deployments work end to end. (#48842) Thanks @Cypherm.
|
||||
- Telegram/topics: auto-rename DM forum topics on first message with LLM-generated labels, with per-account and per-DM `autoTopicLabel` overrides. (#51502) Thanks @Lukavyi.
|
||||
- Docs/plugins: add the community wecom plugin listing to the docs catalog. (#29905) Thanks @sliverp.
|
||||
- Models/GitHub Copilot: allow forward-compat dynamic model ids without code updates, while preserving configured provider and per-model overrides for those synthetic models. (#51325) Thanks @fuller-stack-dev.
|
||||
- Agents/compaction: notify users when followup auto-compaction starts and finishes, keeping those notices out of TTS and preserving reply threading for the real assistant reply. (#38805) Thanks @zidongdesign.
|
||||
- Models/OpenAI: switch the default OpenAI setup model to `openai/gpt-5.4`, keep Codex on `openai-codex/gpt-5.4`, and centralize OpenAI chat, image, TTS, transcription, and embedding defaults in one shared module so future default-model updates stay low-churn. Thanks @vincentkoc.
|
||||
- Memory/plugins: let the active memory plugin register its own system-prompt section while preserving cache-clear and snapshot-load prompt isolation. (#40126) Thanks @jarimustonen.
|
||||
- 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.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Web tools/search provider lists: keep onboarding, configure, and docs provider lists alphabetical while preserving the separate runtime auto-detect precedence used for credential-based provider selection.
|
||||
- Media/Windows security: block remote-host `file://` media URLs and UNC/network paths before local filesystem resolution in core media loading and adjacent prompt/sandbox attachment seams, so the next release no longer allows structured local-media inputs to trigger outbound SMB credential handshakes on Windows. Thanks @RacerZ-fighting for reporting.
|
||||
- Gateway/discovery: fail closed on unresolved Bonjour and DNS-SD service endpoints in CLI discovery, onboarding, and `gateway status` so TXT-only hints can no longer steer routing or SSH auto-target selection. Thanks @nexrin for reporting.
|
||||
- Security/pairing: bind iOS setup codes to the intended node profile and reject first-use bootstrap redemption that asks for broader roles or scopes. Thanks @tdjackey.
|
||||
- Memory/core tools: register `memory_search` and `memory_get` independently so one unavailable memory tool no longer suppresses the other in new sessions. (#50198) Thanks @artwalker.
|
||||
- Web tools/Exa: align the bundled Exa plugin with the current Exa API by supporting newer search types and richer `contents` options, while fixing the result-count cap to honor Exa's higher limit. Thanks @vincentkoc.
|
||||
- Plugins/Matrix: move bundled plugin `KeyedAsyncQueue` imports onto the stable `plugin-sdk/core` surface so Matrix Docker/runtime builds do not depend on the brittle keyed-async-queue subpath. Thanks @ecohash-co and @vincentkoc.
|
||||
- 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.
|
||||
- Synology Chat/security: keep reply delivery bound to stable numeric `user_id` by default, and gate mutable username/nickname recipient lookup behind `dangerouslyAllowNameMatching` with new regression coverage. Thanks @nexrin.
|
||||
- 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/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.
|
||||
- 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.
|
||||
- CLI/startup: lazy-load channel add and root help startup paths to trim avoidable RSS and help latency on constrained hosts. (#46784) Thanks @vincentkoc.
|
||||
- Configure/startup: move outbound send-deps resolution into a lightweight helper so `openclaw configure` no longer stalls after the banner while eagerly loading channel plugins. (#46301) Thanks @scoootscooob.
|
||||
- CLI/auth choice: lazy-load plugin/provider fallback resolution so mapped auth choices stay on the static path and only unknown choices pay the heavy provider load. (#47495) Thanks @vincentkoc.
|
||||
- Gateway/Discord startup: load only configured channel plugins during gateway boot, and lazy-load Discord provider/session runtime setup so startup stops importing unrelated providers and trims cold-start delay. Thanks @vincentkoc.
|
||||
- Agents/inbound: lazy-load media and link understanding for plain-text turns and cache synced auth stores by auth-file state so ordinary inbound replies avoid unnecessary startup churn. Thanks @vincentkoc.
|
||||
- Agents/openai-compatible tool calls: deduplicate repeated tool call ids across live assistant messages and replayed history so OpenAI-compatible backends no longer reject duplicate `tool_call_id` values with HTTP 400. (#40996) Thanks @xaeon2026.
|
||||
- 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.
|
||||
- Models/openai-completions: default non-native OpenAI-compatible providers to omit tool-definition `strict` fields unless users explicitly opt back in, so tool calling keeps working on providers that reject that option. (#45497) Thanks @sahancava.
|
||||
- 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.
|
||||
- Control UI/session routing: preserve established external delivery routes when webchat views or sends in externally originated sessions, so subagent completions still return to the original channel instead of the dashboard. (#47797) Thanks @brokemac79.
|
||||
- Telegram/replies: set `allow_sending_without_reply` on reply-targeted sends and media-error notices so deleted parent messages no longer drop otherwise valid replies. (#52524) Thanks @moltbot886.
|
||||
- Telegram/polling: hard-timeout stuck `getUpdates` requests so wedged network paths fail over sooner instead of waiting for the polling stall watchdog. Thanks @vincentkoc.
|
||||
- Android/location: make current-location requests drop late callbacks after timeout instead of crashing with `Already resumed`. (#52318) Thanks @Kaneki-x.
|
||||
- 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.
|
||||
- Android/canvas: ignore bridge messages from pages outside the bundled scaffold and trusted A2UI surfaces. Thanks @vincentkoc.
|
||||
- CLI/status: keep `status --json` stdout clean by skipping plugin compatibility scans that were not rendered in the JSON payload. (#52449) Thanks @cgdusek.
|
||||
- WhatsApp/reconnect: restore the append recency filter in the extension inbox monitor and handle protobuf `Long` timestamps correctly, so fresh post-reconnect append messages are processed while stale history sync stays suppressed. (#42588) Thanks @MonkeyLeeT.
|
||||
- WhatsApp/login: wait for pending creds writes before reopening after Baileys `515` pairing restarts in both QR login and `channels login` flows, and keep the restart coverage pinned to the real wrapped error shape plus per-account creds queues. (#27910) Thanks @asyncjason.
|
||||
- Android/canvas: serialize A2UI action-status event strings before evaluating WebView JS, so action ids and multiline errors do not break the callback dispatch. (#43784) Thanks @Kaneki-x.
|
||||
- Android/camera: recycle intermediate and final snap bitmaps in `camera.snap` so repeated captures do not leak native image memory. (#41902) Thanks @Kaneki-x.
|
||||
- Control UI/logging: make browser-safe logger imports avoid eager temp-dir resolution so the bundled Control UI no longer crashes to a blank screen when logging reaches `tmp-openclaw-dir`. (#48469) Fixes #48062. Thanks @7inspire.
|
||||
- Control UI/chat sessions: show human-readable labels in the grouped session dropdown again, keep unique scoped fallbacks when metadata is missing, and disambiguate duplicate labels only when needed. (#45130) Thanks @luzhidong.
|
||||
- Telegram/replies: ignore malformed non-string reply text and caption fields when describing reply context, so unexpected Telegram reply payloads no longer break inbound context assembly. (#50500) Thanks @p3nchan.
|
||||
- Control UI/dashboard: preserve structured gateway shutdown reasons across restart disconnects so config-triggered restarts no longer fall back to `disconnected (1006): no reason`. (#46580) Fixes #46532. Thanks @vincentkoc.
|
||||
- Android/chat: theme the thinking dropdown and TLS trust dialogs explicitly so popup surfaces match the active app theme instead of falling back to mismatched Material defaults.
|
||||
- Node/startup: remove leftover debug `console.log("node host PATH: ...")` that printed the resolved PATH on every `openclaw node run` invocation. (#46515) Fixes #46411. Thanks @ademczuk.
|
||||
- Slack/startup: harden `@slack/bolt` import interop across current bundled runtime shapes so Slack monitors no longer crash with `App is not a constructor` after plugin-sdk bundling changes. (#45953) Thanks @merc1305.
|
||||
- Control UI/model switching: preserve the selected provider prefix when switching models from the chat dropdown, so multi-provider setups no longer send `anthropic/gpt-5.2`-style mismatches when the user picked `openai/gpt-5.2`. (#47581) Thanks @chrishham.
|
||||
- Control UI/storage: scope persisted settings keys by gateway base path, with migration from the legacy shared key, so multiple gateways under one domain stop overwriting each other's dashboard preferences. (#47932) Thanks @bobBot-claw.
|
||||
- Control UI/overview: keep the language dropdown aligned with the persisted locale during dashboard startup so refreshing the page does not fall back to English before locale hydration completes. (#48019) Thanks @git-jxj.
|
||||
- macOS/node service startup: use `openclaw node start/stop --json` from the Mac app instead of the removed `openclaw service node ...` command shape, so current CLI installs expose the full node exec surface again. (#46843) Fixes #43171. Thanks @Br1an67.
|
||||
- ACP/gateway startup: use direct Telegram and Discord startup/status helpers instead of routing probes through the plugin runtime, and prepend the selected daemon Node bin dir to service PATH so plugin-local installs can still find `npm` and `pnpm`.
|
||||
- WhatsApp/active-listener: pin the active listener registry to a `globalThis` singleton so split WhatsApp bundle chunks share one listener map and outbound sends stop missing the registered session. (#47433) Thanks @clawdia67.
|
||||
- Gateway/probe: honor caller `--timeout` for active local loopback probes in `gateway status`, keep inactive remote-mode loopback probes fast, and clamp probe timers to JS-safe bounds so slow local/container gateways stop reporting false timeouts. (#47533) Thanks @MonkeyLeeT.
|
||||
- Config/startup: keep bundled web-search allowlist compatibility on a lightweight manifest path so config validation no longer pulls bundled web-search registry imports into startup, while still avoiding accidental auto-allow of config-loaded override plugins. (#51574) Thanks @RichardCao.
|
||||
- Gateway/chat.send: persist uploaded image references across reloads and compaction without delaying first-turn dispatch or double-submitting the same image to vision models. (#51324) Thanks @fuller-stack-dev.
|
||||
- Android/canvas: recycle captured and scaled snapshot bitmaps so repeated canvas snapshots do not leak native image memory. (#41889) Thanks @Kaneki-x.
|
||||
- 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.
|
||||
- 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.
|
||||
- WhatsApp/reconnect: preserve the last inbound timestamp across reconnect attempts so the watchdog can still recycle linked-but-dead listeners after a restart instead of leaving them stuck connected forever.
|
||||
- Gateway/network discovery: guard LAN, tailnet, and pairing interface enumeration so WSL2 and restricted hosts degrade to missing-address fallbacks instead of crashing on `uv_interface_addresses` errors. (#44180, #47590)
|
||||
- Gateway/bonjour: suppress the non-fatal `@homebridge/ciao` IPv4-loss assertion during interface churn so WiFi/VPN/sleep-wake changes no longer take down the gateway. (#38628, #47159, #52431)
|
||||
- Browser/launch: stop forcing an extra blank tab on browser launch so managed browser startup no longer opens an unwanted empty page. (#52451) Thanks @rogerdigital.
|
||||
- CLI/onboarding: import static provider definitions directly for onboarding model/config helpers so those paths no longer pull provider discovery just for built-in defaults. (#47467) Thanks @vincentkoc.
|
||||
- Agents/exec: return plain-text failed tool output for timeouts and other non-success exec outcomes so models no longer parrot raw JSON error payloads back to users. (#52508) Thanks @martingarramon.
|
||||
- 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.
|
||||
- CLI/configure: clarify fresh-setup memory-search warnings so they say semantic recall needs at least one embedding provider, and scope the initial model allowlist picker to the provider selected in configure. Thanks @vincentkoc.
|
||||
- Mattermost/threading: honor `replyToMode: "off"` for already-threaded inbound posts so threaded follow-ups can fall back to top-level replies when configured. (#52543) Thanks @RichardCao.
|
||||
- Onboarding/custom providers: store Azure OpenAI and Azure AI Foundry custom endpoints with the Responses API config shape, normalized `/openai/v1` base URLs, and Azure-safe defaults so TUI and agent runs work after setup. (#49543) Thanks @kunalk16.
|
||||
- CLI/completion: reduce recursive completion-script string churn and fix nested PowerShell command-path matching so generated nested completions resolve on PowerShell too. (#45537) Thanks @yiShanXin and @vincentkoc.
|
||||
- macOS/launch at login: stop emitting `KeepAlive` for the desktop app launch agent so OpenClaw no longer relaunches immediately after a manual quit while launch at login remains enabled. (#40213) Thanks @stablegenius49.
|
||||
- Mattermost/DM send: retry transient direct-channel creation failures for DM deliveries, with configurable backoff and per-request timeout. (#42398) Thanks @JonathanJing.
|
||||
- Secrets/exec refs: require explicit `--allow-exec` for `secrets apply` write plans that contain exec SecretRefs/providers, and align audit/configure/apply dry-run behavior to skip exec checks unless opted in to prevent unexpected command side effects. (#49417) Thanks @restriction and @joshavant.
|
||||
- Signal/runtime API: re-export `SignalAccountConfig` so Signal account resolution type-checks again. (#49470) Thanks @scoootscooob.
|
||||
- Google Chat/runtime API: thin the private runtime barrel onto the curated public SDK surface while keeping public Google Chat exports intact. (#49504) Thanks @scoootscooob.
|
||||
- Onboarding/custom providers: keep Azure AI Foundry `*.services.ai.azure.com` custom endpoints on the selected compatibility path instead of forcing Responses, so chat-completions Foundry models still work after setup. Fixes #50528. (#50535) Thanks @obviyus.
|
||||
- make `openclaw update status` explicitly say `up to date` when the local version already matches npm latest, while keeping the availability logic unchanged. (#51409) Thanks @dongzhenye.
|
||||
- Agents/embedded transport errors: distinguish common network failures like connection refused, DNS lookup failure, and interrupted sockets from true timeouts in embedded-run user messaging and lifecycle diagnostics. (#51419) Thanks @scoootscooob.
|
||||
- Security/pairing: bind iOS setup codes to the intended node profile and reject first-use bootstrap redemption that asks for broader roles or scopes. Thanks @tdjackey.
|
||||
- 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.
|
||||
- Synology Chat/security: keep reply delivery bound to stable numeric `user_id` by default, and gate mutable username/nickname recipient lookup behind `dangerouslyAllowNameMatching` with new regression coverage. Thanks @nexrin.
|
||||
- Browser/node proxy: enforce `nodeHost.browserProxy.allowProfiles` across `query.profile` and `body.profile`, block proxy-side profile create/delete when the allowlist is set, and keep the default full proxy surface when the allowlist is empty.
|
||||
- Security/device pairing: harden `device.token.rotate` deny handling by keeping public failures generic while logging internal deny reasons and preserving approved-baseline enforcement. (`GHSA-7jrw-x62h-64p8`)
|
||||
- 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.
|
||||
- Security/exec approvals: escape blank Hangul filler code points in approval prompts across gateway/chat and the macOS native approval UI so visually empty Unicode padding cannot hide reviewed command text.
|
||||
- Security/exec approvals: unify transparent dispatch-wrapper handling across resolution and allow-always persistence so wrapper metadata cannot silently drift and broaden approvals.
|
||||
- Security/exec: harden macOS allowlist resolution against wrapper and `env` spoofing, require fresh approval for inline interpreter eval with `tools.exec.strictInlineEval`, wrap Discord guild message bodies as untrusted external content, and add audit findings for risky exec approval and open-channel combinations.
|
||||
- Security/network: harden explicit-proxy SSRF pinning by translating target-hop transport hints onto HTTPS proxy tunnels and failing closed for plain HTTP guarded fetches that cannot preserve pinned DNS.
|
||||
- Security/Synology Chat: require explicit per-account webhook paths for multi-account setups by default, reject duplicate exact webhook paths fail-closed, and keep inherited-path behavior behind an explicit dangerous opt-in so shared routes can no longer collapse DM policy contexts across accounts. Thanks @tdjackey for reporting.
|
||||
- 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.
|
||||
- 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.
|
||||
- Plugins/context engines: enforce owner-aware context-engine registration on both loader and public SDK paths so plugins cannot spoof privileged ownership, claim the core `legacy` engine id, or overwrite an existing engine id through direct SDK imports. (#47595) Thanks @vincentkoc.
|
||||
- Browser/remote CDP: honor strict browser SSRF policy during remote CDP reachability and `/json/version` discovery checks, redact sensitive `cdpUrl` tokens from status output, and warn when remote CDP targets private/internal hosts.
|
||||
- Media/security: bound remote-media error-body snippets with the same streaming caps and idle timeouts as successful downloads, so malicious HTTP error responses cannot force unbounded buffering before OpenClaw throws.
|
||||
- Gateway/plugins: pin runtime webhook routes to the gateway startup registry so channel webhooks keep working across plugin-registry churn, and make plugin auth + dispatch resolve routes from the same live HTTP-route registry. (#47902) Fixes #46924 and #47041. Thanks @steipete.
|
||||
- Gateway/auth: ignore spoofed loopback hops in trusted forwarding chains and block device approvals that request scopes above the caller session. (#46800) Thanks @vincentkoc.
|
||||
- Gateway/auth: clear self-declared scopes for device-less trusted-proxy Control UI sessions so proxy-authenticated connects cannot claim admin or secrets scopes without a bound device identity.
|
||||
- Hardening: refresh stale device pairing requests and pending metadata (#50695) Thanks @smaeljaish771 and @joshavant.
|
||||
- Gateway/auth: add regression coverage that keeps device-less trusted-proxy Control UI sessions off privileged pairing approval RPCs. Thanks @vincentkoc.
|
||||
- Media/Windows security: block remote-host `file://` media URLs and UNC/network paths before local filesystem resolution in core media loading and adjacent prompt/sandbox attachment seams, so the next release no longer allows structured local-media inputs to trigger outbound SMB credential handshakes on Windows. Thanks @RacerZ-fighting for reporting.
|
||||
- Web tools/Exa: align the bundled Exa plugin with the current Exa API by supporting newer search types and richer `contents` options, while fixing the result-count cap to honor Exa's higher limit. Thanks @vincentkoc.
|
||||
- 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/restart: defer externally signaled unmanaged restarts through the in-process idle drain, and preserve the restored subagent run as remap fallback during orphan recovery so resumed sessions do not duplicate work. (#47719) Thanks @joeykrug.
|
||||
- Control UI/session routing: preserve established external delivery routes when webchat views or sends in externally originated sessions, so subagent completions still return to the original channel instead of the dashboard. (#47797) Thanks @brokemac79.
|
||||
- Configure/startup: move outbound send-deps resolution into a lightweight helper so `openclaw configure` no longer stalls after the banner while eagerly loading channel plugins. (#46301) Thanks @scoootscooob.
|
||||
- CLI/startup: lazy-load channel add and root help startup paths to trim avoidable RSS and help latency on constrained hosts. (#46784) Thanks @vincentkoc.
|
||||
- CLI/onboarding: import static provider definitions directly for onboarding model/config helpers so those paths no longer pull provider discovery just for built-in defaults. (#47467) Thanks @vincentkoc.
|
||||
- CLI/configure: clarify fresh-setup memory-search warnings so they say semantic recall needs at least one embedding provider, and scope the initial model allowlist picker to the provider selected in configure. Thanks @vincentkoc.
|
||||
- CLI/auth choice: lazy-load plugin/provider fallback resolution so mapped auth choices stay on the static path and only unknown choices pay the heavy provider load. (#47495) Thanks @vincentkoc.
|
||||
- CLI: avoid loading provider discovery during startup model normalization. (#46522) Thanks @ItsAditya-xyz and @vincentkoc.
|
||||
- Agents/Telegram: avoid rebuilding the full model catalog on ordinary inbound replies so Telegram message handling no longer pays multi-second core startup latency before reply generation. Thanks @vincentkoc.
|
||||
- Gateway/Discord startup: load only configured channel plugins during gateway boot, and lazy-load Discord provider/session runtime setup so startup stops importing unrelated providers and trims cold-start delay. Thanks @vincentkoc.
|
||||
- Security/exec: harden macOS allowlist resolution against wrapper and `env` spoofing, require fresh approval for inline interpreter eval with `tools.exec.strictInlineEval`, wrap Discord guild message bodies as untrusted external content, and add audit findings for risky exec approval and open-channel combinations.
|
||||
- Agents/inbound: lazy-load media and link understanding for plain-text turns and cache synced auth stores by auth-file state so ordinary inbound replies avoid unnecessary startup churn. Thanks @vincentkoc.
|
||||
- Telegram/polling: hard-timeout stuck `getUpdates` requests so wedged network paths fail over sooner instead of waiting for the polling stall watchdog. Thanks @vincentkoc.
|
||||
- Agents/models: cache `models.json` readiness by config and auth-file state so embedded runner turns stop paying repeated model-catalog startup work before replies. Thanks @vincentkoc.
|
||||
- Gateway/status: tolerate network interface discovery failures in status, onboarding control-UI links, and self-presence display paths so those surfaces fall back cleanly instead of crashing. (#52195) Thanks @meng-clb.
|
||||
- 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.
|
||||
- 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/status: resolve env-backed `gateway.auth.*` SecretRefs before read-only probe auth checks so status no longer reports false probe failures when auth is configured through SecretRef. (#52513) Thanks @CodeForgeNet.
|
||||
- Gateway/plugins: pin runtime webhook routes to the gateway startup registry so channel webhooks keep working across plugin-registry churn, and make plugin auth + dispatch resolve routes from the same live HTTP-route registry. (#47902) Fixes #46924 and #47041. Thanks @steipete.
|
||||
- Gateway/restart: defer externally signaled unmanaged restarts through the in-process idle drain, and preserve the restored subagent run as remap fallback during orphan recovery so resumed sessions do not duplicate work. (#47719) Thanks @joeykrug.
|
||||
- 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/device pairing: harden `device.token.rotate` deny handling by keeping public failures generic while logging internal deny reasons and preserving approved-baseline enforcement. (`GHSA-7jrw-x62h-64p8`)
|
||||
- Inbound policy hardening: tighten callback and webhook sender checks across Mattermost and Google Chat, match Nextcloud Talk rooms by stable room token, and treat explicit empty Twitch allowlists as deny-all. (#46787) Thanks @zpbrent, @ijxpwastaken and @vincentkoc.
|
||||
- Webhooks/runtime: move auth earlier and tighten pre-auth body limits and timeouts across bundled webhook handlers, including slow-body handling for Mattermost slash commands. (#46802) Thanks @vincentkoc.
|
||||
- Email/webhook wrapping: sanitize sender and subject metadata before external-content wrapping so metadata fields cannot break the wrapper structure. (#46816) Thanks @vincentkoc.
|
||||
- Gateway/chat: only reap orphaned stale chat buffers after the abort controller is gone, and clear abort-time streaming metadata so long-running sessions do not lose buffered output while stale maps still get reclaimed. (#52428) Thanks @karanuppal.
|
||||
- Tools/apply-patch: revalidate workspace-only delete and directory targets immediately before mutating host paths. (#46803) Thanks @vincentkoc.
|
||||
- Gateway/config views: strip embedded credentials from URL-based endpoint fields before returning read-only account and config snapshots. (#46799) Thanks @vincentkoc.
|
||||
- ACP/approvals: use canonical tool identity for prompting decisions and fail closed when conflicting tool identity hints are present. (#46817) Thanks @zpbrent and @vincentkoc.
|
||||
@@ -353,116 +109,154 @@ Docs: https://docs.openclaw.ai
|
||||
- Web search/onboarding: clarify provider labels, key prompts, and missing-key notes so setup/configure more clearly names the required provider credential for Gemini, Kimi, Grok, Brave Search, Firecrawl, Perplexity, and Tavily. Thanks @vincentkoc.
|
||||
- macOS/canvas actions: keep unattended local agent actions on trusted in-app canvas surfaces only, and stop exposing the deep-link fallback key to arbitrary page scripts. (#46790) Thanks @vincentkoc.
|
||||
- Agents/compaction: extend the enclosing run deadline once while compaction is actively in flight, and abort the underlying SDK compaction on timeout/cancel so large-session compactions stop freezing mid-run. (#46889) Thanks @asyncjason.
|
||||
- Gateway/Telegram shutdown: abort stalled Telegram polling fetches on shutdown, clean up per-cycle abort listeners, and keep the in-process watchdog ahead of supervisor stop timeouts so SIGTERM no longer leaves zombie gateways behind. (#51242) Thanks @juliabush.
|
||||
- Agents/openai-compatible tool calls: deduplicate repeated tool call ids across live assistant messages and replayed history so OpenAI-compatible backends no longer reject duplicate `tool_call_id` values with HTTP 400. (#40996) Thanks @xaeon2026.
|
||||
- Models/openai-completions: default non-native OpenAI-compatible providers to omit tool-definition `strict` fields unless users explicitly opt back in, so tool calling keeps working on providers that reject that option. (#45497) Thanks @sahancava.
|
||||
- Telegram/setup: warn when setup leaves DMs on pairing without an allowlist, and show valid account-scoped remediation commands. (#50710) Thanks @ernestodeoliveira.
|
||||
- Doctor/Telegram: replace the fresh-install empty group-allowlist false positive with first-run guidance that explains DM pairing approval and the next group setup steps, so new Telegram installs get actionable setup help instead of a broken-config warning. Thanks @vincentkoc.
|
||||
- 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.
|
||||
- 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.
|
||||
- Feishu/topic threads: fetch full thread context, including prior bot replies, when starting a topic-thread session so follow-up turns in Feishu topics keep the right conversation state. (#45254) Thanks @Coobiw.
|
||||
- Feishu/media: keep native image, file, audio, and video/media handling aligned across outbound sends, inbound downloads, thread replies, directory/action aliases, and capability docs so unsupported areas are explicit instead of implied. (#47968) Thanks @Takhoffman.
|
||||
- Feishu/webhooks: harden signed webhook verification to use constant-time signature comparison and keep malformed short signatures fail-closed in webhook E2E coverage.
|
||||
- WhatsApp/reconnect: restore the append recency filter in the extension inbox monitor and handle protobuf `Long` timestamps correctly, so fresh post-reconnect append messages are processed while stale history sync stays suppressed. (#42588) Thanks @MonkeyLeeT.
|
||||
- WhatsApp/login: wait for pending creds writes before reopening after Baileys `515` pairing restarts in both QR login and `channels login` flows, and keep the restart coverage pinned to the real wrapped error shape plus per-account creds queues. (#27910) Thanks @asyncjason.
|
||||
- Telegram/message send: forward `--force-document` through the `sendPayload` path as well as `sendMedia`, so Telegram payload sends with `channelData` keep uploading images as documents instead of silently falling back to compressed photo sends. (#47119) Thanks @thepagent.
|
||||
- Android/canvas: serialize A2UI action-status event strings before evaluating WebView JS, so action ids and multiline errors do not break the callback dispatch. (#43784) Thanks @Kaneki-x.
|
||||
- Android/camera: recycle intermediate and final snap bitmaps in `camera.snap` so repeated captures do not leak native image memory. (#41902) Thanks @Kaneki-x.
|
||||
- Telegram/message chunking: preserve spaces, paragraph separators, and word boundaries when HTML overflow rechunking splits formatted replies. (#47274) Thanks @obviyus.
|
||||
- Z.AI/onboarding: detect a working default model even for explicit `zai-coding-*` endpoint choices, so Coding Plan setup can keep the selected endpoint while defaulting to `glm-5` when available or `glm-4.7` as fallback. (#45969) Thanks @obviyus.
|
||||
- CI/onboarding smoke: surface `ensure-base-commit` fetch failures as workflow warnings and fail the onboarding Docker smoke when expected setup prompts drift instead of continuing silently. Thanks @Takhoffman.
|
||||
- Z.AI/onboarding: add `glm-5-turbo` to the default Z.AI provider catalog so onboarding-generated configs expose the new model alongside the existing GLM defaults. (#46670) Thanks @tomsun28.
|
||||
- Zalo Personal/group gating: stop reapplying `dmPolicy.allowFrom` as a sender gate for already-allowlisted groups when `groupAllowFrom` is unset, so any member of an allowed group can trigger replies while DMs stay restricted. (#46663) Fixes #40146. Thanks @Takhoffman.
|
||||
- Zalo/plugin runtime: export `resolveClientIp` from `openclaw/plugin-sdk/zalo` so installed builds no longer crash on startup when the webhook monitor loads from the packaged extension instead of the monorepo source tree. (#46549) Thanks @No898.
|
||||
- Onboarding/custom providers: store Azure OpenAI and Azure AI Foundry custom endpoints with the Responses API config shape, normalized `/openai/v1` base URLs, and Azure-safe defaults so TUI and agent runs work after setup. (#49543) Thanks @kunalk16.
|
||||
- Docker/live tests: mount external CLI auth homes into writable container copies, derive Codex OAuth expiry from JWT `exp`, refresh synced CLI creds instead of trusting stale cached expiry, and make gateway live probes wait on transcript output so `pnpm test:docker:all` stays green in Linux.
|
||||
- Plugins/install precedence: keep bundled plugins ahead of auto-discovered globals by default, but let an explicitly installed plugin record win its own duplicate-id tie so installed channel plugins load from `~/.openclaw/extensions` after `openclaw plugins install`. (#46722) Thanks @Takhoffman.
|
||||
- Control UI/logging: make browser-safe logger imports avoid eager temp-dir resolution so the bundled Control UI no longer crashes to a blank screen when logging reaches `tmp-openclaw-dir`. (#48469) Fixes #48062. Thanks @7inspire.
|
||||
- Plugins/scoped ids: preserve scoped plugin ids during install and config keying, and keep bundled plugins ahead of discovered duplicate ids by default so `@scope/name` plugins no longer collide with unscoped installs. (#47413) Thanks @vincentkoc.
|
||||
- Gateway/watch mode: restart on bundled-plugin package and manifest metadata changes, rebuild `dist` for extension source and `tsdown.config.ts` changes, and still ignore extension docs. (#47571) Thanks @gumadeiras.
|
||||
- Gateway/watch mode: recreate bundled plugin runtime metadata after clean or stale `dist` states, so `pnpm gateway:watch` no longer fails on missing `dist/extensions/*/openclaw.plugin.json` manifests after a rebuild. Thanks @gumadeiras.
|
||||
- Control UI/chat sessions: show human-readable labels in the grouped session dropdown again, keep unique scoped fallbacks when metadata is missing, and disambiguate duplicate labels only when needed. (#45130) Thanks @luzhidong.
|
||||
- Control UI: scope persisted session selection per gateway, prevent stale session bleed across tokenized gateway opens, and cap stored gateway session history. (#47453) Thanks @sallyom.
|
||||
- Control UI/dashboard: preserve structured gateway shutdown reasons across restart disconnects so config-triggered restarts no longer fall back to `disconnected (1006): no reason`. (#46580) Fixes #46532. Thanks @vincentkoc.
|
||||
- Models/OpenAI Codex OAuth: start the remote manual-input race for Codex login and keep the pasted-input prompt aligned with the actual accepted values, so remote/VPS auth no longer stalls waiting on an unreachable localhost callback. (#51631) Thanks @cash-echo-bot.
|
||||
- Android/chat: theme the thinking dropdown and TLS trust dialogs explicitly so popup surfaces match the active app theme instead of falling back to mismatched Material defaults.
|
||||
- Group mention gating: reject invalid and unsafe nested-repetition `mentionPatterns`, reuse the shared safe config-regex compiler across mention stripping and detection, and cache strip-time regex compilation so noisy groups avoid repeated recompiles.
|
||||
- Browser/profiles: drop the auto-created `chrome-relay` browser profile; users who need the Chrome extension relay must now create their own profile via `openclaw browser create-profile`. (#46596) Fixes #45777. Thanks @odysseus0.
|
||||
- CI/channel test routing: move the built-in channel suites into `test:channels` and keep them out of `test:extensions`, so extension CI no longer fails after the channel migration while targeted test routing still sends Slack, Signal, and iMessage suites to the right lane. (#46066) Thanks @scoootscooob.
|
||||
- Docs/Mintlify: fix MDX marker syntax on Perplexity, Model Providers, Moonshot, and exec approvals pages so local docs preview no longer breaks rendering or leaves stale pages unpublished. (#46695) Thanks @velvet-shark.
|
||||
- Plugins/runtime barrels: route bundled extension runtime imports through public `openclaw/plugin-sdk/*` subpaths and block relative cross-package escapes so packaged extensions stop depending on monorepo-only relative paths. (#51939) Thanks @vincentkoc.
|
||||
- Gateway/config validation: stop treating the implicit default memory slot as a required explicit plugin config, so startup no longer fails with `plugins.slots.memory: plugin not found: memory-core` when `memory-core` was only inferred. (#47494) Thanks @ngutman.
|
||||
- Tlon: honor explicit empty allowlists and defer cite expansion. (#46788) Thanks @zpbrent and @vincentkoc.
|
||||
- Tlon/DM auth: defer cited-message expansion until after DM authorization and owner command handling, so unauthorized DMs and owner approval/admin commands no longer trigger cross-channel cite fetches before the deny or command path.
|
||||
- Gateway/agent events: stop broadcasting false end-of-run `seq gap` errors to clients, and isolate node-driven ingress turns with per-turn run IDs so stale tail events cannot leak into later session runs. (#43751) Thanks @caesargattuso.
|
||||
- Docs/security audit: spell out that `gateway.controlUi.allowedOrigins: ["*"]` is an explicit allow-all browser-origin policy and should be avoided outside tightly controlled local testing.
|
||||
- Gateway/auth: clear self-declared scopes for device-less trusted-proxy Control UI sessions so proxy-authenticated connects cannot claim admin or secrets scopes without a bound device identity.
|
||||
- Nodes/pending actions: re-check queued foreground actions against the current node command policy before returning them to the node. (#46815) Thanks @zpbrent and @vincentkoc.
|
||||
- Node/startup: remove leftover debug `console.log("node host PATH: ...")` that printed the resolved PATH on every `openclaw node run` invocation. (#46515) Fixes #46411. Thanks @ademczuk.
|
||||
- CLI/completion: reduce recursive completion-script string churn and fix nested PowerShell command-path matching so generated nested completions resolve on PowerShell too. (#45537) Thanks @yiShanXin and @vincentkoc.
|
||||
- Slack/startup: harden `@slack/bolt` import interop across current bundled runtime shapes so Slack monitors no longer crash with `App is not a constructor` after plugin-sdk bundling changes. (#45953) Thanks @merc1305.
|
||||
- Windows/gateway status: accept `schtasks` `Last Result` output as an alias for `Last Run Result`, so running scheduled-task installs no longer show `Runtime: unknown`. (#47844) Thanks @MoerAI.
|
||||
- ACP/acpx: resolve the bundled plugin root from the actual plugin directory so plugin-local installs stay under `dist/extensions/acpx` instead of escaping to `dist/extensions` and failing runtime setup. (#47601) Thanks @ngutman.
|
||||
- Gateway/WS handshake: raise the default pre-auth handshake timeout to 10 seconds and add `OPENCLAW_HANDSHAKE_TIMEOUT_MS` as a runtime override so busy local gateways stop dropping healthy CLI connections at 3 seconds. (#49262) Thanks @fuller-stack-dev.
|
||||
- Gateway/websocket pairing bypass for disabled auth: skip device-pairing enforcement for Control UI operator sessions when `gateway.auth.mode=none`, so reverse-proxied dashboards no longer get stuck on `pairing required` despite auth being explicitly disabled. (#47148) Thanks @ademczuk.
|
||||
- Control UI/model switching: preserve the selected provider prefix when switching models from the chat dropdown, so multi-provider setups no longer send `anthropic/gpt-5.2`-style mismatches when the user picked `openai/gpt-5.2`. (#47581) Thanks @chrishham.
|
||||
- Control UI/storage: scope persisted settings keys by gateway base path, with migration from the legacy shared key, so multiple gateways under one domain stop overwriting each other's dashboard preferences. (#47932) Thanks @bobBot-claw.
|
||||
- Agents/usage tracking: stop forcing `supportsUsageInStreaming: false` on non-native OpenAI-completions providers so compatible backends report token usage and cost again instead of showing all zeros. (#46500) Fixes #46142. Thanks @ademczuk.
|
||||
- ACP/acpx: keep plugin-local backend installs under `extensions/acpx` in live repo checkouts so rebuilds no longer delete the runtime binary, and avoid package-lock churn during runtime repair.
|
||||
- Plugins/subagents: preserve gateway-owned plugin subagent access across runtime, tool, and embedded-runner load paths so gateway plugin tools and context engines can still spawn and manage subagents after the loader cache split. (#46648) Thanks @jalehman.
|
||||
- Control UI/overview: keep the language dropdown aligned with the persisted locale during dashboard startup so refreshing the page does not fall back to English before locale hydration completes. (#48019) Thanks @git-jxj.
|
||||
- Agents/compaction: rerun transcript repair after `session.compact()` so orphaned `tool_result` blocks cannot survive compaction and break later Anthropic requests. (#16095) thanks @claw-sylphx.
|
||||
- Agents/compaction: trigger overflow recovery from the tool-result guard once post-compaction context still exceeds the safe threshold, so long tool loops compact before the next model call hard-fails. (#29371) thanks @keshav55.
|
||||
- macOS/exec approvals: harden exec-host request HMAC verification to use a timing-safe compare and keep malformed or truncated signatures fail-closed in focused IPC auth coverage.
|
||||
- Gateway/exec approvals: surface requested env override keys in gateway-host approval prompts so operators can review surviving env context without inheriting noisy base host env.
|
||||
- Telegram/network: preserve sticky IPv4 fallback state across polling restarts so hosts with unstable IPv6 to `api.telegram.org` stop re-triggering repeated Telegram timeouts after each restart. (#48282) Thanks @yassinebkr.
|
||||
- Plugins/subagents: forward per-run provider and model overrides through gateway plugin subagent dispatch so plugin-launched agent delegations honor explicit model selection again. (#48277) Thanks @jalehman.
|
||||
- Agents/compaction: write minimal boundary summaries for empty preparations while keeping split-turn prefixes on the normal path, so no-summarizable-message sessions stop retriggering the safeguard loop. (#42215) thanks @lml2468.
|
||||
- Models/chat commands: keep `/model ...@YYYYMMDD` version suffixes intact by default, but still honor matching stored numeric auth-profile overrides for the same provider. (#48896) Thanks @Alix-007.
|
||||
- Gateway/channels: serialize per-account channel startup so overlapping starts do not boot the same provider twice, preventing MS Teams `EADDRINUSE` crash loops during startup and restart. (#49583) Thanks @sudie-codes.
|
||||
- Tests/OpenAI Codex auth: align login expectations with the default `gpt-5.4` model so CI coverage stays consistent with the current OpenAI Codex default. (#44367) Thanks @jrrcdev.
|
||||
- Discord: enforce strict DM component allowlist auth (#49997) Thanks @joshavant.
|
||||
- Stabilize plugin loader and Docker extension smoke (#50058) Thanks @joshavant.
|
||||
- Telegram: stabilize pairing/session/forum routing and reply formatting tests (#50155) Thanks @joshavant.
|
||||
- Hardening: refresh stale device pairing requests and pending metadata (#50695) Thanks @smaeljaish771 and @joshavant.
|
||||
- Gateway: harden OpenResponses file-context escaping (#50782) Thanks @YLChen-007 and @joshavant.
|
||||
- LINE: harden Express webhook parsing to verified raw body (#51202) Thanks @gladiator9797 and @joshavant.
|
||||
- Exec: harden host env override handling across gateway and node (#51207) Thanks @gladiator9797 and @joshavant.
|
||||
- Voice Call: enforce spoken-output contract and fix stream TTS silence regression (#51500) Thanks @joshavant.
|
||||
- xAI/models: rename the bundled Grok 4.20 catalog entries to the GA IDs and normalize saved deprecated beta IDs at runtime so existing configs and sessions keep resolving. (#50772) thanks @Jaaneek
|
||||
- Plugins/Matrix TTS: send auto-TTS replies as native Matrix voice bubbles instead of generic audio attachments. (#37080) thanks @Matthew19990919.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Agents/bootstrap warnings: move bootstrap truncation warnings out of the system prompt and into the per-turn prompt body so prompt-cache reuse stays stable when truncation warnings appear or disappear. (#48753) Thanks @scoootscooob and @obviyus.
|
||||
- Telegram/DM topic session keys: route named-account DM topics through the same per-account base session key across inbound messages, native commands, and session-state lookups so `/status` and thread recovery stop creating phantom `agent:main:main:thread:...` sessions. (#48204) Thanks @vincentkoc.
|
||||
- macOS/node service startup: use `openclaw node start/stop --json` from the Mac app instead of the removed `openclaw service node ...` command shape, so current CLI installs expose the full node exec surface again. (#46843) Fixes #43171. Thanks @Br1an67.
|
||||
- macOS/launch at login: stop emitting `KeepAlive` for the desktop app launch agent so OpenClaw no longer relaunches immediately after a manual quit while launch at login remains enabled. (#40213) Thanks @stablegenius49.
|
||||
- ACP/gateway startup: use direct Telegram and Discord startup/status helpers instead of routing probes through the plugin runtime, and prepend the selected daemon Node bin dir to service PATH so plugin-local installs can still find `npm` and `pnpm`.
|
||||
- ACP/configured bindings: reinitialize configured ACP sessions that are stuck in `error` state instead of reusing the failed runtime.
|
||||
- Mattermost/DM send: retry transient direct-channel creation failures for DM deliveries, with configurable backoff and per-request timeout. (#42398) Thanks @JonathanJing.
|
||||
- Telegram/network: unify API and media fetches under the same sticky IPv4 and pinned-IP fallback chain, and re-validate pinned override addresses against SSRF policy. (#49148) Thanks @obviyus.
|
||||
- Agents/prompt composition: append bootstrap truncation warnings to the current-turn prompt and add regression coverage for stable system-prompt cache invariants. (#49237) Thanks @scoootscooob.
|
||||
- Gateway/auth: add regression coverage that keeps device-less trusted-proxy Control UI sessions off privileged pairing approval RPCs. Thanks @vincentkoc.
|
||||
- Plugins/runtime-api: pin extension runtime-api export surfaces with explicit guardrail coverage so future surface creep becomes a deliberate diff. Thanks @vincentkoc.
|
||||
- Synology Chat/multi-account: scope direct-message sessions by account and sender so identical webhook `user_id` values on different Synology accounts no longer share transcript or delivery state.
|
||||
- Telegram/security: add regression coverage proving pinned fallback host overrides stay bound to Telegram and delegate non-matching hostnames back to the original lookup path. Thanks @vincentkoc.
|
||||
- Secrets/exec refs: require explicit `--allow-exec` for `secrets apply` write plans that contain exec SecretRefs/providers, and align audit/configure/apply dry-run behavior to skip exec checks unless opted in to prevent unexpected command side effects. (#49417) Thanks @restriction and @joshavant.
|
||||
- Tools/image generation: add bundled fal image generation support so `image_generate` can target `fal/*` models with `FAL_KEY`, including single-image edit flows via FLUX image-to-image. Thanks @vincentkoc.
|
||||
- Gateway/hooks: preserve immutable hook ingress provenance across async isolated-agent dispatch so normalized hook session routes keep external wrapping, Gmail-specific policy, and Gmail model selection intact.
|
||||
- Messages/polls: treat zero-valued poll params on `message.send` as unset defaults while keeping non-zero poll params on the poll validation path. (#52150) Fixes #52118. Thanks @Bartok9.
|
||||
- xAI/web search: add missing Grok credential metadata so the bundled provider registration type-checks again. (#49472) thanks @scoootscooob.
|
||||
- Agents/session cache: opportunistically sweep expired embedded-runner session cache entries during later cache activity, so one-shot session files do not accumulate forever. (#52427) Thanks @karanuppal.
|
||||
- Signal/runtime API: re-export `SignalAccountConfig` so Signal account resolution type-checks again. (#49470) Thanks @scoootscooob.
|
||||
- Google Chat/runtime API: thin the private runtime barrel onto the curated public SDK surface while keeping public Google Chat exports intact. (#49504) Thanks @scoootscooob.
|
||||
- WhatsApp: stabilize inbound monitor and setup tests (#50007) Thanks @joshavant.
|
||||
- Matrix: make onboarding status runtime-safe (#49995) Thanks @joshavant.
|
||||
- Channels: stabilize lane harness and monitor tests (#50167) Thanks @joshavant.
|
||||
- WhatsApp/active-listener: pin the active listener registry to a `globalThis` singleton so split WhatsApp bundle chunks share one listener map and outbound sends stop missing the registered session. (#47433) Thanks @clawdia67.
|
||||
- Plugins/WhatsApp: share split-load singleton state for plugin command registration and active WhatsApp listeners so duplicate module graphs no longer lose native plugin commands or outbound listener state. (#50418) Thanks @huntharo.
|
||||
- Onboarding/custom providers: keep Azure AI Foundry `*.services.ai.azure.com` custom endpoints on the selected compatibility path instead of forcing Responses, so chat-completions Foundry models still work after setup. Fixes #50528. (#50535) Thanks @obviyus.
|
||||
- Plugins/update: let `openclaw plugins update <npm-spec>` target tracked npm installs by dist-tag or exact version, and preserve the recorded npm spec for later id-based updates. (#49998) Thanks @huntharo.
|
||||
- Tests/CLI: reduce command-secret gateway test import pressure while keeping the real protocol payload validator in place, so the isolated lane no longer carries the heavier runtime-web and message-channel graphs. (#50663) Thanks @huntharo.
|
||||
- Gateway/plugins: share plugin interactive callback routing and plugin bind approval state across duplicate module graphs so Telegram Codex picker buttons and plugin bind approvals no longer fall through to normal inbound message routing. (#50722) Thanks @huntharo.
|
||||
- Agents/compaction: add an opt-in post-compaction session JSONL truncation step that drops summarized transcript entries while preserving the retained branch tail and live session metadata. (#41021) thanks @thirumaleshp.
|
||||
- Telegram/routing: fail loud when `message send` targets an unknown non-default Telegram `accountId`, instead of silently falling back to the channel-level bot token and sending through the wrong bot. (#50853) Thanks @hclsys.
|
||||
- Web search: align onboarding, configure, and finalize with plugin-owned provider contracts, including disabled-provider recovery, config-aware credential hooks, and runtime-visible summaries. (#50935) Thanks @gumadeiras.
|
||||
- Agents/replay: sanitize malformed assistant tool-call replay blocks before provider replay so follow-up Anthropic requests do not inherit the downstream `replace` crash. (#50005) Thanks @jalehman.
|
||||
- Discord/startup logging: report client initialization while the gateway is still connecting instead of claiming Discord is logged in before readiness is reached. (#51425) Thanks @scoootscoob.
|
||||
- Agents/compaction safeguard: preserve split-turn context and preserved recent turns when capped retry fallback reuses the last successful summary. (#27727) thanks @Pandadadadazxf.
|
||||
- Agents/memory flush: keep transcript-hash dedup active across memory-flush fallback retries so a write-then-throw flush attempt cannot append duplicate `MEMORY.md` entries before the fallback cycle completes. (#34222) Thanks @lml2468.
|
||||
- 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.
|
||||
- ACP/Codex session replay: preserve hidden assistant thinking when loading or rebinding existing ACP sessions so stored thought chunks do not replay into visible assistant text. Thanks @vincentkoc.
|
||||
- Gateway/commands: keep internal `chat.send` slash-command UX while requiring `operator.admin` before internal callers can persist `/exec` defaults or mutate `phone-control` node policy through `/phone arm|disarm`.
|
||||
- Plugins/Matrix: move bundled plugin `KeyedAsyncQueue` imports onto the stable `plugin-sdk/core` surface so Matrix Docker/runtime builds do not depend on the brittle keyed-async-queue subpath. Thanks @ecohash-co and @vincentkoc.
|
||||
- Plugins/context engines: enforce owner-aware context-engine registration on both loader and public SDK paths so plugins cannot spoof privileged ownership, claim the core `legacy` engine id, or overwrite an existing engine id through direct SDK imports. (#47595) Thanks @vincentkoc.
|
||||
- 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.
|
||||
- Plugins/install precedence: keep bundled plugins ahead of auto-discovered globals by default, but let an explicitly installed plugin record win its own duplicate-id tie so installed channel plugins load from `~/.openclaw/extensions` after `openclaw plugins install`. (#46722) Thanks @Takhoffman.
|
||||
- Plugins/scoped ids: preserve scoped plugin ids during install and config keying, and keep bundled plugins ahead of discovered duplicate ids by default so `@scope/name` plugins no longer collide with unscoped installs. (#47413) Thanks @vincentkoc.
|
||||
- Docs/Mintlify: fix MDX marker syntax on Perplexity, Model Providers, Moonshot, and exec approvals pages so local docs preview no longer breaks rendering or leaves stale pages unpublished. (#46695) Thanks @velvet-shark.
|
||||
- Plugins/runtime barrels: route bundled extension runtime imports through public `openclaw/plugin-sdk/*` subpaths and block relative cross-package escapes so packaged extensions stop depending on monorepo-only relative paths. (#51939) Thanks @vincentkoc.
|
||||
- Docs/security audit: spell out that `gateway.controlUi.allowedOrigins: ["*"]` is an explicit allow-all browser-origin policy and should be avoided outside tightly controlled local testing.
|
||||
- Plugins/subagents: preserve gateway-owned plugin subagent access across runtime, tool, and embedded-runner load paths so gateway plugin tools and context engines can still spawn and manage subagents after the loader cache split. (#46648) Thanks @jalehman.
|
||||
- Plugins/subagents: forward per-run provider and model overrides through gateway plugin subagent dispatch so plugin-launched agent delegations honor explicit model selection again. (#48277) Thanks @jalehman.
|
||||
- Tests/OpenAI Codex auth: align login expectations with the default `gpt-5.4` model so CI coverage stays consistent with the current OpenAI Codex default. (#44367) Thanks @jrrcdev.
|
||||
- Plugins/Matrix TTS: send auto-TTS replies as native Matrix voice bubbles instead of generic audio attachments. (#37080) thanks @Matthew19990919.
|
||||
- Plugins/discovery: distinguish missing package entry files from package-path escape violations so startup skips absent plugin entry paths without raising false security diagnostics. (#52491) Thanks @hclsys.
|
||||
- Plugins/Matrix: accept shared send-tool media aliases (`mediaUrl`, `filePath`, `path`) and preserve `asVoice` / `audioAsVoice` through Matrix action dispatch so media-only sends and voice-message intents reach the plugin send layer correctly. Thanks @psacc and @vincentkoc.
|
||||
- Plugins/runtime-api: pin extension runtime-api export surfaces with explicit guardrail coverage so future surface creep becomes a deliberate diff. Thanks @vincentkoc.
|
||||
- Plugins/WhatsApp: share split-load singleton state for plugin command registration and active WhatsApp listeners so duplicate module graphs no longer lose native plugin commands or outbound listener state. (#50418) Thanks @huntharo.
|
||||
- Plugins/update: let `openclaw plugins update <npm-spec>` target tracked npm installs by dist-tag or exact version, and preserve the recorded npm spec for later id-based updates. (#49998) Thanks @huntharo.
|
||||
- Tests/CLI: reduce command-secret gateway test import pressure while keeping the real protocol payload validator in place, so the isolated lane no longer carries the heavier runtime-web and message-channel graphs. (#50663) Thanks @huntharo.
|
||||
- Gateway/plugins: share plugin interactive callback routing and plugin bind approval state across duplicate module graphs so Telegram Codex picker buttons and plugin bind approvals no longer fall through to normal inbound message routing. (#50722) Thanks @huntharo.
|
||||
- Plugins/context engines: retry strict legacy `assemble()` calls without the new `prompt` field when older engines reject it, preserving prompt-aware retrieval compatibility for pre-prompt plugins. (#50848) thanks @danhdoan.
|
||||
- make `openclaw update status` explicitly say `up to date` when the local version already matches npm latest, while keeping the availability logic unchanged. (#51409) Thanks @dongzhenye.
|
||||
- Agents/embedded transport errors: distinguish common network failures like connection refused, DNS lookup failure, and interrupted sockets from true timeouts in embedded-run user messaging and lifecycle diagnostics. (#51419) Thanks @scoootscooob.
|
||||
- Discord/startup logging: report client initialization while the gateway is still connecting instead of claiming Discord is logged in before readiness is reached. (#51425) Thanks @scoootscoob.
|
||||
- Gateway/probe: honor caller `--timeout` for active local loopback probes in `gateway status`, keep inactive remote-mode loopback probes fast, and clamp probe timers to JS-safe bounds so slow local/container gateways stop reporting false timeouts. (#47533) Thanks @MonkeyLeeT.
|
||||
- Config/startup: keep bundled web-search allowlist compatibility on a lightweight manifest path so config validation no longer pulls bundled web-search registry imports into startup, while still avoiding accidental auto-allow of config-loaded override plugins. (#51574) Thanks @RichardCao.
|
||||
- Gateway/chat.send: persist uploaded image references across reloads and compaction without delaying first-turn dispatch or double-submitting the same image to vision models. (#51324) Thanks @fuller-stack-dev.
|
||||
- Plugins/runtime state: share plugin-facing infra singleton state across duplicate module graphs and keep session-binding adapter ownership stable until the active owner unregisters. (#50725) thanks @huntharo.
|
||||
- Agents/compaction safeguard: preserve split-turn context and preserved recent turns when capped retry fallback reuses the last successful summary. (#27727) thanks @Pandadadadazxf.
|
||||
- Discord/pickers: keep `/codex_resume --browse-projects` picker callbacks alive in Discord by sharing component callback state across duplicate module graphs, preserving callback fallbacks, and acknowledging matched plugin interactions before dispatch. (#51260) Thanks @huntharo.
|
||||
- Memory/core tools: register `memory_search` and `memory_get` independently so one unavailable memory tool no longer suppresses the other in new sessions. (#50198) Thanks @artwalker.
|
||||
- Telegram/Mattermost message tool: keep plugin button schemas optional in isolated and cron sessions so plain sends do not fail validation when no current channel is active. (#52589) Thanks @tylerliu612.
|
||||
- Release/npm publish: fail the npm release check when `dist/control-ui/index.html` is missing from the packed tarball, so broken Control UI asset releases are blocked before publish. Fixes #52808. (#52852) Thanks @kevinheinrichs.
|
||||
- Slack/embedded delivery: suppress transcript-only `delivery-mirror` assistant messages before embedded re-delivery and raise the default Slack chunk fallback so messages just over 4000 characters stay in a single post. (#45489) Thanks @theo674.
|
||||
- Slack/embedded delivery: suppress transcript-only `delivery-mirror` assistant messages before embedded re-delivery and raise the default Slack chunk fallback so messages just over 4000 characters stay in a single post. (#45489) Thanks @theo674.
|
||||
- Agents/memory flush: keep transcript-hash dedup active across memory-flush fallback retries so a write-then-throw flush attempt cannot append duplicate `MEMORY.md` entries before the fallback cycle completes. (#34222) Thanks @lml2468.
|
||||
- make `openclaw update status` explicitly say `up to date` when the local version already matches npm latest, while keeping the availability logic unchanged. (#51409) Thanks @dongzhenye.
|
||||
- Android/canvas: recycle captured and scaled snapshot bitmaps so repeated canvas snapshots do not leak native image memory. (#41889) Thanks @Kaneki-x.
|
||||
- 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.
|
||||
|
||||
### Fixes
|
||||
### Breaking
|
||||
|
||||
- Agents/edit tool: accept common path/text alias spellings, show current file contents on exact-match failures, and avoid false edit failures after successful writes. (#52516) thanks @mbelinky.
|
||||
- Skills/image generation: remove the bundled `nano-banana-pro` skill wrapper. Use `agents.defaults.imageGenerationModel.primary: "google/gemini-3-pro-image-preview"` for the native Nano Banana-style path instead.
|
||||
|
||||
- Browser/Chrome MCP: remove the legacy Chrome extension relay path, bundled extension assets, `driver: "extension"`, and `browser.relayBindHost`. Run `openclaw doctor --fix` to migrate host-local browser config to `existing-session` / `user`; Docker, headless, sandbox, and remote browser flows still use raw CDP. (#47893) Thanks @vincentkoc.
|
||||
- Plugins/runtime: remove the public `openclaw/extension-api` surface with no compatibility shim. Bundled plugins must use injected runtime for host-side operations (for example `api.runtime.agent.runEmbeddedPiAgent`) and any remaining direct imports must come from narrow `openclaw/plugin-sdk/*` subpaths instead of the monolithic SDK root.
|
||||
- Tools/image generation: standardize the stock image create/edit path on the core `image_generate` tool. The old `nano-banana-pro` docs/examples are gone; if you previously copied that sample-skill config, switch to `agents.defaults.imageGenerationModel` for built-in image generation or install a separate third-party skill explicitly.
|
||||
- Skills/image generation: remove the bundled `nano-banana-pro` skill wrapper. Use `agents.defaults.imageGenerationModel.primary: "google/gemini-3-pro-image-preview"` for the native Nano Banana-style path instead.
|
||||
- Plugins/message discovery: require `ChannelMessageActionAdapter.describeMessageTool(...)` for shared `message` tool discovery. The legacy `listActions`, `getCapabilities`, and `getToolSchema` adapter methods are removed. Plugin authors should migrate message discovery to `describeMessageTool(...)` and keep channel-specific action runtime code inside the owning plugin package. Thanks @gumadeiras.
|
||||
- Exec/env sandbox: block build-tool JVM injection (`MAVEN_OPTS`, `SBT_OPTS`, `GRADLE_OPTS`, `ANT_OPTS`), glibc tunable exploitation (`GLIBC_TUNABLES`), and .NET dependency resolution hijack (`DOTNET_ADDITIONAL_DEPS`) from the host exec environment, and restrict Gradle init script redirect (`GRADLE_USER_HOME`) as an override-only block so user-configured Gradle homes still propagate. (#49702)
|
||||
- Plugins/Matrix: add a new Matrix plugin backed by the official `matrix-js-sdk`. If you are upgrading from the previous public Matrix plugin, follow the migration guide: https://docs.openclaw.ai/install/migrating-matrix Thanks @gumadeiras.
|
||||
- Discord/commands: switch native command deployment to Carbon reconcile by default so Discord restarts stop churning slash commands through OpenClaw’s local deploy path. (#46597) Thanks @huntharo and @thewilloftheshadow.
|
||||
- Plugins/Matrix: durably dedupe inbound room events across gateway restarts so previously handled Matrix messages are not replayed as new, while preserving clean-restart backlog delivery for unseen events. (#50922) thanks @gumadeiras
|
||||
- Agents/media replies: migrate the remaining browser, canvas, and nodes snapshot outputs onto `details.media` so generated media keeps attaching to assistant replies after the collect-then-attach refactor. (#51731) Thanks @christianklotz.
|
||||
- Android/contacts search: escape literal `%` and `_` in contact-name queries so searches like `100%` or `_id` no longer match unrelated contacts through SQL `LIKE` wildcards. (#41891) Thanks @Kaneki-x.
|
||||
|
||||
## 2026.3.13
|
||||
|
||||
@@ -760,12 +554,6 @@ Docs: https://docs.openclaw.ai
|
||||
- Gateway/node pending drain followup: keep `hasMore` true when the deferred baseline status item still needs delivery, and avoid allocating empty pending-work state for drain-only nodes with no queued work. (#41429) Thanks @mbelinky.
|
||||
- Protocol/Swift model sync: regenerate pending node work Swift bindings after the landed `node.pending.*` schema additions so generated protocol artifacts are consistent again. (#41477) Thanks @mbelinky.
|
||||
- Cron/subagent followup: do not misclassify empty or `NO_REPLY` cron responses as interim acknowledgements that need a rerun, so deliberately silent cron jobs are no longer retried. (#41383) thanks @jackal092927.
|
||||
- CLI/memory teardown: close cached memory search/index managers in the one-shot CLI shutdown path so watcher-backed memory caches no longer keep completed CLI runs alive after output finishes. (#40389) thanks @Julbarth.
|
||||
- Tools/web search: treat Brave `llm-context` grounding snippets as plain strings so `web_search` no longer returns empty snippet arrays in LLM Context mode. (#41387) thanks @zheliu2.
|
||||
- ACP/run-mode delivery: restore inline delivery for one-shot ACP run spawns from non-subagent (main) requester sessions so completions reach the originating Discord/Telegram/etc. channel again. Subagent orchestrators continue to use stream-to-parent when an active heartbeat relay route is available. (#52426) Thanks @distractedCoding.
|
||||
- Telegram/exec approvals: reject `/approve` commands aimed at other bots, keep deterministic approval prompts visible when tool-result delivery fails, and stop resolved exact IDs from matching other pending approvals by prefix. (#37233) Thanks @huntharo.
|
||||
- Control UI/Sessions: restore single-column session table collapse on narrow viewport or container widths by moving the responsive table override next to the base grid rule and enabling inline-size container queries. (#12175) Thanks @benjipeng.
|
||||
- Telegram/final preview delivery: split active preview lifecycle from cleanup retention so missing archived preview edits avoid duplicate fallback sends without clearing the live preview or blocking later in-place finalization. (#41662) thanks @hougangdev.
|
||||
- Cron/state errors: record `lastErrorReason` in cron job state and keep the gateway schema aligned with the full failover-reason set, including regression coverage for protocol conformance. (#14382) thanks @futuremind2026.
|
||||
- Browser/Browserbase 429 handling: surface stable no-retry rate-limit guidance without buffering discarded HTTP 429 response bodies from remote browser services. (#40491) thanks @mvanhorn.
|
||||
- CI/CodeQL Swift toolchain: select Xcode 26.1 before installing Swift build tools so the CodeQL Swift job uses Swift tools 6.2 on `macos-latest`. (#41787) thanks @BunsDev.
|
||||
|
||||
@@ -24,7 +24,7 @@ Welcome to the lobster tank! 🦞
|
||||
- GitHub: [@joshp123](https://github.com/joshp123) · X: [@jjpcodes](https://x.com/jjpcodes)
|
||||
|
||||
- **Ayaan Zaidi** - Telegram subsystem, Android app
|
||||
- GitHub: [@obviyus](https://github.com/obviyus) · X: [@obviyus](https://x.com/obviyus)
|
||||
- GitHub: [@obviyus](https://github.com/obviyus) · X: [@0bviyus](https://x.com/0bviyus)
|
||||
|
||||
- **Tyler Yust** - Agents/subagents, cron, BlueBubbles, macOS app
|
||||
- GitHub: [@tyler6204](https://github.com/tyler6204) · X: [@tyleryust](https://x.com/tyleryust)
|
||||
@@ -58,7 +58,6 @@ Welcome to the lobster tank! 🦞
|
||||
|
||||
- **Jonathan Taylor** - ACP subsystem, Gateway features/bugs, Gog/Mog/Sog CLI's, SEDMAT
|
||||
- GitHub [@visionik](https://github.com/visionik) · X: [@visionik](https://x.com/visionik)
|
||||
|
||||
- **Josh Lehman** - Compaction, Tlon/Urbit subsystem
|
||||
- GitHub [@jalehman](https://github.com/jalehman) · X: [@jlehman\_](https://x.com/jlehman_)
|
||||
|
||||
@@ -77,6 +76,9 @@ Welcome to the lobster tank! 🦞
|
||||
- **Tengji (George) Zhang** - Chinese model APIs, cloud, pi
|
||||
- GitHub: [@odysseus0](https://github.com/odysseus0) · X: [@odysseus0z](https://x.com/odysseus0z)
|
||||
|
||||
- **Andrew (Bubbles) Demczuk** - Agents/Gateway/TTS/VTT
|
||||
- GitHub: [@ademczuk](https://github.com/ademczuk) · X: [@ademczuk](https://x.com/ademczuk)
|
||||
|
||||
## How to Contribute
|
||||
|
||||
1. **Bugs & small fixes** → Open a PR!
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
# 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"
|
||||
@@ -114,7 +113,6 @@ 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:
|
||||
@@ -131,14 +129,10 @@ 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 && \
|
||||
if [ "${OPENCLAW_DOCKER_APT_UPGRADE}" != "0" ]; then \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends; \
|
||||
fi && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get upgrade -y --no-install-recommends && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
procps hostname curl git lsof openssl
|
||||
|
||||
|
||||
115
appcast.xml
115
appcast.xml
@@ -2,47 +2,6 @@
|
||||
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
|
||||
<channel>
|
||||
<title>OpenClaw</title>
|
||||
<item>
|
||||
<title>2026.3.23</title>
|
||||
<pubDate>Mon, 23 Mar 2026 16:59:51 -0700</pubDate>
|
||||
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
|
||||
<sparkle:version>2026032390</sparkle:version>
|
||||
<sparkle:shortVersionString>2026.3.23</sparkle:shortVersionString>
|
||||
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
|
||||
<description><![CDATA[<h2>OpenClaw 2026.3.23</h2>
|
||||
<h3>Breaking</h3>
|
||||
<h3>Changes</h3>
|
||||
<h3>Fixes</h3>
|
||||
<ul>
|
||||
<li>Browser/Chrome MCP: wait for existing-session browser tabs to become usable after attach instead of treating the initial Chrome MCP handshake as ready, which reduces user-profile timeouts and repeated consent churn on macOS Chrome attach flows. Fixes #52930. Thanks @vincentkoc.</li>
|
||||
<li>Browser/CDP: reuse an already-running loopback browser after a short initial reachability miss instead of immediately falling back to relaunch detection, which fixes second-run browser start/open regressions on slower headless Linux setups. Fixes #53004. Thanks @vincentkoc.</li>
|
||||
<li>ClawHub/macOS auth: honor macOS auth config and XDG auth paths for saved ClawHub credentials, so <code>openclaw skills ...</code> and gateway skill browsing keep using the signed-in auth state instead of silently falling back to unauthenticated mode. Fixes #53034.</li>
|
||||
<li>ClawHub/macOS: read the local ClawHub login from the macOS Application Support path and still honor XDG config on macOS, so skill browsing uses the logged-in token on both default and XDG-style setups. Fixes #52949. Thanks @scoootscooob.</li>
|
||||
<li>ClawHub/skills: resolve the local ClawHub auth token for gateway skill browsing and switch browse-all requests to search so ClawControl stops falling into unauthenticated 429s and empty authenticated skill lists. Fixes #52949. Thanks @vincentkoc.</li>
|
||||
<li>Plugins/message tool: make Discord <code>components</code> and Slack <code>blocks</code> optional again, and route Feishu <code>message(..., media=...)</code> sends through the outbound media path, so pin/unpin/react flows stop failing schema validation and Feishu file/image attachments actually send. Fixes #52970 and #52962. Thanks @vincentkoc.</li>
|
||||
<li>Gateway/model pricing: stop <code>openrouter/auto</code> pricing refresh from recursing indefinitely during bootstrap, so OpenRouter auto routes can populate cached pricing and <code>usage.cost</code> again. Fixes #53035. Thanks @vincentkoc.</li>
|
||||
<li>Mistral/models: lower bundled Mistral max-token defaults to safe output budgets and teach <code>openclaw doctor --fix</code> to repair old persisted Mistral provider configs that still carry context-sized output limits, avoiding deterministic Mistral 422 rejects on fresh and existing setups. Fixes #52599. Thanks @vincentkoc.</li>
|
||||
<li>Agents/web_search: use the active runtime <code>web_search</code> provider instead of stale/default selection, so agent turns keep hitting the provider you actually configured. Fixes #53020. Thanks @jzakirov.</li>
|
||||
<li>Models/OpenAI Codex OAuth: bootstrap the env-configured HTTP/HTTPS proxy dispatcher on the stored-credential refresh path before token renewal runs, so expired Codex OAuth profiles can refresh successfully in proxy-required environments instead of locking users out after the first token expiry.</li>
|
||||
<li>Plugins/memory-lancedb: bootstrap LanceDB into plugin runtime state on first use when the bundled npm install does not already have it, so <code>plugins.slots.memory="memory-lancedb"</code> works again after global npm installs without moving LanceDB into OpenClaw core dependencies. Fixes #26100.</li>
|
||||
<li>Config/plugins: treat stale unknown <code>plugins.allow</code> ids as warnings instead of fatal config errors, so recovery commands like <code>plugins install</code>, <code>doctor --fix</code>, and <code>status</code> still run when a plugin is missing locally. Fixes #52992. Thanks @vincentkoc.</li>
|
||||
<li>Doctor/WhatsApp: stop auto-enable from appending built-in channel ids like <code>whatsapp</code> to <code>plugins.allow</code>, so <code>openclaw doctor --fix</code> no longer writes schema-invalid plugin allowlist entries when repairing built-in channels. Fixes #52931. Thanks @vincentkoc.</li>
|
||||
<li>Telegram/auto-reply: preserve same-chat inbound debounce order without stranding stale busy-session followups, and keep same-key overflow turns ordered when tracked debounce keys are saturated. (#52998) Thanks @osolmaz.</li>
|
||||
<li>Discord/commands: return an explicit unauthorized reply for privileged native slash commands instead of falling through to Discord's misleading generic completion when auth gates reject the sender. Fixes #53041. Thanks @scoootscooob.</li>
|
||||
<li>Channels/catalog: let external channel catalogs override shipped fallback metadata and honor overridden npm specs during channel setup, so custom channel catalogs no longer fall back to bundled packages when a channel id matches. (#52988)</li>
|
||||
<li>Voice-call/Plivo: stabilize Plivo v2 replay keys so webhook retries and replay protection stop colliding on valid follow-up deliveries.</li>
|
||||
<li>Agents/skills: prefer the active resolved runtime snapshot for embedded skill config and env injection, so <code>skills.entries.<skill>.apiKey</code> SecretRefs resolve correctly during embedded startup instead of failing on raw source config. Fixes #53098. Thanks @vincentkoc.</li>
|
||||
<li>Agents/subagents: recheck timed-out worker waits against the latest runtime snapshot before sending completion events, so fast-finishing workers stop being reported as timed out when they actually succeeded. Fixes #53106. Thanks @vincentkoc.</li>
|
||||
<li>Agents/Anthropic: preserve latest assistant thinking and redacted-thinking block ordering during transcript image sanitization so follow-up turns do not trip Anthropic's unmodified-thinking validation. (#52961) Thanks @vincentkoc.</li>
|
||||
<li>Gateway/probe: stop successful gateway handshakes from timing out as unreachable while post-connect detail RPCs are still loading, so slow devices report a reachable RPC failure instead of a false negative dead gateway. Fixes #52927. Thanks @vincentkoc.</li>
|
||||
<li>Gateway/supervision: stop lock conflicts from crash-looping under launchd and systemd by keeping the duplicate process in a retry wait instead of exiting as a failure while another healthy gateway still owns the lock. Fixes #52922. Thanks @vincentkoc.</li>
|
||||
<li>Gateway/auth: require auth for canvas routes and admin scope for agent session reset, so anonymous canvas access and non-admin reset requests fail closed.</li>
|
||||
<li>Release/install: keep previously released bundled plugins and Control UI assets in published openclaw npm installs, and fail release checks when those shipped artifacts are missing. Thanks @vincentkoc.</li>
|
||||
</ul>
|
||||
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
|
||||
]]></description>
|
||||
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.3.23/OpenClaw-2026.3.23.zip" length="24522883" type="application/octet-stream" sparkle:edSignature="ptBgHYLBqq/TSdONYCfIB5d6aP/ij/9G0gYQ5mJI9jf8Y31sbQIh5CqpJVxEEWLTMIGQKsHQir/kXZjtRvvZAg=="/>
|
||||
</item>
|
||||
<item>
|
||||
<title>2026.3.13</title>
|
||||
<pubDate>Sat, 14 Mar 2026 05:19:48 +0000</pubDate>
|
||||
@@ -211,5 +170,79 @@
|
||||
]]></description>
|
||||
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.3.12/OpenClaw-2026.3.12.zip" length="23628700" type="application/octet-stream" sparkle:edSignature="o6Zdcw36l3I0jUg14H+RBqNwrhuuSsq1WMDi4tBRa1+5TC3VCVdFKZ2hzmH2Xjru9lDEzVMP8v2A6RexSbOCBQ=="/>
|
||||
</item>
|
||||
<item>
|
||||
<title>2026.3.8-beta.1</title>
|
||||
<pubDate>Mon, 09 Mar 2026 07:19:57 +0000</pubDate>
|
||||
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
|
||||
<sparkle:version>2026030801</sparkle:version>
|
||||
<sparkle:shortVersionString>2026.3.8-beta.1</sparkle:shortVersionString>
|
||||
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
|
||||
<description><![CDATA[<h2>OpenClaw 2026.3.8-beta.1</h2>
|
||||
<h3>Changes</h3>
|
||||
<ul>
|
||||
<li>CLI/backup: add <code>openclaw backup create</code> and <code>openclaw backup verify</code> for local state archives, including <code>--only-config</code>, <code>--no-include-workspace</code>, manifest/payload validation, and backup guidance in destructive flows. (#40163) thanks @shichangs.</li>
|
||||
<li>macOS/onboarding: add a remote gateway token field for remote mode, preserve existing non-plaintext <code>gateway.remote.token</code> config values until explicitly replaced, and warn when the loaded token shape cannot be used directly from the macOS app. (#40187, supersedes #34614) Thanks @cgdusek.</li>
|
||||
<li>Talk mode: add top-level <code>talk.silenceTimeoutMs</code> config so Talk waits a configurable amount of silence before auto-sending the current transcript, while keeping each platform's existing default pause window when unset. (#39607) Thanks @danodoesdesign. Fixes #17147.</li>
|
||||
<li>TUI: infer the active agent from the current workspace when launched inside a configured agent workspace, while preserving explicit <code>agent:</code> session targets. (#39591) thanks @arceus77-7.</li>
|
||||
<li>Tools/Brave web search: add opt-in <code>tools.web.search.brave.mode: "llm-context"</code> so <code>web_search</code> can call Brave's LLM Context endpoint and return extracted grounding snippets with source metadata, plus config/docs/test coverage. (#33383) Thanks @thirumaleshp.</li>
|
||||
<li>CLI/install: include the short git commit hash in <code>openclaw --version</code> output when metadata is available, and keep installer version checks compatible with the decorated format. (#39712) thanks @sourman.</li>
|
||||
<li>CLI/backup: improve archive naming for date sorting, add config-only backup mode, and harden backup planning, publication, and verification edge cases. (#40163) Thanks @gumadeiras.</li>
|
||||
<li>ACP/Provenance: add optional ACP ingress provenance metadata and visible receipt injection (<code>openclaw acp --provenance off|meta|meta+receipt</code>) so OpenClaw agents can retain and report ACP-origin context with session trace IDs. (#40473) thanks @mbelinky.</li>
|
||||
<li>Tools/web search: alphabetize provider ordering across runtime selection, onboarding/configure pickers, and config metadata, so provider lists stay neutral and multi-key auto-detect now prefers Grok before Kimi. (#40259) thanks @kesku.</li>
|
||||
<li>Docs/Web search: restore $5/month free-credit details, replace defunct "Data for Search"/"Data for AI" plan names with current "Search" plan, and note legacy subscription validity in Brave setup docs. Follows up on #26860. (#40111) Thanks @remusao.</li>
|
||||
<li>Extensions/ACPX tests: move the shared runtime fixture helper from <code>src/runtime-internals/</code> to <code>src/test-utils/</code> so the test-only helper no longer looks like shipped runtime code.</li>
|
||||
</ul>
|
||||
<h3>Fixes</h3>
|
||||
<ul>
|
||||
<li>macOS app/chat UI: route browser proxy through the local node browser service, preserve plain-text paste semantics, strip completed assistant trace/debug wrapper noise from transcripts, refresh permission state after returning from System Settings, and tolerate malformed cron rows in the macOS tab. (#39516) Thanks @Imhermes1.</li>
|
||||
<li>Android/Play distribution: remove self-update, background location, <code>screen.record</code>, and background mic capture from the Android app, narrow the foreground service to <code>dataSync</code> only, and clean up the legacy <code>location.enabledMode=always</code> preference migration. (#39660) Thanks @obviyus.</li>
|
||||
<li>Telegram/DM routing: dedupe inbound Telegram DMs per agent instead of per session key so the same DM cannot trigger duplicate replies when both <code>agent:main:main</code> and <code>agent:main:telegram:direct:<id></code> resolve for one agent. Fixes #40005. Supersedes #40116. (#40519) thanks @obviyus.</li>
|
||||
<li>Cron/Telegram announce delivery: route text-only announce jobs through the real outbound adapters after finalizing descendant output so plain Telegram targets no longer report <code>delivered: true</code> when no message actually reached Telegram. (#40575) thanks @obviyus.</li>
|
||||
<li>Matrix/DM routing: add safer fallback detection for broken <code>m.direct</code> homeservers, honor explicit room bindings over DM classification, and preserve room-bound agent selection for Matrix DM rooms. (#19736) Thanks @derbronko.</li>
|
||||
<li>Feishu/plugin onboarding: clear the short-lived plugin discovery cache before reloading the registry after installing a channel plugin, so onboarding no longer re-prompts to download Feishu immediately after a successful install. Fixes #39642. (#39752) Thanks @GazeKingNuWu.</li>
|
||||
<li>Plugins/channel onboarding: prefer bundled channel plugins over duplicate npm-installed copies during onboarding and release-channel sync, preventing bundled plugins from being shadowed by npm installs with the same plugin ID. (#40092)</li>
|
||||
<li>Config/runtime snapshots: keep secrets-runtime-resolved config and auth-profile snapshots intact after config writes so follow-up reads still see file-backed secret values while picking up the persisted config update. (#37313) thanks @bbblending.</li>
|
||||
<li>Gateway/Control UI: resolve bundled dashboard assets through symlinked global wrappers and auto-detected package roots, while keeping configured and custom roots on the strict hardlink boundary. (#40385) Thanks @LarytheLord.</li>
|
||||
<li>Browser/extension relay: add <code>browser.relayBindHost</code> so the Chrome relay can bind to an explicit non-loopback address for WSL2 and other cross-namespace setups, while preserving loopback-only defaults. (#39364) Thanks @mvanhorn.</li>
|
||||
<li>Browser/CDP: normalize loopback direct WebSocket CDP URLs back to HTTP(S) for <code>/json/*</code> tab operations so local <code>ws://</code> / <code>wss://</code> profiles can still list, focus, open, and close tabs after the new direct-WS support lands. (#31085) Thanks @shrey150.</li>
|
||||
<li>Browser/CDP: rewrite wildcard <code>ws://0.0.0.0</code> and <code>ws://[::]</code> debugger URLs from remote <code>/json/version</code> responses back to the external CDP host/port, fixing Browserless-style container endpoints. (#17760) Thanks @joeharouni.</li>
|
||||
<li>Browser/extension relay: wait briefly for a previously attached Chrome tab to reappear after transient relay drops before failing with <code>tab not found</code>, reducing noisy reconnect flakes. (#32461) Thanks @AaronWander.</li>
|
||||
<li>macOS/Tailscale gateway discovery: keep Tailscale Serve probing alive when other remote gateways are already discovered, prefer direct transport for resolved <code>.ts.net</code> and Tailscale Serve gateways, and set <code>TERM=dumb</code> for GUI-launched Tailscale CLI discovery. (#40167) thanks @ngutman.</li>
|
||||
<li>TUI/theme: detect light terminal backgrounds via <code>COLORFGBG</code> and pick a WCAG AA-compliant light palette, with <code>OPENCLAW_THEME=light|dark</code> override for terminals without auto-detection. (#38636) Thanks @ademczuk and @vincentkoc.</li>
|
||||
<li>Agents/openai-codex: normalize <code>gpt-5.4</code> fallback transport back to <code>openai-codex-responses</code> on <code>chatgpt.com/backend-api</code> when config drifts to the generic OpenAI responses endpoint. (#38736) Thanks @0xsline.</li>
|
||||
<li>Models/openai-codex GPT-5.4 forward-compat: use the GPT-5.4 1,050,000-token context window and 128,000 max tokens for <code>openai-codex/gpt-5.4</code> instead of inheriting stale legacy Codex limits in resolver fallbacks and model listing. (#37876) thanks @yuweuii.</li>
|
||||
<li>Tools/web search: restore Perplexity OpenRouter/Sonar compatibility for legacy <code>OPENROUTER_API_KEY</code>, <code>sk-or-...</code>, and explicit <code>perplexity.baseUrl</code> / <code>model</code> setups while keeping direct Perplexity keys on the native Search API path. (#39937) Thanks @obviyus.</li>
|
||||
<li>Agents/failover: detect Amazon Bedrock <code>Too many tokens per day</code> quota errors as rate limits across fallback, cron retry, and memory embeddings while keeping context-window <code>too many tokens per request</code> errors out of the rate-limit lane. (#39377) Thanks @gambletan.</li>
|
||||
<li>Mattermost replies: keep <code>root_id</code> pinned to the existing thread root when an agent replies inside a thread, while still using reply-target threading for top-level posts. (#27744) thanks @hnykda.</li>
|
||||
<li>Telegram/DM partial streaming: keep DM preview lanes on real message edits instead of native draft materialization so final replies no longer flash a second duplicate copy before collapsing back to one.</li>
|
||||
<li>macOS overlays: fix VoiceWake, Talk, and Notify overlay exclusivity crashes by removing shared <code>inout</code> visibility mutation from <code>OverlayPanelFactory.present</code>, and add a repeated Talk overlay smoke test. (#39275, #39321) Thanks @fellanH.</li>
|
||||
<li>macOS Talk Mode: set the speech recognition request <code>taskHint</code> to <code>.dictation</code> for mic capture, and add regression coverage for the request defaults. (#38445) Thanks @dmiv.</li>
|
||||
<li>macOS release packaging: default <code>scripts/package-mac-app.sh</code> to universal binaries for <code>BUILD_CONFIG=release</code>, and clarify that <code>scripts/package-mac-dist.sh</code> already produces the release zip + DMG. (#33891) Thanks @cgdusek.</li>
|
||||
<li>Hooks/session-memory: keep <code>/new</code> and <code>/reset</code> memory artifacts in the bound agent workspace and align saved reset session keys with that workspace when stale main-agent keys leak into the hook path. (#39875) thanks @rbutera.</li>
|
||||
<li>Sessions/model switch: clear stale cached <code>contextTokens</code> when a session changes models so status and runtime paths recompute against the active model window. (#38044) thanks @yuweuii.</li>
|
||||
<li>ACP/session history: persist transcripts for successful ACP child runs, preserve exact transcript text, record ACP spawned-session lineage, and keep spawn-time transcript-path persistence best-effort so history storage failures do not block execution. (#40137) thanks @mbelinky.</li>
|
||||
<li>Docs/browser: add a layered WSL2 + Windows remote Chrome CDP troubleshooting guide, including Control UI origin pitfalls and extension-relay bind-address guidance. (#39407) Thanks @Owlock.</li>
|
||||
<li>Context engine registry/bundled builds: share the registry state through a <code>globalThis</code> singleton so duplicated bundled module copies can resolve engines registered by each other at runtime, with regression coverage for duplicate-module imports. (#40115) thanks @jalehman.</li>
|
||||
<li>Podman/setup: fix <code>cannot chdir: Permission denied</code> in <code>run_as_user</code> when <code>setup-podman.sh</code> is invoked from a directory the target user cannot access, by wrapping user-switch calls in a subshell that cd's to <code>/tmp</code> with <code>/</code> fallback. (#39435) Thanks @langdon and @jlcbk.</li>
|
||||
<li>Podman/SELinux: auto-detect SELinux enforcing/permissive mode and add <code>:Z</code> relabel to bind mounts in <code>run-openclaw-podman.sh</code> and the Quadlet template, fixing <code>EACCES</code> on Fedora/RHEL hosts. Supports <code>OPENCLAW_BIND_MOUNT_OPTIONS</code> override. (#39449) Thanks @langdon and @githubbzxs.</li>
|
||||
<li>Agents/context-engine plugins: bootstrap runtime plugins once at embedded-run, compaction, and subagent boundaries so plugin-provided context engines and hooks load from the active workspace before runtime resolution. (#40232)</li>
|
||||
<li>Docs/Changelog: correct the contributor credit for the bundled Control UI global-install fix to @LarytheLord. (#40420) Thanks @velvet-shark.</li>
|
||||
<li>Telegram/media downloads: time out only stalled body reads so polling recovers from hung file downloads without aborting slow downloads that are still streaming data. (#40098) thanks @tysoncung.</li>
|
||||
<li>Docker/runtime image: prune dev dependencies, strip build-only dist metadata for smaller Docker images. (#40307) Thanks @vincentkoc.</li>
|
||||
<li>Gateway/restart timeout recovery: exit non-zero when restart-triggered shutdown drains time out so launchd/systemd restart the gateway instead of treating the failed restart as a clean stop. Landed from contributor PR #40380 by @dsantoreis. Thanks @dsantoreis.</li>
|
||||
<li>Gateway/config restart guard: validate config before service start/restart and keep post-SIGUSR1 startup failures from crashing the gateway process, reducing invalid-config restart loops and macOS permission loss. Landed from contributor PR #38699 by @lml2468. Thanks @lml2468.</li>
|
||||
<li>Gateway/launchd respawn detection: treat <code>XPC_SERVICE_NAME</code> as a launchd supervision hint so macOS restarts exit cleanly under launchd instead of attempting detached self-respawn. Landed from contributor PR #20555 by @dimat. Thanks @dimat.</li>
|
||||
<li>Telegram/poll restart cleanup: abort the in-flight Telegram API fetch when shutdown or forced polling restarts stop a runner, preventing stale <code>getUpdates</code> long polls from colliding with the replacement runner. Landed from contributor PR #23950 by @Gkinthecodeland. Thanks @Gkinthecodeland.</li>
|
||||
<li>Cron/restart catch-up staggering: limit immediate missed-job replay on startup and reschedule the deferred remainder from the post-catchup clock so restart bursts do not starve the gateway or silently skip overdue recurring jobs. Landed from contributor PR #18925 by @rexlunae. Thanks @rexlunae.</li>
|
||||
<li>Cron/owner-only tools: pass trusted isolated cron runs into the embedded agent with owner context so <code>cron</code>/<code>gateway</code> tooling remains available after the owner-auth hardening narrowed direct-message ownership inference.</li>
|
||||
<li>Browser/SSRF: block private-network intermediate redirect hops in strict browser navigation flows and fail closed when remote tab-open paths cannot inspect redirect chains. Thanks @zpbrent.</li>
|
||||
<li>MS Teams/authz: keep <code>groupPolicy: "allowlist"</code> enforcing sender allowlists even when a team/channel route allowlist is configured, so route matches no longer widen group access to every sender in that route. Thanks @zpbrent.</li>
|
||||
<li>Security/system.run: bind approved <code>bun</code> and <code>deno run</code> script operands to on-disk file snapshots so post-approval script rewrites are denied before execution.</li>
|
||||
<li>Skills/download installs: pin the validated per-skill tools root before writing downloaded archives, so rebinding the lexical tools path cannot redirect download writes outside the intended tools directory. Thanks @tdjackey.</li>
|
||||
</ul>
|
||||
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
|
||||
]]></description>
|
||||
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.3.8-beta.1/OpenClaw-2026.3.8-beta.1.zip" length="23407015" type="application/octet-stream" sparkle:edSignature="KCqhSmu4b0tHf55RqcQOHorsc55CgBI5BUmK/NTizxNq04INn/7QvsamHYQou9DbB2IW6B2nawBC4nn4au5yDA=="/>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>
|
||||
@@ -65,8 +65,8 @@ android {
|
||||
applicationId = "ai.openclaw.app"
|
||||
minSdk = 31
|
||||
targetSdk = 36
|
||||
versionCode = 2026032400
|
||||
versionName = "2026.3.24"
|
||||
versionCode = 2026032000
|
||||
versionName = "2026.3.20"
|
||||
ndk {
|
||||
// Support all major ABIs — native libs are tiny (~47 KB per ABI)
|
||||
abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
|
||||
|
||||
@@ -237,10 +237,6 @@ class MainViewModel(app: Application) : AndroidViewModel(app) {
|
||||
ensureRuntime().handleCanvasA2UIActionFromWebView(payloadJson)
|
||||
}
|
||||
|
||||
fun isTrustedCanvasActionUrl(rawUrl: String?): Boolean {
|
||||
return ensureRuntime().isTrustedCanvasActionUrl(rawUrl)
|
||||
}
|
||||
|
||||
fun requestCanvasRehydrate(source: String = "screen_tab") {
|
||||
ensureRuntime().requestCanvasRehydrate(source = source, force = true)
|
||||
}
|
||||
|
||||
@@ -904,10 +904,6 @@ class NodeRuntime(
|
||||
}
|
||||
}
|
||||
|
||||
fun isTrustedCanvasActionUrl(rawUrl: String?): Boolean {
|
||||
return a2uiHandler.isTrustedCanvasActionUrl(rawUrl)
|
||||
}
|
||||
|
||||
fun loadChat(sessionKey: String) {
|
||||
val key = sessionKey.trim().ifEmpty { resolveMainSessionKey() }
|
||||
chat.load(key)
|
||||
|
||||
@@ -13,13 +13,6 @@ class A2UIHandler(
|
||||
private val getNodeCanvasHostUrl: () -> String?,
|
||||
private val getOperatorCanvasHostUrl: () -> String?,
|
||||
) {
|
||||
fun isTrustedCanvasActionUrl(rawUrl: String?): Boolean {
|
||||
return CanvasActionTrust.isTrustedCanvasActionUrl(
|
||||
rawUrl = rawUrl,
|
||||
trustedA2uiUrls = listOfNotNull(resolveA2uiHostUrl()),
|
||||
)
|
||||
}
|
||||
|
||||
fun resolveA2uiHostUrl(): String? {
|
||||
val nodeRaw = getNodeCanvasHostUrl()?.trim().orEmpty()
|
||||
val operatorRaw = getOperatorCanvasHostUrl()?.trim().orEmpty()
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
package ai.openclaw.app.node
|
||||
|
||||
import java.net.URI
|
||||
|
||||
object CanvasActionTrust {
|
||||
const val scaffoldAssetUrl: String = "file:///android_asset/CanvasScaffold/scaffold.html"
|
||||
|
||||
fun isTrustedCanvasActionUrl(rawUrl: String?, trustedA2uiUrls: List<String>): Boolean {
|
||||
val candidate = rawUrl?.trim().orEmpty()
|
||||
if (candidate.isEmpty()) return false
|
||||
if (candidate == scaffoldAssetUrl) return true
|
||||
|
||||
val candidateUri = parseUri(candidate) ?: return false
|
||||
if (candidateUri.scheme.equals("file", ignoreCase = true)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return trustedA2uiUrls.any { trusted ->
|
||||
isTrustedA2uiPage(candidateUri, trusted)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isTrustedA2uiPage(candidateUri: URI, trustedUrl: String): Boolean {
|
||||
val trustedUri = parseUri(trustedUrl) ?: return false
|
||||
if (!candidateUri.scheme.equals(trustedUri.scheme, ignoreCase = true)) return false
|
||||
if (candidateUri.host?.equals(trustedUri.host, ignoreCase = true) != true) return false
|
||||
if (effectivePort(candidateUri) != effectivePort(trustedUri)) return false
|
||||
|
||||
val trustedPath = trustedUri.rawPath?.takeIf { it.isNotBlank() } ?: return false
|
||||
val candidatePath = candidateUri.rawPath?.takeIf { it.isNotBlank() } ?: return false
|
||||
val trustedPrefix = if (trustedPath.endsWith("/")) trustedPath else "$trustedPath/"
|
||||
return candidatePath == trustedPath || candidatePath.startsWith(trustedPrefix)
|
||||
}
|
||||
|
||||
private fun effectivePort(uri: URI): Int {
|
||||
if (uri.port >= 0) return uri.port
|
||||
return when (uri.scheme?.lowercase()) {
|
||||
"https" -> 443
|
||||
"http" -> 80
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseUri(raw: String): URI? =
|
||||
try {
|
||||
URI(raw)
|
||||
} catch (_: Throwable) {
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ 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) {
|
||||
@@ -98,15 +100,18 @@ class LocationCaptureManager(private val context: Context) {
|
||||
val resolved =
|
||||
providers.firstOrNull { manager.isProviderEnabled(it) }
|
||||
?: throw IllegalStateException("LOCATION_UNAVAILABLE: no providers available")
|
||||
val location = withTimeout(timeoutMs.coerceAtLeast(1)) {
|
||||
suspendCancellableCoroutine<Location?> { cont ->
|
||||
return withTimeout(timeoutMs.coerceAtLeast(1)) {
|
||||
suspendCancellableCoroutine { cont ->
|
||||
val signal = CancellationSignal()
|
||||
cont.invokeOnCancellation { signal.cancel() }
|
||||
manager.getCurrentLocation(resolved, signal, context.mainExecutor) { location ->
|
||||
cont.resume(location) { _, _, _ -> }
|
||||
if (location != null) {
|
||||
cont.resume(location)
|
||||
} else {
|
||||
cont.resumeWithException(IllegalStateException("LOCATION_UNAVAILABLE: no fix"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return location ?: throw IllegalStateException("LOCATION_UNAVAILABLE: no fix")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.webkit.WebSettingsCompat
|
||||
import androidx.webkit.WebViewFeature
|
||||
import ai.openclaw.app.MainViewModel
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Composable
|
||||
@@ -30,7 +29,6 @@ fun CanvasScreen(viewModel: MainViewModel, visible: Boolean, modifier: Modifier
|
||||
val context = LocalContext.current
|
||||
val isDebuggable = (context.applicationInfo.flags and android.content.pm.ApplicationInfo.FLAG_DEBUGGABLE) != 0
|
||||
val webViewRef = remember { mutableStateOf<WebView?>(null) }
|
||||
val currentPageUrlRef = remember { AtomicReference<String?>(null) }
|
||||
|
||||
DisposableEffect(viewModel) {
|
||||
onDispose {
|
||||
@@ -70,14 +68,6 @@ fun CanvasScreen(viewModel: MainViewModel, visible: Boolean, modifier: Modifier
|
||||
isHorizontalScrollBarEnabled = true
|
||||
webViewClient =
|
||||
object : WebViewClient() {
|
||||
override fun onPageStarted(
|
||||
view: WebView,
|
||||
url: String?,
|
||||
favicon: android.graphics.Bitmap?,
|
||||
) {
|
||||
currentPageUrlRef.set(url)
|
||||
}
|
||||
|
||||
override fun onReceivedError(
|
||||
view: WebView,
|
||||
request: WebResourceRequest,
|
||||
@@ -100,7 +90,6 @@ fun CanvasScreen(viewModel: MainViewModel, visible: Boolean, modifier: Modifier
|
||||
}
|
||||
|
||||
override fun onPageFinished(view: WebView, url: String?) {
|
||||
currentPageUrlRef.set(url)
|
||||
if (isDebuggable) {
|
||||
Log.d("OpenClawWebView", "onPageFinished: $url")
|
||||
}
|
||||
@@ -133,12 +122,7 @@ fun CanvasScreen(viewModel: MainViewModel, visible: Boolean, modifier: Modifier
|
||||
}
|
||||
}
|
||||
|
||||
val bridge =
|
||||
CanvasA2UIActionBridge(
|
||||
isTrustedPage = { viewModel.isTrustedCanvasActionUrl(currentPageUrlRef.get()) },
|
||||
) { payload ->
|
||||
viewModel.handleCanvasA2UIActionFromWebView(payload)
|
||||
}
|
||||
val bridge = CanvasA2UIActionBridge { payload -> viewModel.handleCanvasA2UIActionFromWebView(payload) }
|
||||
addJavascriptInterface(bridge, CanvasA2UIActionBridge.interfaceName)
|
||||
viewModel.canvas.attach(this)
|
||||
webViewRef.value = this
|
||||
@@ -163,15 +147,11 @@ private fun disableForceDarkIfSupported(settings: WebSettings) {
|
||||
WebSettingsCompat.setForceDark(settings, WebSettingsCompat.FORCE_DARK_OFF)
|
||||
}
|
||||
|
||||
private class CanvasA2UIActionBridge(
|
||||
private val isTrustedPage: () -> Boolean,
|
||||
private val onMessage: (String) -> Unit,
|
||||
) {
|
||||
private class CanvasA2UIActionBridge(private val onMessage: (String) -> Unit) {
|
||||
@JavascriptInterface
|
||||
fun postMessage(payload: String?) {
|
||||
val msg = payload?.trim().orEmpty()
|
||||
if (msg.isEmpty()) return
|
||||
if (!isTrustedPage()) return
|
||||
onMessage(msg)
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,6 @@ 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
|
||||
@@ -764,9 +763,7 @@ class TalkModeManager(
|
||||
try {
|
||||
withContext(Dispatchers.IO) { tempFile.writeBytes(audioBytes) }
|
||||
val player = MediaPlayer()
|
||||
synchronized(playerLock) {
|
||||
this.player = player
|
||||
}
|
||||
this.player = player
|
||||
val finished = CompletableDeferred<Unit>()
|
||||
player.setAudioAttributes(
|
||||
AudioAttributes.Builder()
|
||||
@@ -787,7 +784,7 @@ class TalkModeManager(
|
||||
ensurePlaybackActive(playbackToken)
|
||||
} finally {
|
||||
try {
|
||||
cleanupPlayer(player)
|
||||
cleanupPlayer()
|
||||
} catch (_: Throwable) {}
|
||||
tempFile.delete()
|
||||
}
|
||||
@@ -824,11 +821,7 @@ class TalkModeManager(
|
||||
return
|
||||
}
|
||||
if (resetInterrupt) {
|
||||
val currentMs = synchronized(playerLock) {
|
||||
try {
|
||||
player?.currentPosition?.toDouble() ?: 0.0
|
||||
} catch (_: IllegalStateException) { 0.0 }
|
||||
}
|
||||
val currentMs = player?.currentPosition?.toDouble() ?: 0.0
|
||||
lastInterruptedAtSeconds = currentMs / 1000.0
|
||||
}
|
||||
cleanupPlayer()
|
||||
@@ -871,16 +864,10 @@ class TalkModeManager(
|
||||
audioFocusRequest = 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 cleanupPlayer() {
|
||||
player?.stop()
|
||||
player?.release()
|
||||
player = null
|
||||
}
|
||||
|
||||
private fun shouldInterrupt(transcript: String): Boolean {
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package ai.openclaw.app.node
|
||||
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class CanvasActionTrustTest {
|
||||
@Test
|
||||
fun acceptsBundledScaffoldAsset() {
|
||||
assertTrue(CanvasActionTrust.isTrustedCanvasActionUrl(CanvasActionTrust.scaffoldAssetUrl, emptyList()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun acceptsTrustedA2uiPageOnAdvertisedCanvasHost() {
|
||||
assertTrue(
|
||||
CanvasActionTrust.isTrustedCanvasActionUrl(
|
||||
rawUrl = "https://canvas.example.com:9443/__openclaw__/cap/token/__openclaw__/a2ui/?platform=android",
|
||||
trustedA2uiUrls = listOf("https://canvas.example.com:9443/__openclaw__/cap/token/__openclaw__/a2ui/?platform=android"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rejectsDifferentOriginEvenIfPathMatches() {
|
||||
assertFalse(
|
||||
CanvasActionTrust.isTrustedCanvasActionUrl(
|
||||
rawUrl = "https://evil.example.com:9443/__openclaw__/cap/token/__openclaw__/a2ui/?platform=android",
|
||||
trustedA2uiUrls = listOf("https://canvas.example.com:9443/__openclaw__/cap/token/__openclaw__/a2ui/?platform=android"),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rejectsUntrustedCanvasPagePathOnTrustedOrigin() {
|
||||
assertFalse(
|
||||
CanvasActionTrust.isTrustedCanvasActionUrl(
|
||||
rawUrl = "https://canvas.example.com:9443/untrusted/index.html",
|
||||
trustedA2uiUrls = listOf("https://canvas.example.com:9443/__openclaw__/cap/token/__openclaw__/a2ui/?platform=android"),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
// Shared iOS version defaults.
|
||||
// Generated overrides live in build/Version.xcconfig (git-ignored).
|
||||
|
||||
OPENCLAW_GATEWAY_VERSION = 2026.3.24-beta.1
|
||||
OPENCLAW_MARKETING_VERSION = 2026.3.24
|
||||
OPENCLAW_BUILD_VERSION = 202603240
|
||||
OPENCLAW_GATEWAY_VERSION = 2026.3.14
|
||||
OPENCLAW_MARKETING_VERSION = 2026.3.14
|
||||
OPENCLAW_BUILD_VERSION = 202603140
|
||||
|
||||
#include? "../build/Version.xcconfig"
|
||||
|
||||
@@ -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.22-beta.1` becomes:
|
||||
- `CFBundleShortVersionString = 2026.3.22`
|
||||
- `CFBundleVersion = next TestFlight build number for 2026.3.22`
|
||||
- A root version like `2026.3.13-beta.1` becomes:
|
||||
- `CFBundleShortVersionString = 2026.3.13`
|
||||
- `CFBundleVersion = next TestFlight build number for 2026.3.13`
|
||||
|
||||
Required env for beta builds:
|
||||
|
||||
|
||||
@@ -46,13 +46,6 @@ struct IOSGatewayChatTransport: OpenClawChatTransport, Sendable {
|
||||
_ = try await self.gateway.request(method: "sessions.reset", paramsJSON: json, timeoutSeconds: 10)
|
||||
}
|
||||
|
||||
func compactSession(sessionKey: String) async throws {
|
||||
struct Params: Codable { var key: String }
|
||||
let data = try JSONEncoder().encode(Params(key: sessionKey))
|
||||
let json = String(data: data, encoding: .utf8)
|
||||
_ = try await self.gateway.request(method: "sessions.compact", paramsJSON: json, timeoutSeconds: 10)
|
||||
}
|
||||
|
||||
func requestHistory(sessionKey: String) async throws -> OpenClawChatHistoryPayload {
|
||||
struct Params: Codable { var sessionKey: String }
|
||||
let data = try JSONEncoder().encode(Params(sessionKey: sessionKey))
|
||||
|
||||
@@ -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 YYYY.M.D or YYYY.M.D-beta.N.")
|
||||
UI.user_error!("Invalid package.json version '#{raw_value}'. Expected 2026.3.13 or 2026.3.13-beta.1.")
|
||||
end
|
||||
|
||||
version
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -57,7 +57,8 @@ final class CanvasWindowController: NSWindowController, WKNavigationDelegate, NS
|
||||
let allowedSchemesJSON = (
|
||||
try? String(
|
||||
data: JSONSerialization.data(withJSONObject: CanvasScheme.allSchemes),
|
||||
encoding: .utf8)) ?? "[]"
|
||||
encoding: .utf8)
|
||||
) ?? "[]"
|
||||
let bridgeScript = """
|
||||
(() => {
|
||||
try {
|
||||
|
||||
@@ -73,7 +73,7 @@ extension ConfigSettings {
|
||||
|
||||
private var sidebar: some View {
|
||||
SettingsSidebarScroll {
|
||||
LazyVStack(alignment: .leading, spacing: 4) {
|
||||
LazyVStack(alignment: .leading, spacing: 8) {
|
||||
if self.sections.isEmpty {
|
||||
Text("No config sections available.")
|
||||
.font(.caption)
|
||||
@@ -82,7 +82,7 @@ extension ConfigSettings {
|
||||
.padding(.vertical, 4)
|
||||
} else {
|
||||
ForEach(self.sections) { section in
|
||||
self.sidebarSection(section)
|
||||
self.sidebarRow(section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,6 +128,7 @@ extension ConfigSettings {
|
||||
}
|
||||
self.actionRow
|
||||
self.sectionHeader(section)
|
||||
self.subsectionNav(section)
|
||||
self.sectionForm(section)
|
||||
if self.store.configDirty, !self.isNixMode {
|
||||
Text("Unsaved changes")
|
||||
@@ -181,76 +182,78 @@ extension ConfigSettings {
|
||||
.buttonStyle(.bordered)
|
||||
}
|
||||
|
||||
private func sidebarSection(_ section: ConfigSection) -> some View {
|
||||
let isExpanded = self.activeSectionKey == section.key
|
||||
let subsections = isExpanded ? self.resolveSubsections(for: section) : []
|
||||
|
||||
return VStack(alignment: .leading, spacing: 2) {
|
||||
Button {
|
||||
self.selectSection(section)
|
||||
} label: {
|
||||
HStack(spacing: 6) {
|
||||
Image(systemName: "chevron.right")
|
||||
.font(.caption2.weight(.semibold))
|
||||
.foregroundStyle(.tertiary)
|
||||
.rotationEffect(.degrees(isExpanded ? 90 : 0))
|
||||
Text(section.label)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.padding(.vertical, 5)
|
||||
.padding(.horizontal, 8)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(isExpanded && subsections.isEmpty
|
||||
? Color.accentColor.opacity(0.18)
|
||||
: Color.clear)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous))
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.contentShape(Rectangle())
|
||||
|
||||
if isExpanded, !subsections.isEmpty {
|
||||
VStack(alignment: .leading, spacing: 1) {
|
||||
self.sidebarSubRow(title: "All", key: nil, sectionKey: section.key)
|
||||
ForEach(subsections) { sub in
|
||||
self.sidebarSubRow(title: sub.label, key: sub.key, sectionKey: section.key)
|
||||
}
|
||||
}
|
||||
.padding(.leading, 20)
|
||||
.transition(.opacity.combined(with: .move(edge: .top)))
|
||||
}
|
||||
}
|
||||
.animation(.easeInOut(duration: 0.18), value: isExpanded)
|
||||
}
|
||||
|
||||
private func sidebarSubRow(title: String, key: String?, sectionKey: String) -> some View {
|
||||
let isSelected: Bool = {
|
||||
guard self.activeSectionKey == sectionKey else { return false }
|
||||
if let key { return self.activeSubsection == .key(key) }
|
||||
return self.activeSubsection == .all
|
||||
}()
|
||||
|
||||
private func sidebarRow(_ section: ConfigSection) -> some View {
|
||||
let isSelected = self.activeSectionKey == section.key
|
||||
return Button {
|
||||
if let key {
|
||||
self.activeSubsection = .key(key)
|
||||
} else {
|
||||
self.activeSubsection = .all
|
||||
}
|
||||
self.selectSection(section)
|
||||
} label: {
|
||||
Text(title)
|
||||
.font(.callout)
|
||||
.lineLimit(1)
|
||||
.padding(.vertical, 4)
|
||||
.padding(.horizontal, 8)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(isSelected ? Color.accentColor.opacity(0.18) : Color.clear)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 7, style: .continuous))
|
||||
.contentShape(Rectangle())
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(section.label)
|
||||
if let help = section.help {
|
||||
Text(help)
|
||||
.font(.caption)
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(2)
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 6)
|
||||
.padding(.horizontal, 8)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.background(isSelected ? Color.accentColor.opacity(0.18) : Color.clear)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
|
||||
.background(Color.clear)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.buttonStyle(.plain)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func subsectionNav(_ section: ConfigSection) -> some View {
|
||||
let subsections = self.resolveSubsections(for: section)
|
||||
if subsections.isEmpty {
|
||||
EmptyView()
|
||||
} else {
|
||||
ScrollView(.horizontal, showsIndicators: false) {
|
||||
HStack(spacing: 8) {
|
||||
self.subsectionButton(
|
||||
title: "All",
|
||||
isSelected: self.activeSubsection == .all)
|
||||
{
|
||||
self.activeSubsection = .all
|
||||
}
|
||||
ForEach(subsections) { subsection in
|
||||
self.subsectionButton(
|
||||
title: subsection.label,
|
||||
isSelected: self.activeSubsection == .key(subsection.key))
|
||||
{
|
||||
self.activeSubsection = .key(subsection.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func subsectionButton(
|
||||
title: String,
|
||||
isSelected: Bool,
|
||||
action: @escaping () -> Void) -> some View
|
||||
{
|
||||
Button(action: action) {
|
||||
Text(title)
|
||||
.font(.callout.weight(.semibold))
|
||||
.foregroundStyle(isSelected ? Color.accentColor : .primary)
|
||||
.padding(.horizontal, 10)
|
||||
.padding(.vertical, 6)
|
||||
.background(isSelected ? Color.accentColor.opacity(0.18) : Color(nsColor: .controlBackgroundColor))
|
||||
.clipShape(Capsule())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
|
||||
private func sectionForm(_ section: ConfigSection) -> some View {
|
||||
let subsection = self.activeSubsection
|
||||
let defaultPath: ConfigPath = [.key(section.key)]
|
||||
|
||||
@@ -17,10 +17,10 @@ extension CronJobEditor {
|
||||
self.enabled = job.enabled
|
||||
self.deleteAfterRun = job.deleteAfterRun ?? false
|
||||
switch job.parsedSessionTarget {
|
||||
case let .predefined(target):
|
||||
case .predefined(let target):
|
||||
self.sessionTarget = target
|
||||
self.preservedSessionTargetRaw = nil
|
||||
case let .session(id):
|
||||
case .session(let id):
|
||||
self.sessionTarget = .isolated
|
||||
self.preservedSessionTargetRaw = "session:\(id)"
|
||||
}
|
||||
@@ -265,10 +265,7 @@ 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
|
||||
|
||||
@@ -16,10 +16,10 @@ enum CronCustomSessionTarget: Codable, Equatable {
|
||||
|
||||
var rawValue: String {
|
||||
switch self {
|
||||
case let .predefined(target):
|
||||
target.rawValue
|
||||
case let .session(id):
|
||||
"session:\(id)"
|
||||
case .predefined(let target):
|
||||
return target.rawValue
|
||||
case .session(let id):
|
||||
return "session:\(id)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,10 +328,10 @@ struct CronJob: Identifiable, Codable, Equatable {
|
||||
/// predefined enum.
|
||||
var sessionTarget: CronSessionTarget {
|
||||
switch self.parsedSessionTarget {
|
||||
case let .predefined(target):
|
||||
target
|
||||
case .predefined(let target):
|
||||
return target
|
||||
case .session:
|
||||
.isolated
|
||||
return .isolated
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,20 +342,20 @@ struct CronJob: Identifiable, Codable, Equatable {
|
||||
var transcriptSessionKey: String? {
|
||||
switch self.parsedSessionTarget {
|
||||
case .predefined(.main):
|
||||
nil
|
||||
return nil
|
||||
case .predefined(.isolated), .predefined(.current):
|
||||
"cron:\(self.id)"
|
||||
case let .session(id):
|
||||
id
|
||||
return "cron:\(self.id)"
|
||||
case .session(let id):
|
||||
return id
|
||||
}
|
||||
}
|
||||
|
||||
var supportsAnnounceDelivery: Bool {
|
||||
switch self.parsedSessionTarget {
|
||||
case .predefined(.main):
|
||||
false
|
||||
return false
|
||||
case .predefined(.isolated), .predefined(.current), .session:
|
||||
true
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
import Foundation
|
||||
|
||||
enum ExecApprovalCommandDisplaySanitizer {
|
||||
private static let invisibleCodePoints: Set<UInt32> = [
|
||||
0x115F,
|
||||
0x1160,
|
||||
0x3164,
|
||||
0xFFA0,
|
||||
]
|
||||
|
||||
static func sanitize(_ text: String) -> String {
|
||||
var sanitized = ""
|
||||
sanitized.reserveCapacity(text.count)
|
||||
for scalar in text.unicodeScalars {
|
||||
if self.shouldEscape(scalar) {
|
||||
sanitized.append(self.escape(scalar))
|
||||
} else {
|
||||
sanitized.append(String(scalar))
|
||||
}
|
||||
}
|
||||
return sanitized
|
||||
}
|
||||
|
||||
private static func shouldEscape(_ scalar: UnicodeScalar) -> Bool {
|
||||
scalar.properties.generalCategory == .format || self.invisibleCodePoints.contains(scalar.value)
|
||||
}
|
||||
|
||||
private static func escape(_ scalar: UnicodeScalar) -> String {
|
||||
"\\u{\(String(scalar.value, radix: 16, uppercase: true))}"
|
||||
}
|
||||
}
|
||||
@@ -89,11 +89,11 @@ final class ExecApprovalsGatewayPrompter {
|
||||
private static func shouldAsk(security: ExecSecurity, ask: ExecAsk) -> Bool {
|
||||
switch ask {
|
||||
case .always:
|
||||
true
|
||||
return true
|
||||
case .onMiss:
|
||||
security == .allowlist
|
||||
return security == .allowlist
|
||||
case .off:
|
||||
false
|
||||
return 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,
|
||||
|
||||
@@ -271,7 +271,7 @@ enum ExecApprovalsPromptPresenter {
|
||||
commandText.drawsBackground = true
|
||||
commandText.backgroundColor = NSColor.textBackgroundColor
|
||||
commandText.font = NSFont.monospacedSystemFont(ofSize: NSFont.systemFontSize, weight: .regular)
|
||||
commandText.string = ExecApprovalCommandDisplaySanitizer.sanitize(request.command)
|
||||
commandText.string = request.command
|
||||
commandText.textContainerInset = NSSize(width: 6, height: 6)
|
||||
commandText.textContainer?.lineFragmentPadding = 0
|
||||
commandText.textContainer?.widthTracksTextView = true
|
||||
|
||||
@@ -147,9 +147,7 @@ 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")
|
||||
}
|
||||
|
||||
|
||||
@@ -337,6 +337,7 @@ extension OnboardingView {
|
||||
self.remoteProbePreflightMessage == nil && self.remoteProbeState != .checking
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func remoteConnectionSection() -> some View {
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
HStack(alignment: .top, spacing: 12) {
|
||||
@@ -502,17 +503,17 @@ extension OnboardingView {
|
||||
{
|
||||
switch issue {
|
||||
case .tokenRequired:
|
||||
("key.fill", .orange)
|
||||
return ("key.fill", .orange)
|
||||
case .tokenMismatch:
|
||||
("exclamationmark.triangle.fill", .orange)
|
||||
return ("exclamationmark.triangle.fill", .orange)
|
||||
case .gatewayTokenNotConfigured:
|
||||
("wrench.and.screwdriver.fill", .orange)
|
||||
return ("wrench.and.screwdriver.fill", .orange)
|
||||
case .setupCodeExpired:
|
||||
("qrcode.viewfinder", .orange)
|
||||
return ("qrcode.viewfinder", .orange)
|
||||
case .passwordRequired:
|
||||
("lock.slash.fill", .orange)
|
||||
return ("lock.slash.fill", .orange)
|
||||
case .pairingRequired:
|
||||
("link.badge.plus", .orange)
|
||||
return ("link.badge.plus", .orange)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import CryptoKit
|
||||
import Foundation
|
||||
import OpenClawProtocol
|
||||
|
||||
enum OpenClawConfigFile {
|
||||
private static let logger = Logger(subsystem: "ai.openclaw", category: "config")
|
||||
private static let configAuditFileName = "config-audit.jsonl"
|
||||
private static let configHealthFileName = "config-health.json"
|
||||
|
||||
static func url() -> URL {
|
||||
OpenClawPaths.configURL
|
||||
@@ -25,11 +23,9 @@ enum OpenClawConfigFile {
|
||||
do {
|
||||
let data = try Data(contentsOf: url)
|
||||
guard let root = self.parseConfigData(data) else {
|
||||
self.observeConfigRead(data: data, root: nil, configURL: url, valid: false)
|
||||
self.logger.warning("config JSON root invalid")
|
||||
return [:]
|
||||
}
|
||||
self.observeConfigRead(data: data, root: root, configURL: url, valid: true)
|
||||
return root
|
||||
} catch {
|
||||
self.logger.warning("config read failed: \(error.localizedDescription)")
|
||||
@@ -80,7 +76,6 @@ enum OpenClawConfigFile {
|
||||
"gatewayModeAfter": gatewayModeAfter ?? NSNull(),
|
||||
"suspicious": suspicious,
|
||||
])
|
||||
self.observeConfigRead(data: data, root: output, configURL: url, valid: true)
|
||||
} catch {
|
||||
self.logger.error("config save failed: \(error.localizedDescription)")
|
||||
self.appendConfigWriteAudit([
|
||||
@@ -321,211 +316,6 @@ enum OpenClawConfigFile {
|
||||
.appendingPathComponent(self.configAuditFileName, isDirectory: false)
|
||||
}
|
||||
|
||||
private static func configHealthStateURL() -> URL {
|
||||
self.stateDirURL()
|
||||
.appendingPathComponent("logs", isDirectory: true)
|
||||
.appendingPathComponent(self.configHealthFileName, isDirectory: false)
|
||||
}
|
||||
|
||||
private static func readConfigHealthState() -> [String: Any] {
|
||||
let url = self.configHealthStateURL()
|
||||
guard let data = try? Data(contentsOf: url),
|
||||
let root = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
|
||||
else {
|
||||
return [:]
|
||||
}
|
||||
return root
|
||||
}
|
||||
|
||||
private static func writeConfigHealthState(_ root: [String: Any]) {
|
||||
guard JSONSerialization.isValidJSONObject(root),
|
||||
let data = try? JSONSerialization.data(withJSONObject: root, options: [.prettyPrinted, .sortedKeys])
|
||||
else {
|
||||
return
|
||||
}
|
||||
let url = self.configHealthStateURL()
|
||||
do {
|
||||
try FileManager().createDirectory(
|
||||
at: url.deletingLastPathComponent(),
|
||||
withIntermediateDirectories: true)
|
||||
try data.write(to: url, options: [.atomic])
|
||||
} catch {
|
||||
// best-effort
|
||||
}
|
||||
}
|
||||
|
||||
private static func configHealthEntry(state: [String: Any], configPath: String) -> [String: Any] {
|
||||
let entries = state["entries"] as? [String: Any]
|
||||
return entries?[configPath] as? [String: Any] ?? [:]
|
||||
}
|
||||
|
||||
private static func setConfigHealthEntry(
|
||||
state: [String: Any],
|
||||
configPath: String,
|
||||
entry: [String: Any]) -> [String: Any]
|
||||
{
|
||||
var next = state
|
||||
var entries = next["entries"] as? [String: Any] ?? [:]
|
||||
entries[configPath] = entry
|
||||
next["entries"] = entries
|
||||
return next
|
||||
}
|
||||
|
||||
private static func isUpdateChannelOnlyRoot(_ root: [String: Any]) -> Bool {
|
||||
let keys = Array(root.keys)
|
||||
guard keys.count == 1, keys.first == "update" else { return false }
|
||||
guard let update = root["update"] as? [String: Any] else { return false }
|
||||
let updateKeys = Array(update.keys)
|
||||
return updateKeys.count == 1 && update["channel"] is String
|
||||
}
|
||||
|
||||
private static func fileTimestampMs(_ value: Any?) -> Double? {
|
||||
guard let date = value as? Date else { return nil }
|
||||
return date.timeIntervalSince1970 * 1000
|
||||
}
|
||||
|
||||
private static func configFingerprint(
|
||||
data: Data,
|
||||
root: [String: Any]?,
|
||||
configURL: URL,
|
||||
observedAt: String) -> [String: Any]
|
||||
{
|
||||
let attributes = try? FileManager().attributesOfItem(atPath: configURL.path)
|
||||
return [
|
||||
"hash": SHA256.hash(data: data).compactMap { String(format: "%02x", $0) }.joined(),
|
||||
"bytes": data.count,
|
||||
"mtimeMs": self.fileTimestampMs(attributes?[.modificationDate]) ?? NSNull(),
|
||||
"ctimeMs": self.fileTimestampMs(attributes?[.creationDate]) ?? NSNull(),
|
||||
"hasMeta": self.hasMeta(root),
|
||||
"gatewayMode": self.gatewayMode(root) ?? NSNull(),
|
||||
"observedAt": observedAt,
|
||||
]
|
||||
}
|
||||
|
||||
private static func sameFingerprint(_ left: [String: Any]?, _ right: [String: Any]) -> Bool {
|
||||
guard let left else { return false }
|
||||
return (left["hash"] as? String) == (right["hash"] as? String) &&
|
||||
(left["bytes"] as? Int) == (right["bytes"] as? Int) &&
|
||||
(left["mtimeMs"] as? Double) == (right["mtimeMs"] as? Double) &&
|
||||
(left["ctimeMs"] as? Double) == (right["ctimeMs"] as? Double) &&
|
||||
(left["hasMeta"] as? Bool) == (right["hasMeta"] as? Bool) &&
|
||||
(left["gatewayMode"] as? String) == (right["gatewayMode"] as? String)
|
||||
}
|
||||
|
||||
private static func observeSuspiciousReasons(
|
||||
root: [String: Any]?,
|
||||
bytes: Int,
|
||||
lastKnownGood: [String: Any]?) -> [String]
|
||||
{
|
||||
guard let lastKnownGood else { return [] }
|
||||
var reasons: [String] = []
|
||||
if let previousBytes = lastKnownGood["bytes"] as? Int,
|
||||
previousBytes >= 512,
|
||||
bytes < max(1, previousBytes / 2)
|
||||
{
|
||||
reasons.append("size-drop-vs-last-good:\(previousBytes)->\(bytes)")
|
||||
}
|
||||
if (lastKnownGood["hasMeta"] as? Bool) == true, !self.hasMeta(root) {
|
||||
reasons.append("missing-meta-vs-last-good")
|
||||
}
|
||||
if (lastKnownGood["gatewayMode"] as? String) != nil, self.gatewayMode(root) == nil {
|
||||
reasons.append("gateway-mode-missing-vs-last-good")
|
||||
}
|
||||
if let root, (lastKnownGood["gatewayMode"] as? String) != nil, self.isUpdateChannelOnlyRoot(root) {
|
||||
reasons.append("update-channel-only-root")
|
||||
}
|
||||
return reasons
|
||||
}
|
||||
|
||||
private static func readConfigFingerprint(at url: URL) -> [String: Any]? {
|
||||
guard let data = try? Data(contentsOf: url) else { return nil }
|
||||
let root = self.parseConfigData(data)
|
||||
return self.configFingerprint(
|
||||
data: data,
|
||||
root: root,
|
||||
configURL: url,
|
||||
observedAt: ISO8601DateFormatter().string(from: Date()))
|
||||
}
|
||||
|
||||
private static func configTimestampToken(_ timestamp: String) -> String {
|
||||
timestamp.replacingOccurrences(of: ":", with: "-")
|
||||
.replacingOccurrences(of: ".", with: "-")
|
||||
}
|
||||
|
||||
private static func persistClobberedSnapshot(data: Data, configURL: URL, observedAt: String) -> String? {
|
||||
let url = configURL.deletingLastPathComponent()
|
||||
.appendingPathComponent("\(configURL.lastPathComponent).clobbered.\(self.configTimestampToken(observedAt))")
|
||||
guard !FileManager().fileExists(atPath: url.path) else { return url.path }
|
||||
do {
|
||||
try data.write(to: url, options: [])
|
||||
return url.path
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private static func observeConfigRead(data: Data, root: [String: Any]?, configURL: URL, valid: Bool) {
|
||||
let observedAt = ISO8601DateFormatter().string(from: Date())
|
||||
let current = self.configFingerprint(data: data, root: root, configURL: configURL, observedAt: observedAt)
|
||||
var state = self.readConfigHealthState()
|
||||
let entry = self.configHealthEntry(state: state, configPath: configURL.path)
|
||||
let lastKnownGood = entry["lastKnownGood"] as? [String: Any]
|
||||
let suspicious = self.observeSuspiciousReasons(
|
||||
root: root,
|
||||
bytes: current["bytes"] as? Int ?? 0,
|
||||
lastKnownGood: lastKnownGood)
|
||||
|
||||
if suspicious.isEmpty {
|
||||
guard valid else { return }
|
||||
let nextEntry: [String: Any] = [
|
||||
"lastKnownGood": current,
|
||||
"lastObservedSuspiciousSignature": NSNull(),
|
||||
]
|
||||
if !self.sameFingerprint(lastKnownGood, current) || entry["lastObservedSuspiciousSignature"] != nil {
|
||||
state = self.setConfigHealthEntry(state: state, configPath: configURL.path, entry: nextEntry)
|
||||
self.writeConfigHealthState(state)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let signature = "\((current["hash"] as? String) ?? ""):\(suspicious.joined(separator: ","))"
|
||||
if (entry["lastObservedSuspiciousSignature"] as? String) == signature {
|
||||
return
|
||||
}
|
||||
|
||||
let backup = self.readConfigFingerprint(at: configURL.deletingLastPathComponent().appendingPathComponent("\(configURL.lastPathComponent).bak"))
|
||||
let clobberedPath = self.persistClobberedSnapshot(data: data, configURL: configURL, observedAt: observedAt)
|
||||
self.logger.warning("config observe anomaly (\(suspicious.joined(separator: ", "))) at \(configURL.path)")
|
||||
self.appendConfigObserveAudit([
|
||||
"phase": "read",
|
||||
"configPath": configURL.path,
|
||||
"exists": true,
|
||||
"valid": valid,
|
||||
"hash": current["hash"] ?? NSNull(),
|
||||
"bytes": current["bytes"] ?? NSNull(),
|
||||
"mtimeMs": current["mtimeMs"] ?? NSNull(),
|
||||
"ctimeMs": current["ctimeMs"] ?? NSNull(),
|
||||
"hasMeta": current["hasMeta"] ?? false,
|
||||
"gatewayMode": current["gatewayMode"] ?? NSNull(),
|
||||
"suspicious": suspicious,
|
||||
"lastKnownGoodHash": lastKnownGood?["hash"] ?? NSNull(),
|
||||
"lastKnownGoodBytes": lastKnownGood?["bytes"] ?? NSNull(),
|
||||
"lastKnownGoodMtimeMs": lastKnownGood?["mtimeMs"] ?? NSNull(),
|
||||
"lastKnownGoodCtimeMs": lastKnownGood?["ctimeMs"] ?? NSNull(),
|
||||
"lastKnownGoodGatewayMode": lastKnownGood?["gatewayMode"] ?? NSNull(),
|
||||
"backupHash": backup?["hash"] ?? NSNull(),
|
||||
"backupBytes": backup?["bytes"] ?? NSNull(),
|
||||
"backupMtimeMs": backup?["mtimeMs"] ?? NSNull(),
|
||||
"backupCtimeMs": backup?["ctimeMs"] ?? NSNull(),
|
||||
"backupGatewayMode": backup?["gatewayMode"] ?? NSNull(),
|
||||
"clobberedPath": clobberedPath ?? NSNull(),
|
||||
])
|
||||
var nextEntry = entry
|
||||
nextEntry["lastObservedSuspiciousSignature"] = signature
|
||||
state = self.setConfigHealthEntry(state: state, configPath: configURL.path, entry: nextEntry)
|
||||
self.writeConfigHealthState(state)
|
||||
}
|
||||
|
||||
private static func appendConfigWriteAudit(_ fields: [String: Any]) {
|
||||
var record: [String: Any] = [
|
||||
"ts": ISO8601DateFormatter().string(from: Date()),
|
||||
@@ -561,40 +351,4 @@ enum OpenClawConfigFile {
|
||||
// best-effort
|
||||
}
|
||||
}
|
||||
|
||||
private static func appendConfigObserveAudit(_ fields: [String: Any]) {
|
||||
var record: [String: Any] = [
|
||||
"ts": ISO8601DateFormatter().string(from: Date()),
|
||||
"source": "macos-openclaw-config-file",
|
||||
"event": "config.observe",
|
||||
"pid": ProcessInfo.processInfo.processIdentifier,
|
||||
"argv": Array(ProcessInfo.processInfo.arguments.prefix(8)),
|
||||
]
|
||||
for (key, value) in fields {
|
||||
record[key] = value is NSNull ? NSNull() : value
|
||||
}
|
||||
guard JSONSerialization.isValidJSONObject(record),
|
||||
let data = try? JSONSerialization.data(withJSONObject: record)
|
||||
else {
|
||||
return
|
||||
}
|
||||
var line = Data()
|
||||
line.append(data)
|
||||
line.append(0x0A)
|
||||
let logURL = self.configAuditLogURL()
|
||||
do {
|
||||
try FileManager().createDirectory(
|
||||
at: logURL.deletingLastPathComponent(),
|
||||
withIntermediateDirectories: true)
|
||||
if !FileManager().fileExists(atPath: logURL.path) {
|
||||
FileManager().createFile(atPath: logURL.path, contents: nil)
|
||||
}
|
||||
let handle = try FileHandle(forWritingTo: logURL)
|
||||
defer { try? handle.close() }
|
||||
try handle.seekToEnd()
|
||||
try handle.write(contentsOf: line)
|
||||
} catch {
|
||||
// best-effort
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ enum RemoteGatewayProbe {
|
||||
}
|
||||
|
||||
do {
|
||||
_ = try await GatewayConnection.shared.healthSnapshot(timeoutMs: 10000)
|
||||
_ = try await GatewayConnection.shared.healthSnapshot(timeoutMs: 10_000)
|
||||
let authSource = await GatewayConnection.shared.authSource()
|
||||
return .ready(RemoteGatewayProbeSuccess(authSource: authSource))
|
||||
} catch {
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2026.3.24</string>
|
||||
<string>2026.3.14</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>202603240</string>
|
||||
<string>202603140</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>OpenClaw</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
||||
@@ -95,8 +95,7 @@ struct SkillsSettings: View {
|
||||
skillKey: skill.skillKey,
|
||||
skillName: skill.name,
|
||||
envKey: envKey,
|
||||
isPrimary: isPrimary,
|
||||
homepage: skill.homepage)
|
||||
isPrimary: isPrimary)
|
||||
})
|
||||
}
|
||||
if !self.model.skills.isEmpty, self.filteredSkills.isEmpty {
|
||||
@@ -259,12 +258,8 @@ private struct SkillRow: View {
|
||||
guard let raw = self.skill.homepage?.trimmingCharacters(in: .whitespacesAndNewlines) else {
|
||||
return nil
|
||||
}
|
||||
guard !raw.isEmpty, let url = URL(string: raw),
|
||||
let scheme = url.scheme?.lowercased(),
|
||||
scheme == "http" || scheme == "https" else {
|
||||
return nil
|
||||
}
|
||||
return url
|
||||
guard !raw.isEmpty else { return nil }
|
||||
return URL(string: raw)
|
||||
}
|
||||
|
||||
private var enabledBinding: Binding<Bool> {
|
||||
@@ -433,7 +428,6 @@ private struct EnvEditorState: Identifiable {
|
||||
let skillName: String
|
||||
let envKey: String
|
||||
let isPrimary: Bool
|
||||
let homepage: String?
|
||||
|
||||
var id: String {
|
||||
"\(self.skillKey)::\(self.envKey)"
|
||||
@@ -453,15 +447,8 @@ private struct EnvEditorView: View {
|
||||
Text(self.subtitle)
|
||||
.font(.subheadline)
|
||||
.foregroundStyle(.secondary)
|
||||
if let homepageUrl = self.homepageUrl {
|
||||
Link("Get your key →", destination: homepageUrl)
|
||||
.font(.caption)
|
||||
}
|
||||
SecureField(self.editor.envKey, text: self.$value)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
Text("Saved to openclaw.json under skills.entries.\(self.editor.skillKey)")
|
||||
.font(.caption2)
|
||||
.foregroundStyle(.tertiary)
|
||||
HStack {
|
||||
Button("Cancel") { self.dismiss() }
|
||||
Spacer()
|
||||
@@ -477,18 +464,6 @@ private struct EnvEditorView: View {
|
||||
.frame(width: 420)
|
||||
}
|
||||
|
||||
private var homepageUrl: URL? {
|
||||
guard let raw = self.editor.homepage?.trimmingCharacters(in: .whitespacesAndNewlines) else {
|
||||
return nil
|
||||
}
|
||||
guard !raw.isEmpty, let url = URL(string: raw),
|
||||
let scheme = url.scheme?.lowercased(),
|
||||
scheme == "http" || scheme == "https" else {
|
||||
return nil
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
private var title: String {
|
||||
self.editor.isPrimary ? "Set API Key" : "Set Environment Variable"
|
||||
}
|
||||
@@ -564,12 +539,12 @@ final class SkillsSettingsModel {
|
||||
_ = try await GatewayConnection.shared.skillsUpdate(
|
||||
skillKey: skillKey,
|
||||
apiKey: value)
|
||||
self.statusMessage = "Saved API key — stored in openclaw.json (skills.entries.\(skillKey))"
|
||||
self.statusMessage = "Saved API key"
|
||||
} else {
|
||||
_ = try await GatewayConnection.shared.skillsUpdate(
|
||||
skillKey: skillKey,
|
||||
env: [envKey: value])
|
||||
self.statusMessage = "Saved \(envKey) — stored in openclaw.json (skills.entries.\(skillKey).env)"
|
||||
self.statusMessage = "Saved \(envKey)"
|
||||
}
|
||||
} catch {
|
||||
self.statusMessage = error.localizedDescription
|
||||
@@ -633,8 +608,7 @@ extension SkillsSettings {
|
||||
skillKey: "test",
|
||||
skillName: "Test Skill",
|
||||
envKey: "API_KEY",
|
||||
isPrimary: true,
|
||||
homepage: "https://example.com"),
|
||||
isPrimary: true),
|
||||
onSave: { _ in })
|
||||
_ = editor.body
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -126,13 +126,6 @@ struct MacGatewayChatTransport: OpenClawChatTransport {
|
||||
timeoutMs: 10000)
|
||||
}
|
||||
|
||||
func compactSession(sessionKey: String) async throws {
|
||||
_ = try await GatewayConnection.shared.request(
|
||||
method: "sessions.compact",
|
||||
params: ["key": AnyCodable(sessionKey)],
|
||||
timeoutMs: 10000)
|
||||
}
|
||||
|
||||
func events() -> AsyncStream<OpenClawChatTransportEvent> {
|
||||
AsyncStream { continuation in
|
||||
let task = Task {
|
||||
|
||||
@@ -2764,110 +2764,6 @@ public struct ToolsCatalogResult: Codable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ToolsEffectiveParams: Codable, Sendable {
|
||||
public let agentid: String?
|
||||
public let sessionkey: String
|
||||
|
||||
public init(
|
||||
agentid: String?,
|
||||
sessionkey: String)
|
||||
{
|
||||
self.agentid = agentid
|
||||
self.sessionkey = sessionkey
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case agentid = "agentId"
|
||||
case sessionkey = "sessionKey"
|
||||
}
|
||||
}
|
||||
|
||||
public struct ToolsEffectiveEntry: Codable, Sendable {
|
||||
public let id: String
|
||||
public let label: String
|
||||
public let description: String
|
||||
public let rawdescription: String
|
||||
public let source: AnyCodable
|
||||
public let pluginid: String?
|
||||
public let channelid: String?
|
||||
|
||||
public init(
|
||||
id: String,
|
||||
label: String,
|
||||
description: String,
|
||||
rawdescription: String,
|
||||
source: AnyCodable,
|
||||
pluginid: String?,
|
||||
channelid: String?)
|
||||
{
|
||||
self.id = id
|
||||
self.label = label
|
||||
self.description = description
|
||||
self.rawdescription = rawdescription
|
||||
self.source = source
|
||||
self.pluginid = pluginid
|
||||
self.channelid = channelid
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case label
|
||||
case description
|
||||
case rawdescription = "rawDescription"
|
||||
case source
|
||||
case pluginid = "pluginId"
|
||||
case channelid = "channelId"
|
||||
}
|
||||
}
|
||||
|
||||
public struct ToolsEffectiveGroup: Codable, Sendable {
|
||||
public let id: AnyCodable
|
||||
public let label: String
|
||||
public let source: AnyCodable
|
||||
public let tools: [ToolsEffectiveEntry]
|
||||
|
||||
public init(
|
||||
id: AnyCodable,
|
||||
label: String,
|
||||
source: AnyCodable,
|
||||
tools: [ToolsEffectiveEntry])
|
||||
{
|
||||
self.id = id
|
||||
self.label = label
|
||||
self.source = source
|
||||
self.tools = tools
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case label
|
||||
case source
|
||||
case tools
|
||||
}
|
||||
}
|
||||
|
||||
public struct ToolsEffectiveResult: Codable, Sendable {
|
||||
public let agentid: String
|
||||
public let profile: String
|
||||
public let groups: [ToolsEffectiveGroup]
|
||||
|
||||
public init(
|
||||
agentid: String,
|
||||
profile: String,
|
||||
groups: [ToolsEffectiveGroup])
|
||||
{
|
||||
self.agentid = agentid
|
||||
self.profile = profile
|
||||
self.groups = groups
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case agentid = "agentId"
|
||||
case profile
|
||||
case groups
|
||||
}
|
||||
}
|
||||
|
||||
public struct SkillsBinsParams: Codable, Sendable {}
|
||||
|
||||
public struct SkillsBinsResult: Codable, Sendable {
|
||||
@@ -2884,6 +2780,54 @@ 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?
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import Foundation
|
||||
import Testing
|
||||
@testable import OpenClaw
|
||||
|
||||
struct ExecApprovalCommandDisplaySanitizerTests {
|
||||
@Test func `escapes invisible command spoofing characters`() {
|
||||
let input = "date\u{200B}\u{3164}\u{FFA0}\u{115F}\u{1160}가"
|
||||
#expect(
|
||||
ExecApprovalCommandDisplaySanitizer.sanitize(input) ==
|
||||
"date\\u{200B}\\u{3164}\\u{FFA0}\\u{115F}\\u{1160}가")
|
||||
}
|
||||
}
|
||||
@@ -135,69 +135,4 @@ struct OpenClawConfigFileTests {
|
||||
#expect(auditRoot?["configPath"] as? String == configPath.path)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
@Test
|
||||
func `load dict audits suspicious out-of-band clobbers`() async throws {
|
||||
let stateDir = FileManager().temporaryDirectory
|
||||
.appendingPathComponent("openclaw-state-\(UUID().uuidString)", isDirectory: true)
|
||||
let configPath = stateDir.appendingPathComponent("openclaw.json")
|
||||
let auditPath = stateDir.appendingPathComponent("logs/config-audit.jsonl")
|
||||
|
||||
defer { try? FileManager().removeItem(at: stateDir) }
|
||||
|
||||
try await TestIsolation.withEnvValues([
|
||||
"OPENCLAW_STATE_DIR": stateDir.path,
|
||||
"OPENCLAW_CONFIG_PATH": configPath.path,
|
||||
]) {
|
||||
OpenClawConfigFile.saveDict([
|
||||
"update": ["channel": "beta"],
|
||||
"browser": ["enabled": true],
|
||||
"gateway": ["mode": "local"],
|
||||
"channels": [
|
||||
"discord": [
|
||||
"enabled": true,
|
||||
"dmPolicy": "pairing",
|
||||
],
|
||||
],
|
||||
])
|
||||
_ = OpenClawConfigFile.loadDict()
|
||||
|
||||
let clobbered = """
|
||||
{
|
||||
"update": {
|
||||
"channel": "beta"
|
||||
}
|
||||
}
|
||||
"""
|
||||
try clobbered.write(to: configPath, atomically: true, encoding: .utf8)
|
||||
|
||||
let loaded = OpenClawConfigFile.loadDict()
|
||||
#expect((loaded["gateway"] as? [String: Any]) == nil)
|
||||
|
||||
let rawAudit = try String(contentsOf: auditPath, encoding: .utf8)
|
||||
let lines = rawAudit
|
||||
.split(whereSeparator: \.isNewline)
|
||||
.map(String.init)
|
||||
let observeLine = lines.reversed().first { $0.contains("\"event\":\"config.observe\"") }
|
||||
#expect(observeLine != nil)
|
||||
guard let observeLine else {
|
||||
Issue.record("Missing config.observe audit line")
|
||||
return
|
||||
}
|
||||
let auditRoot = try JSONSerialization.jsonObject(with: Data(observeLine.utf8)) as? [String: Any]
|
||||
#expect(auditRoot?["source"] as? String == "macos-openclaw-config-file")
|
||||
#expect(auditRoot?["configPath"] as? String == configPath.path)
|
||||
let suspicious = auditRoot?["suspicious"] as? [String] ?? []
|
||||
#expect(suspicious.contains("gateway-mode-missing-vs-last-good"))
|
||||
#expect(suspicious.contains("update-channel-only-root"))
|
||||
|
||||
let clobberedPath = auditRoot?["clobberedPath"] as? String
|
||||
#expect(clobberedPath != nil)
|
||||
if let clobberedPath {
|
||||
let preserved = try String(contentsOfFile: clobberedPath, encoding: .utf8)
|
||||
#expect(preserved == clobbered)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ public protocol OpenClawChatTransport: Sendable {
|
||||
|
||||
func setActiveSessionKey(_ sessionKey: String) async throws
|
||||
func resetSession(sessionKey: String) async throws
|
||||
func compactSession(sessionKey: String) async throws
|
||||
}
|
||||
|
||||
extension OpenClawChatTransport {
|
||||
@@ -41,13 +40,6 @@ extension OpenClawChatTransport {
|
||||
userInfo: [NSLocalizedDescriptionKey: "sessions.reset not supported by this transport"])
|
||||
}
|
||||
|
||||
public func compactSession(sessionKey _: String) async throws {
|
||||
throw NSError(
|
||||
domain: "OpenClawChatTransport",
|
||||
code: 0,
|
||||
userInfo: [NSLocalizedDescriptionKey: "sessions.compact not supported by this transport"])
|
||||
}
|
||||
|
||||
public func abortRun(sessionKey _: String, runId _: String) async throws {
|
||||
throw NSError(
|
||||
domain: "OpenClawChatTransport",
|
||||
|
||||
@@ -60,9 +60,6 @@ public final class OpenClawChatViewModel {
|
||||
private var nextThinkingSelectionRequestID: UInt64 = 0
|
||||
private var latestThinkingSelectionRequestIDsBySession: [String: UInt64] = [:]
|
||||
private var latestThinkingLevelsBySession: [String: String] = [:]
|
||||
private var isCompacting = false
|
||||
private var lastCompactAt: Date?
|
||||
private let compactCooldown: TimeInterval = 60
|
||||
|
||||
private var pendingToolCallsById: [String: OpenClawChatPendingToolCall] = [:] {
|
||||
didSet {
|
||||
@@ -468,7 +465,6 @@ public final class OpenClawChatViewModel {
|
||||
}
|
||||
|
||||
private static let resetTriggers: Set<String> = ["/new", "/reset", "/clear"]
|
||||
private static let compactTriggers: Set<String> = ["/compact"]
|
||||
|
||||
private func performSend() async {
|
||||
guard !self.isSending else { return }
|
||||
@@ -480,11 +476,6 @@ public final class OpenClawChatViewModel {
|
||||
await self.performReset()
|
||||
return
|
||||
}
|
||||
if Self.compactTriggers.contains(trimmed.lowercased()) {
|
||||
self.input = ""
|
||||
await self.performCompact()
|
||||
return
|
||||
}
|
||||
|
||||
let sessionKey = self.sessionKey
|
||||
|
||||
@@ -632,42 +623,6 @@ public final class OpenClawChatViewModel {
|
||||
await self.bootstrap()
|
||||
}
|
||||
|
||||
private func performCompact() async {
|
||||
guard !self.isCompacting else { return }
|
||||
guard !self.isSending, self.pendingRuns.isEmpty, !self.isAborting else {
|
||||
self.errorText = "Wait for the current response before compacting the session."
|
||||
return
|
||||
}
|
||||
if let lastCompactAt,
|
||||
Date().timeIntervalSince(lastCompactAt) < self.compactCooldown
|
||||
{
|
||||
self.errorText = "Please wait before compacting this session again."
|
||||
return
|
||||
}
|
||||
|
||||
self.isCompacting = true
|
||||
self.isLoading = true
|
||||
self.errorText = nil
|
||||
defer {
|
||||
self.isLoading = false
|
||||
self.isCompacting = false
|
||||
}
|
||||
|
||||
do {
|
||||
try await self.transport.compactSession(sessionKey: self.sessionKey)
|
||||
} catch {
|
||||
self.errorText = "Unable to compact the session. Please try again."
|
||||
let nsError = error as NSError
|
||||
chatUILogger.error(
|
||||
"session compact failed domain=\(nsError.domain, privacy: .public) code=\(nsError.code, privacy: .public) details=\(String(describing: error), privacy: .private)"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
self.lastCompactAt = Date()
|
||||
await self.bootstrap()
|
||||
}
|
||||
|
||||
private func performSelectThinkingLevel(_ level: String) async {
|
||||
let next = Self.normalizedThinkingLevel(level) ?? "off"
|
||||
guard next != self.thinkingLevel else { return }
|
||||
|
||||
@@ -2764,110 +2764,6 @@ public struct ToolsCatalogResult: Codable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct ToolsEffectiveParams: Codable, Sendable {
|
||||
public let agentid: String?
|
||||
public let sessionkey: String
|
||||
|
||||
public init(
|
||||
agentid: String?,
|
||||
sessionkey: String)
|
||||
{
|
||||
self.agentid = agentid
|
||||
self.sessionkey = sessionkey
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case agentid = "agentId"
|
||||
case sessionkey = "sessionKey"
|
||||
}
|
||||
}
|
||||
|
||||
public struct ToolsEffectiveEntry: Codable, Sendable {
|
||||
public let id: String
|
||||
public let label: String
|
||||
public let description: String
|
||||
public let rawdescription: String
|
||||
public let source: AnyCodable
|
||||
public let pluginid: String?
|
||||
public let channelid: String?
|
||||
|
||||
public init(
|
||||
id: String,
|
||||
label: String,
|
||||
description: String,
|
||||
rawdescription: String,
|
||||
source: AnyCodable,
|
||||
pluginid: String?,
|
||||
channelid: String?)
|
||||
{
|
||||
self.id = id
|
||||
self.label = label
|
||||
self.description = description
|
||||
self.rawdescription = rawdescription
|
||||
self.source = source
|
||||
self.pluginid = pluginid
|
||||
self.channelid = channelid
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case label
|
||||
case description
|
||||
case rawdescription = "rawDescription"
|
||||
case source
|
||||
case pluginid = "pluginId"
|
||||
case channelid = "channelId"
|
||||
}
|
||||
}
|
||||
|
||||
public struct ToolsEffectiveGroup: Codable, Sendable {
|
||||
public let id: AnyCodable
|
||||
public let label: String
|
||||
public let source: AnyCodable
|
||||
public let tools: [ToolsEffectiveEntry]
|
||||
|
||||
public init(
|
||||
id: AnyCodable,
|
||||
label: String,
|
||||
source: AnyCodable,
|
||||
tools: [ToolsEffectiveEntry])
|
||||
{
|
||||
self.id = id
|
||||
self.label = label
|
||||
self.source = source
|
||||
self.tools = tools
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case label
|
||||
case source
|
||||
case tools
|
||||
}
|
||||
}
|
||||
|
||||
public struct ToolsEffectiveResult: Codable, Sendable {
|
||||
public let agentid: String
|
||||
public let profile: String
|
||||
public let groups: [ToolsEffectiveGroup]
|
||||
|
||||
public init(
|
||||
agentid: String,
|
||||
profile: String,
|
||||
groups: [ToolsEffectiveGroup])
|
||||
{
|
||||
self.agentid = agentid
|
||||
self.profile = profile
|
||||
self.groups = groups
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case agentid = "agentId"
|
||||
case profile
|
||||
case groups
|
||||
}
|
||||
}
|
||||
|
||||
public struct SkillsBinsParams: Codable, Sendable {}
|
||||
|
||||
public struct SkillsBinsResult: Codable, Sendable {
|
||||
@@ -2884,6 +2780,54 @@ 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?
|
||||
|
||||
@@ -84,7 +84,6 @@ private func makeViewModel(
|
||||
sessionsResponses: [OpenClawChatSessionsListResponse] = [],
|
||||
modelResponses: [[OpenClawChatModelChoice]] = [],
|
||||
resetSessionHook: (@Sendable (String) async throws -> Void)? = nil,
|
||||
compactSessionHook: (@Sendable (String) async throws -> Void)? = nil,
|
||||
setSessionModelHook: (@Sendable (String?) async throws -> Void)? = nil,
|
||||
setSessionThinkingHook: (@Sendable (String) async throws -> Void)? = nil,
|
||||
initialThinkingLevel: String? = nil,
|
||||
@@ -96,7 +95,6 @@ private func makeViewModel(
|
||||
sessionsResponses: sessionsResponses,
|
||||
modelResponses: modelResponses,
|
||||
resetSessionHook: resetSessionHook,
|
||||
compactSessionHook: compactSessionHook,
|
||||
setSessionModelHook: setSessionModelHook,
|
||||
setSessionThinkingHook: setSessionThinkingHook)
|
||||
let vm = await MainActor.run {
|
||||
@@ -221,25 +219,11 @@ private actor AsyncGate {
|
||||
}
|
||||
}
|
||||
|
||||
private actor AsyncCounter {
|
||||
private var value: Int
|
||||
|
||||
init(_ initialValue: Int = 0) {
|
||||
self.value = initialValue
|
||||
}
|
||||
|
||||
func increment() -> Int {
|
||||
self.value += 1
|
||||
return self.value
|
||||
}
|
||||
}
|
||||
|
||||
private actor TestChatTransportState {
|
||||
var historyCallCount: Int = 0
|
||||
var sessionsCallCount: Int = 0
|
||||
var modelsCallCount: Int = 0
|
||||
var resetSessionKeys: [String] = []
|
||||
var compactSessionKeys: [String] = []
|
||||
var sentRunIds: [String] = []
|
||||
var sentThinkingLevels: [String] = []
|
||||
var abortedRunIds: [String] = []
|
||||
@@ -253,7 +237,6 @@ private final class TestChatTransport: @unchecked Sendable, OpenClawChatTranspor
|
||||
private let sessionsResponses: [OpenClawChatSessionsListResponse]
|
||||
private let modelResponses: [[OpenClawChatModelChoice]]
|
||||
private let resetSessionHook: (@Sendable (String) async throws -> Void)?
|
||||
private let compactSessionHook: (@Sendable (String) async throws -> Void)?
|
||||
private let setSessionModelHook: (@Sendable (String?) async throws -> Void)?
|
||||
private let setSessionThinkingHook: (@Sendable (String) async throws -> Void)?
|
||||
|
||||
@@ -265,7 +248,6 @@ private final class TestChatTransport: @unchecked Sendable, OpenClawChatTranspor
|
||||
sessionsResponses: [OpenClawChatSessionsListResponse] = [],
|
||||
modelResponses: [[OpenClawChatModelChoice]] = [],
|
||||
resetSessionHook: (@Sendable (String) async throws -> Void)? = nil,
|
||||
compactSessionHook: (@Sendable (String) async throws -> Void)? = nil,
|
||||
setSessionModelHook: (@Sendable (String?) async throws -> Void)? = nil,
|
||||
setSessionThinkingHook: (@Sendable (String) async throws -> Void)? = nil)
|
||||
{
|
||||
@@ -273,7 +255,6 @@ private final class TestChatTransport: @unchecked Sendable, OpenClawChatTranspor
|
||||
self.sessionsResponses = sessionsResponses
|
||||
self.modelResponses = modelResponses
|
||||
self.resetSessionHook = resetSessionHook
|
||||
self.compactSessionHook = compactSessionHook
|
||||
self.setSessionModelHook = setSessionModelHook
|
||||
self.setSessionThinkingHook = setSessionThinkingHook
|
||||
var cont: AsyncStream<OpenClawChatTransportEvent>.Continuation!
|
||||
@@ -355,13 +336,6 @@ private final class TestChatTransport: @unchecked Sendable, OpenClawChatTranspor
|
||||
}
|
||||
}
|
||||
|
||||
func compactSession(sessionKey: String) async throws {
|
||||
await self.state.compactSessionKeysAppend(sessionKey)
|
||||
if let compactSessionHook = self.compactSessionHook {
|
||||
try await compactSessionHook(sessionKey)
|
||||
}
|
||||
}
|
||||
|
||||
func setSessionThinking(sessionKey _: String, thinkingLevel: String) async throws {
|
||||
await self.state.patchedThinkingLevelsAppend(thinkingLevel)
|
||||
if let setSessionThinkingHook = self.setSessionThinkingHook {
|
||||
@@ -401,10 +375,6 @@ private final class TestChatTransport: @unchecked Sendable, OpenClawChatTranspor
|
||||
func resetSessionKeys() async -> [String] {
|
||||
await self.state.resetSessionKeys
|
||||
}
|
||||
|
||||
func compactSessionKeys() async -> [String] {
|
||||
await self.state.compactSessionKeys
|
||||
}
|
||||
}
|
||||
|
||||
extension TestChatTransportState {
|
||||
@@ -443,10 +413,6 @@ extension TestChatTransportState {
|
||||
fileprivate func resetSessionKeysAppend(_ v: String) {
|
||||
self.resetSessionKeys.append(v)
|
||||
}
|
||||
|
||||
fileprivate func compactSessionKeysAppend(_ v: String) {
|
||||
self.compactSessionKeys.append(v)
|
||||
}
|
||||
}
|
||||
|
||||
@Suite struct ChatViewModelTests {
|
||||
@@ -949,140 +915,6 @@ extension TestChatTransportState {
|
||||
#expect(await transport.lastSentRunId() == nil)
|
||||
}
|
||||
|
||||
@Test func compactTriggerCompactsSessionAndReloadsHistory() async throws {
|
||||
let before = historyPayload(
|
||||
messages: [
|
||||
chatTextMessage(role: "assistant", text: "before compact", timestamp: 1),
|
||||
])
|
||||
let after = historyPayload(
|
||||
messages: [
|
||||
chatTextMessage(role: "assistant", text: "after compact", timestamp: 2),
|
||||
])
|
||||
|
||||
let (transport, vm) = await makeViewModel(historyResponses: [before, after])
|
||||
try await loadAndWaitBootstrap(vm: vm)
|
||||
try await waitUntil("initial history loaded") {
|
||||
await MainActor.run { vm.messages.first?.content.first?.text == "before compact" }
|
||||
}
|
||||
|
||||
await MainActor.run {
|
||||
vm.input = "/compact"
|
||||
vm.send()
|
||||
}
|
||||
|
||||
try await waitUntil("compact called") {
|
||||
await transport.compactSessionKeys() == ["main"]
|
||||
}
|
||||
try await waitUntil("history reloaded") {
|
||||
await MainActor.run { vm.messages.first?.content.first?.text == "after compact" }
|
||||
}
|
||||
#expect(await transport.lastSentRunId() == nil)
|
||||
}
|
||||
|
||||
@Test func compactTriggerShowsGenericErrorMessageOnFailure() async throws {
|
||||
let history = historyPayload()
|
||||
let (transport, vm) = await makeViewModel(
|
||||
historyResponses: [history],
|
||||
compactSessionHook: { _ in
|
||||
throw NSError(
|
||||
domain: "TestCompact",
|
||||
code: 42,
|
||||
userInfo: [NSLocalizedDescriptionKey: "backend details should not leak"])
|
||||
})
|
||||
try await loadAndWaitBootstrap(vm: vm)
|
||||
|
||||
await MainActor.run {
|
||||
vm.input = "/compact"
|
||||
vm.send()
|
||||
}
|
||||
|
||||
try await waitUntil("compact attempted") {
|
||||
await transport.compactSessionKeys() == ["main"]
|
||||
}
|
||||
#expect(await MainActor.run { vm.errorText } == "Unable to compact the session. Please try again.")
|
||||
}
|
||||
|
||||
@Test func compactTriggerIgnoresConcurrentAndImmediateRepeatRequests() async throws {
|
||||
let before = historyPayload(
|
||||
messages: [
|
||||
chatTextMessage(role: "assistant", text: "before compact", timestamp: 1),
|
||||
])
|
||||
let after = historyPayload(
|
||||
messages: [
|
||||
chatTextMessage(role: "assistant", text: "after compact", timestamp: 2),
|
||||
])
|
||||
let gate = AsyncGate()
|
||||
let (transport, vm) = await makeViewModel(
|
||||
historyResponses: [before, after],
|
||||
compactSessionHook: { _ in
|
||||
await gate.wait()
|
||||
})
|
||||
try await loadAndWaitBootstrap(vm: vm)
|
||||
|
||||
await MainActor.run {
|
||||
vm.input = "/compact"
|
||||
vm.send()
|
||||
vm.input = "/compact"
|
||||
vm.send()
|
||||
}
|
||||
|
||||
try await waitUntil("single compact request issued") {
|
||||
await transport.compactSessionKeys() == ["main"]
|
||||
}
|
||||
#expect(await MainActor.run { vm.errorText } == nil)
|
||||
|
||||
await gate.open()
|
||||
try await waitUntil("history reloaded after compact") {
|
||||
await MainActor.run { vm.messages.first?.content.first?.text == "after compact" }
|
||||
}
|
||||
|
||||
await MainActor.run {
|
||||
vm.input = "/compact"
|
||||
vm.send()
|
||||
}
|
||||
|
||||
try await Task.sleep(for: .milliseconds(50))
|
||||
#expect(await transport.compactSessionKeys() == ["main"])
|
||||
#expect(await MainActor.run { vm.errorText } == "Please wait before compacting this session again.")
|
||||
}
|
||||
|
||||
@Test func compactTriggerAllowsImmediateRetryAfterFailure() async throws {
|
||||
let history = historyPayload()
|
||||
let attemptCount = AsyncCounter()
|
||||
let (transport, vm) = await makeViewModel(
|
||||
historyResponses: [history],
|
||||
compactSessionHook: { _ in
|
||||
let next = await attemptCount.increment()
|
||||
if next == 1 {
|
||||
throw NSError(
|
||||
domain: "TestCompact",
|
||||
code: 42,
|
||||
userInfo: [NSLocalizedDescriptionKey: "temporary failure"])
|
||||
}
|
||||
})
|
||||
try await loadAndWaitBootstrap(vm: vm)
|
||||
|
||||
await MainActor.run {
|
||||
vm.input = "/compact"
|
||||
vm.send()
|
||||
}
|
||||
|
||||
try await waitUntil("first compact attempted") {
|
||||
await transport.compactSessionKeys() == ["main"]
|
||||
}
|
||||
#expect(await MainActor.run { vm.errorText } == "Unable to compact the session. Please try again.")
|
||||
|
||||
await MainActor.run {
|
||||
vm.input = "/compact"
|
||||
vm.send()
|
||||
}
|
||||
|
||||
try await waitUntil("second compact attempted") {
|
||||
await transport.compactSessionKeys() == ["main", "main"]
|
||||
}
|
||||
#expect(await MainActor.run { vm.errorText } == nil)
|
||||
}
|
||||
|
||||
@Test func bootstrapsModelSelectionFromSessionAndDefaults() async throws {
|
||||
let now = Date().timeIntervalSince1970 * 1000
|
||||
let history = historyPayload()
|
||||
|
||||
@@ -6869,16 +6869,6 @@
|
||||
"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",
|
||||
@@ -7530,16 +7520,6 @@
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "auth.profiles.*.displayName",
|
||||
"kind": "core",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "auth.profiles.*.email",
|
||||
"kind": "core",
|
||||
@@ -10392,20 +10372,6 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.discord.accounts.*.guilds.*.channels.*.autoThreadName",
|
||||
"kind": "channel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"enumValues": [
|
||||
"message",
|
||||
"generated"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.discord.accounts.*.guilds.*.channels.*.enabled",
|
||||
"kind": "channel",
|
||||
@@ -13338,20 +13304,6 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.discord.guilds.*.channels.*.autoThreadName",
|
||||
"kind": "channel",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"enumValues": [
|
||||
"message",
|
||||
"generated"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.discord.guilds.*.channels.*.enabled",
|
||||
"kind": "channel",
|
||||
@@ -17117,7 +17069,8 @@
|
||||
"path": "channels.feishu.requireMention",
|
||||
"kind": "channel",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"required": true,
|
||||
"defaultValue": true,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
@@ -24361,7 +24314,7 @@
|
||||
"network"
|
||||
],
|
||||
"label": "Microsoft Teams",
|
||||
"help": "Teams SDK; enterprise support.",
|
||||
"help": "Bot Framework; enterprise support.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
@@ -31134,26 +31087,6 @@
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.synology-chat.dangerouslyAllowInheritedWebhookPath",
|
||||
"kind": "channel",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.synology-chat.dangerouslyAllowNameMatching",
|
||||
"kind": "channel",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "channels.telegram",
|
||||
"kind": "channel",
|
||||
@@ -42213,46 +42146,6 @@
|
||||
"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",
|
||||
@@ -45790,7 +45683,7 @@
|
||||
"storage"
|
||||
],
|
||||
"label": "Node Browser Proxy Allowed Profiles",
|
||||
"help": "Optional allowlist of browser profile names exposed through node proxy routing. Leave empty to preserve the default full profile surface, including profile create/delete routes. When set, OpenClaw enforces least-privilege profile access and blocks persistent profile create/delete through the proxy.",
|
||||
"help": "Optional allowlist of browser profile names exposed through node proxy routing. Leave empty to expose all configured profiles, or use a tight list to enforce least-privilege profile access.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
@@ -46101,7 +45994,7 @@
|
||||
"advanced"
|
||||
],
|
||||
"label": "Expected acpx Version",
|
||||
"help": "Exact version to enforce or \"any\" to skip strict version matching.",
|
||||
"help": "Exact version to enforce (for example 0.1.16) or \"any\" to skip strict version matching.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
@@ -47366,248 +47259,6 @@
|
||||
"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
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/deepgram-provider",
|
||||
"help": "OpenClaw Deepgram media-understanding provider (plugin: deepgram)",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.config",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/deepgram-provider Config",
|
||||
"help": "Plugin-defined config payload for deepgram.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.enabled",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Enable @openclaw/deepgram-provider",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.hooks",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Hook Policy",
|
||||
"help": "Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.hooks.allowPromptInjection",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Prompt Injection Hooks",
|
||||
"help": "Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.subagent",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Subagent Policy",
|
||||
"help": "Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.subagent.allowedModels",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Plugin Subagent Allowed Models",
|
||||
"help": "Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.subagent.allowedModels.*",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepgram.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
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepseek",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/deepseek-provider",
|
||||
"help": "OpenClaw DeepSeek provider plugin (plugin: deepseek)",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepseek.config",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/deepseek-provider Config",
|
||||
"help": "Plugin-defined config payload for deepseek.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepseek.enabled",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Enable @openclaw/deepseek-provider",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepseek.hooks",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Hook Policy",
|
||||
"help": "Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepseek.hooks.allowPromptInjection",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Prompt Injection Hooks",
|
||||
"help": "Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepseek.subagent",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Subagent Policy",
|
||||
"help": "Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepseek.subagent.allowedModels",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Plugin Subagent Allowed Models",
|
||||
"help": "Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepseek.subagent.allowedModels.*",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.deepseek.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
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.device-pair",
|
||||
"kind": "plugin",
|
||||
@@ -48443,170 +48094,6 @@
|
||||
"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
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/duckduckgo-plugin",
|
||||
"help": "OpenClaw DuckDuckGo plugin (plugin: duckduckgo)",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.config",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/duckduckgo-plugin Config",
|
||||
"help": "Plugin-defined config payload for duckduckgo.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.config.webSearch",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.config.webSearch.region",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "DuckDuckGo Region",
|
||||
"help": "Optional DuckDuckGo region code such as us-en, uk-en, or de-de.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.config.webSearch.safeSearch",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"enumValues": [
|
||||
"strict",
|
||||
"moderate",
|
||||
"off"
|
||||
],
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "DuckDuckGo SafeSearch",
|
||||
"help": "SafeSearch level for DuckDuckGo results.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.enabled",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Enable @openclaw/duckduckgo-plugin",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.hooks",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Hook Policy",
|
||||
"help": "Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.hooks.allowPromptInjection",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Prompt Injection Hooks",
|
||||
"help": "Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.subagent",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Subagent Policy",
|
||||
"help": "Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.subagent.allowedModels",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Plugin Subagent Allowed Models",
|
||||
"help": "Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.subagent.allowedModels.*",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.duckduckgo.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
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.elevenlabs",
|
||||
"kind": "plugin",
|
||||
@@ -48728,155 +48215,6 @@
|
||||
"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
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/exa-plugin",
|
||||
"help": "OpenClaw Exa plugin (plugin: exa)",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.config",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/exa-plugin Config",
|
||||
"help": "Plugin-defined config payload for exa.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.config.webSearch",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.config.webSearch.apiKey",
|
||||
"kind": "plugin",
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": true,
|
||||
"tags": [
|
||||
"auth",
|
||||
"security"
|
||||
],
|
||||
"label": "Exa API Key",
|
||||
"help": "Exa Search API key (fallback: EXA_API_KEY env var).",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.enabled",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Enable @openclaw/exa-plugin",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.hooks",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Hook Policy",
|
||||
"help": "Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.hooks.allowPromptInjection",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Prompt Injection Hooks",
|
||||
"help": "Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.subagent",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Subagent Policy",
|
||||
"help": "Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.subagent.allowedModels",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Plugin Subagent Allowed Models",
|
||||
"help": "Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.subagent.allowedModels.*",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.exa.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
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.fal",
|
||||
"kind": "plugin",
|
||||
@@ -49687,127 +49025,6 @@
|
||||
"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
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/groq-provider",
|
||||
"help": "OpenClaw Groq media-understanding provider (plugin: groq)",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.config",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "@openclaw/groq-provider Config",
|
||||
"help": "Plugin-defined config payload for groq.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.enabled",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Enable @openclaw/groq-provider",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.hooks",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Hook Policy",
|
||||
"help": "Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.hooks.allowPromptInjection",
|
||||
"kind": "plugin",
|
||||
"type": "boolean",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Allow Prompt Injection Hooks",
|
||||
"help": "Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.",
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.subagent",
|
||||
"kind": "plugin",
|
||||
"type": "object",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"advanced"
|
||||
],
|
||||
"label": "Plugin Subagent Policy",
|
||||
"help": "Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.subagent.allowedModels",
|
||||
"kind": "plugin",
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [
|
||||
"access"
|
||||
],
|
||||
"label": "Plugin Subagent Allowed Models",
|
||||
"help": "Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.",
|
||||
"hasChildren": true
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.subagent.allowedModels.*",
|
||||
"kind": "plugin",
|
||||
"type": "string",
|
||||
"required": false,
|
||||
"deprecated": false,
|
||||
"sensitive": false,
|
||||
"tags": [],
|
||||
"hasChildren": false
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.groq.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
|
||||
},
|
||||
{
|
||||
"path": "plugins.entries.huggingface",
|
||||
"kind": "plugin",
|
||||
@@ -58457,46 +57674,6 @@
|
||||
"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",
|
||||
@@ -61253,20 +60430,6 @@
|
||||
"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",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{"generatedBy":"scripts/generate-config-doc-baseline.ts","recordType":"meta","totalPaths":5631}
|
||||
{"generatedBy":"scripts/generate-config-doc-baseline.ts","recordType":"meta","totalPaths":5566}
|
||||
{"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,7 +614,6 @@
|
||||
{"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}
|
||||
@@ -669,7 +668,6 @@
|
||||
{"recordType":"path","path":"auth.order.*.*","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"auth.profiles","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["access","auth","storage"],"label":"Auth Profiles","help":"Named auth profiles (provider + mode + optional email).","hasChildren":true}
|
||||
{"recordType":"path","path":"auth.profiles.*","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"auth.profiles.*.displayName","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"auth.profiles.*.email","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"auth.profiles.*.mode","kind":"core","type":"string","required":true,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"auth.profiles.*.provider","kind":"core","type":"string","required":true,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
@@ -917,7 +915,6 @@
|
||||
{"recordType":"path","path":"channels.discord.accounts.*.guilds.*.channels.*.allow","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.discord.accounts.*.guilds.*.channels.*.autoArchiveDuration","kind":"channel","type":["number","string"],"required":false,"enumValues":["60","1440","4320","10080"],"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.discord.accounts.*.guilds.*.channels.*.autoThread","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.discord.accounts.*.guilds.*.channels.*.autoThreadName","kind":"channel","type":"string","required":false,"enumValues":["message","generated"],"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.discord.accounts.*.guilds.*.channels.*.enabled","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.discord.accounts.*.guilds.*.channels.*.ignoreOtherMentions","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.discord.accounts.*.guilds.*.channels.*.includeThreadStarter","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
@@ -1184,7 +1181,6 @@
|
||||
{"recordType":"path","path":"channels.discord.guilds.*.channels.*.allow","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.discord.guilds.*.channels.*.autoArchiveDuration","kind":"channel","type":["number","string"],"required":false,"enumValues":["60","1440","4320","10080"],"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.discord.guilds.*.channels.*.autoThread","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.discord.guilds.*.channels.*.autoThreadName","kind":"channel","type":"string","required":false,"enumValues":["message","generated"],"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.discord.guilds.*.channels.*.enabled","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.discord.guilds.*.channels.*.ignoreOtherMentions","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.discord.guilds.*.channels.*.includeThreadStarter","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
@@ -1519,7 +1515,7 @@
|
||||
{"recordType":"path","path":"channels.feishu.reactionNotifications","kind":"channel","type":"string","required":true,"enumValues":["off","own","all"],"defaultValue":"own","deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.feishu.renderMode","kind":"channel","type":"string","required":false,"enumValues":["auto","raw","card"],"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.feishu.replyInThread","kind":"channel","type":"string","required":false,"enumValues":["disabled","enabled"],"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.feishu.requireMention","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.feishu.requireMention","kind":"channel","type":"boolean","required":true,"defaultValue":true,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.feishu.resolveSenderNames","kind":"channel","type":"boolean","required":true,"defaultValue":true,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.feishu.streaming","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.feishu.textChunkLimit","kind":"channel","type":"integer","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
@@ -2184,7 +2180,7 @@
|
||||
{"recordType":"path","path":"channels.mattermost.requireMention","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["channels","network"],"label":"Mattermost Require Mention","help":"Require @mention in channels before responding (default: true).","hasChildren":false}
|
||||
{"recordType":"path","path":"channels.mattermost.responsePrefix","kind":"channel","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.mattermost.textChunkLimit","kind":"channel","type":"integer","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.msteams","kind":"channel","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["channels","network"],"label":"Microsoft Teams","help":"Teams SDK; enterprise support.","hasChildren":true}
|
||||
{"recordType":"path","path":"channels.msteams","kind":"channel","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["channels","network"],"label":"Microsoft Teams","help":"Bot Framework; enterprise support.","hasChildren":true}
|
||||
{"recordType":"path","path":"channels.msteams.allowFrom","kind":"channel","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"channels.msteams.allowFrom.*","kind":"channel","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.msteams.appId","kind":"channel","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
@@ -2807,8 +2803,6 @@
|
||||
{"recordType":"path","path":"channels.slack.webhookPath","kind":"channel","type":"string","required":true,"defaultValue":"/slack/events","deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.synology-chat","kind":"channel","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["channels","network"],"label":"Synology Chat","help":"Connect your Synology NAS Chat to OpenClaw with full agent capabilities.","hasChildren":true}
|
||||
{"recordType":"path","path":"channels.synology-chat.*","kind":"channel","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.synology-chat.dangerouslyAllowInheritedWebhookPath","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.synology-chat.dangerouslyAllowNameMatching","kind":"channel","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"channels.telegram","kind":"channel","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["channels","network"],"label":"Telegram","help":"simplest way to get started — register a bot with @BotFather and get going.","hasChildren":true}
|
||||
{"recordType":"path","path":"channels.telegram.accounts","kind":"channel","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"channels.telegram.accounts.*","kind":"channel","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
@@ -3762,10 +3756,6 @@
|
||||
{"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}
|
||||
@@ -4063,7 +4053,7 @@
|
||||
{"recordType":"path","path":"models.providers.*.models.*.reasoning","kind":"core","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"nodeHost","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Node Host","help":"Node host controls for features exposed from this gateway node to other nodes or clients. Keep defaults unless you intentionally proxy local capabilities across your node network.","hasChildren":true}
|
||||
{"recordType":"path","path":"nodeHost.browserProxy","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["network"],"label":"Node Browser Proxy","help":"Groups browser-proxy settings for exposing local browser control through node routing. Enable only when remote node workflows need your local browser profiles.","hasChildren":true}
|
||||
{"recordType":"path","path":"nodeHost.browserProxy.allowProfiles","kind":"core","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access","network","storage"],"label":"Node Browser Proxy Allowed Profiles","help":"Optional allowlist of browser profile names exposed through node proxy routing. Leave empty to preserve the default full profile surface, including profile create/delete routes. When set, OpenClaw enforces least-privilege profile access and blocks persistent profile create/delete through the proxy.","hasChildren":true}
|
||||
{"recordType":"path","path":"nodeHost.browserProxy.allowProfiles","kind":"core","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access","network","storage"],"label":"Node Browser Proxy Allowed Profiles","help":"Optional allowlist of browser profile names exposed through node proxy routing. Leave empty to expose all configured profiles, or use a tight list to enforce least-privilege profile access.","hasChildren":true}
|
||||
{"recordType":"path","path":"nodeHost.browserProxy.allowProfiles.*","kind":"core","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"nodeHost.browserProxy.enabled","kind":"core","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["network"],"label":"Node Browser Proxy Enabled","help":"Expose the local browser control server through node proxy routing so remote clients can use this host's browser capabilities. Keep disabled unless remote automation explicitly depends on it.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins","kind":"core","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugins","help":"Plugin system controls for enabling extensions, constraining load scope, configuring entries, and tracking installs. Keep plugin policy explicit and least-privilege in production environments.","hasChildren":true}
|
||||
@@ -4087,7 +4077,7 @@
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"ACPX Runtime Config","help":"Plugin-defined config payload for acpx.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.command","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"acpx Command","help":"Optional path/command override for acpx (for example /home/user/repos/acpx/dist/cli.js). Leave unset to use plugin-local bundled acpx.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.cwd","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Default Working Directory","help":"Default cwd for ACP session operations when not set per session.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.expectedVersion","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Expected acpx Version","help":"Exact version to enforce or \"any\" to skip strict version matching.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.expectedVersion","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Expected acpx Version","help":"Exact version to enforce (for example 0.1.16) or \"any\" to skip strict version matching.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.mcpServers","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"MCP Servers","help":"Named MCP server definitions to inject into ACPX-backed session bootstrap. Each entry needs a command and can include args and env.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.mcpServers.*","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.acpx.config.mcpServers.*.args","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
@@ -4182,24 +4172,6 @@
|
||||
{"recordType":"path","path":"plugins.entries.copilot-proxy.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.copilot-proxy.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.copilot-proxy.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.entries.deepgram","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/deepgram-provider","help":"OpenClaw Deepgram media-understanding provider (plugin: deepgram)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/deepgram-provider Config","help":"Plugin-defined config payload for deepgram.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/deepgram-provider","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.hooks","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Hook Policy","help":"Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.hooks.allowPromptInjection","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Prompt Injection Hooks","help":"Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.subagent","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Subagent Policy","help":"Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepgram.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.entries.deepseek","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/deepseek-provider","help":"OpenClaw DeepSeek provider plugin (plugin: deepseek)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.deepseek.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/deepseek-provider Config","help":"Plugin-defined config payload for deepseek.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepseek.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/deepseek-provider","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepseek.hooks","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Hook Policy","help":"Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.deepseek.hooks.allowPromptInjection","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Prompt Injection Hooks","help":"Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepseek.subagent","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Subagent Policy","help":"Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.deepseek.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.deepseek.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.deepseek.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.entries.device-pair","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Device Pairing","help":"Generate setup codes and approve device pairing requests. (plugin: device-pair)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.device-pair.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Device Pairing Config","help":"Plugin-defined config payload for device-pair.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.device-pair.config.publicUrl","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Gateway URL","help":"Public WebSocket URL used for /pair setup codes (ws/wss or http/https).","hasChildren":false}
|
||||
@@ -4259,18 +4231,6 @@
|
||||
{"recordType":"path","path":"plugins.entries.discord.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.discord.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.discord.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.entries.duckduckgo","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/duckduckgo-plugin","help":"OpenClaw DuckDuckGo plugin (plugin: duckduckgo)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/duckduckgo-plugin Config","help":"Plugin-defined config payload for duckduckgo.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.config.webSearch","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.config.webSearch.region","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"DuckDuckGo Region","help":"Optional DuckDuckGo region code such as us-en, uk-en, or de-de.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.config.webSearch.safeSearch","kind":"plugin","type":"string","required":false,"enumValues":["strict","moderate","off"],"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"DuckDuckGo SafeSearch","help":"SafeSearch level for DuckDuckGo results.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/duckduckgo-plugin","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.hooks","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Hook Policy","help":"Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.hooks.allowPromptInjection","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Prompt Injection Hooks","help":"Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.subagent","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Subagent Policy","help":"Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.duckduckgo.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.entries.elevenlabs","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/elevenlabs-speech","help":"OpenClaw ElevenLabs speech plugin (plugin: elevenlabs)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.elevenlabs.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/elevenlabs-speech Config","help":"Plugin-defined config payload for elevenlabs.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.elevenlabs.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/elevenlabs-speech","hasChildren":false}
|
||||
@@ -4280,17 +4240,6 @@
|
||||
{"recordType":"path","path":"plugins.entries.elevenlabs.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.elevenlabs.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.elevenlabs.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.entries.exa","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/exa-plugin","help":"OpenClaw Exa plugin (plugin: exa)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.exa.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/exa-plugin Config","help":"Plugin-defined config payload for exa.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.exa.config.webSearch","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.exa.config.webSearch.apiKey","kind":"plugin","type":["object","string"],"required":false,"deprecated":false,"sensitive":true,"tags":["auth","security"],"label":"Exa API Key","help":"Exa Search API key (fallback: EXA_API_KEY env var).","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.exa.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/exa-plugin","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.exa.hooks","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Hook Policy","help":"Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.exa.hooks.allowPromptInjection","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Prompt Injection Hooks","help":"Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.exa.subagent","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Subagent Policy","help":"Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.exa.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.exa.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.exa.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.entries.fal","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/fal-provider","help":"OpenClaw fal provider plugin (plugin: fal)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.fal.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/fal-provider Config","help":"Plugin-defined config payload for fal.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.fal.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/fal-provider","hasChildren":false}
|
||||
@@ -4351,15 +4300,6 @@
|
||||
{"recordType":"path","path":"plugins.entries.googlechat.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.googlechat.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.googlechat.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.entries.groq","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/groq-provider","help":"OpenClaw Groq media-understanding provider (plugin: groq)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.groq.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/groq-provider Config","help":"Plugin-defined config payload for groq.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.groq.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/groq-provider","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.groq.hooks","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Hook Policy","help":"Per-plugin typed hook policy controls for core-enforced safety gates. Use this to constrain high-impact hook categories without disabling the entire plugin.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.groq.hooks.allowPromptInjection","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Allow Prompt Injection Hooks","help":"Controls whether this plugin may mutate prompts through typed hooks. Set false to block `before_prompt_build` and ignore prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride` behavior.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.groq.subagent","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Plugin Subagent Policy","help":"Per-plugin subagent runtime controls for model override trust and allowlists. Keep this unset unless a plugin must explicitly steer subagent model selection.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.groq.subagent.allowedModels","kind":"plugin","type":"array","required":false,"deprecated":false,"sensitive":false,"tags":["access"],"label":"Plugin Subagent Allowed Models","help":"Allowed override targets for trusted plugin subagent runs as canonical \"provider/model\" refs. Use \"*\" only when you intentionally allow any model.","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.groq.subagent.allowedModels.*","kind":"plugin","type":"string","required":false,"deprecated":false,"sensitive":false,"tags":[],"hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.groq.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.entries.huggingface","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/huggingface-provider","help":"OpenClaw Hugging Face provider plugin (plugin: huggingface)","hasChildren":true}
|
||||
{"recordType":"path","path":"plugins.entries.huggingface.config","kind":"plugin","type":"object","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"@openclaw/huggingface-provider Config","help":"Plugin-defined config payload for huggingface.","hasChildren":false}
|
||||
{"recordType":"path","path":"plugins.entries.huggingface.enabled","kind":"plugin","type":"boolean","required":false,"deprecated":false,"sensitive":false,"tags":["advanced"],"label":"Enable @openclaw/huggingface-provider","hasChildren":false}
|
||||
@@ -5019,10 +4959,6 @@
|
||||
{"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}
|
||||
@@ -5247,7 +5183,6 @@
|
||||
{"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
@@ -1,36 +1,36 @@
|
||||
{"category":"legacy","entrypoint":"index","importSpecifier":"openclaw/plugin-sdk","recordType":"module","sourceLine":1,"sourcePath":"src/plugin-sdk/index.ts"}
|
||||
{"declaration":"export function buildFalImageGenerationProvider(): ImageGenerationProvider;","entrypoint":"index","exportName":"buildFalImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":190,"sourcePath":"extensions/fal/image-generation-provider.ts"}
|
||||
{"declaration":"export function buildGoogleImageGenerationProvider(): ImageGenerationProvider;","entrypoint":"index","exportName":"buildGoogleImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":98,"sourcePath":"extensions/google/image-generation-provider.ts"}
|
||||
{"declaration":"export function buildOpenAIImageGenerationProvider(): ImageGenerationProvider;","entrypoint":"index","exportName":"buildOpenAIImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":22,"sourcePath":"extensions/openai/image-generation-provider.ts"}
|
||||
{"declaration":"export function buildFalImageGenerationProvider(): ImageGenerationProvider;","entrypoint":"index","exportName":"buildFalImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":188,"sourcePath":"src/image-generation/providers/fal.ts"}
|
||||
{"declaration":"export function buildGoogleImageGenerationProvider(): ImageGenerationProvider;","entrypoint":"index","exportName":"buildGoogleImageGenerationProvider","importSpecifier":"openclaw/plugin-sdk","kind":"function","recordType":"export","sourceLine":96,"sourcePath":"src/image-generation/providers/google.ts"}
|
||||
{"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 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":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":230,"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 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 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":516,"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":482,"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 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":55,"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":53,"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":63,"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":60,"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":100,"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":97,"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":10,"sourcePath":"src/context-engine/registry.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 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"}
|
||||
@@ -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":951,"sourcePath":"src/plugins/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 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":1314,"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 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 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":4,"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":3,"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":933,"sourcePath":"src/plugins/types.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 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":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 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 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":558,"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":564,"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":216,"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":516,"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":482,"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 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 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":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":365,"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":379,"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":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"}
|
||||
{"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":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 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 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":14,"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":13,"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(\"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(\"/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 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"}
|
||||
@@ -147,8 +147,8 @@
|
||||
{"declaration":"export function createReplyPrefixContext(params: { cfg: OpenClawConfig; agentId: string; channel?: string | undefined; accountId?: string | undefined; }): ReplyPrefixContextBundle;","entrypoint":"channel-runtime","exportName":"createReplyPrefixContext","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":28,"sourcePath":"src/channels/reply-prefix.ts"}
|
||||
{"declaration":"export function createReplyPrefixOptions(params: { cfg: OpenClawConfig; agentId: string; channel?: string | undefined; accountId?: string | undefined; }): ReplyPrefixOptions;","entrypoint":"channel-runtime","exportName":"createReplyPrefixOptions","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":64,"sourcePath":"src/channels/reply-prefix.ts"}
|
||||
{"declaration":"export function createTypingCallbacks(params: CreateTypingCallbacksParams): TypingCallbacks;","entrypoint":"channel-runtime","exportName":"createTypingCallbacks","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":23,"sourcePath":"src/channels/typing.ts"}
|
||||
{"declaration":"export function isWhatsAppGroupJid(value: string): boolean;","entrypoint":"channel-runtime","exportName":"isWhatsAppGroupJid","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":17,"sourcePath":"extensions/whatsapp/src/normalize-target.ts"}
|
||||
{"declaration":"export function isWhatsAppUserTarget(value: string): boolean;","entrypoint":"channel-runtime","exportName":"isWhatsAppUserTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":30,"sourcePath":"extensions/whatsapp/src/normalize-target.ts"}
|
||||
{"declaration":"export function isWhatsAppGroupJid(value: string): boolean;","entrypoint":"channel-runtime","exportName":"isWhatsAppGroupJid","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":17,"sourcePath":"src/whatsapp/normalize.ts"}
|
||||
{"declaration":"export function isWhatsAppUserTarget(value: string): boolean;","entrypoint":"channel-runtime","exportName":"isWhatsAppUserTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":33,"sourcePath":"src/whatsapp/normalize.ts"}
|
||||
{"declaration":"export function keepHttpServerTaskAlive(params: { server: CloseAwareServer; abortSignal?: AbortSignal | undefined; onAbort?: (() => void | Promise<void>) | undefined; }): Promise<void>;","entrypoint":"channel-runtime","exportName":"keepHttpServerTaskAlive","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":79,"sourcePath":"src/plugin-sdk/channel-lifecycle.ts"}
|
||||
{"declaration":"export function looksLikeSignalTargetId(raw: string, normalized?: string | undefined): boolean;","entrypoint":"channel-runtime","exportName":"looksLikeSignalTargetId","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":38,"sourcePath":"src/channels/plugins/normalize/signal.ts"}
|
||||
{"declaration":"export function looksLikeWhatsAppTargetId(raw: string): boolean;","entrypoint":"channel-runtime","exportName":"looksLikeWhatsAppTargetId","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":20,"sourcePath":"src/channels/plugins/normalize/whatsapp.ts"}
|
||||
@@ -158,23 +158,23 @@
|
||||
{"declaration":"export function normalizeSignalMessagingTarget(raw: string): string | undefined;","entrypoint":"channel-runtime","exportName":"normalizeSignalMessagingTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":1,"sourcePath":"src/channels/plugins/normalize/signal.ts"}
|
||||
{"declaration":"export function normalizeWhatsAppAllowFromEntries(allowFrom: (string | number)[]): string[];","entrypoint":"channel-runtime","exportName":"normalizeWhatsAppAllowFromEntries","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":12,"sourcePath":"src/channels/plugins/normalize/whatsapp.ts"}
|
||||
{"declaration":"export function normalizeWhatsAppMessagingTarget(raw: string): string | undefined;","entrypoint":"channel-runtime","exportName":"normalizeWhatsAppMessagingTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":4,"sourcePath":"src/channels/plugins/normalize/whatsapp.ts"}
|
||||
{"declaration":"export function normalizeWhatsAppTarget(value: string): string | null;","entrypoint":"channel-runtime","exportName":"normalizeWhatsAppTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":47,"sourcePath":"extensions/whatsapp/src/normalize-target.ts"}
|
||||
{"declaration":"export function normalizeWhatsAppTarget(value: string): string | null;","entrypoint":"channel-runtime","exportName":"normalizeWhatsAppTarget","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":55,"sourcePath":"src/whatsapp/normalize.ts"}
|
||||
{"declaration":"export function reduceInteractiveReply<TState>(interactive: InteractiveReply | undefined, initialState: TState, reduce: (state: TState, block: InteractiveReplyBlock, index: number) => TState): TState;","entrypoint":"channel-runtime","exportName":"reduceInteractiveReply","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":3,"sourcePath":"src/channels/plugins/outbound/interactive.ts"}
|
||||
{"declaration":"export function resolvePollMaxSelections(optionCount: number, allowMultiselect: boolean | undefined): number;","entrypoint":"channel-runtime","exportName":"resolvePollMaxSelections","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":29,"sourcePath":"src/polls.ts"}
|
||||
{"declaration":"export function resolveWhatsAppHeartbeatRecipients(cfg: OpenClawConfig, opts?: HeartbeatRecipientsOpts): HeartbeatRecipientsResult;","entrypoint":"channel-runtime","exportName":"resolveWhatsAppHeartbeatRecipients","importSpecifier":"openclaw/plugin-sdk/channel-runtime","kind":"function","recordType":"export","sourceLine":48,"sourcePath":"src/channels/plugins/whatsapp-heartbeat.ts"}
|
||||
{"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":558,"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":564,"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":463,"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 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 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":230,"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":223,"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":469,"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":467,"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":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 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":216,"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":210,"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":116,"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":113,"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":209,"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":260,"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":516,"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":482,"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 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 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":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":395,"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 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 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":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":547,"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":538,"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":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 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":254,"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":245,"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":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 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":63,"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":60,"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":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":279,"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":288,"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":322,"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":365,"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":379,"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":509,"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":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 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,27 +245,26 @@
|
||||
{"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":40,"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":37,"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":411,"sourcePath":"src/channels/plugins/setup-wizard-helpers.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"}
|
||||
{"declaration":"export function setSetupChannelEnabled(cfg: OpenClawConfig, channel: string, enabled: boolean): OpenClawConfig;","entrypoint":"channel-setup","exportName":"setSetupChannelEnabled","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":813,"sourcePath":"src/channels/plugins/setup-wizard-helpers.ts"}
|
||||
{"declaration":"export function splitSetupEntries(raw: string): string[];","entrypoint":"channel-setup","exportName":"splitSetupEntries","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":80,"sourcePath":"src/channels/plugins/setup-wizard-helpers.ts"}
|
||||
{"declaration":"export function setSetupChannelEnabled(cfg: OpenClawConfig, channel: string, enabled: boolean): OpenClawConfig;","entrypoint":"channel-setup","exportName":"setSetupChannelEnabled","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":765,"sourcePath":"src/channels/plugins/setup-wizard-helpers.ts"}
|
||||
{"declaration":"export function splitSetupEntries(raw: string): string[];","entrypoint":"channel-setup","exportName":"splitSetupEntries","importSpecifier":"openclaw/plugin-sdk/channel-setup","kind":"function","recordType":"export","sourceLine":76,"sourcePath":"src/channels/plugins/setup-wizard-helpers.ts"}
|
||||
{"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":63,"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":60,"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":29,"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":27,"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":1049,"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":1058,"sourcePath":"src/auto-reply/status.ts"}
|
||||
{"declaration":"export function buildCommandsPaginationKeyboard(currentPage: number, totalPages: number, agentId?: string | undefined): { text: string; callback_data: string; }[][];","entrypoint":"command-auth","exportName":"buildCommandsPaginationKeyboard","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":196,"sourcePath":"src/auto-reply/reply/commands-info.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"}
|
||||
{"declaration":"export function buildCommandsPaginationKeyboard(currentPage: number, totalPages: number, agentId?: string | undefined): { text: string; callback_data: string; }[][];","entrypoint":"command-auth","exportName":"buildCommandsPaginationKeyboard","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":89,"sourcePath":"src/auto-reply/reply/commands-info.ts"}
|
||||
{"declaration":"export function buildCommandText(commandName: string, args?: string | undefined): string;","entrypoint":"command-auth","exportName":"buildCommandText","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":199,"sourcePath":"src/auto-reply/commands-registry.ts"}
|
||||
{"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":844,"sourcePath":"src/auto-reply/status.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"}
|
||||
@@ -287,16 +286,15 @@
|
||||
{"declaration":"export function parseCommandArgs(command: ChatCommandDefinition, raw?: string | undefined): CommandArgs | undefined;","entrypoint":"command-auth","exportName":"parseCommandArgs","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":254,"sourcePath":"src/auto-reply/commands-registry.ts"}
|
||||
{"declaration":"export function resolveCommandArgChoices(params: { command: ChatCommandDefinition; arg: CommandArgDefinition; cfg?: OpenClawConfig | undefined; provider?: string | undefined; model?: string | undefined; }): ResolvedCommandArgChoice[];","entrypoint":"command-auth","exportName":"resolveCommandArgChoices","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":316,"sourcePath":"src/auto-reply/commands-registry.ts"}
|
||||
{"declaration":"export function resolveCommandArgMenu(params: { command: ChatCommandDefinition; args?: CommandArgs | undefined; cfg?: OpenClawConfig | undefined; }): { arg: CommandArgDefinition; choices: ResolvedCommandArgChoice[]; title?: string | undefined; } | null;","entrypoint":"command-auth","exportName":"resolveCommandArgMenu","importSpecifier":"openclaw/plugin-sdk/command-auth","kind":"function","recordType":"export","sourceLine":346,"sourcePath":"src/auto-reply/commands-registry.ts"}
|
||||
{"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":461,"sourcePath":"src/auto-reply/command-auth.ts"}
|
||||
{"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":120,"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":114,"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":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 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 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"}
|
||||
@@ -310,190 +308,175 @@
|
||||
{"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":104,"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":98,"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":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 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 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":163,"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":38,"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":44,"sourcePath":"src/agents/schema/typebox.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 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":437,"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":414,"sourcePath":"src/plugin-sdk/core.ts"}
|
||||
{"declaration":"export function defineChannelPluginEntry<TPlugin>({ id, name, description, plugin, configSchema, setRuntime, registerFull, }: DefineChannelPluginEntryOptions<TPlugin>): DefinedPluginEntry;","entrypoint":"core","exportName":"defineChannelPluginEntry","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":246,"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":277,"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":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 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 enqueueKeyedTask<T>(params: { tails: Map<string, Promise<void>>; key: string; task: () => Promise<T>; hooks?: KeyedAsyncQueueHooks | undefined; }): Promise<...>;","entrypoint":"core","exportName":"enqueueKeyedTask","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":7,"sourcePath":"src/plugin-sdk/keyed-async-queue.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":155,"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":142,"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"}
|
||||
{"declaration":"export function normalizeAccountId(value: string | null | undefined): string;","entrypoint":"core","exportName":"normalizeAccountId","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":34,"sourcePath":"src/routing/account-id.ts"}
|
||||
{"declaration":"export function normalizeAtHashSlug(raw?: string | null | undefined): string;","entrypoint":"core","exportName":"normalizeAtHashSlug","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":19,"sourcePath":"src/shared/string-normalization.ts"}
|
||||
{"declaration":"export function normalizeHyphenSlug(raw?: string | null | undefined): string;","entrypoint":"core","exportName":"normalizeHyphenSlug","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":9,"sourcePath":"src/shared/string-normalization.ts"}
|
||||
{"declaration":"export function optionalStringEnum<T extends readonly string[]>(values: T, options?: StringEnumOptions<T>): TOptional<TUnsafe<T[number]>>;","entrypoint":"core","exportName":"optionalStringEnum","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":31,"sourcePath":"src/agents/schema/typebox.ts"}
|
||||
{"declaration":"export function optionalStringEnum<T extends readonly string[]>(values: T, options?: StringEnumOptions<T>): TOptional<TUnsafe<T[number]>>;","entrypoint":"core","exportName":"optionalStringEnum","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":26,"sourcePath":"src/agents/schema/typebox.ts"}
|
||||
{"declaration":"export function parseOptionalDelimitedEntries(value?: string | undefined): string[] | undefined;","entrypoint":"core","exportName":"parseOptionalDelimitedEntries","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":23,"sourcePath":"src/channels/plugins/helpers.ts"}
|
||||
{"declaration":"export function readSecretFileSync(filePath: string, label: string, options?: SecretFileReadOptions): string;","entrypoint":"core","exportName":"readSecretFileSync","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":118,"sourcePath":"src/infra/secret-file.ts"}
|
||||
{"declaration":"export function resolveGatewayBindUrl(params: { bind?: string | undefined; customBindHost?: string | undefined; scheme: \"ws\" | \"wss\"; port: number; pickTailnetHost: () => string | null; pickLanHost: () => string | null; }): GatewayBindUrlResult;","entrypoint":"core","exportName":"resolveGatewayBindUrl","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":11,"sourcePath":"src/shared/gateway-bind-url.ts"}
|
||||
{"declaration":"export function resolveGatewayPort(cfg?: OpenClawConfig | undefined, env?: ProcessEnv): number;","entrypoint":"core","exportName":"resolveGatewayPort","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":285,"sourcePath":"src/config/paths.ts"}
|
||||
{"declaration":"export function resolveTailnetHostWithRunner(runCommandWithTimeout?: TailscaleStatusCommandRunner | undefined): Promise<string | null>;","entrypoint":"core","exportName":"resolveTailnetHostWithRunner","importSpecifier":"openclaw/plugin-sdk/core","kind":"function","recordType":"export","sourceLine":43,"sourcePath":"src/shared/tailscale-status.ts"}
|
||||
{"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":143,"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":155,"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":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 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":482,"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":395,"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":309,"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":138,"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 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 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":112,"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":951,"sourcePath":"src/plugins/types.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 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":1314,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginCommandDefinition = OpenClawPluginCommandDefinition;","entrypoint":"core","exportName":"OpenClawPluginCommandDefinition","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1068,"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":1296,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginService = OpenClawPluginService;","entrypoint":"core","exportName":"OpenClawPluginService","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1285,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type OpenClawPluginServiceContext = OpenClawPluginServiceContext;","entrypoint":"core","exportName":"OpenClawPluginServiceContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1277,"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":966,"sourcePath":"src/plugins/types.ts"}
|
||||
{"declaration":"export type PluginInteractiveTelegramHandlerContext = PluginInteractiveTelegramHandlerContext;","entrypoint":"core","exportName":"PluginInteractiveTelegramHandlerContext","importSpecifier":"openclaw/plugin-sdk/core","kind":"type","recordType":"export","sourceLine":1097,"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 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 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":477,"sourcePath":"src/plugins/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 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":933,"sourcePath":"src/plugins/types.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 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"}
|
||||
{"declaration":"export class KeyedAsyncQueue","entrypoint":"core","exportName":"KeyedAsyncQueue","importSpecifier":"openclaw/plugin-sdk/core","kind":"class","recordType":"export","sourceLine":34,"sourcePath":"src/plugin-sdk/keyed-async-queue.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":88,"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 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":951,"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":935,"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":1314,"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":1068,"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":1296,"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":1285,"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":1277,"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":966,"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":1097,"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":933,"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":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"}
|
||||
{"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 applyCloudflareAiGatewayConfig(cfg: OpenClawConfig, params?: { accountId?: string | undefined; gatewayId?: string | undefined; } | undefined): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyCloudflareAiGatewayConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":85,"sourcePath":"extensions/cloudflare-ai-gateway/onboard.ts"}
|
||||
{"declaration":"export function applyCloudflareAiGatewayProviderConfig(cfg: OpenClawConfig, params?: { accountId?: string | undefined; gatewayId?: string | undefined; } | undefined): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyCloudflareAiGatewayProviderConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":41,"sourcePath":"extensions/cloudflare-ai-gateway/onboard.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"}
|
||||
{"declaration":"export function applyProviderConfigWithDefaultModel(cfg: OpenClawConfig, params: { agentModels: Record<string, AgentModelEntryConfig>; providerId: string; api: \"github-copilot\" | \"openai-completions\" | ... 5 more ... | \"ollama\"; baseUrl: string; defaultModel: ModelDefinitionConfig; defaultModelId?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithDefaultModel","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":131,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithDefaultModelPreset(cfg: OpenClawConfig, params: { providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\"; ... 4 more ...; primaryModelRef?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithDefaultModelPreset","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":152,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithDefaultModels(cfg: OpenClawConfig, params: { agentModels: Record<string, AgentModelEntryConfig>; providerId: string; api: \"github-copilot\" | \"openai-completions\" | ... 5 more ... | \"ollama\"; baseUrl: string; defaultModels: ModelDefinitionConfig[]; defaultModelId?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithDefaultModels","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":96,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithDefaultModelsPreset(cfg: OpenClawConfig, params: { providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\"; ... 4 more ...; primaryModelRef?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithDefaultModelsPreset","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":230,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithModelCatalog(cfg: OpenClawConfig, params: { agentModels: Record<string, AgentModelEntryConfig>; providerId: string; api: \"github-copilot\" | \"openai-completions\" | ... 5 more ... | \"ollama\"; baseUrl: string; catalogModels: ModelDefinitionConfig[]; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithModelCatalog","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":272,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithModelCatalogPreset(cfg: OpenClawConfig, params: { providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\"; baseUrl: string; catalogModels: ModelDefinitionConfig[]; aliases?: readonly AgentModelAliasEntry[] | undefined; primaryModelRef?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithModelCatalogPreset","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":304,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyVercelAiGatewayConfig(cfg: OpenClawConfig): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyVercelAiGatewayConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":27,"sourcePath":"extensions/vercel-ai-gateway/onboard.ts"}
|
||||
{"declaration":"export function applyVercelAiGatewayProviderConfig(cfg: OpenClawConfig): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyVercelAiGatewayProviderConfig","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":8,"sourcePath":"extensions/vercel-ai-gateway/onboard.ts"}
|
||||
{"declaration":"export function createDefaultModelPresetAppliers<TArgs extends unknown[]>(params: { resolveParams: (cfg: OpenClawConfig, ...args: TArgs) => Omit<{ providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | ... 4 more ... | \"ollama\"; ... 4 more ...; primaryModelRef?: string | undefined; }, \"primaryModelRef\"> | null | undefined; primaryModelRef: string; }): ProviderOnboardPresetAppliers<...>;","entrypoint":"provider-onboard","exportName":"createDefaultModelPresetAppliers","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":213,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function createDefaultModelsPresetAppliers<TArgs extends unknown[]>(params: { resolveParams: (cfg: OpenClawConfig, ...args: TArgs) => Omit<{ providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | ... 4 more ... | \"ollama\"; ... 4 more ...; primaryModelRef?: string | undefined; }, \"primaryModelRef\"> | null | undefined; primaryModelRef: string; }): ProviderOnboardPresetAppliers<...>;","entrypoint":"provider-onboard","exportName":"createDefaultModelsPresetAppliers","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":255,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function createModelCatalogPresetAppliers<TArgs extends unknown[]>(params: { resolveParams: (cfg: OpenClawConfig, ...args: TArgs) => Omit<{ providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | ... 4 more ... | \"ollama\"; baseUrl: string; catalogModels: ModelDefinitionConfig[]; aliases?: readonly AgentModelAliasEntry[] | undefined; primaryModelRef?: string | undefined; }, \"primaryModelRef\"> | null | undefined; primaryModelRef: string; }): ProviderOnboardPresetAppliers<...>;","entrypoint":"provider-onboard","exportName":"createModelCatalogPresetAppliers","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":327,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithDefaultModelsPreset(cfg: OpenClawConfig, params: { providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\"; ... 4 more ...; primaryModelRef?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithDefaultModelsPreset","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":177,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithModelCatalog(cfg: OpenClawConfig, params: { agentModels: Record<string, AgentModelEntryConfig>; providerId: string; api: \"github-copilot\" | \"openai-completions\" | ... 5 more ... | \"ollama\"; baseUrl: string; catalogModels: ModelDefinitionConfig[]; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithModelCatalog","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":202,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function applyProviderConfigWithModelCatalogPreset(cfg: OpenClawConfig, params: { providerId: string; api: \"github-copilot\" | \"openai-completions\" | \"openai-responses\" | \"openai-codex-responses\" | \"anthropic-messages\" | \"google-generative-ai\" | \"bedrock-converse-stream\" | \"ollama\"; baseUrl: string; catalogModels: ModelDefinitionConfig[]; aliases?: readonly AgentModelAliasEntry[] | undefined; primaryModelRef?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"applyProviderConfigWithModelCatalogPreset","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":234,"sourcePath":"src/plugins/provider-onboarding-config.ts"}
|
||||
{"declaration":"export function ensureModelAllowlistEntry(params: { cfg: OpenClawConfig; modelRef: string; defaultProvider?: string | undefined; }): OpenClawConfig;","entrypoint":"provider-onboard","exportName":"ensureModelAllowlistEntry","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"function","recordType":"export","sourceLine":5,"sourcePath":"src/plugins/provider-model-allowlist.ts"}
|
||||
{"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 const CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF: \"cloudflare-ai-gateway/claude-sonnet-4-5\";","entrypoint":"provider-onboard","exportName":"CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"const","recordType":"export","sourceLine":5,"sourcePath":"src/agents/cloudflare-ai-gateway.ts"}
|
||||
{"declaration":"export const VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF: \"vercel-ai-gateway/anthropic/claude-opus-4.6\";","entrypoint":"provider-onboard","exportName":"VERCEL_AI_GATEWAY_DEFAULT_MODEL_REF","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"const","recordType":"export","sourceLine":6,"sourcePath":"extensions/vercel-ai-gateway/onboard.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":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 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 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"}
|
||||
{"declaration":"export type ProviderOnboardPresetAppliers = ProviderOnboardPresetAppliers<TArgs>;","entrypoint":"provider-onboard","exportName":"ProviderOnboardPresetAppliers","importSpecifier":"openclaw/plugin-sdk/provider-onboard","kind":"type","recordType":"export","sourceLine":177,"sourcePath":"src/plugins/provider-onboarding-config.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"}
|
||||
{"declaration":"export function countOutboundMedia(payload: { mediaUrls?: string[] | undefined; mediaUrl?: string | undefined; }): number;","entrypoint":"reply-payload","exportName":"countOutboundMedia","importSpecifier":"openclaw/plugin-sdk/reply-payload","kind":"function","recordType":"export","sourceLine":83,"sourcePath":"src/plugin-sdk/reply-payload.ts"}
|
||||
@@ -522,25 +505,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":54,"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":53,"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":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 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 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":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 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 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":144,"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":139,"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":54,"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":53,"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"}
|
||||
@@ -550,16 +533,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":47,"sourcePath":"src/infra/http-body.ts"}
|
||||
{"declaration":"export function normalizePluginHttpPath(path?: string | null | undefined, fallback?: string | null | undefined): string | null;","entrypoint":"webhook-ingress","exportName":"normalizePluginHttpPath","importSpecifier":"openclaw/plugin-sdk/webhook-ingress","kind":"function","recordType":"export","sourceLine":1,"sourcePath":"src/plugins/http-path.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 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":122,"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":121,"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":60,"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":59,"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"}
|
||||
|
||||
@@ -261,7 +261,7 @@ Isolated jobs (`agentTurn`) can set `lightContext: true` to run with lightweight
|
||||
Isolated jobs can deliver output to a channel via the top-level `delivery` config:
|
||||
|
||||
- `delivery.mode`: `announce` (channel delivery), `webhook` (HTTP POST), or `none`.
|
||||
- `delivery.channel`: `whatsapp` / `telegram` / `discord` / `slack` / `signal` / `imessage` / `irc` / `googlechat` / `line` / `last`, plus extension channels like `msteams` / `mattermost` (plugins).
|
||||
- `delivery.channel`: `whatsapp` / `telegram` / `discord` / `slack` / `mattermost` (plugin) / `signal` / `imessage` / `last`.
|
||||
- `delivery.to`: channel-specific recipient target.
|
||||
|
||||
`announce` delivery is only valid for isolated jobs (`sessionTarget: "isolated"`).
|
||||
@@ -363,7 +363,7 @@ Recurring job in a custom persistent session:
|
||||
Notes:
|
||||
|
||||
- `schedule.kind`: `at` (`at`), `every` (`everyMs`), or `cron` (`expr`, optional `tz`).
|
||||
- `schedule.at` accepts ISO 8601. Tool/API values without a timezone are treated as UTC; the CLI also accepts `openclaw cron add|edit --at "<offset-less-iso>" --tz <iana>` for local wall-clock one-shots.
|
||||
- `schedule.at` accepts ISO 8601 (timezone optional; treated as UTC when omitted).
|
||||
- `everyMs` is milliseconds.
|
||||
- `sessionTarget`: `"main"`, `"isolated"`, `"current"`, or `"session:<custom-id>"`.
|
||||
- `"current"` is resolved to `"session:<sessionKey>"` at creation time.
|
||||
|
||||
@@ -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 inspected with `openclaw hooks`, while hook-pack installation and updates now go through `openclaw plugins`.
|
||||
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.
|
||||
|
||||
## 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). `openclaw hooks list` shows both standalone hooks and plugin-managed hooks.
|
||||
Hooks can also be bundled inside plugins; see [Plugin hooks](/plugins/architecture#provider-runtime-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. 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.
|
||||
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.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -43,7 +43,7 @@ The hooks system allows you to:
|
||||
|
||||
OpenClaw ships with four bundled hooks that are automatically discovered:
|
||||
|
||||
- **💾 session-memory**: Saves session context to your agent workspace (default `~/.openclaw/workspace/memory/`) when you issue `/new` or `/reset`
|
||||
- **💾 session-memory**: Saves session context to your agent workspace (default `~/.openclaw/workspace/memory/`) when you issue `/new`
|
||||
- **📎 bootstrap-extra-files**: Injects additional workspace bootstrap files from configured glob/path patterns during `agent:bootstrap`
|
||||
- **📝 command-logger**: Logs all command events to `~/.openclaw/logs/commands.log`
|
||||
- **🚀 boot-md**: Runs `BOOT.md` when the gateway starts (requires internal hooks enabled)
|
||||
@@ -76,20 +76,13 @@ 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 these directories, in order of increasing override precedence:
|
||||
Hooks are automatically discovered from three directories (in order of precedence):
|
||||
|
||||
1. **Bundled hooks**: shipped with OpenClaw; located at `<openclaw>/dist/hooks/bundled/` for npm installs (or a sibling `hooks/bundled/` for compiled binaries)
|
||||
2. **Plugin hooks**: hooks bundled inside installed plugins (see [Plugin hooks](/plugins/architecture#provider-runtime-hooks))
|
||||
3. **Managed hooks**: `~/.openclaw/hooks/` (user-installed, shared across workspaces; can override bundled and plugin hooks). **Extra hook directories** configured via `hooks.internal.load.extraDirs` are also treated as managed hooks and share the same override precedence.
|
||||
4. **Workspace hooks**: `<workspace>/hooks/` (per-agent, disabled by default until explicitly enabled; cannot override hooks from other sources)
|
||||
|
||||
Workspace hooks can add new hook names for a repo, but they cannot override bundled, managed, or plugin-provided hooks with the same name.
|
||||
1. **Workspace hooks**: `<workspace>/hooks/` (per-agent, highest precedence)
|
||||
2. **Managed hooks**: `~/.openclaw/hooks/` (user-installed, shared across workspaces)
|
||||
3. **Bundled hooks**: `<openclaw>/dist/hooks/bundled/` (shipped with OpenClaw)
|
||||
|
||||
Managed hook directories can be either a **single hook** or a **hook pack** (package directory).
|
||||
|
||||
@@ -107,7 +100,7 @@ Hook packs are standard npm packages that export one or more hooks via `openclaw
|
||||
`package.json`. Install them with:
|
||||
|
||||
```bash
|
||||
openclaw plugins install <path-or-spec>
|
||||
openclaw hooks install <path-or-spec>
|
||||
```
|
||||
|
||||
Npm specs are registry-only (package name + optional exact version or dist-tag).
|
||||
@@ -134,7 +127,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 plugins install` installs hook-pack dependencies with `npm install --ignore-scripts`
|
||||
Security note: `openclaw hooks install` installs 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.
|
||||
|
||||
@@ -180,12 +173,12 @@ The `metadata.openclaw` object supports:
|
||||
- **`events`**: Array of events to listen for (e.g., `["command:new", "command:reset"]`)
|
||||
- **`export`**: Named export to use (defaults to `"default"`)
|
||||
- **`homepage`**: Documentation URL
|
||||
- **`os`**: Required platforms (e.g., `["darwin", "linux"]`)
|
||||
- **`requires`**: Optional requirements
|
||||
- **`bins`**: Required binaries on PATH (e.g., `["git", "node"]`)
|
||||
- **`anyBins`**: At least one of these binaries must be present
|
||||
- **`env`**: Required environment variables
|
||||
- **`config`**: Required config paths (e.g., `["workspace.dir"]`)
|
||||
- **`os`**: Required platforms (e.g., `["darwin", "linux"]`)
|
||||
- **`always`**: Bypass eligibility checks (boolean)
|
||||
- **`install`**: Installation methods (for bundled hooks: `[{"id":"bundled","kind":"bundled"}]`)
|
||||
|
||||
@@ -225,17 +218,15 @@ Each event includes:
|
||||
timestamp: Date, // When the event occurred
|
||||
messages: string[], // Push messages here to send to user
|
||||
context: {
|
||||
// Command events (command:new, command:reset):
|
||||
sessionEntry?: SessionEntry, // current session entry
|
||||
previousSessionEntry?: SessionEntry, // pre-reset entry (preferred for session-memory)
|
||||
commandSource?: string, // e.g., 'whatsapp', 'telegram'
|
||||
// Command events:
|
||||
sessionEntry?: SessionEntry,
|
||||
sessionId?: string,
|
||||
sessionFile?: string,
|
||||
commandSource?: string, // e.g., 'whatsapp', 'telegram'
|
||||
senderId?: string,
|
||||
workspaceDir?: string,
|
||||
cfg?: OpenClawConfig,
|
||||
// Command events (command:stop only):
|
||||
sessionId?: string,
|
||||
// Agent bootstrap events (agent:bootstrap):
|
||||
bootstrapFiles?: WorkspaceBootstrapFile[],
|
||||
cfg?: OpenClawConfig,
|
||||
// Message events (see Message Events section for full details):
|
||||
from?: string, // message:received
|
||||
to?: string, // message:sent
|
||||
@@ -275,68 +266,6 @@ Triggered when the gateway starts:
|
||||
|
||||
- **`gateway:startup`**: After channels start and hooks are loaded
|
||||
|
||||
### Session Patch Events
|
||||
|
||||
Triggered when session properties are modified:
|
||||
|
||||
- **`session:patch`**: When a session is updated
|
||||
|
||||
#### Session Event Context
|
||||
|
||||
Session events include rich context about the session and changes:
|
||||
|
||||
```typescript
|
||||
{
|
||||
sessionEntry: SessionEntry, // The complete updated session entry
|
||||
patch: { // The patch object (only changed fields)
|
||||
// Session identity & labeling
|
||||
label?: string | null, // Human-readable session label
|
||||
|
||||
// AI model configuration
|
||||
model?: string | null, // Model override (e.g., "claude-opus-4-5")
|
||||
thinkingLevel?: string | null, // Thinking level ("off"|"low"|"med"|"high")
|
||||
verboseLevel?: string | null, // Verbose output level
|
||||
reasoningLevel?: string | null, // Reasoning mode override
|
||||
elevatedLevel?: string | null, // Elevated mode override
|
||||
responseUsage?: "off" | "tokens" | "full" | null, // Usage display mode
|
||||
|
||||
// Tool execution settings
|
||||
execHost?: string | null, // Exec host (sandbox|gateway|node)
|
||||
execSecurity?: string | null, // Security mode (deny|allowlist|full)
|
||||
execAsk?: string | null, // Approval mode (off|on-miss|always)
|
||||
execNode?: string | null, // Node ID for host=node
|
||||
|
||||
// Subagent coordination
|
||||
spawnedBy?: string | null, // Parent session key (for subagents)
|
||||
spawnDepth?: number | null, // Nesting depth (0 = root)
|
||||
|
||||
// Communication policies
|
||||
sendPolicy?: "allow" | "deny" | null, // Message send policy
|
||||
groupActivation?: "mention" | "always" | null, // Group chat activation
|
||||
},
|
||||
cfg: OpenClawConfig // Current gateway config
|
||||
}
|
||||
```
|
||||
|
||||
**Security note:** Only privileged clients (including the Control UI) can trigger `session:patch` events. Standard WebChat clients are blocked from patching sessions (see PR #20800), so the hook will not fire from those connections.
|
||||
|
||||
See `SessionsPatchParamsSchema` in `src/gateway/protocol/schema/sessions.ts` for the complete type definition.
|
||||
|
||||
#### Example: Session Patch Logger Hook
|
||||
|
||||
```typescript
|
||||
const handler = async (event) => {
|
||||
if (event.type !== "session" || event.action !== "patch") {
|
||||
return;
|
||||
}
|
||||
const { patch } = event.context;
|
||||
console.log(`[session-patch] Session updated: ${event.sessionKey}`);
|
||||
console.log(`[session-patch] Changes:`, patch);
|
||||
};
|
||||
|
||||
export default handler;
|
||||
```
|
||||
|
||||
### Message Events
|
||||
|
||||
Triggered when messages are received or sent:
|
||||
@@ -365,13 +294,11 @@ Message events include rich context about the message:
|
||||
to?: string,
|
||||
provider?: string,
|
||||
surface?: string,
|
||||
threadId?: string | number,
|
||||
threadId?: string,
|
||||
senderId?: string,
|
||||
senderName?: string,
|
||||
senderUsername?: string,
|
||||
senderE164?: string,
|
||||
guildId?: string, // Discord guild / server ID
|
||||
channelName?: string, // Channel name (e.g., Discord channel name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,42 +318,22 @@ 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,
|
||||
}
|
||||
@@ -476,8 +383,8 @@ Planned event types:
|
||||
|
||||
### 1. Choose Location
|
||||
|
||||
- **Workspace hooks** (`<workspace>/hooks/`): Per-agent; can add new hook names but cannot override bundled, managed, or plugin hooks with the same name
|
||||
- **Managed hooks** (`~/.openclaw/hooks/`): Shared across workspaces; can override bundled and plugin hooks
|
||||
- **Workspace hooks** (`<workspace>/hooks/`): Per-agent, highest precedence
|
||||
- **Managed hooks** (`~/.openclaw/hooks/`): Shared across workspaces
|
||||
|
||||
### 2. Create Directory Structure
|
||||
|
||||
@@ -572,7 +479,7 @@ Hooks can have custom configuration:
|
||||
|
||||
### Extra Directories
|
||||
|
||||
Load hooks from additional directories (treated as managed hooks, same override precedence):
|
||||
Load hooks from additional directories:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -664,9 +571,9 @@ openclaw hooks disable command-logger
|
||||
|
||||
### session-memory
|
||||
|
||||
Saves session context to memory when you issue `/new` or `/reset`.
|
||||
Saves session context to memory when you issue `/new`.
|
||||
|
||||
**Events**: `command:new`, `command:reset`
|
||||
**Events**: `command:new`
|
||||
|
||||
**Requirements**: `workspace.dir` must be configured
|
||||
|
||||
@@ -675,7 +582,7 @@ Saves session context to memory when you issue `/new` or `/reset`.
|
||||
**What it does**:
|
||||
|
||||
1. Uses the pre-reset session entry to locate the correct transcript
|
||||
2. Extracts the last 15 user/assistant messages from the conversation (configurable)
|
||||
2. Extracts the last 15 lines of conversation
|
||||
3. Uses LLM to generate a descriptive filename slug
|
||||
4. Saves session metadata to a dated memory file
|
||||
|
||||
@@ -687,11 +594,6 @@ Saves session context to memory when you issue `/new` or `/reset`.
|
||||
- **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**:
|
||||
@@ -734,18 +636,12 @@ Injects additional bootstrap files (for example monorepo-local `AGENTS.md` / `TO
|
||||
}
|
||||
```
|
||||
|
||||
**Config options**:
|
||||
|
||||
- `paths` (string[]): glob/path patterns to resolve from the workspace.
|
||||
- `patterns` (string[]): alias of `paths`.
|
||||
- `files` (string[]): alias of `paths`.
|
||||
|
||||
**Notes**:
|
||||
|
||||
- Paths are resolved relative to workspace.
|
||||
- Files must stay inside workspace (realpath-checked).
|
||||
- Only recognized bootstrap basenames are loaded (`AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md`, `MEMORY.md`, `memory.md`).
|
||||
- For subagent/cron sessions a narrower allowlist applies (`AGENTS.md`, `TOOLS.md`, `SOUL.md`, `IDENTITY.md`, `USER.md`).
|
||||
- Only recognized bootstrap basenames are loaded.
|
||||
- Subagent allowlist is preserved (`AGENTS.md` and `TOOLS.md` only).
|
||||
|
||||
**Enable**:
|
||||
|
||||
@@ -978,12 +874,10 @@ test("my handler works", async () => {
|
||||
```
|
||||
Gateway startup
|
||||
↓
|
||||
Scan directories (bundled → plugin → managed + extra dirs → workspace)
|
||||
Scan directories (workspace → managed → bundled)
|
||||
↓
|
||||
Parse HOOK.md files
|
||||
↓
|
||||
Sort by override precedence (bundled < plugin < managed < workspace)
|
||||
↓
|
||||
Check eligibility (bins, env, config, os)
|
||||
↓
|
||||
Load handlers from eligible hooks
|
||||
|
||||
@@ -43,7 +43,7 @@ Each program specifies:
|
||||
The agent loads these instructions every session via the workspace bootstrap files (see [Agent Workspace](/concepts/agent-workspace) for the full list of auto-injected files) and executes against them, combined with [cron jobs](/automation/cron-jobs) for time-based enforcement.
|
||||
|
||||
<Tip>
|
||||
Put standing orders in `AGENTS.md` to guarantee they're loaded every session. The workspace bootstrap automatically injects `AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, `BOOTSTRAP.md`, and `MEMORY.md` — but not arbitrary files in subdirectories.
|
||||
Put standing orders in `AGENTS.md` to guarantee they're loaded every session. The workspace bootstrap automatically injects `AGENTS.md`, `SOUL.md`, `TOOLS.md`, `IDENTITY.md`, `USER.md`, `HEARTBEAT.md`, and `MEMORY.md` — but not arbitrary files in subdirectories.
|
||||
</Tip>
|
||||
|
||||
## Anatomy of a Standing Order
|
||||
@@ -86,7 +86,7 @@ Agent: Reads standing orders → executes steps → reports results
|
||||
The cron job prompt should reference the standing order rather than duplicating it:
|
||||
|
||||
```bash
|
||||
openclaw cron add \
|
||||
openclaw cron create \
|
||||
--name daily-inbox-triage \
|
||||
--cron "0 8 * * 1-5" \
|
||||
--tz America/New_York \
|
||||
@@ -237,7 +237,7 @@ Each program should have:
|
||||
- Review agent logs weekly to verify standing orders are being followed
|
||||
- Update standing orders as your needs evolve — they're living documents
|
||||
|
||||
### Avoid
|
||||
### Don't
|
||||
|
||||
- Grant broad authority on day one ("do whatever you think is best")
|
||||
- Skip escalation rules — every program needs a "when to stop and ask" clause
|
||||
|
||||
@@ -107,7 +107,7 @@ Quick rules:
|
||||
- `Config path not found: agents.defaults.userTimezone` means the key is unset; heartbeat falls back to host timezone (or `activeHours.timezone` if set).
|
||||
- Cron without `--tz` uses gateway host timezone.
|
||||
- Heartbeat `activeHours` uses configured timezone resolution (`user`, `local`, or explicit IANA tz).
|
||||
- Cron `at` schedules treat ISO timestamps without timezone as UTC unless you used CLI `--at "<offset-less-iso>" --tz <iana>`.
|
||||
- ISO timestamps without timezone are treated as UTC for cron `at` schedules.
|
||||
|
||||
Common signatures:
|
||||
|
||||
|
||||
@@ -84,9 +84,9 @@ Payload:
|
||||
- `sessionKey` optional (string): The key used to identify the agent's session. By default this field is rejected unless `hooks.allowRequestSessionKey=true`.
|
||||
- `wakeMode` optional (`now` | `next-heartbeat`): Whether to trigger an immediate heartbeat (default `now`) or wait for the next periodic check.
|
||||
- `deliver` optional (boolean): If `true`, the agent's response will be sent to the messaging channel. Defaults to `true`. Responses that are only heartbeat acknowledgments are automatically skipped.
|
||||
- `channel` optional (string): The messaging channel for delivery. Core channels: `last`, `whatsapp`, `telegram`, `discord`, `slack`, `signal`, `imessage`, `irc`, `googlechat`, `line`. Extension channels (plugins): `msteams`, `mattermost`, and others. Defaults to `last`.
|
||||
- `channel` optional (string): The messaging channel for delivery. One of: `last`, `whatsapp`, `telegram`, `discord`, `slack`, `mattermost` (plugin), `signal`, `imessage`, `msteams`. Defaults to `last`.
|
||||
- `to` optional (string): The recipient identifier for the channel (e.g., phone number for WhatsApp/Signal, chat ID for Telegram, channel ID for Discord/Slack/Mattermost (plugin), conversation ID for Microsoft Teams). Defaults to the last recipient in the main session.
|
||||
- `model` optional (string): Model override (e.g., `anthropic/claude-sonnet-4-6` or an alias). Must be in the allowed model list if restricted.
|
||||
- `model` optional (string): Model override (e.g., `anthropic/claude-3-5-sonnet` or an alias). Must be in the allowed model list if restricted.
|
||||
- `thinking` optional (string): Thinking level override (e.g., `low`, `medium`, `high`).
|
||||
- `timeoutSeconds` optional (number): Maximum duration for the agent run in seconds.
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ summary: "Brave Search API setup for web_search"
|
||||
read_when:
|
||||
- You want to use Brave Search for web_search
|
||||
- You need a BRAVE_API_KEY or plan details
|
||||
title: "Brave Search (legacy path)"
|
||||
title: "Brave Search"
|
||||
---
|
||||
|
||||
# Brave Search API
|
||||
|
||||
@@ -13,7 +13,7 @@ host configuration.
|
||||
|
||||
## Key terms
|
||||
|
||||
- **Channel**: `telegram`, `whatsapp`, `discord`, `irc`, `googlechat`, `slack`, `signal`, `imessage`, `line`, plus extension channels. `webchat` is the internal WebChat UI channel and is not a configurable outbound channel.
|
||||
- **Channel**: `whatsapp`, `telegram`, `discord`, `slack`, `signal`, `imessage`, `webchat`.
|
||||
- **AccountId**: per‑channel account instance (when supported).
|
||||
- Optional channel default account: `channels.<channel>.defaultAccount` chooses
|
||||
which account is used when an outbound path does not specify `accountId`.
|
||||
|
||||
@@ -92,7 +92,7 @@ You will need to create a new application with a bot, add the bot to your server
|
||||
|
||||
</Step>
|
||||
|
||||
<Step title="Set your bot token securely (do not send it in chat)">
|
||||
<Step title="Step 0: Set your bot token securely (do not send it in chat)">
|
||||
Your Discord bot token is a secret (like a password). Set it on the machine running OpenClaw before messaging your agent.
|
||||
|
||||
```bash
|
||||
@@ -582,7 +582,6 @@ 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.
|
||||
|
||||
@@ -185,7 +185,7 @@ Edit `~/.openclaw/openclaw.json`:
|
||||
main: {
|
||||
appId: "cli_xxx",
|
||||
appSecret: "xxx",
|
||||
name: "My AI assistant",
|
||||
botName: "My AI assistant",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -316,43 +316,41 @@ After approval, you can chat normally.
|
||||
|
||||
**1. Group policy** (`channels.feishu.groupPolicy`):
|
||||
|
||||
- `"open"` = allow everyone in groups
|
||||
- `"open"` = allow everyone in groups (default)
|
||||
- `"allowlist"` = only allow `groupAllowFrom`
|
||||
- `"disabled"` = disable group messages
|
||||
|
||||
Default: `allowlist`
|
||||
**2. Mention requirement** (`channels.feishu.groups.<chat_id>.requireMention`):
|
||||
|
||||
**2. Mention requirement** (`channels.feishu.requireMention`, overridable via `channels.feishu.groups.<chat_id>.requireMention`):
|
||||
|
||||
- explicit `true` = require @mention
|
||||
- explicit `false` = respond without mentions
|
||||
- when unset and `groupPolicy: "open"` = default to `false`
|
||||
- when unset and `groupPolicy` is not `"open"` = default to `true`
|
||||
- `true` = require @mention (default)
|
||||
- `false` = respond without mentions
|
||||
|
||||
---
|
||||
|
||||
## Group configuration examples
|
||||
|
||||
### Allow all groups, no @mention required (default for open groups)
|
||||
### Allow all groups, require @mention (default)
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
groupPolicy: "open",
|
||||
// Default requireMention: true
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Allow all groups, but still require @mention
|
||||
### Allow all groups, no @mention required
|
||||
|
||||
```json5
|
||||
{
|
||||
channels: {
|
||||
feishu: {
|
||||
groupPolicy: "open",
|
||||
requireMention: true,
|
||||
groups: {
|
||||
oc_xxx: { requireMention: false },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -496,12 +494,12 @@ openclaw pairing list feishu
|
||||
main: {
|
||||
appId: "cli_xxx",
|
||||
appSecret: "xxx",
|
||||
name: "Primary bot",
|
||||
botName: "Primary bot",
|
||||
},
|
||||
backup: {
|
||||
appId: "cli_yyy",
|
||||
appSecret: "yyy",
|
||||
name: "Backup bot",
|
||||
botName: "Backup bot",
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
@@ -682,10 +680,9 @@ Key options:
|
||||
| `channels.feishu.accounts.<id>.domain` | Per-account API domain override | `feishu` |
|
||||
| `channels.feishu.dmPolicy` | DM policy | `pairing` |
|
||||
| `channels.feishu.allowFrom` | DM allowlist (open_id list) | - |
|
||||
| `channels.feishu.groupPolicy` | Group policy | `allowlist` |
|
||||
| `channels.feishu.groupPolicy` | Group policy | `open` |
|
||||
| `channels.feishu.groupAllowFrom` | Group allowlist | - |
|
||||
| `channels.feishu.requireMention` | Default require @mention | conditional |
|
||||
| `channels.feishu.groups.<chat_id>.requireMention` | Per-group require @mention override | inherited |
|
||||
| `channels.feishu.groups.<chat_id>.requireMention` | Require @mention | `true` |
|
||||
| `channels.feishu.groups.<chat_id>.enabled` | Enable group | `true` |
|
||||
| `channels.feishu.textChunkLimit` | Message chunk size | `2000` |
|
||||
| `channels.feishu.mediaMaxMb` | Media size limit | `30` |
|
||||
|
||||
@@ -116,7 +116,7 @@ Want “groups can only see folder X” instead of “no host access”? Keep `w
|
||||
|
||||
Related:
|
||||
|
||||
- Configuration keys and defaults: [Gateway configuration](/gateway/configuration-reference#agentsdefaultssandbox)
|
||||
- Configuration keys and defaults: [Gateway configuration](/gateway/configuration-reference#agents-defaults-sandbox)
|
||||
- Debugging why a tool is blocked: [Sandbox vs Tool Policy vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated)
|
||||
- Bind mounts details: [Sandboxing](/gateway/sandboxing#custom-bind-mounts)
|
||||
|
||||
|
||||
@@ -26,12 +26,11 @@ Text is supported everywhere; media and reactions vary by channel.
|
||||
- [Nextcloud Talk](/channels/nextcloud-talk) — Self-hosted chat via Nextcloud Talk (plugin, installed separately).
|
||||
- [Nostr](/channels/nostr) — Decentralized DMs via NIP-04 (plugin, installed separately).
|
||||
- [Signal](/channels/signal) — signal-cli; privacy-focused.
|
||||
- [Slack](/channels/slack) — Bolt SDK; workspace apps.
|
||||
- [Synology Chat](/channels/synology-chat) — Synology NAS Chat via outgoing+incoming webhooks (plugin, installed separately).
|
||||
- [Slack](/channels/slack) — Bolt SDK; workspace apps.
|
||||
- [Telegram](/channels/telegram) — Bot API via grammY; supports groups.
|
||||
- [Tlon](/channels/tlon) — Urbit-based messenger (plugin, installed separately).
|
||||
- [Twitch](/channels/twitch) — Twitch chat via IRC connection (plugin, installed separately).
|
||||
- [Voice Call](/plugins/voice-call) — Telephony via Plivo or Twilio (plugin, installed separately).
|
||||
- [WebChat](/web/webchat) — Gateway WebChat UI over WebSocket.
|
||||
- [WhatsApp](/channels/whatsapp) — Most popular; uses Baileys and requires QR pairing.
|
||||
- [Zalo](/channels/zalo) — Zalo Bot API; Vietnam's popular messenger (plugin, installed separately).
|
||||
|
||||
@@ -74,7 +74,7 @@ If you see logs like:
|
||||
|
||||
Example (allow anyone in `#tuirc-dev` to talk to the bot):
|
||||
|
||||
```json5
|
||||
```json55
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
@@ -95,7 +95,7 @@ That means you may see logs like `drop channel … (missing-mention)` unless the
|
||||
|
||||
To make the bot reply in an IRC channel **without needing a mention**, disable mention gating for that channel:
|
||||
|
||||
```json5
|
||||
```json55
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
@@ -113,7 +113,7 @@ To make the bot reply in an IRC channel **without needing a mention**, disable m
|
||||
|
||||
Or to allow **all** IRC channels (no per-channel allowlist) and still reply without mentions:
|
||||
|
||||
```json5
|
||||
```json55
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
@@ -133,7 +133,7 @@ To reduce risk, restrict tools for that channel.
|
||||
|
||||
### Same tools for everyone in the channel
|
||||
|
||||
```json5
|
||||
```json55
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
@@ -154,7 +154,7 @@ To reduce risk, restrict tools for that channel.
|
||||
|
||||
Use `toolsBySender` to apply a stricter policy to `"*"` and a looser one to your nick:
|
||||
|
||||
```json5
|
||||
```json55
|
||||
{
|
||||
channels: {
|
||||
irc: {
|
||||
|
||||
@@ -130,12 +130,6 @@ 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
|
||||
@@ -240,7 +234,6 @@ 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)
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ openclaw pairing list telegram
|
||||
openclaw pairing approve telegram <CODE>
|
||||
```
|
||||
|
||||
Supported channels: `bluebubbles`, `discord`, `feishu`, `googlechat`, `imessage`, `irc`, `line`, `matrix`, `mattermost`, `msteams`, `nextcloud-talk`, `nostr`, `signal`, `slack`, `synology-chat`, `telegram`, `twitch`, `whatsapp`, `zalo`, `zalouser`.
|
||||
Supported channels: `telegram`, `whatsapp`, `signal`, `imessage`, `discord`, `slack`, `feishu`.
|
||||
|
||||
### Where the state lives
|
||||
|
||||
|
||||
@@ -79,7 +79,6 @@ Config values override env vars.
|
||||
- In `allowlist` mode, an empty `allowedUserIds` list is treated as misconfiguration and the webhook route will not start (use `dmPolicy: "open"` for allow-all).
|
||||
- `dmPolicy: "open"` allows any sender.
|
||||
- `dmPolicy: "disabled"` blocks DMs.
|
||||
- Reply recipient binding stays on stable numeric `user_id` by default. `channels.synology-chat.dangerouslyAllowNameMatching: true` is break-glass compatibility mode that re-enables mutable username/nickname lookup for reply delivery.
|
||||
- Pairing approvals work with:
|
||||
- `openclaw pairing list synology-chat`
|
||||
- `openclaw pairing approve synology-chat <CODE>`
|
||||
@@ -103,11 +102,6 @@ Multiple Synology Chat accounts are supported under `channels.synology-chat.acco
|
||||
Each account can override token, incoming URL, webhook path, DM policy, and limits.
|
||||
Direct-message sessions are isolated per account and user, so the same numeric `user_id`
|
||||
on two different Synology accounts does not share transcript state.
|
||||
Give each enabled account a distinct `webhookPath`. OpenClaw now rejects duplicate exact paths
|
||||
and refuses to start named accounts that only inherit a shared webhook path in multi-account setups.
|
||||
If you intentionally need legacy inheritance for a named account, set
|
||||
`dangerouslyAllowInheritedWebhookPath: true` on that account or at `channels.synology-chat`,
|
||||
but duplicate exact paths are still rejected fail-closed. Prefer explicit per-account paths.
|
||||
|
||||
```json5
|
||||
{
|
||||
@@ -138,5 +132,3 @@ but duplicate exact paths are still rejected fail-closed. Prefer explicit per-ac
|
||||
- Keep `allowInsecureSsl: false` unless you explicitly trust a self-signed local NAS cert.
|
||||
- Inbound webhook requests are token-verified and rate-limited per sender.
|
||||
- Prefer `dmPolicy: "allowlist"` for production.
|
||||
- Keep `dangerouslyAllowNameMatching` off unless you explicitly need legacy username-based reply delivery.
|
||||
- Keep `dangerouslyAllowInheritedWebhookPath` off unless you explicitly accept shared-path routing risk in a multi-account setup.
|
||||
|
||||
@@ -115,4 +115,4 @@ Full troubleshooting: [/channels/signal#troubleshooting](/channels/signal#troubl
|
||||
| DMs do not process | `openclaw pairing list matrix` | Approve sender or adjust DM policy. |
|
||||
| Encrypted rooms fail | Verify crypto module and encryption settings | Enable encryption support and rejoin/sync room. |
|
||||
|
||||
Full setup and config: [Matrix](/channels/matrix)
|
||||
Full troubleshooting: [/channels/matrix#troubleshooting](/channels/matrix#troubleshooting)
|
||||
|
||||
30
docs/ci.md
30
docs/ci.md
@@ -12,21 +12,20 @@ The CI runs on every push to `main` and every pull request. It uses smart scopin
|
||||
|
||||
## Job Overview
|
||||
|
||||
| Job | Purpose | When it runs |
|
||||
| ----------------- | ------------------------------------------------------------------------- | ------------------------------------------------ |
|
||||
| `preflight` | Docs scope, change scope, key scan, workflow audit, prod dependency audit | Always; node-based audit only on non-doc changes |
|
||||
| `docs-scope` | Detect docs-only changes | Always |
|
||||
| `changed-scope` | Detect which areas changed (node/macos/android/windows) | Non-doc changes |
|
||||
| `check` | TypeScript types, lint, format | Non-docs, node changes |
|
||||
| `check-docs` | Markdown lint + broken link check | Docs changed |
|
||||
| `secrets` | Detect leaked secrets | Always |
|
||||
| `build-artifacts` | Build dist once, share with `release-check` | Pushes to `main`, node changes |
|
||||
| `release-check` | Validate npm pack contents | Pushes to `main` after build |
|
||||
| `checks` | Node tests + protocol check on PRs; Bun compat on push | Non-docs, node changes |
|
||||
| `compat-node22` | Minimum supported Node runtime compatibility | Pushes to `main`, node changes |
|
||||
| `checks-windows` | Windows-specific tests | Non-docs, windows-relevant changes |
|
||||
| `macos` | Swift lint/build/test + TS tests | PRs with macos changes |
|
||||
| `android` | Gradle build + tests | Non-docs, android changes |
|
||||
| Job | Purpose | When it runs |
|
||||
| ----------------- | ------------------------------------------------------- | ---------------------------------- |
|
||||
| `docs-scope` | Detect docs-only changes | Always |
|
||||
| `changed-scope` | Detect which areas changed (node/macos/android/windows) | Non-doc changes |
|
||||
| `check` | TypeScript types, lint, format | Non-docs, node changes |
|
||||
| `check-docs` | Markdown lint + broken link check | Docs changed |
|
||||
| `secrets` | Detect leaked secrets | Always |
|
||||
| `build-artifacts` | Build dist once, share with `release-check` | Pushes to `main`, node changes |
|
||||
| `release-check` | Validate npm pack contents | Pushes to `main` after build |
|
||||
| `checks` | Node tests + protocol check on PRs; Bun compat on push | Non-docs, node changes |
|
||||
| `compat-node22` | Minimum supported Node runtime compatibility | Pushes to `main`, node changes |
|
||||
| `checks-windows` | Windows-specific tests | Non-docs, windows-relevant changes |
|
||||
| `macos` | Swift lint/build/test + TS tests | PRs with macos changes |
|
||||
| `android` | Gradle build + tests | Non-docs, android changes |
|
||||
|
||||
## Fail-Fast Order
|
||||
|
||||
@@ -37,7 +36,6 @@ 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
|
||||
|
||||
|
||||
@@ -21,9 +21,6 @@ output internal. `--deliver` remains as a deprecated alias for `--announce`.
|
||||
|
||||
Note: one-shot (`--at`) jobs delete after success by default. Use `--keep-after-run` to keep them.
|
||||
|
||||
Note: for one-shot CLI jobs, offset-less `--at` datetimes are treated as UTC unless you also pass
|
||||
`--tz <iana>`, which interprets that local wall-clock time in the given timezone.
|
||||
|
||||
Note: recurring jobs now use exponential retry backoff after consecutive errors (30s → 1m → 5m → 15m → 60m), then return to normal schedule after the next successful run.
|
||||
|
||||
Note: `openclaw cron run` now returns as soon as the manual run is queued for execution. Successful responses include `{ ok: true, enqueued: true, runId }`; use `openclaw cron runs --id <job-id>` to follow the eventual outcome.
|
||||
|
||||
@@ -193,7 +193,7 @@ Notes:
|
||||
- When token auth requires a token and `gateway.auth.token` is SecretRef-managed, `gateway install` validates that the SecretRef is resolvable but does not persist the resolved token into service environment metadata.
|
||||
- If token auth requires a token and the configured token SecretRef is unresolved, install fails closed instead of persisting fallback plaintext.
|
||||
- For password auth on `gateway run`, prefer `OPENCLAW_GATEWAY_PASSWORD`, `--password-file`, or a SecretRef-backed `gateway.auth.password` over inline `--password`.
|
||||
- In inferred auth mode, shell-only `OPENCLAW_GATEWAY_PASSWORD` does not relax install token requirements; use durable config (`gateway.auth.password` or config `env`) when installing a managed service.
|
||||
- In inferred auth mode, shell-only `OPENCLAW_GATEWAY_PASSWORD`/`CLAWDBOT_GATEWAY_PASSWORD` does not relax install token requirements; use durable config (`gateway.auth.password` or config `env`) when installing a managed service.
|
||||
- If both `gateway.auth.token` and `gateway.auth.password` are configured and `gateway.auth.mode` is unset, install is blocked until mode is set explicitly.
|
||||
- Lifecycle commands accept `--json` for scripting.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
summary: "CLI reference for `openclaw hooks` (agent hooks)"
|
||||
read_when:
|
||||
- You want to manage agent hooks
|
||||
- You want to inspect hook availability or enable workspace hooks
|
||||
- You want to install or update hooks
|
||||
title: "hooks"
|
||||
---
|
||||
|
||||
@@ -21,7 +21,7 @@ Related:
|
||||
openclaw hooks list
|
||||
```
|
||||
|
||||
List all discovered hooks from workspace, managed, extra, and bundled directories.
|
||||
List all discovered hooks from workspace, managed, and bundled directories.
|
||||
|
||||
**Options:**
|
||||
|
||||
@@ -38,7 +38,7 @@ Ready:
|
||||
🚀 boot-md ✓ - Run BOOT.md on gateway startup
|
||||
📎 bootstrap-extra-files ✓ - Inject extra workspace bootstrap files during agent bootstrap
|
||||
📝 command-logger ✓ - Log all command events to a centralized audit file
|
||||
💾 session-memory ✓ - Save session context to memory when /new or /reset command is issued
|
||||
💾 session-memory ✓ - Save session context to memory when /new command is issued
|
||||
```
|
||||
|
||||
**Example (verbose):**
|
||||
@@ -84,14 +84,14 @@ openclaw hooks info session-memory
|
||||
```
|
||||
💾 session-memory ✓ Ready
|
||||
|
||||
Save session context to memory when /new or /reset command is issued
|
||||
Save session context to memory when /new command is issued
|
||||
|
||||
Details:
|
||||
Source: openclaw-bundled
|
||||
Path: /path/to/openclaw/hooks/bundled/session-memory/HOOK.md
|
||||
Handler: /path/to/openclaw/hooks/bundled/session-memory/handler.ts
|
||||
Homepage: https://docs.openclaw.ai/automation/hooks#session-memory
|
||||
Events: command:new, command:reset
|
||||
Events: command:new
|
||||
|
||||
Requirements:
|
||||
Config: ✓ workspace.dir
|
||||
@@ -127,7 +127,8 @@ openclaw hooks enable <name>
|
||||
|
||||
Enable a specific hook by adding it to your config (`~/.openclaw/config.json`).
|
||||
|
||||
**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 can’t be enabled/disabled here. Enable/disable the plugin instead.
|
||||
**Note:** Hooks managed by plugins show `plugin:<id>` in `openclaw hooks list` and
|
||||
can’t be enabled/disabled here. Enable/disable the plugin instead.
|
||||
|
||||
**Arguments:**
|
||||
|
||||
@@ -151,9 +152,6 @@ 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).
|
||||
@@ -186,18 +184,14 @@ openclaw hooks disable command-logger
|
||||
|
||||
- Restart the gateway so hooks reload
|
||||
|
||||
## Install Hook Packs
|
||||
## Install Hooks
|
||||
|
||||
```bash
|
||||
openclaw plugins install <package> # ClawHub first, then npm
|
||||
openclaw plugins install <package> --pin # pin version
|
||||
openclaw plugins install <path> # local path
|
||||
openclaw hooks install <path-or-spec>
|
||||
openclaw hooks install <npm-spec> --pin
|
||||
```
|
||||
|
||||
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`.
|
||||
Install a hook pack from a local folder/archive or npm.
|
||||
|
||||
Npm specs are **registry-only** (package name + optional **exact version** or
|
||||
**dist-tag**). Git/URL/file specs and semver ranges are rejected. Dependency
|
||||
@@ -224,32 +218,26 @@ prerelease tag such as `@beta`/`@rc` or an exact prerelease version.
|
||||
|
||||
```bash
|
||||
# Local directory
|
||||
openclaw plugins install ./my-hook-pack
|
||||
openclaw hooks install ./my-hook-pack
|
||||
|
||||
# Local archive
|
||||
openclaw plugins install ./my-hook-pack.zip
|
||||
openclaw hooks install ./my-hook-pack.zip
|
||||
|
||||
# NPM package
|
||||
openclaw plugins install @openclaw/my-hook-pack
|
||||
openclaw hooks install @openclaw/my-hook-pack
|
||||
|
||||
# Link a local directory without copying
|
||||
openclaw plugins install -l ./my-hook-pack
|
||||
openclaw hooks install -l ./my-hook-pack
|
||||
```
|
||||
|
||||
Linked hook packs are treated as managed hooks from an operator-configured
|
||||
directory, not as workspace hooks.
|
||||
|
||||
## Update Hook Packs
|
||||
## Update Hooks
|
||||
|
||||
```bash
|
||||
openclaw plugins update <id>
|
||||
openclaw plugins update --all
|
||||
openclaw hooks update <id>
|
||||
openclaw hooks update --all
|
||||
```
|
||||
|
||||
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`.
|
||||
Update installed hook packs (npm installs only).
|
||||
|
||||
**Options:**
|
||||
|
||||
@@ -264,7 +252,7 @@ global `--yes` to bypass prompts in CI/non-interactive runs.
|
||||
|
||||
### session-memory
|
||||
|
||||
Saves session context to memory when you issue `/new` or `/reset`.
|
||||
Saves session context to memory when you issue `/new`.
|
||||
|
||||
**Enable:**
|
||||
|
||||
|
||||
@@ -113,9 +113,7 @@ openclaw [--dev] [--profile <name>] <command>
|
||||
audit
|
||||
secrets
|
||||
reload
|
||||
audit
|
||||
configure
|
||||
apply
|
||||
migrate
|
||||
reset
|
||||
uninstall
|
||||
update
|
||||
@@ -134,21 +132,16 @@ openclaw [--dev] [--profile <name>] <command>
|
||||
check
|
||||
plugins
|
||||
list
|
||||
inspect
|
||||
info
|
||||
install
|
||||
uninstall
|
||||
update
|
||||
enable
|
||||
disable
|
||||
doctor
|
||||
marketplace list
|
||||
memory
|
||||
status
|
||||
index
|
||||
search
|
||||
message
|
||||
send
|
||||
broadcast
|
||||
agent
|
||||
agents
|
||||
list
|
||||
@@ -492,9 +485,6 @@ 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.
|
||||
@@ -505,7 +495,7 @@ Options:
|
||||
- `--json`: output JSON (no styling).
|
||||
- `-v`, `--verbose`: include missing requirements detail.
|
||||
|
||||
Tip: use `openclaw skills search`, `openclaw skills install`, and `openclaw skills update` for ClawHub-backed skills.
|
||||
Tip: use `npx clawhub` to search, install, and sync skills.
|
||||
|
||||
### `pairing`
|
||||
|
||||
@@ -1042,7 +1032,7 @@ Subcommands:
|
||||
Auth notes:
|
||||
|
||||
- `node` resolves gateway auth from env/config (no `--token`/`--password` flags): `OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD`, then `gateway.auth.*`. In local mode, node host intentionally ignores `gateway.remote.*`; in `gateway.mode=remote`, `gateway.remote.*` participates per remote precedence rules.
|
||||
- Node-host auth resolution only honors `OPENCLAW_GATEWAY_*` env vars.
|
||||
- Legacy `CLAWDBOT_GATEWAY_*` env vars are intentionally ignored for node-host auth resolution.
|
||||
|
||||
## Nodes
|
||||
|
||||
|
||||
@@ -31,11 +31,6 @@ Node hosts automatically advertise a browser proxy if `browser.enabled` is not
|
||||
disabled on the node. This lets the agent use browser automation on that node
|
||||
without extra configuration.
|
||||
|
||||
By default, the proxy exposes the node's normal browser profile surface. If you
|
||||
set `nodeHost.browserProxy.allowProfiles`, the proxy becomes restrictive:
|
||||
non-allowlisted profile targeting is rejected, and persistent profile
|
||||
create/delete routes are blocked through the proxy.
|
||||
|
||||
Disable it on the node if needed:
|
||||
|
||||
```json5
|
||||
@@ -72,7 +67,7 @@ Options:
|
||||
- In local mode, node host intentionally does not inherit `gateway.remote.token` / `gateway.remote.password`.
|
||||
- If `gateway.auth.token` / `gateway.auth.password` is explicitly configured via SecretRef and unresolved, node auth resolution fails closed (no remote fallback masking).
|
||||
- In `gateway.mode=remote`, remote client fields (`gateway.remote.token` / `gateway.remote.password`) are also eligible per remote precedence rules.
|
||||
- Node host auth resolution only honors `OPENCLAW_GATEWAY_*` env vars.
|
||||
- Legacy `CLAWDBOT_GATEWAY_*` env vars are ignored for node host auth resolution.
|
||||
|
||||
## Service (background)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ title: "plugins"
|
||||
|
||||
# `openclaw plugins`
|
||||
|
||||
Manage Gateway plugins/extensions, hook packs, and compatible bundles.
|
||||
Manage Gateway plugins/extensions and compatible bundles.
|
||||
|
||||
Related:
|
||||
|
||||
@@ -46,20 +46,13 @@ capabilities.
|
||||
### Install
|
||||
|
||||
```bash
|
||||
openclaw plugins install <package> # ClawHub first, then npm
|
||||
openclaw plugins install clawhub:<package> # ClawHub only
|
||||
openclaw plugins install <package> --pin # pin version
|
||||
openclaw plugins install <path> # local path
|
||||
openclaw plugins install <plugin>@<marketplace> # marketplace
|
||||
openclaw plugins install <plugin> --marketplace <name> # marketplace (explicit)
|
||||
openclaw plugins install <path-or-spec>
|
||||
openclaw plugins install <npm-spec> --pin
|
||||
openclaw plugins install <plugin>@<marketplace>
|
||||
openclaw plugins install <plugin> --marketplace <marketplace>
|
||||
```
|
||||
|
||||
Bare package names are checked against ClawHub first, then npm. 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.
|
||||
Security note: treat plugin installs like running code. Prefer pinned versions.
|
||||
|
||||
Npm specs are **registry-only** (package name + optional **exact version** or
|
||||
**dist-tag**). Git/URL/file specs and semver ranges are rejected. Dependency
|
||||
@@ -78,25 +71,6 @@ 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`:
|
||||
|
||||
@@ -120,11 +94,6 @@ Marketplace sources can be:
|
||||
- a GitHub repo shorthand such as `owner/repo`
|
||||
- a git URL
|
||||
|
||||
For remote marketplaces loaded from GitHub or git, plugin entries must stay
|
||||
inside the cloned marketplace repo. OpenClaw accepts relative path sources from
|
||||
that repo and rejects external git, GitHub, URL/archive, and absolute-path
|
||||
plugin sources from remote manifests.
|
||||
|
||||
For local paths and archives, OpenClaw auto-detects:
|
||||
|
||||
- native OpenClaw plugins (`openclaw.plugin.json`)
|
||||
@@ -175,8 +144,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` and tracked hook-pack
|
||||
installs in `hooks.internal.installs`.
|
||||
Updates apply to tracked installs in `plugins.installs`, currently npm and
|
||||
marketplace 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
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
---
|
||||
summary: "CLI reference for `openclaw skills` (search/install/update/list/info/check)"
|
||||
summary: "CLI reference for `openclaw skills` (list/info/check) and skill eligibility"
|
||||
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 local skills and install/update skills from ClawHub.
|
||||
Inspect skills (bundled + workspace + managed overrides) and see what’s eligible vs missing requirements.
|
||||
|
||||
Related:
|
||||
|
||||
@@ -20,17 +19,8 @@ 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.
|
||||
|
||||
@@ -92,13 +92,6 @@ These run inside the agent loop or gateway pipeline:
|
||||
- **`session_start` / `session_end`**: session lifecycle boundaries.
|
||||
- **`gateway_start` / `gateway_stop`**: gateway lifecycle events.
|
||||
|
||||
Hook decision rules for outbound/tool guards:
|
||||
|
||||
- `before_tool_call`: `{ block: true }` is terminal and stops lower-priority handlers.
|
||||
- `before_tool_call`: `{ block: false }` is a no-op and does not clear a prior block.
|
||||
- `message_sending`: `{ cancel: true }` is terminal and stops lower-priority handlers.
|
||||
- `message_sending`: `{ cancel: false }` is a no-op and does not clear a prior cancel.
|
||||
|
||||
See [Plugin hooks](/plugins/architecture#provider-runtime-hooks) for the hook API and registration details.
|
||||
|
||||
## Streaming + partial replies
|
||||
|
||||
@@ -81,10 +81,10 @@ Legacy session folders from other tools are not read.
|
||||
## Steering while streaming
|
||||
|
||||
When queue mode is `steer`, inbound messages are injected into the current run.
|
||||
Queued steering is delivered **after the current assistant turn finishes
|
||||
executing its tool calls**, before the next LLM call. Steering no longer skips
|
||||
remaining tool calls from the current assistant message; it injects the queued
|
||||
message at the next model boundary instead.
|
||||
The queue is checked **after each tool call**; if a queued message is present,
|
||||
remaining tool calls from the current assistant message are skipped (error tool
|
||||
results with "Skipped due to queued user message."), then the queued user
|
||||
message is injected before the next assistant response.
|
||||
|
||||
When queue mode is `followup` or `collect`, inbound messages are held until the
|
||||
current turn ends, then a new agent turn starts with the queued payloads. See
|
||||
|
||||
@@ -23,7 +23,8 @@ The default workspace layout uses two memory layers:
|
||||
- Read today + yesterday at session start.
|
||||
- `MEMORY.md` (optional)
|
||||
- Curated long-term memory.
|
||||
- If both `MEMORY.md` and `memory.md` exist at the workspace root, OpenClaw loads both (deduplicated by realpath so symlinks pointing to the same file are not injected twice).
|
||||
- If both `MEMORY.md` and `memory.md` exist at the workspace root, OpenClaw only loads `MEMORY.md`.
|
||||
- Lowercase `memory.md` is only used as a fallback when `MEMORY.md` is absent.
|
||||
- **Only load in the main, private session** (never in group contexts).
|
||||
|
||||
These files live under the workspace (`agents.defaults.workspace`, default
|
||||
|
||||
@@ -26,7 +26,7 @@ Related:
|
||||
|
||||
- `agents.defaults.models` is the allowlist/catalog of models OpenClaw can use (plus aliases).
|
||||
- `agents.defaults.imageModel` is used **only when** the primary model can’t accept images.
|
||||
- `agents.defaults.imageGenerationModel` is used by the shared image-generation capability. If omitted, `image_generate` can still infer a provider default from compatible auth-backed image-generation plugins. If you set a specific provider/model, also configure that provider's auth/API key.
|
||||
- `agents.defaults.imageGenerationModel` is used by the shared image-generation capability. If omitted, `image_generate` can still infer a provider default from compatible auth-backed image-generation plugins.
|
||||
- Per-agent defaults can override `agents.defaults.model` via `agents.list[].model` plus bindings (see [/concepts/multi-agent](/concepts/multi-agent)).
|
||||
|
||||
## Quick model policy
|
||||
|
||||
@@ -162,20 +162,13 @@ Enforcement points:
|
||||
|
||||
## sessions_spawn
|
||||
|
||||
Spawn an isolated delegated session.
|
||||
|
||||
- Default runtime: OpenClaw sub-agent (`runtime: "subagent"`).
|
||||
- ACP harness sessions use `runtime: "acp"` and follow ACP-specific targeting/policy rules.
|
||||
- This section focuses on sub-agent behavior unless noted otherwise. For ACP-specific behavior, see [ACP Agents](/tools/acp-agents).
|
||||
Spawn a sub-agent run in an isolated session and announce the result back to the requester chat channel.
|
||||
|
||||
Parameters:
|
||||
|
||||
- `task` (required)
|
||||
- `runtime?` (`subagent|acp`; defaults to `subagent`)
|
||||
- `label?` (optional; used for logs/UI)
|
||||
- `agentId?` (optional)
|
||||
- `runtime: "subagent"`: target another OpenClaw agent id if allowed by `subagents.allowAgents`
|
||||
- `runtime: "acp"`: target an ACP harness id if allowed by `acp.allowedAgents`
|
||||
- `agentId?` (optional; spawn under another agent id if allowed)
|
||||
- `model?` (optional; overrides the sub-agent model; invalid values error)
|
||||
- `thinking?` (optional; overrides thinking level for the sub-agent run)
|
||||
- `runTimeoutSeconds?` (defaults to `agents.defaults.subagents.runTimeoutSeconds` when set, otherwise `0`; when set, aborts the sub-agent run after N seconds)
|
||||
@@ -188,14 +181,12 @@ Parameters:
|
||||
|
||||
Allowlist:
|
||||
|
||||
- `runtime: "subagent"`: `agents.list[].subagents.allowAgents` controls which OpenClaw agent ids are allowed via `agentId` (`["*"]` to allow any). Default: only the requester agent.
|
||||
- `runtime: "acp"`: `acp.allowedAgents` controls which ACP harness ids are allowed. This is a separate policy from `subagents.allowAgents`.
|
||||
- `agents.list[].subagents.allowAgents`: list of agent ids allowed via `agentId` (`["*"]` to allow any). Default: only the requester agent.
|
||||
- Sandbox inheritance guard: if the requester session is sandboxed, `sessions_spawn` rejects targets that would run unsandboxed.
|
||||
|
||||
Discovery:
|
||||
|
||||
- Use `agents_list` to discover allowed targets for `runtime: "subagent"`.
|
||||
- For `runtime: "acp"`, use configured ACP harness ids and `acp.allowedAgents`; `agents_list` does not list ACP harness targets.
|
||||
- Use `agents_list` to discover which agent ids are allowed for `sessions_spawn`.
|
||||
|
||||
Behavior:
|
||||
|
||||
|
||||
@@ -84,30 +84,6 @@
|
||||
"source": "/perplexity",
|
||||
"destination": "/tools/perplexity-search"
|
||||
},
|
||||
{
|
||||
"source": "/web-fetch",
|
||||
"destination": "/tools/web-fetch"
|
||||
},
|
||||
{
|
||||
"source": "/duckduckgo-search",
|
||||
"destination": "/tools/duckduckgo-search"
|
||||
},
|
||||
{
|
||||
"source": "/exa-search",
|
||||
"destination": "/tools/exa-search"
|
||||
},
|
||||
{
|
||||
"source": "/gemini-search",
|
||||
"destination": "/tools/gemini-search"
|
||||
},
|
||||
{
|
||||
"source": "/grok-search",
|
||||
"destination": "/tools/grok-search"
|
||||
},
|
||||
{
|
||||
"source": "/kimi-search",
|
||||
"destination": "/tools/kimi-search"
|
||||
},
|
||||
{
|
||||
"source": "/tts",
|
||||
"destination": "/tools/tts"
|
||||
@@ -950,7 +926,6 @@
|
||||
"pages": [
|
||||
"install/updating",
|
||||
"install/migrating",
|
||||
"install/migrating-matrix",
|
||||
"install/uninstall",
|
||||
"install/development-channels"
|
||||
]
|
||||
@@ -980,8 +955,8 @@
|
||||
"channels/nextcloud-talk",
|
||||
"channels/nostr",
|
||||
"channels/signal",
|
||||
"channels/slack",
|
||||
"channels/synology-chat",
|
||||
"channels/slack",
|
||||
"channels/telegram",
|
||||
"channels/tlon",
|
||||
"channels/twitch",
|
||||
@@ -1069,8 +1044,7 @@
|
||||
"pages": [
|
||||
"plugins/building-plugins",
|
||||
"plugins/sdk-channel-plugins",
|
||||
"plugins/sdk-provider-plugins",
|
||||
"plugins/sdk-migration"
|
||||
"plugins/sdk-provider-plugins"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1081,6 +1055,7 @@
|
||||
"plugins/sdk-runtime",
|
||||
"plugins/sdk-setup",
|
||||
"plugins/sdk-testing",
|
||||
"plugins/sdk-migration",
|
||||
"plugins/manifest",
|
||||
"plugins/architecture"
|
||||
]
|
||||
@@ -1117,7 +1092,7 @@
|
||||
"pages": [
|
||||
"tools/apply-patch",
|
||||
{
|
||||
"group": "Web Browser",
|
||||
"group": "Browser",
|
||||
"pages": [
|
||||
"tools/browser",
|
||||
"tools/browser-login",
|
||||
@@ -1125,22 +1100,6 @@
|
||||
"tools/browser-wsl2-windows-remote-cdp-troubleshooting"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Web Tools",
|
||||
"pages": [
|
||||
"tools/web-fetch",
|
||||
"tools/web",
|
||||
"tools/brave-search",
|
||||
"tools/duckduckgo-search",
|
||||
"tools/exa-search",
|
||||
"tools/firecrawl",
|
||||
"tools/gemini-search",
|
||||
"tools/grok-search",
|
||||
"tools/kimi-search",
|
||||
"tools/perplexity-search",
|
||||
"tools/tavily"
|
||||
]
|
||||
},
|
||||
"tools/btw",
|
||||
"tools/diffs",
|
||||
"tools/elevated",
|
||||
@@ -1151,7 +1110,17 @@
|
||||
"tools/loop-detection",
|
||||
"tools/pdf",
|
||||
"tools/reactions",
|
||||
"tools/thinking"
|
||||
"tools/thinking",
|
||||
{
|
||||
"group": "Web and search",
|
||||
"pages": [
|
||||
"tools/web",
|
||||
"tools/brave-search",
|
||||
"tools/firecrawl",
|
||||
"tools/perplexity-search",
|
||||
"tools/tavily"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -1181,26 +1150,25 @@
|
||||
"pages": [
|
||||
"providers/anthropic",
|
||||
"providers/bedrock",
|
||||
"providers/claude-max-api-proxy",
|
||||
"providers/cloudflare-ai-gateway",
|
||||
"providers/claude-max-api-proxy",
|
||||
"providers/deepgram",
|
||||
"providers/deepseek",
|
||||
"providers/github-copilot",
|
||||
"providers/glm",
|
||||
"providers/google",
|
||||
"providers/groq",
|
||||
"providers/huggingface",
|
||||
"providers/kilocode",
|
||||
"providers/litellm",
|
||||
"providers/glm",
|
||||
"providers/minimax",
|
||||
"providers/mistral",
|
||||
"providers/modelstudio",
|
||||
"providers/moonshot",
|
||||
"providers/mistral",
|
||||
"providers/nvidia",
|
||||
"providers/ollama",
|
||||
"providers/openai",
|
||||
"providers/opencode",
|
||||
"providers/opencode-go",
|
||||
"providers/opencode",
|
||||
"providers/openrouter",
|
||||
"providers/perplexity-provider",
|
||||
"providers/qianfan",
|
||||
@@ -1208,8 +1176,8 @@
|
||||
"providers/sglang",
|
||||
"providers/synthetic",
|
||||
"providers/together",
|
||||
"providers/venice",
|
||||
"providers/vercel-ai-gateway",
|
||||
"providers/venice",
|
||||
"providers/vllm",
|
||||
"providers/volcengine",
|
||||
"providers/xai",
|
||||
@@ -1746,6 +1714,7 @@
|
||||
{
|
||||
"group": "扩展",
|
||||
"pages": [
|
||||
"zh-CN/plugins/architecture",
|
||||
"zh-CN/plugins/voice-call",
|
||||
"zh-CN/plugins/zalouser",
|
||||
"zh-CN/plugins/manifest",
|
||||
|
||||
@@ -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; opt in explicitly to avoid preview-edit rate limits)
|
||||
streaming: "partial", // off | partial | block | progress (default: off)
|
||||
actions: { reactions: true, sendMessage: true },
|
||||
reactionNotifications: "own", // off | own | all
|
||||
mediaMaxMb: 100,
|
||||
@@ -905,8 +905,8 @@ Time format in system prompt. Default: `auto` (OS preference).
|
||||
- `imageGenerationModel`: accepts either a string (`"provider/model"`) or an object (`{ primary, fallbacks }`).
|
||||
- Used by the shared image-generation capability and any future tool/plugin surface that generates images.
|
||||
- Typical values: `google/gemini-3-pro-image-preview` for the native Nano Banana-style flow, `fal/fal-ai/flux/dev` for fal, or `openai/gpt-image-1` for OpenAI Images.
|
||||
- If you select a provider/model directly, configure the matching provider auth/API key too (for example `GEMINI_API_KEY` or `GOOGLE_API_KEY` for `google/*`, `OPENAI_API_KEY` for `openai/*`, `FAL_KEY` for `fal/*`).
|
||||
- If omitted, `image_generate` can still infer a best-effort provider default from compatible auth-backed image-generation providers.
|
||||
- Typical values: `google/gemini-3-pro-image-preview`, `fal/fal-ai/flux/dev`, `openai/gpt-image-1`.
|
||||
- `pdfModel`: accepts either a string (`"provider/model"`) or an object (`{ primary, fallbacks }`).
|
||||
- Used by the `pdf` tool for model routing.
|
||||
- If omitted, the PDF tool falls back to `imageModel`, then to best-effort provider defaults.
|
||||
|
||||
@@ -251,7 +251,7 @@ When validation fails:
|
||||
|
||||
Build the image first: `scripts/sandbox-setup.sh`
|
||||
|
||||
See [Sandboxing](/gateway/sandboxing) for the full guide and [full reference](/gateway/configuration-reference#agentsdefaultssandbox) for all options.
|
||||
See [Sandboxing](/gateway/sandboxing) for the full guide and [full reference](/gateway/configuration-reference#agents-defaults-sandbox) for all options.
|
||||
|
||||
</Accordion>
|
||||
|
||||
|
||||
@@ -70,35 +70,11 @@ Default mode is `gateway.reload.mode="hybrid"`.
|
||||
- One always-on process for routing, control plane, and channel connections.
|
||||
- Single multiplexed port for:
|
||||
- WebSocket control/RPC
|
||||
- HTTP APIs, OpenAI compatible (`/v1/models`, `/v1/embeddings`, `/v1/chat/completions`, `/v1/responses`, `/tools/invoke`)
|
||||
- HTTP APIs (OpenAI-compatible, Responses, tools invoke)
|
||||
- Control UI and hooks
|
||||
- Default bind mode: `loopback`.
|
||||
- Auth is required by default (`gateway.auth.token` / `gateway.auth.password`, or `OPENCLAW_GATEWAY_TOKEN` / `OPENCLAW_GATEWAY_PASSWORD`).
|
||||
|
||||
## OpenAI-compatible endpoints
|
||||
|
||||
OpenClaw’s highest-leverage compatibility surface is now:
|
||||
|
||||
- `GET /v1/models`
|
||||
- `GET /v1/models/{id}`
|
||||
- `POST /v1/embeddings`
|
||||
- `POST /v1/chat/completions`
|
||||
- `POST /v1/responses`
|
||||
|
||||
Why this set matters:
|
||||
|
||||
- Most Open WebUI, LobeChat, and LibreChat integrations probe `/v1/models` first.
|
||||
- Many RAG and memory pipelines expect `/v1/embeddings`.
|
||||
- Agent-native clients increasingly prefer `/v1/responses`.
|
||||
|
||||
Planning note:
|
||||
|
||||
- `/v1/models` is agent-first: it returns `openclaw`, `openclaw/default`, and `openclaw/<agentId>`.
|
||||
- `openclaw/default` is the stable alias that always maps to the configured default agent.
|
||||
- Use `x-openclaw-model` when you want a backend provider/model override; otherwise the selected agent's normal model and embedding setup stays in control.
|
||||
|
||||
All of these run on the main Gateway port and use the same trusted operator auth boundary as the rest of the Gateway HTTP API.
|
||||
|
||||
### Port and bind precedence
|
||||
|
||||
| Setting | Resolution order |
|
||||
|
||||
@@ -3,7 +3,7 @@ summary: "Logging surfaces, file logs, WS log styles, and console formatting"
|
||||
read_when:
|
||||
- Changing logging output or formats
|
||||
- Debugging CLI or gateway output
|
||||
title: "Gateway Logging"
|
||||
title: "Logging"
|
||||
---
|
||||
|
||||
# Logging
|
||||
|
||||
@@ -14,13 +14,6 @@ This endpoint is **disabled by default**. Enable it in config first.
|
||||
- `POST /v1/chat/completions`
|
||||
- Same port as the Gateway (WS + HTTP multiplex): `http://<gateway-host>:<port>/v1/chat/completions`
|
||||
|
||||
When the Gateway’s OpenAI-compatible HTTP surface is enabled, it also serves:
|
||||
|
||||
- `GET /v1/models`
|
||||
- `GET /v1/models/{id}`
|
||||
- `POST /v1/embeddings`
|
||||
- `POST /v1/responses`
|
||||
|
||||
Under the hood, requests are executed as a normal Gateway agent run (same codepath as `openclaw agent`), so routing/permissions/config match your Gateway.
|
||||
|
||||
## Authentication
|
||||
@@ -48,25 +41,20 @@ Treat this endpoint as a **full operator-access** surface for the gateway instan
|
||||
|
||||
See [Security](/gateway/security) and [Remote access](/gateway/remote).
|
||||
|
||||
## Agent-first model contract
|
||||
## Choosing an agent
|
||||
|
||||
OpenClaw treats the OpenAI `model` field as an **agent target**, not a raw provider model id.
|
||||
No custom headers required: encode the agent id in the OpenAI `model` field:
|
||||
|
||||
- `model: "openclaw"` routes to the configured default agent.
|
||||
- `model: "openclaw/default"` also routes to the configured default agent.
|
||||
- `model: "openclaw/<agentId>"` routes to a specific agent.
|
||||
- `model: "openclaw:<agentId>"` (example: `"openclaw:main"`, `"openclaw:beta"`)
|
||||
- `model: "agent:<agentId>"` (alias)
|
||||
|
||||
Optional request headers:
|
||||
Or target a specific OpenClaw agent by header:
|
||||
|
||||
- `x-openclaw-model: <provider/model-or-bare-id>` overrides the backend model for the selected agent.
|
||||
- `x-openclaw-agent-id: <agentId>` remains supported as a compatibility override.
|
||||
- `x-openclaw-session-key: <sessionKey>` fully controls session routing.
|
||||
- `x-openclaw-message-channel: <channel>` sets the synthetic ingress channel context for channel-aware prompts and policies.
|
||||
- `x-openclaw-agent-id: <agentId>` (default: `main`)
|
||||
|
||||
Compatibility aliases still accepted:
|
||||
Advanced:
|
||||
|
||||
- `model: "openclaw:<agentId>"`
|
||||
- `model: "agent:<agentId>"`
|
||||
- `x-openclaw-session-key: <sessionKey>` to fully control session routing.
|
||||
|
||||
## Enabling the endpoint
|
||||
|
||||
@@ -106,57 +94,6 @@ By default the endpoint is **stateless per request** (a new session key is gener
|
||||
|
||||
If the request includes an OpenAI `user` string, the Gateway derives a stable session key from it, so repeated calls can share an agent session.
|
||||
|
||||
## Why this surface matters
|
||||
|
||||
This is the highest-leverage compatibility set for self-hosted frontends and tooling:
|
||||
|
||||
- Most Open WebUI, LobeChat, and LibreChat setups expect `/v1/models`.
|
||||
- Many RAG systems expect `/v1/embeddings`.
|
||||
- Existing OpenAI chat clients can usually start with `/v1/chat/completions`.
|
||||
- More agent-native clients increasingly prefer `/v1/responses`.
|
||||
|
||||
## Model list and agent routing
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What does `/v1/models` return?">
|
||||
An OpenClaw agent-target list.
|
||||
|
||||
The returned ids are `openclaw`, `openclaw/default`, and `openclaw/<agentId>` entries.
|
||||
Use them directly as OpenAI `model` values.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Does `/v1/models` list agents or sub-agents?">
|
||||
It lists top-level agent targets, not backend provider models and not sub-agents.
|
||||
|
||||
Sub-agents remain internal execution topology. They do not appear as pseudo-models.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="Why is `openclaw/default` included?">
|
||||
`openclaw/default` is the stable alias for the configured default agent.
|
||||
|
||||
That means clients can keep using one predictable id even if the real default agent id changes between environments.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="How do I override the backend model?">
|
||||
Use `x-openclaw-model`.
|
||||
|
||||
Examples:
|
||||
`x-openclaw-model: openai/gpt-5.4`
|
||||
`x-openclaw-model: gpt-5.4`
|
||||
|
||||
If you omit it, the selected agent runs with its normal configured model choice.
|
||||
|
||||
</Accordion>
|
||||
<Accordion title="How do embeddings fit this contract?">
|
||||
`/v1/embeddings` uses the same agent-target `model` ids.
|
||||
|
||||
Use `model: "openclaw/default"` or `model: "openclaw/<agentId>"`.
|
||||
When you need a specific embedding model, send it in `x-openclaw-model`.
|
||||
Without that header, the request passes through to the selected agent's normal embedding setup.
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Streaming (SSE)
|
||||
|
||||
Set `stream: true` to receive Server-Sent Events (SSE):
|
||||
@@ -173,8 +110,9 @@ Non-streaming:
|
||||
curl -sS http://127.0.0.1:18789/v1/chat/completions \
|
||||
-H 'Authorization: Bearer YOUR_TOKEN' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'x-openclaw-agent-id: main' \
|
||||
-d '{
|
||||
"model": "openclaw/default",
|
||||
"model": "openclaw",
|
||||
"messages": [{"role":"user","content":"hi"}]
|
||||
}'
|
||||
```
|
||||
@@ -185,44 +123,10 @@ Streaming:
|
||||
curl -N http://127.0.0.1:18789/v1/chat/completions \
|
||||
-H 'Authorization: Bearer YOUR_TOKEN' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'x-openclaw-model: openai/gpt-5.4' \
|
||||
-H 'x-openclaw-agent-id: main' \
|
||||
-d '{
|
||||
"model": "openclaw/research",
|
||||
"model": "openclaw",
|
||||
"stream": true,
|
||||
"messages": [{"role":"user","content":"hi"}]
|
||||
}'
|
||||
```
|
||||
|
||||
List models:
|
||||
|
||||
```bash
|
||||
curl -sS http://127.0.0.1:18789/v1/models \
|
||||
-H 'Authorization: Bearer YOUR_TOKEN'
|
||||
```
|
||||
|
||||
Fetch one model:
|
||||
|
||||
```bash
|
||||
curl -sS http://127.0.0.1:18789/v1/models/openclaw%2Fdefault \
|
||||
-H 'Authorization: Bearer YOUR_TOKEN'
|
||||
```
|
||||
|
||||
Create embeddings:
|
||||
|
||||
```bash
|
||||
curl -sS http://127.0.0.1:18789/v1/embeddings \
|
||||
-H 'Authorization: Bearer YOUR_TOKEN' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'x-openclaw-model: openai/text-embedding-3-small' \
|
||||
-d '{
|
||||
"model": "openclaw/default",
|
||||
"input": ["alpha", "beta"]
|
||||
}'
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- `/v1/models` returns OpenClaw agent targets, not raw provider catalogs.
|
||||
- `openclaw/default` is always present so one stable id works across environments.
|
||||
- Backend provider/model overrides belong in `x-openclaw-model`, not the OpenAI `model` field.
|
||||
- `/v1/embeddings` supports `input` as a string or array of strings.
|
||||
|
||||
@@ -24,22 +24,11 @@ Operational behavior matches [OpenAI Chat Completions](/gateway/openai-http-api)
|
||||
|
||||
- use `Authorization: Bearer <token>` with the normal Gateway auth config
|
||||
- treat the endpoint as full operator access for the gateway instance
|
||||
- select agents with `model: "openclaw"`, `model: "openclaw/default"`, `model: "openclaw/<agentId>"`, or `x-openclaw-agent-id`
|
||||
- use `x-openclaw-model` when you want to override the selected agent's backend model
|
||||
- select agents with `model: "openclaw:<agentId>"`, `model: "agent:<agentId>"`, or `x-openclaw-agent-id`
|
||||
- use `x-openclaw-session-key` for explicit session routing
|
||||
- use `x-openclaw-message-channel` when you want a non-default synthetic ingress channel context
|
||||
|
||||
Enable or disable this endpoint with `gateway.http.endpoints.responses.enabled`.
|
||||
|
||||
The same compatibility surface also includes:
|
||||
|
||||
- `GET /v1/models`
|
||||
- `GET /v1/models/{id}`
|
||||
- `POST /v1/embeddings`
|
||||
- `POST /v1/chat/completions`
|
||||
|
||||
For the canonical explanation of how agent-target models, `openclaw/default`, embeddings pass-through, and backend model overrides fit together, see [OpenAI Chat Completions](/gateway/openai-http-api#agent-first-model-contract) and [Model list and agent routing](/gateway/openai-http-api#model-list-and-agent-routing).
|
||||
|
||||
## Session behavior
|
||||
|
||||
By default the endpoint is **stateless per request** (a new session key is generated each call).
|
||||
@@ -65,12 +54,9 @@ Accepted but **currently ignored**:
|
||||
- `reasoning`
|
||||
- `metadata`
|
||||
- `store`
|
||||
- `previous_response_id`
|
||||
- `truncation`
|
||||
|
||||
Supported:
|
||||
|
||||
- `previous_response_id`: OpenClaw reuses the earlier response session when the request stays within the same agent/user/requested-session scope.
|
||||
|
||||
## Items (input)
|
||||
|
||||
### `message`
|
||||
|
||||
@@ -181,13 +181,6 @@ The Gateway treats these as **claims** and enforces server-side allowlists.
|
||||
- `source`: `core` or `plugin`
|
||||
- `pluginId`: plugin owner when `source="plugin"`
|
||||
- `optional`: whether a plugin tool is optional
|
||||
- Operators may call `tools.effective` (`operator.read`) to fetch the runtime-effective tool
|
||||
inventory for a session.
|
||||
- `sessionKey` is required.
|
||||
- The gateway derives trusted runtime context from the session server-side instead of accepting
|
||||
caller-supplied auth or delivery context.
|
||||
- The response is session-scoped and reflects what the active conversation can use right now,
|
||||
including core, plugin, and channel tools.
|
||||
|
||||
## Exec approvals
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ Gateway credential resolution follows one shared contract across call/probe/stat
|
||||
- password: `OPENCLAW_GATEWAY_PASSWORD` -> `gateway.remote.password` -> `gateway.auth.password`
|
||||
- Node-host local-mode exception: `gateway.remote.token` / `gateway.remote.password` are ignored.
|
||||
- Remote probe/status token checks are strict by default: they use `gateway.remote.token` only (no local token fallback) when targeting remote mode.
|
||||
- Gateway env overrides use `OPENCLAW_GATEWAY_*` only.
|
||||
- Legacy `CLAWDBOT_GATEWAY_*` env vars are only used by compatibility call paths; probe/status/auth resolution uses `OPENCLAW_GATEWAY_*` only.
|
||||
|
||||
## Chat UI over SSH
|
||||
|
||||
|
||||
@@ -402,7 +402,7 @@ Docker installs and the containerized gateway live here:
|
||||
For Docker gateway deployments, `scripts/docker/setup.sh` can bootstrap sandbox config.
|
||||
Set `OPENCLAW_SANDBOX=1` (or `true`/`yes`/`on`) to enable that path. You can
|
||||
override socket location with `OPENCLAW_DOCKER_SOCKET`. Full setup and env
|
||||
reference: [Docker](/install/docker#enable-agent-sandbox-for-docker-gateway).
|
||||
reference: [Docker](/install/docker#enable-agent-sandbox-for-docker-gateway-opt-in).
|
||||
|
||||
## setupCommand (one-time container setup)
|
||||
|
||||
@@ -463,7 +463,7 @@ See [Multi-Agent Sandbox & Tools](/tools/multi-agent-sandbox-tools) for preceden
|
||||
## Related docs
|
||||
|
||||
- [OpenShell](/gateway/openshell) -- managed sandbox backend setup, workspace modes, and config reference
|
||||
- [Sandbox Configuration](/gateway/configuration-reference#agentsdefaultssandbox)
|
||||
- [Sandbox Configuration](/gateway/configuration-reference#agents-defaults-sandbox)
|
||||
- [Sandbox vs Tool Policy vs Elevated](/gateway/sandbox-vs-tool-policy-vs-elevated) -- debugging "why is this blocked?"
|
||||
- [Multi-Agent Sandbox & Tools](/tools/multi-agent-sandbox-tools) -- per-agent overrides and precedence
|
||||
- [Security](/gateway/security)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user