Commit Graph

233 Commits

Author SHA1 Message Date
Ayaan Zaidi d90dcc2111 feat(plugin-sdk): export saveMediaSource from media-store (#125278)
Plugins holding a remote URL had no non-deprecated Plugin SDK path to turn it into managed media; saveMediaSource was only reachable through the deprecated media-runtime barrel while docs pointed at media-store. Re-export it from the focused subpath and move the bundled qa-channel plugin off the deprecated barrel. Maintainer decision: full saveMediaSource (local path + HTTP(S)) is the supported media-store contract.

Fixes #125259
2026-08-17 12:54:52 +00:00
Peter Steinberger 23ea04a375 refactor(media): remove orphan runtime facades (#125121) 2026-08-17 00:42:33 -07:00
Peter Steinberger 0e3a3aa203 refactor: finish canonicalization stragglers (#125056)
* refactor: finish canonicalization stragglers

* chore: remove release-owned changelog entry

* refactor: narrow SecretRef SDK import
2026-08-17 00:09:29 -07:00
Peter Steinberger b555a32ee9 fix(openrouter): keep OAuth loopback open after invalid callbacks (#124922)
Amp-Thread-ID: https://ampcode.com/threads/T-01a00ae0-190d-718b-8a76-b75f3e8d1fae

Co-authored-by: Amp <amp@ampcode.com>
2026-08-16 20:11:04 -07:00
Peter Steinberger 33f3b72a19 refactor(plugin-sdk): extract stream and SecretRef primitives (#124835) 2026-08-16 14:30:11 -07:00
Peter Steinberger 4d4ee7bc86 refactor(plugin-sdk): consolidate session catalog families (#124801) 2026-08-16 13:25:11 -07:00
Peter Steinberger aeff737da9 fix(agents): prevent invalid names from targeting the default agent (#124670)
* fix(agents): reject unrepresentable agent ids

* refactor(system-agent): split model selection setup

* chore: shrink assertion safety baseline

* docs: record strict agent id validation proof

* style: format strict agent id report

* chore: drop stray unrelated report artifact

* chore: restore REPORT.md to main state
2026-08-16 10:37:06 -07:00
Peter Steinberger 6aa27d6ecd refactor: retire August compat windows (embedding API, pi aliases, target parser, spawning hook, setup exports, WhatsApp inbound aliases) (#124416)
* refactor(plugin-sdk): retire embedded Pi aliases

* refactor(channels): retire explicit target compatibility

* refactor(plugins): retire subagent spawning hook

* refactor(plugin-sdk): retire shipped channel setup exports

* refactor(whatsapp): retire inbound callback aliases

Proof: focused build and WhatsApp E2E green; broad WhatsApp suite 188/189 files green. extensions/whatsapp/src/monitor-inbox.policy.test.ts flakes only in the parallel batch and passes isolated (10/10).

* refactor(plugin-sdk): retire memory embedding registrar

Migrate every bundled provider and manifest to registerEmbeddingProvider and contracts.embeddingProviders. Preserve memory-specific batching, local-service acquisition, index identity, and auto-selection through the canonical generic registry adapter, then remove the parallel registrar, registry, diagnostics, contracts, tests, and docs.

* chore(plugin-sdk): tighten retired surface budgets

Pin the post-retirement public SDK surface to 144 entrypoints, 4,312 exports, 2,564 callable exports, and 1,133 deprecated exports; agent-harness-runtime now permits exactly nine deprecated exports.
2026-08-15 22:43:47 -07:00
Peter Steinberger d7d059c7e6 perf(test): move direct import smoke to test fixtures (#123923) 2026-08-14 19:07:48 -07:00
Peter Steinberger 7cadfb0bd6 fix: speed up local node launches and isolate scratch state (#123503)
* perf(node-host): reuse advertised worker build identity

* fix(agents): keep default workspaces inside state dir

* fix(plugins): package llama.cpp private SSRF runtime

* fix(node-host): silence missing skills directory
2026-08-13 23:24:54 -07:00
Bek eb1035e861 fix(codex): retain direct-child hook policy after parent yield (#122503) 2026-08-13 22:51:34 -04:00
Peter Steinberger 1348387076 refactor(plugins): replace node-llama-cpp with managed llama-server (#123105)
Move llama.cpp chat and local embeddings onto a verified externally managed llama-server runtime. Remove the in-process native runtime, forked embedding workers, and node-llama-cpp dependency while preserving guided setup, local GGUF models, tool-capable agent runs, diagnostics, and operator docs.
2026-08-13 16:58:20 -07:00
Peter Steinberger dceb2c343c refactor: retire due compat-ledger surfaces (context-engine host params, deactivate alias, logging internals) (#121845)
* refactor(plugins): retire deactivate hook alias

* refactor(plugin-sdk): prune retired facade exports

* test(logging): isolate logger test controls

* refactor(logging): internalize file transport controls

* test(plugin-sdk): preserve retired facade coverage

* test(auto-reply): remove stale diagnostic imports

* refactor(logging): delete dead config-read guard

shouldSkipMutatingLoggingConfigRead had no production caller even on main;
it survived the dead-export scan only via logger's testApi re-export. The
test-isolation commit removed that mask, exposing the fossil. Delete the
guard, its test-only re-export, its mock entry, and its dedicated test file.

* refactor(plugin-sdk): retire due compatibility subpaths

* test(plugin-sdk): type group policy predicates

* refactor(plugin-sdk): split removed subpath records

* refactor(secrets): remove retired collector barrel

* test(plugin-sdk): tighten wildcard surface pin

* refactor(plugin-sdk): retire matrix facade metadata

* style(plugin-sdk): format facade metadata

* fix(ci): load channel setup contracts from source

Repair the main-owned regression from 99d662473c (Peter Steinberger): the new env-contract test could consume stale ignored dist metadata instead of the checked-in plugin declaration.

* test(plugin-sdk): refresh API baseline after rebase
2026-08-12 12:41:27 -07:00
Peter Steinberger 508dd471b0 feat(slack): live session cards as the default progress mode (#122552)
* feat(slack): render live session cards as the default Slack progress mode

Slack streaming.mode default flips partial->progress.
Progress mode renders one live Block Kit session card with a status header, narration, plan, activity, diff stat, and elapsed time; it is edited in place and finalized to success or error with an Open in OpenClaw button when gateway.publicOrigin is set.
Final assistant text always delivers separately.
The shared progress compositor gains a success-only additive per-turn diffStat mirroring the task ledger fold.
resolveGatewayPublicOrigin is exported through the plugin SDK.
The diffs viewer URL falls back to publicOrigin.
The old rich/text progress render fork is deleted.
Native task cards remain unchanged and opt-in.

* chore(config): regenerate bundled channel config metadata

* refactor(slack): keep session card state type internal

* refactor(slack): split session-card and diff-stat owners under lint ceilings

* refactor(channels): reuse diff-stat type from its owner module

Import ChannelProgressDraftDiffStat from progress-draft-diffstat instead of
redeclaring it in the compositor, resolving the all-exports deadcode scan.

* chore(plugin-sdk): regenerate api baselines for channel barrels

Baselines drifted after the rebase reconciled them against main; regenerate to
match the branch's actual channel-message/channel-outbound surface.

* fix(slack): drop a session card that cannot terminalize after final delivery

If the final reply is delivered but the terminal card edit fails, the caller
now clears the stale card instead of leaving it stuck in its Working state
(mirrors the pre-card preview cleanup). Adds a transport-failure regression and
corrects three tests that asserted the prior ignore-the-result behavior.

Documents resolveGatewayPublicOrigin as a dependency-light runtime helper on the
config-contracts SDK subpath, which previously described a type-only surface.

Addresses ClawSweeper P2 (unfinalized card) and P1 (runtime SDK contract).

* fix(slack): suppress default tool messages under the default progress card

resolveChannelStreamingSuppressDefaultToolProgressMessages re-derived the stream
mode from config with an "off" default, unlike its sibling resolvers which take
a caller-resolved mode override. After this branch made progress the Slack
default, a default-config channel turn saw mode "off" and left a stray
"Using tool: X" plain message posting alongside the session card. Thread the
caller-resolved mode through (compositor passes params.mode; Slack dispatch passes
slackStreaming.mode), matching resolveChannelStreamingPreviewToolProgress.

Retarget the progress-session-card delivery-trace golden at an EMPTY Slack config
so it proves the real default path; the regenerated golden is byte-identical,
confirming defaults now yield the clean card sequence (one card post, separate
final text, one terminal update with the Open in OpenClaw button, no stray tool
message). Switch the dispatch delivery-mode mock to the real resolver so the card
tests exercise the true channel default (automatic), not a hand-rolled one.

* chore(plugin-sdk): regenerate api baselines for the streaming mode param

resolveChannelStreamingSuppressDefaultToolProgressMessages gained an optional
mode override; the changed signature reflows the surface hash of every barrel
that re-exports it, so regenerate the affected baselines.

* chore(config): regenerate config baselines
2026-08-12 10:38:31 -07:00
Peter Steinberger c23d66e3b5 refactor: consolidate coercion ownership (#122692)
* refactor: consolidate coercion ownership

* test: align shard check with weighted planning

* chore: refresh plugin SDK API baseline
2026-08-12 09:25:28 -07:00
Peter Steinberger 2731dc24e5 fix(plugin-sdk): keep inbound reply shim through next SDK major (#121922)
* fix(plugin-sdk): honor major-gated reply shim retirement

* fix(plugin-sdk): preserve compat code literals

* chore(plugin-sdk): refresh compatibility API baseline
2026-08-11 03:18:07 -07:00
Peter Steinberger d6f70a96cb fix(plugins): native commands execute the selected plugin (#121544)
* fix(plugins): preserve selected command identity

* test(telegram): use scoped command registries

* test(telegram): isolate command runtime fixtures

* test(telegram): warm native command runtime

* refactor(plugins): keep command metadata private

* fix(plugins): accept synchronous command handlers

* fix(plugins): scope command drain bypass to live execution

* test(telegram): use scoped command registry fixtures

* test(telegram): isolate native menu runtime fixtures

* test(telegram): isolate login session store

* test(telegram): surface login flow failures

* test(telegram): preload native login module

* test(telegram): scope native command registries

* fix(plugins): complete command dispatch contracts

* fix(plugins): break command dispatch import cycles

* fix(plugins): stabilize command dispatch contracts

* fix(channels): keep plugin dispatch options internal

* fix(plugins): keep command dispatch carrier opaque

* test(channels): align delivery adapter fixtures

* test(delivery): align custody ownership coverage

* test(delivery): align latest queue reconciliation

* test(channels): drop obsolete delivery wrappers

* fix(plugins): rebind channel reload starts

* fix(plugins): scope command catalog reloads

* fix(ci): align current runtime contracts

* chore(plugin-sdk): refresh API baseline
2026-08-10 19:30:47 -07:00
Peter Steinberger 8ee945b907 refactor(channels): flatten channel-turn dispatch naming layers (#121308)
* refactor(channels): flatten channel turn dispatch naming

* docs(plugin-sdk): narrow inbound reply compat guidance

* docs(channels): point stale references at turn defining modules

* fix(channels): preserve dispatch contracts after flattening

* chore(plugin-sdk): ratchet surface budgets after flattening

* chore(channels): ratchet removed export collisions

* fix(plugin-sdk): restore inbound reply compat exports

Restore eight still-existing legacy callable re-exports from canonical SDK seams and cover the deprecated package subpath with a table-driven compatibility test.

Raise the public export, callable export, and deprecated export budgets by exactly eight; the three maintainer-authorized zero-consumer symbols remain removed.

* test(channels): split channel turn kernel coverage

Replace the oversized kernel test with independently mocked delivery, pipeline, and finalize suites, preserving all 51 tests while removing the max-lines suppression and stale ratchet entry.

* chore(plugin-sdk): refresh inbound reply API hash

* fix(ci): align channel turn review fixes

Restore the test-local DeliveryResult type removed during the split.

Ratchet the public export, callable export, and deprecated export budgets by exactly seven: six channel-inbound plus one channel-outbound legacy re-export.
2026-08-09 22:22:46 -07:00
Peter Steinberger ce53f7e82e refactor(agents)!: remove the session write lease (#121113)
* refactor(agents): remove session write lease

* refactor(plugin-sdk): deprecate session write lease

* refactor(doctor): remove session lock checks

* test(agents): remove session lease fixtures

* test(agents): align writer rebound assertion

* refactor(infra): remove retired session lock exports

* test(tooling): preserve embedded abort race shard
2026-08-09 15:30:48 -07:00
Peter Steinberger 9809375fda refactor(plugins)!: remove the plugin state lease API (#121140)
* refactor(plugins)!: remove plugin state lease API

* docs(plugins): document state lease removal
2026-08-09 11:16:07 -07:00
Peter Steinberger 8b0735e89f refactor(memory)!: remove the QMD backend; builtin is the only memory engine (#120936)
* refactor(memory): remove qmd backend

Make builtin the sole memory-core engine, rename the retained session helper barrel, retire QMD config with doctor migrations, and remove QMD runtime/UI/policy surfaces.

* docs(memory): remove qmd backend guidance

Delete the QMD concept page, rewrite memory documentation for builtin retrieval, and remove QMD from navigation and taxonomy source.

* refactor(memory): remove qmd-only leftovers

* refactor(memory): finish qmd integration cleanup

* build(deps): align root string-width types

* build(deps): model root string-width tooling

* refactor(memory): align qmd removal ui and docs

* fix(memory): preserve qmd external paths in doctor

* test(memory): remove obsolete backend probe case

* test(plugin-sdk): refresh private type baseline
2026-08-09 03:05:47 -07:00
Peter Steinberger 0e56fce87b fix(plugin-sdk): preserve system event snapshot identity (#120984)
Assign queue-owned opaque IDs to modern system-event snapshots so copied stale snapshots cannot acknowledge a later identical event. Keep structural matching only for shipped legacy ID-less consumers.
2026-08-09 02:05:36 -07:00
Peter Steinberger 6246f67784 refactor(clickclack): reuse session URL contract (#120810) 2026-08-08 21:22:51 -07:00
Peter Steinberger c2e7c819f5 perf(doctor): slim remaining heavy doctor contract closures (#120811)
* perf(doctor): slim remaining heavy doctor contract closures

Follow-up to #120698: several doctor closures still cold-loaded multi-second
kysely-bearing graphs through other broad barrels (session-store-runtime,
realtime-voice, channel-outbound, logging-core, memory-host-core/-events,
sqlite-runtime, persistent-dedupe, and plugin-local barrels).

- lazy-import heavy helpers inside async migration bodies (codex, msteams,
  zalouser, workboard, matrix inbound-dedupe, memory-core migrations)
- bypass plugin-local barrels to defining modules (reef protocol,
  memory-core short-term-promotion)
- move to lighter existing subpaths (slack -> channel-streaming, matrix
  logger -> security-runtime, memory-wiki -> agent-scope-runtime, which now
  also exports resolveSessionAgentId)
- add narrow openclaw/plugin-sdk/realtime-voice-activation for discord's
  sync wake-name doctor rules
- split src/infra/kysely-sync-cache-state.ts so sqlite-transaction clears
  Kysely caches without value-loading kysely; split the memory-host-sdk
  kysely bridge off the schema/transaction bridge
- guard: forbid the heavy barrels in doctor closures with per-kind scoping

Cold enumeration per plugin: discord 52.6s->0.3s, msteams 30.9s->0.5s,
codex 29.6s->2.6s, zalouser 28.8s->2.3s, matrix 27.2s->3.2s,
slack 17.5s->1.5s, reef 9.9s->0.7s, memory-core 6.4s->3.6s,
workboard 3.4s->0.25s; all kysely-free except llm-task (named follow-up).

* fix(plugins): route slack streaming compat through a focused streaming-config subpath

The channel-streaming compat barrel is deprecated for extension production
code (deprecated-api-usage guard + SDK package contract). Add the narrow
non-deprecated openclaw/plugin-sdk/channel-streaming-config subpath for the
pure streaming config readers, and drop the now consumer-less
short-term-promotion barrel re-exports knip flagged.

* test(plugins): register memory-host-sdk kysely bridge in package boundary inventory

* fix(plugins): classify realtime-voice-activation as private-local

ClawSweeper P2: the subpath exports only a default target, which is the
private-local shape; register it in plugin-sdk-private-local-only-subpaths,
the package-boundary d.ts alias maps, and correct the public surface budgets
(realtime-voice-activation no longer counts as public).

* fix(release): exclude realtime-voice-activation declarations from the published package

Private-local subpaths ship without d.ts; register the files negation the
release pack-path check requires.
2026-08-08 20:28:58 -07:00
Peter Steinberger da4a656cdb improve: doctor migration checks no longer load every bundled plugin runtime (#120678)
* perf(plugins): declare doctor contract surfaces

* perf(doctor): slim migration import closures

* perf(plugins): narrow doctor declaration record surface and wire owner-test lane

Registry records carry only the doctorContract declaration instead of the whole
parsed manifest, and check:changed now selects the src/plugins-owned declaration
honesty and closure-guard tests for extension module/manifest changes so
cross-lane drift cannot pass PR classification.

* fix(doctor): keep control-plane dist imports require-safe

Keep doctor and channel control-plane chunks off exec-class dependencies, and enforce native require(esm) loading during postbuild.

* chore(plugin-sdk): regenerate API baseline

* chore(plugin-sdk): sync export ordering

* fix(plugins): satisfy doctor contract CI boundaries

* perf(doctor): make qqbot doctor closure dependency-light

qqbot was the last plugin above 5s in doctor state-migration enumeration
(~8s under tsx/jiti). The cost was not the state-key builder (already a
leaf): its doctor closure value-imported the runtime-doctor SDK barrel,
whose plugin-state-store/state-db re-exports pull kysely (~330 modules),
plus security-runtime for one fileExists (~200 modules), all resolved
per-module by jiti during enumeration.

Split the migration-define helpers and light re-exports into a new
private-local plugin-sdk/runtime-doctor-migrations subpath; runtime-doctor
re-exports it so its public surface is byte-identical (API baseline hash
unchanged). qqbot's doctor-contract and state-migrations now import only
the light subpath, swapping fileExists for the equivalent async
legacyStateFileExists already in the closure.

qqbot enumeration: ~8.0s/531 modules -> ~0.25s/18 modules.

* chore(plugin-sdk): drop private-local subpath from API baseline

runtime-doctor-migrations is private-local-only; the baseline tracks public
modules, and the earlier line was generated before the classification.

* fix(plugins): register runtime-doctor-migrations boundary paths

The private-local subpath list feeds the extension package boundary map;
the shared paths config and xai's derived overrides must carry the same
entry or the boundary contract test fails.
2026-08-08 13:29:18 -07:00
Vincent Koc e35d22807e perf(xai): lazy-load optional capability runtimes (#119374)
Punchcard-Session: coral-workshop-workshop-3f
2026-08-05 11:26:40 +08:00
Peter Steinberger deb682abfe refactor(plugins): consolidate extension runtime helpers (#118509)
* refactor(plugins): consolidate extension runtime helpers

* fix(ci): satisfy extension type and lint checks

* chore(plugin-sdk): regenerate API baseline for #118509
2026-08-03 02:56:43 -07:00
Peter Steinberger ac28f4d558 fix: release channel delivery resources reliably (#117855)
* fix(channels): consolidate delivery lifecycle ownership

* test(msteams): match release mock contract

* test(plugin-sdk): satisfy promise executor lint

* chore(plugin-sdk): regenerate API baseline for delivery-correlation + fetch-runtime exports
2026-08-02 00:24:47 -07:00
Omar Shahine 5db7e1c4ec fix(talk): preserve owner authorization in realtime consults (#114163)
* feat(talk): forward realtime consult sender auth

* docs(talk): clarify realtime sender auth contract

* ci: constrain oxlint on hosted runners

* ci: split oxlint core on hosted runners

---------

Co-authored-by: Omar Shahine <10343873+omarshahine@users.noreply.github.com>
2026-08-01 09:37:17 -07:00
Vincent Koc 8a3f5c862b fix(plugin-sdk): ship documented public typings (#116345)
* fix(plugin-sdk): ship documented public typings

* fix(plugin-sdk): refresh public contract artifacts
2026-07-30 18:20:07 +08:00
Josh Lehman 6beaff450e fix(codex): avoid transcript mirror snapshot churn (#115070) 2026-07-29 11:59:14 -07:00
Peter Steinberger f78ba09120 feat(talk): support GPT-Live realtime voice over ChatGPT OAuth (#115226)
* feat(gateway): share the canonical browser-origin policy with plugins

Export resolveAcceptedBrowserOrigin through openclaw/plugin-sdk/webhook-request-guards
so browser-facing plugin routes reuse the Gateway's real origin contract instead of a
narrow allowedOrigins array check. Private LAN/Tailnet Control UI loads and the
Host-header fallback were previously rejected with 403 by plugin offer routes while the
Control UI itself worked.

Moves the loopback/forwarded-header helpers to net.ts (re-exported from auth.ts) so the
guard can delegate without importing gateway auth, and migrates the Codex realtime
broker onto the shared seam.

* feat(talk): let providers own agent delegation for realtime voice

Adds an optional runAgentConsult callback to the browser-session create request and
injects the existing embedded consult runtime from talk-client, bound to the same agent
and session key the GA tool path uses. Providers whose realtime protocol delegates work
through their own control channel (rather than GA function calls) can now reach the
OpenClaw agent without a client round-trip.

Threads the effective per-session model into browser-session capability resolution so a
request-level model override selects the right capability set, and propagates a caller
abort signal into consultRealtimeVoiceAgent so a superseded delegation stops its run.

* feat(openai): support GPT-Live realtime voice over ChatGPT OAuth

Implements OpenAI's quicksilver/frameless session natively for Talk browser sessions.
The Gateway creates the WebRTC call (multipart sdp+session to https://api.openai.com/v1/live)
and owns the sideband control socket, so the browser never holds upstream credentials;
delegation.created events run through the OpenClaw agent and stream back as speakable
context appends.

Verified end-to-end on 2026-07-28 against a ChatGPT Pro OAuth profile: call create 201
with an rtc_* id and answer SDP, sideband session.started, session.close teardown.
ChatGPT OAuth is preferred over a Platform API key because /v1/live access for platform
keys is waitlist-gated; the legacy chatgpt.com backend route returns 403 for every model
and protocol version and is not used.

Accepted models are gpt-live-1-codex and gpt-live-1-boulder-alpha; the voice allowlist is
the ten values the route actually accepts, since an invalid voice is rejected at call
creation and cannot be repaired afterwards (session.update reports immutable_field_update).

* docs: document GPT-Live Talk support and its route gotchas

Records the working route and auth, the accepted models and voices, the browser-only
scope, and the two traps that cost the most time: the chatgpt.com backend route returns
403 Voice session access denied for every model, and that same 403 is also what an
invalid voice returns, so it must not be read as an account entitlement block.

* fix(openai): resolve GPT-Live CI failures

* refactor(openai): own zod runtime dependency

* fix(openai): satisfy lint and live-shard gates for GPT-Live

Types the retry-delay finish callback as Error so the rejection reason is provably an
Error at the call site; the abort path already normalized a non-Error AbortSignal reason,
but the unknown parameter type hid that from static analysis.

Registers the new GPT-Live live test in the native-live-extensions-openai shard
expectation. The shard selector already picked the file up from the real tree; only the
hardcoded list in the tooling test lagged.

* fix(openai): clean up post-rebase capability resolver

* fix(openai): preserve GPT-Live delegation fragments

* fix(openai): close GPT-Live sideband handoff race

* fix(openai): accept UUID GPT-Live call ids

* style: apply oxfmt to GPT-Live sources and Talk docs

* style: format Talk docs after rebase

* fix(openai): keep GPT-Live transcript context across ignored delegations
2026-07-28 15:05:55 -04:00
Peter Steinberger 0d7fb8eb39 refactor(fs): adopt fs-safe 0.5 core primitives (#113705)
* refactor(fs): unify exclusive file publication

* fix(fs): fence stale lock reclamation

* refactor(fs): bound wiki scans and secret reads

* chore(fs): finalize fs-safe 0.5 compatibility

* fix(fs): preserve publication ownership and legacy mode

* fix(fs): fail closed on unverifiable lock owners

* fix(fs): preserve concurrent backup publications

* refactor(fs): preserve ambiguous backup outputs

* fix(fs): preserve mixed-version lock coordination

* refactor(file-transfer): adopt fs-safe archive extraction

* refactor(fs): add bounded walk and secret seams

* refactor(auth): replace proper-lockfile with fs-safe

* fix(fs): honor Windows mode override casing

* refactor(snapshot): adopt fs-safe publication

* refactor(memory-wiki): adopt prunable root walks

* refactor(fleet): adopt bounded archive restore

* fix(fs): preserve post-publication ownership receipts

* refactor(fs): harvest final fs-safe primitives

* style(fs): clean harvest lint

* chore(plugin-sdk): refresh move helper API baseline

* refactor(snapshot): adopt native Windows ACL facts

* refactor(fs): adopt hardened atomic outputs

* fix(fs): scope lock reentrancy to logical owners

* chore(config): lower env var count budget

* fix(deps): adopt published fs-safe 0.5.0

* fix(ci): align SDK surface ratchets

* fix(ci): regenerate SDK API baseline after rebase

* fix(fs): preserve owner-scoped file lock nesting

* fix(ci): refresh SDK API baseline for file locks

* fix(fs): separate SQLite and file lock reentrancy

* fix(imessage): bound pinned attachment reads

* fix(agents): narrow session-key lock options

* fix(fs): preserve fs-safe 0.5 compatibility contracts

* fix(windows): retain private SQLite directory owner

* refactor(sqlite): centralize exclusive coordinator

* refactor(snapshot): isolate Windows ACL policy

* fix(windows): retain snapshot ACL inspector

* chore(config): realign env budget after rebase

* test(agents): accept canonical sandbox escape error

* docs(changelog): defer fs-safe release note
2026-07-28 03:41:47 -04:00
Peter Steinberger 577a0642fa fix(plugin-sdk): classify loopback hosts consistently (#114832)
* fix(plugin-sdk): expose loopback host classifier

* fix(ollama): remove stale host normalizer import

* chore: keep release notes in PR context
2026-07-27 22:55:44 -04:00
Peter Steinberger 269bc5c89e fix(cli): preserve machine-readable stdout (#113654)
Co-authored-by: 1052326311 <65798732+1052326311@users.noreply.github.com>
2026-07-27 05:44:16 -04:00
Peter Steinberger 4859d524ed refactor(tasks): classify harness-owned subagent rows without plugin ids (#113964)
* refactor(tasks): classify harness-owned subagent rows without plugin ids

* refactor(plugin-sdk): require taskKind for harness-owned subagent runtimes

* docs(tasks): record harness-ownership invariant at the predicate

* test(plugin-sdk): declare harness task kind in scope fixtures
2026-07-25 18:41:13 -07:00
Peter Steinberger caa01f4f5b refactor(providers): table-driven forward compat and manifest-derived contract tests (#113940)
* refactor(providers): share family forward compat resolution

* test(providers): derive runtime contracts from manifests

* test(providers): validate manifest fixture inputs

* refactor(zai): narrow forward compat inputs
2026-07-25 18:09:37 -07:00
Peter Steinberger 603f839058 refactor(providers): collapse live model discovery onto shared projection hook (#113903)
* feat(plugin-sdk): add live catalog row projection

* refactor(providers): share live catalog projection

* fix(venice): keep live projection internal
2026-07-25 16:17:27 -07:00
Peter Steinberger 3d1369ff4f test(telegram): consolidate bot test harness (#113571)
* test(telegram): consolidate bot test harness

* test(plugin-sdk): expose isolated test state

Promote the isolated OpenClaw test-state lifecycle through a narrow published Plugin SDK subpath so extension tests no longer import private core helpers. This intentional SDK surface addition is maintainer-approved.

* test(telegram): use public test-state seam

* test(plugin-sdk): keep test state local-only

Match the existing channel test-helper boundary: bundled extension tests can import the focused SDK source entrypoint, while ordinary builds and the published npm package exclude it. The earlier public classification existed only on this unmerged PR branch and was never a shipped contract.

* test(plugins): map test-state in package boundaries
2026-07-25 05:28:26 -07:00
joshavant f153858045 fix(onepassword): make SecretRef setup production-safe 2026-07-25 06:03:30 -05:00
Peter Steinberger a5d758e74b refactor(plugin-sdk): share channel DM policy setup (#113537) 2026-07-25 01:00:53 -07:00
Peter Steinberger d6971f46ca fix: make filesystem publication crash-durable (#113453)
* fix(fs): centralize directory durability

* chore: keep release notes in PR body

* test(sqlite): canonicalize read-only race paths

* test(fs): clean durability fixtures

* chore(lint): prune sqlite snapshot baseline

* fix(backup): reject unsupported commit sync

* fix(fs): enforce strict durability outcomes

* refactor(tls): flatten preserved-output failures

* fix(reef): require durable journal commits

* fix(fs): route durability through policy boundaries

* fix(reef): preserve Windows journal compatibility

* fix(fs): bind publication to canonical directories

* fix(ci): align durability boundary fixtures
2026-07-24 20:58:17 -07:00
Peter Steinberger 1e9d918037 feat(sdk): always persist media facts and ship facts-first replacements for legacy Media* surfaces (#113355)
* feat(sdk): always persist media facts and ship facts-first replacements for legacy Media* surfaces

PR 1 of the media legacy retirement program (audit-frozen, 4 PRs).

- Every media-bearing user turn now persists normalized __openclaw.media
  facts unconditionally while continuing to emit the legacy top-level
  Media* projection byte-identically (dual-write bridge; the conditional
  shouldPersistStructuredMediaEntries gate now always includes media).
- New replacement APIs, shipped before any removal: typed hook media
  facts (media[], originalMedia[], mediaStagingPending) on message
  events; {{AttachmentPath}}/{{AttachmentUrl}}/{{AttachmentContentType}}/
  {{AttachmentDir}}/{{AttachmentIndex}} template variables; focused
  openclaw/plugin-sdk/media-local-roots subpath split out of the
  deprecated agent-media-payload facade.
- Every legacy surface carries @deprecated naming its replacement, under
  one named compatibility record media-legacy-projection with the
  operator-approved removeAfter 2026-10-01 (two release trains; deletion
  additionally gates on a clean published-plugin artifact sweep).
- Generic transcript append invariant documented; SDK migration, hooks,
  and configuration docs updated to the facts-first path.

Writer golden matrix proves legacy bytes and model prompt bytes are
unchanged while nested facts become unconditional. 2,189 broad media
tests green; SDK api-baseline regenerated on fresh-env Testbox.

* feat(sdk): register media-local-roots subpath exports and deprecation metadata

Completes PR 1: package export map for openclaw/plugin-sdk/media-local-roots
plus the deprecated-subpath inventory and doc metadata entries for the
media-legacy-projection record.

* chore(sdk): track media-local-roots entrypoint and deprecated-export budgets

* fix(sdk): keep deprecated MSTeams buildMediaPayload re-export through the compat window

Deleting shipped runtime-api re-exports belongs to retirement PR 4 after
the media-legacy-projection window; PR 1 only deprecates. Also formats
the migration-guide schedule table.

* docs: regenerate docs map for media migration additions
2026-07-24 10:42:17 -07:00
Vincent Koc 5ff16901ef refactor(browser): reuse shared error coercion (#113229) 2026-07-24 13:58:29 +08:00
Peter Steinberger 129f86bbf5 feat: auto-collect durable meeting transcripts (#113122)
* feat(meetings): auto-collect durable transcripts

* chore(plugin-sdk): refresh meeting transcript API baseline

* fix(plugin-sdk): keep meeting transcript options implicit

* fix(meetings): satisfy transcript bridge typecheck

* fix(google-meet): preserve optional caption policy context

* fix(google-meet): retain caption mode callback type

* refactor(meetings): split transcript lifecycle helpers

* chore(plugin-sdk): refresh split meeting runtime baseline

* refactor(google-meet): split session helpers

* fix(meetings): decouple transcript retries from leave

* fix(meetings): isolate provider subscribers

* fix(meetings): harden capture lifecycle

* fix(meetings): preserve capture during storage outages

* fix(meetings): preserve pending transcript ordering

* fix(meetings): retry capture initialization

* test(agents): reflect default transcript registration
2026-07-23 11:41:08 -07:00
Jesse Merhi 4a2a600809 feat(channels): add channel-owned setup contracts (#112176)
* feat(channels): add channel-owned setup contracts

* test(channels): align legacy setup fixtures

* chore(channels): regenerate config and SDK baselines after rebase

* fix(update): run fresh doctor after current-process core changes

* fix(channels): align add pre-scan with execution precedence

* style(cli): format channels-cli test additions

* fix(channels): restore option-before-positional channel resolution via metadata arity scan

* fix(channels): keep help flags out of metadata arity escalation

* test(update): mock fresh post-update doctor in current-process suites

* style: format review fixes and correct entrypoint mock type

* fix(channels): register only modern contract options for dual-publishing plugins

* test(update): align downgrade suites with fresh-doctor child invocation

* docs(channels): record empty-contract and input-forwarding invariants

* fix(line): keep the shipped --token switch as a channel access token alias

* fix(signal): stop treating exact cross-family loopback endpoints as bind-aligned

* chore(config): regenerate docs config baselines after second rebase

* style: format rebased channels add tests

* fix(channels): enforce field-key and flag-name agreement in setup contracts

* fix(signal): detect container endpoints for bare --http-url setup

* fix(signal): ignore unconfigured accounts in transport collision checks

* fix(channels): validate negated setup flags in contract and normalizer

* fix(signal): preserve existing transport kind when setup detection is unreachable

* style(signal): use direct boolean check in collision guard

* style(signal): type test config literals

* docs(update): record two-read design of fresh-doctor validation gate

* fix(channels): satisfy post-rebase architecture gates

* docs: refresh channel setup map

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-22 19:57:42 -04:00
Jason (Json) 8968e955f7 fix(plugins): restore external runtime imports (#112021)
* fix(plugins): restore external runtime imports

* fix(plugins): support synthetic runtime builds

* test(plugins): type synthetic runtime plan
2026-07-20 21:45:23 -06:00
Peter Steinberger bcbbf28093 docs(plugin-sdk): migrate retained SDK contracts (#111535)
* refactor(plugin-sdk): finish retained public demotions

* test(plugin-sdk): tighten surface budgets

* fix(plugin-sdk): retain static tool metadata contract

* fix(plugin-sdk): keep retained exports pending

* fix(plugin-sdk): satisfy registry lint

* docs(plugin-sdk): document retained consumer seams
2026-07-19 15:00:45 -07:00
Peter Steinberger c7e7ac2728 refactor: remove expired plugin compatibility surfaces (#111451)
* docs(secrets): remove retired web credential paths

* refactor(web): remove retired provider compatibility paths

* refactor(providers): delete retired compatibility routes

* refactor(secrets): remove retired credential aliases

* refactor(plugin-sdk): delete retired compatibility surfaces

* docs(plugin-sdk): remove retired migration guidance

* chore(plugin-sdk): refresh rebased surface budgets

* chore(plugin-sdk): refresh API removal baseline

* refactor(compat): migrate retired internal callers

* chore(plugin-sdk): refresh current-main baselines

* test(config): migrate plugin-owned secret assertions

* test(gateway): narrow plugin secret refs

* fix(plugin-sdk): preserve private boundary type identity

* chore(compat): remove stale sweep references

* chore(lint): lower max-lines budget

* refactor(secrets): remove unused web helper

* build(plugin-sdk): drop removed compat entries

* chore(plugin-sdk): refresh rebased API baseline

* chore(plugin-sdk): use Linux API baseline hash

* fix(plugin-sdk): preserve private bundled build entries

* fix(plugin-sdk): package private runtime facades

* fix(plugins): preserve external credential contracts
2026-07-19 11:04:48 -07:00
Josh Lehman 453444636c feat: bound transcript reads across replacements (#110374) 2026-07-18 11:41:39 -07:00