Commit graph

607 commits

Author SHA1 Message Date
Peter Steinberger
3ada371449
fix(gateway): accept Mac approval usage timestamps (#102688)
* fix(gateway): accept Mac approval usage timestamps

* chore: move release note to PR body
2026-07-09 12:32:23 +01:00
Peter Steinberger
3ccf2a0739
feat: render inline web chat widgets via capability-gated show_widget tool (#101840)
Adds client-capability-gated tool availability: gateway clients declare
capabilities at connect (new inline-widgets cap), chat.send stamps them into
the run context, and every tool assembly path (embedded runner, queued
followups, Codex app-server harness, plugin-only construction plans) drops
tools whose requiredClientCaps the originating client did not declare. The
Canvas plugin ships the first such tool, show_widget: agents pass SVG or an
HTML fragment plus a title; the plugin hosts it as a bounded, retention-scoped
Canvas document and returns the existing canvas preview handle, which web chat
renders as a sandboxed iframe fitted to the widget's reported content height.
Widget frames never get allow-same-origin (per-preview sandbox ceiling,
including the sidebar path) and the Canvas host serves widget documents with a
CSP sandbox header so direct navigation runs in an opaque origin. Verified
live end-to-end on a Testbox with gpt-5.5 (screenshots on the PR). CLI-backed
model backends do not carry client caps yet and stay fail-closed (#102577).

Closes #101790
2026-07-09 12:29:50 +01:00
lsr911
bb1fa4012e
fix(memory-host): use truncateUtf16Safe for QMD stderr context truncation (#102547)
* fix(memory-host): use truncateUtf16Safe for QMD stderr context truncation

* test(memory): cover UTF-16-safe qmd stderr summary

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 10:38:43 +01:00
wings1029
f7cc6ebe1e
fix(agent-core,memory-core): keep compaction summary and memory snippet truncation UTF-16 safe (#102542)
* fix(agent-core,memory-core): keep compaction summary and memory snippet truncation UTF-16 safe

* fix: make compaction and memory truncation UTF-16 safe

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 10:08:11 +01:00
lsr911
3ac7729f4c
fix(mistral): use truncateUtf16Safe for error text truncation (#102539)
* fix(mistral): use truncateUtf16Safe for error text truncation

Replace naive .slice(0, maxChars) with truncateUtf16Safe() in
truncateErrorText() to prevent surrogate pair splitting in
Mistral provider error messages shown to users.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(ai): keep Mistral errors UTF-16 safe

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 10:03:51 +01:00
Ted Li
f984209f54
fix: keep Gemini thinking disabled after clamp (#101832)
* fix: keep Gemini thinking disabled after clamp

* fix: preserve clamped Gemini thinking in wrapper

* test(ai): cover generic Gemini clamp to off

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 09:54:52 +01:00
Harjoth Khara
85aa26d34f
fix(agent-core): stop canceled parallel tools from starting (#102276)
* fix(agent-core): skip prepared tools after abort

* docs(agent-core): explain parallel abort guard

* docs(changelog): note parallel cancellation fix

* docs(changelog): leave release notes release-owned

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 09:48:11 +01:00
QiuYuang
d5a31888ed
fix(memory-host): reject queued worker requests on shutdown (#102451)
* fix(memory-host): reject queued worker requests on shutdown

* fix(memory-host): settle queued requests on shutdown

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 09:26:05 +01:00
qingminlong
c3d567db95
fix(memory): snippets split emoji when truncated (#102478)
* fix(memory): snippets split emoji when truncated

* refactor(memory): reuse shared UTF-16 truncation

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 08:27:42 +01:00
qingminlong
b20b02a476
fix(tool-payload): enforce UTF-8 byte limits for serialized payloads (#102450)
* fix(tool-payload): reject oversized XML payload bytes

* fix(tools): enforce serialized payload byte limits

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-09 07:47:23 +01:00
Peter Steinberger
5533d979d4
feat: add follow-up task suggestions (#102422)
* feat(tools): add follow-up task suggestions

* chore: leave changelog to release flow

* fix(tools): add task suggestion display metadata

* fix(tools): update task suggestion display snapshot

* docs: format task suggestion tool table

* test(gateway): expect compaction worktree workspace

* test(gateway): preserve configured compaction workspace

* fix(ui): translate task suggestions
2026-07-09 06:30:01 +01:00
Peter Steinberger
d6ec1c6cea
fix(secrets): prevent capture and sentinel credential retention (#102420)
* fix(secrets): harden sentinel capture lifecycle

* chore: leave release notes to release automation
2026-07-09 05:50:28 +01:00
Dallin Romney
8fa83d2742
refactor(gateway): consolidate client contracts (#101012) 2026-07-08 10:56:31 -06:00
Peter Steinberger
4bf70be01a
feat(secrets): egress-time credential injection with process-local sentinels (#102009)
* feat(secrets): resolve SecretRef model credentials at egress via process-local sentinels

SecretRef-managed model-provider credentials now travel as opaque
oc-sent-v1 sentinels through auth storage, stream options, and SDK
config; the guarded model fetch injects real values into headers and
URLs immediately before the SSRF-guarded send and fails closed on
unknown sentinels. packages/ai adapters converge on the host guarded
fetch where the SDK supports custom fetch and unwrap at construction
where it does not. Resolved values (and their percent-encoded forms)
register for exact-value log redaction. Kill switch:
OPENCLAW_SECRET_SENTINELS=off. Also fixes a pre-existing unhandled
rejection race in capNonOkResponseBodyLazily (pipeThrough writer leak).

* test(plugin-sdk): update public surface budget
2026-07-08 12:56:41 +01:00
Vincent Koc
380bc24d25
refactor(deadcode): localize AI provider declarations (#101907) 2026-07-07 16:26:22 -07:00
Vincent Koc
1b6f3e43d1
refactor(deadcode): trim private helper exports (#101886) 2026-07-07 14:43:45 -07:00
NianJiu
dbbab1044e
fix: require full frontmatter delimiter lines (#101795)
Co-authored-by: NianJiuZst <180004567+NianJiuZst@users.noreply.github.com>
2026-07-07 11:53:03 -07:00
Peter Steinberger
a6768d9de5
feat(cron): event triggers — polled condition-watcher scripts via code mode (#101195)
* feat(cron): add headless code-mode driver and trigger-script evaluator

Part A of cron event triggers: runCodeModeScriptHeadless runs a script
to completion (exec/settle/resume, no snapshots, no session), plus the
cron-facing evaluator with per-job tool catalog cache, semaphore, 16KB
state cap, and closed failure taxonomy.

* fix(cron): correct trigger-script bootstrap flags and cache narrowing

* feat(cron): add event triggers (polled condition-watcher scripts)

Part B: trigger field on cron jobs gated by cron.triggers.enabled;
timer evaluates the script each due tick, quiet ticks leave no run
history, fired runs append the script message to the payload; once
semantics, min-interval floor, SQLite columns, RPC/CLI/agent-tool
surfaces, and docs.

* fix(cron): propagate triggerEval through startup catch-up outcomes

* fix(cron): honor cron staggering on quiet trigger ticks; fix trigger test types

* fix(cron): reject with Error reason in trigger-script abort test

* fix(cron): regenerate protocol/docs/snapshot artifacts and break madge cycle for trigger types

CI fixes for #101195: trigger evaluator result types move to the cron
types leaf (madge cycle), cron tool schema inventory gains trigger,
Swift protocol bindings + docs map + Linux prompt snapshots regenerated.

* fix(cron): drop underscore-dangle names in trigger code sync assert

* fix(cron): adopt registerHeadlessToolSearchCatalog after tool-search symbol localization

Upstream #101831 made registerToolSearchCatalog module-private; fold the
headless ref-only catalog registration into one public seam.
2026-07-07 19:12:38 +01:00
Peter Steinberger
a7faec8ca1
fix(gateway): support native Windows exec approvals (#101669)
* fix(gateway): support native Windows exec approvals

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>

* chore: defer changelog entry to release

* test: use tracked approvals temp directories

---------

Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
2026-07-07 14:50:59 +01:00
Vincent Koc
fee997c8ad
refactor(memory): trim unused host SDK exports (#101604) 2026-07-07 04:33:43 -07:00
Vincent Koc
988f30e30e
refactor(memory): trim unused Windows spawn exports (#101594) 2026-07-07 04:17:32 -07:00
Peter Steinberger
84d0a71406
fix(memory): preserve UTF-16 chunk boundaries (#101574)
* fix(memory): preserve UTF-16 chunk boundaries

* test(memory): require coarse boundary split

Co-authored-by: jensenwang560-blip <267012233+jensenwang560-blip@users.noreply.github.com>

* fix(memory): retain chunk budget at surrogate boundaries

---------

Co-authored-by: jensenwang560-blip <267012233+jensenwang560-blip@users.noreply.github.com>
2026-07-07 12:01:32 +01:00
Vincent Koc
098b471143
refactor(memory): remove unused runtime facade exports (#101583) 2026-07-07 03:57:51 -07:00
Vincent Koc
036686ab95
refactor(memory): localize host SDK helpers (#101568) 2026-07-07 03:28:00 -07:00
Peter Steinberger
354a151544
feat(gateway): archive-gated session deletes give Android delete parity (#101522)
sessions.delete gains an explicit archivedOnly param (additive protocol
schema change, Swift models regenerated): with archivedOnly=true, the
dispatcher grants operator.write and the handler requires the target to
already be archived (archive-then-delete keeps destructive intent a
two-step action). Without the flag nothing changes: deletes require
operator.admin, so internal fallback/synthetic dispatch, subagent cleanup,
and CLI minting keep their admin contracts, and the session-kill HTTP
endpoint pins admin explicitly since it terminates live runs.

Android sends archivedOnly and offers Delete only on archived rows, where
its bounded (non-admin) operator session is now authorized; active rows
archive first. iOS/web connect with admin and keep unrestricted deletes.

Refs #100712
2026-07-07 10:52:53 +01:00
Vincent Koc
78399a194c
refactor(agent-core): localize exec timeout helper (#101523) 2026-07-07 02:29:18 -07:00
Vincent Koc
2e4e982ff0
refactor(memory): localize host SDK internals (#101508) 2026-07-07 01:50:53 -07:00
pick-cat
e72dadbb3b
fix(anthropic): resolve thinking as disabled when legacy budget is below 1024 (#101415)
* fix(anthropic): resolve thinking as disabled when legacy budget is below 1024

When adjustMaxTokensForThinking collapses the thinking budget below the
Anthropic minimum (1024), option resolution now sets thinkingEnabled to
false instead of always forcing it to true. This keeps every downstream
consumer (payload, replay, temperature, tool-choice) consistent — they
all see the same disabled state instead of an enabled flag with a
missing or API-rejected thinking block.

|| → ?? in both builders is defensive: the resolution layer already
prevents invalid budgets from reaching the builder through the normal
path, but ?? preserves an explicit zero when the builder is called
directly.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(anthropic): guard raw streamAnthropic builder path against sub-minimum budgets

Add budget guards in both Anthropic payload builders so direct
streamAnthropic and bundled-plugin callers (e.g. Mantle) that bypass
option resolution also get the disabled-state rule instead of producing
API-rejected { type: "enabled", budget_tokens: < 1024 } requests.

Add proof-anthropic-thinking-budget.mts driving real production
functions with terminal output and negative control.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(anthropic): normalize legacy thinking budgets

Co-authored-by: Pick-cat <huang.ting3@xydigit.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-07 08:42:40 +01:00
wings1029
5c4b63964c
fix(memory-host-sdk): handle stdout/stderr stream errors in runCliCommand (#101402)
* fix(memory-host-sdk): handle stdout/stderr stream errors in runCliCommand

Register error handlers on stdout and stderr streams in
runCliCommand() to prevent uncaught exceptions when a pipe
breaks (e.g. EPIPE after child process exit).

Without these listeners, Node.js throws an uncaught exception
that crashes the process.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(memory-host-sdk): extract listenForChildOutputErrors helper

Refactor the inline stream error handling into a reusable
listenForChildOutputErrors helper, matching the pattern
established in the merged #101370 (agent-core).

The helper registers error listeners on stdout/stderr via a
shared loop, keeping the pattern consistent across the codebase.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(memory-host-sdk): harden qmd stream failures

* fix(memory-host-sdk): harden qmd stream failures

* docs(changelog): note qmd stream hardening

* chore: keep release changelog out of contributor PR

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-07 08:37:21 +01:00
Wynne668
55fa22b482
fix(process): handle taskkill spawn errors (#101392) 2026-07-07 08:06:31 +01:00
wings1029
e779abf70e
fix(agent-core): handle stdout/stderr stream errors in harness exec (#101370)
* fix(agent-core): handle stdout/stderr stream errors in harness exec

Register error handlers on stdout and stderr streams in
NodeExecutionEnv.exec() to prevent uncaught exceptions when
a pipe breaks (e.g. EPIPE after child process exit).

Without these listeners, Node.js throws an uncaught exception
that crashes the entire agent-core process.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(agent-core): address review — hoist-safe mock and curly lint

- Use vi.hoisted pattern for spawnMock to fix ReferenceError in CI
- Wrap one-line if guard in braces per repo curly rule

Co-Authored-By: Claude <noreply@anthropic.com>

* chore: keep release notes in PR context

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-07 07:34:11 +01:00
snowzlmbot
53580e13a4
fix(usage): preserve provider-billed zero totals (#101177)
* fix(usage): preserve provider-billed zero totals

* fix(usage): harden provider-billed cost provenance

* fix(openrouter): retry delayed generation metadata

* fix(openrouter): satisfy retry lint

* refactor(openrouter): consume streamed billed cost

* chore: keep release notes out of contributor PR

---------

Co-authored-by: snowzlmbot <293528334+snowzlmbot@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-07 06:22:28 +01:00
Peter Steinberger
473b3cf789
fix(anthropic): keep error tool results non-empty (#101373)
Co-authored-by: Galin Iliev <5711535+galiniliev@users.noreply.github.com>
2026-07-07 06:17:27 +01:00
Vincent Koc
85d6d94afd
refactor(memory): remove unused host SDK exports (#101362) 2026-07-06 21:54:06 -07:00
Peter Steinberger
c5d42593be
fix(anthropic): guard SDK client transport (#101357)
Co-authored-by: wangmiao0668000666 <wang.miao86@xydigit.com>
2026-07-07 05:45:49 +01:00
NickNMorty
59097783e2
fix(markdown-core): CJK-friendly emphasis flanking so **标签:**正文 renders bold (#101120) (#101230)
* test(telegram): reproduce CJK emphasis flanking bug

* fix(markdown-core): support CJK emphasis flanking

* fix(markdown-core): type CJK delimiter state (#101120)

* fix(markdown-core): mirror markdown-it Unicode whitespace in CJK delimiter override

Preserves markdown-it isWhiteSpace classification (U+3000, U+00A0, U+2000-200A, etc.) before forcing CJK-adjacent delimiter flags, and adds U+3000/U+2009 regressions. Addresses clawsweeper P1 finding on #101230.

* refactor(markdown): use maintained CJK flanking plugin

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-07 05:43:42 +01:00
Vincent Koc
84e5327720
fix(text): keep bounded outputs UTF-16 safe (#101355)
Co-authored-by: Alix-007 <li.long15@xydigit.com>
2026-07-06 21:33:24 -07:00
Peter Steinberger
ad5b81e884
fix(memory): trust structured cron archive provenance (#101322)
Prevent user-authored [cron:] text from clearing reset or deleted session memory while preserving structured cron-run opacity.

Co-authored-by: ly-wang19 <ly-wang19@users.noreply.github.com>
2026-07-07 04:52:21 +01:00
Ayaan Zaidi
c718afe247 refactor(agents): thread runtime-context carrier indexes 2026-07-06 20:34:01 -07:00
Peter Lindsey
f5931f5516 fix(agents): carry current-turn inbound metadata in a tail runtime-context message for byte-stable prompt caching
The active user turn was decorated at request-build time with an inbound
metadata block (Conversation info / reply-target / sender / forwarded /
chat-history), but the session store persists the bare text and the LLM boundary
strips that block from historical replay. So a user message's serialized bytes
changed retroactively — decorated as the active turn, bare as history — on every
turn, invalidating any prefix/exact-match provider prompt cache from that point
onward, every turn. (#90811 fixed the timestamp half of this same asymmetry.)

Rework of the earlier "strip the active turn" approach (which lost model-visible
context — ClawSweeper's P1) into one that keeps the context AND recovers the
cache cost:

- Route current-turn inbound metadata out of the user prompt and into the hidden
  runtime-context custom message (the mechanism from openclaw#89428), and
  relocate that carrier to the ABSOLUTE TAIL of the wire request (after the
  active user turn and any tool-call scaffolding). The user turn stays bare and
  byte-identical in both the active and historical positions; the volatile
  carrier vanishes next turn exactly where the assistant reply begins anyway, so
  the request is an append-only prefix-extension through the active user turn.
- A durable marker (UserMessage.runtimeContextCarrier, set by convertToLlm from
  the carrier's details) lets the Anthropic SDK transport, the managed Anthropic
  transport (anthropic-transport-stream / anthropic-payload-policy), and
  OpenAI-completions skip the carrier when selecting the deepest cache_control
  breakpoint, keeping the anchor on the last stable user turn.

Storage stays BARE (invariant preserved); runtime-only turns (room events) keep
their existing inline behavior, which is byte-stable because room-event/system
context is not strip-eligible; legacy bare-stored sessions are unchanged.

Reviewed with adversarial gpt-5.5/codex sweeps (correctness, byte-identity,
compatibility, test adequacy): found + fixed the managed Anthropic transport
cache-anchor path and added the missing OpenAI-completions/managed-transport
breakpoint tests; a theoretical runtime-only mutation was verified unreachable
and pinned with a test. Final sweep clean.

Co-authored-by: openclaw#89428 (runtime-context handoff approach)
2026-07-06 20:34:01 -07:00
Peter Lindsey
3d87932541 fix(agents): send session_id affinity header to ChatGPT Responses backend
The ChatGPT backend routes requests by session_id (codex-cli sends it); without it each request lands on an arbitrary machine and the prompt cache misses. Measured on live traffic: 56.0% -> 81.8% TRUE cache hit rate (12-turn A/B, identical prompts).
2026-07-06 20:33:51 -07:00
Peter Steinberger
1a307be2e0
feat(skills): add lifecycle curator for workshop-created skills (#101214)
Tracks per-skill usage from the skill.used diagnostic event (trusted-only
delivery, file-scoped identity), sweeps workshop-created skills daily from
gateway maintenance (active -> stale 30d -> archived 90d, pinned bypass,
restore-only unarchive, files never touched), filters archived skills from
snapshots fail-open, reports workspace-scoped overlap candidates, and adds
openclaw skills curator CLI, additive gateway methods, and a warn-only
doctor finding. Zero new config keys; SQLite/Kysely state only.
2026-07-07 03:25:44 +01:00
Ayaan Zaidi
486033b183
fix(agents): normalize compaction recovery tails
Compaction failure and timeout recovery can no longer leave a session transcript assistant-last and wedged after restoring pre-compaction state.

Transcript-continuation failures now carry a typed agent-core error code and no longer demote the active model through model fallback scoring.

Surface: embedded agent runner compaction recovery, model fallback classification, packages/agent-core.

Refs #100312. Includes regression coverage for #99943.
2026-07-07 02:09:21 +00:00
qingminlong
d6f097b3de
fix(agents): normalize surrogate cache fingerprints (#101009)
* fix(agents): normalize surrogate cache fingerprints

* fix(agents): reuse provider surrogate sanitizer

* chore(agents): keep transport imports grouped

* fix(agents): avoid runtime import for surrogate sanitizer

* fix(agents): scope surrogate cache normalization

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-07 03:06:56 +01:00
Vincent Koc
f305e707a3
feat(models): add Claude Mythos 5 support (#101238) 2026-07-06 17:19:49 -07:00
Dallin Romney
95e3b9243b
test: execute media and Talk runtime boundaries (#101091)
* test: execute media and Talk runtime boundaries

* test(qa): centralize gateway fixture startup

* test(qa): check in voice call plugin fixture
2026-07-06 16:25:33 -07:00
Vortex Openclaw
1f6ddb5df0
feat(models): add Claude Sonnet 5 support (#98254)
* feat(models): add Claude Sonnet 5 support

Co-authored-by: Ariel Bravy <ariel@vortexradar.com>

* fix(models): align Sonnet 5 validation baselines

* fix(models): satisfy Sonnet 5 CI contracts

* fix(models): enforce Sonnet 5 provider contracts

* docs(changelog): defer Sonnet 5 release note

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
Co-authored-by: Ariel Bravy <ariel@vortexradar.com>
2026-07-07 00:05:35 +01:00
Peter Steinberger
80537c1ba4
feat(macos): load provider catalog during AI onboarding (#101132)
* feat(macos): load onboarding providers from gateway

* test(crestodian): widen setup config mock

* fix(crestodian): satisfy onboarding lint gate

* chore(macos): refresh onboarding localization inventory

* test(plugins): cover guided Copilot secret metadata
2026-07-06 20:57:56 +01:00
Peter Steinberger
912af0a56f
fix(gateway): keep N-1 nodes manageable during upgrades (#101109)
* fix(gateway): allow N-1 node protocol maintenance

* docs: refresh generated map for node upgrade guide
2026-07-06 20:01:20 +01:00
Vincent Koc
65a9cb4ed1
refactor(packages): localize internal helper types (#101041) 2026-07-06 10:30:58 -07:00