Commit Graph

40091 Commits

Author SHA1 Message Date
Peter Steinberger
a1cc41acbc fix: recognize Bash completion installed in login profiles (#113790)
* fix(cli): recognize Bash completion in login profiles

* test: track Bash completion profile fixtures

---------

Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 11:08:59 -07:00
Peter Steinberger
0ff2c82033 refactor(mattermost): split inbound monitor (#113775)
* refactor(mattermost): split inbound monitor

* test(channels): follow mattermost history split
2026-07-25 10:56:58 -07:00
Peter Steinberger
c65f509658 refactor(doctor): split configured plugin repair (#113777) 2026-07-25 10:56:40 -07:00
Peter Steinberger
6f1950ec1a fix(tui): expose supported verbose and reasoning levels (#113782)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 10:52:53 -07:00
Jason (Json)
8028a3a5b2 feat(anthropic): gate live model discovery on contract coverage (#113757)
* feat(anthropic): gate live model discovery on contract coverage

Live catalog discovery cloned a template for any newly discovered Claude id, so
a future model generation would be selectable while request shaping treated it
as pre-4.6 and 400d. Add an opt-in acceptUnknownModel gate to the shared live
catalog seam and have the Anthropic plugin accept a discovered model only when
Anthropic's advertised capabilities agree with the contracts we would apply.
Manifest-published ids bypass the gate and keep their metadata.

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

* docs(plugins): document the live-discovery admission hook

Record acceptUnknownModel in the provider-plugin SDK reference: when to use
it, that manifest-published ids bypass it, and the fail-closed guidance.

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

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-25 11:27:58 -06:00
Peter Steinberger
ce7ec43c45 fix(media): preserve streamed attachment filename MIME detection (#113762)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 10:24:57 -07:00
Peter Steinberger
1b2dc18190 test(doctor): validate bundled provider catalogs (#113761) 2026-07-25 10:18:35 -07:00
Peter Steinberger
7db5d5450e refactor(config): split validation responsibilities (#113713)
* refactor(config): split validation god file

* refactor(config): keep validation helper type private
2026-07-25 09:56:09 -07:00
Peter Steinberger
bd71c34015 refactor(gateway): split server implementation (#113725) 2026-07-25 09:12:12 -07:00
Peter Steinberger
1bfd207a54 refactor(doctor): split legacy model migrations (#113717) 2026-07-25 08:52:43 -07:00
Peter Steinberger
1e93e78ee1 fix(cron): deliver globally configured failure alerts (#113737)
* fix(cron): deliver globally configured failure alerts

* fix(cron): respect failure destination and skipped alerts

---------

Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 08:52:29 -07:00
Peter Steinberger
924aef2e7c fix(nodes): deliver single-field notifications to native devices (#113747)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 08:47:33 -07:00
Peter Steinberger
c51fd61e1a fix(cron): keep paused jobs off descending next-run pages (#113745)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 08:42:38 -07:00
Peter Steinberger
e19841c725 feat: continue Pi and OpenCode sessions from the session catalog (#113718)
* feat(plugins): add acpSessionBinding seam for ACP session adoption

* feat(acpx,opencode): adopt existing Pi and OpenCode sessions from the catalog

* fix(ci): satisfy dead-code and temp-path guards

* docs(acpx): record why pi-acp session-root resolution stays strict
2026-07-25 08:35:47 -07:00
Peter Steinberger
14da8a2523 refactor(agents): validate workspace attestation rows structurally, not by filename allowlist (#113686)
* refactor(agents): validate attestation hashes structurally

* fix(agents): reject Windows reserved device names in attestation filenames

* refactor(agents): close attestation filename set with an ASCII markdown charset
2026-07-25 08:32:50 -07:00
Peter Steinberger
481d826ff4 fix(vault): prevent insecure secrets plan writes (#113707)
* fix(vault): harden secrets plan writes

* fix(secrets): avoid env marker collision

* style(secrets): type plan write rejection

* refactor(onepassword): remove obsolete path resolver

* fix(secrets): preserve Windows plan path trust

* refactor(secrets): compact ACL token policy

* fix(secrets): route permission checks through facade
2026-07-25 08:27:33 -07:00
Peter Steinberger
589f28b57a refactor(plugins): split manifest normalization (#113720) 2026-07-25 08:27:03 -07:00
Peter Steinberger
a95486cefc feat: session rail with read-only session companion in Control UI chat (#113698)
* feat(protocol): add session companion schemas

* feat(gateway): add session companion service

* feat(gateway): expose session companion rpc

* fix(gateway): harden companion runtime limits

* test(gateway): fix companion type assertions

* test(gateway): align companion test target

* feat(ui): replace observer HUD and side chat with session rail

* docs: session rail companion for control ui

* test(ui): align session rail client mock

* fix(ui): drop stale chat search import

* fix: satisfy session companion lint contracts

* refactor(gateway): isolate companion state contract

* fix(ui): keep session rail reachable while idle

* fix(agents): clamp derived openai prompt cache keys at boundary

* fix(ai): clamp chatgpt responses session_id affinity header

* fix(ci): align session companion branch gates

* fix(ui): require run id for sessionless terminal chat events

* fix(agents): scope internal run events to transcript

* chore: revert changelog edit (release generation owns changelog)
2026-07-25 08:14:32 -07:00
Peter Steinberger
78e600bc1c refactor(gateway): build one attachment message and project image-stripped text at routing (#113738)
The attachment parser accumulated two parallel message strings via
conditional appends inside the offload loop (all markers vs non-image
markers). Markers are presentation-only now that MediaFact[] carries
identity, so the parser builds one message and the routing decision in
chat-send-attachments projects the image-stripped variant from the
structured offloaded refs (stripImageMediaMarkers) exactly where
routeImageOffloadsAsMediaPaths chose a string before. Marker order,
trailing placement, and trim semantics are byte-identical; goldens
unchanged.
2026-07-25 08:14:18 -07:00
Peter Steinberger
42515c4f07 fix(openai): prevent realtime transcript turns from reordering (#113723)
* fix(openai): preserve realtime transcript order

* chore: defer realtime note to release

* test(openai): align heartbeat prompt contract

* test(openai): align direct context contract
2026-07-25 08:11:09 -07:00
Peter Steinberger
22226bf2f6 refactor(agents): split CLI runner execution (#113716)
* refactor(agents): split CLI runner execution

* refactor(agents): keep CLI log helper private
2026-07-25 08:07:41 -07:00
Sanjay Santhanam
65526ed389 fix: gmail setup fails to load gcloud when an unsupported Python is first on PATH (#112983)
* fix(gmail-setup): skip python interpreters gcloud can't use

resolvePythonExecutablePath accepted the first python3/python found on
PATH without checking its version, so macOS' bundled Python 3.9 (earlier
on PATH than a Homebrew 3.10-3.14 install) was chosen as CLOUDSDK_PYTHON
and gcloud failed to load. Query each candidate's version and skip any
outside gcloud's supported 3.10-3.14 range so a compatible interpreter
later on PATH is selected instead.

Closes #112712

* test(gmail): cover gcloud Python upper bound

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 07:53:38 -07:00
Vincent Koc
21694787f0 fix(sqlite): pin snapshot backups to one read state (#113708) 2026-07-25 22:31:23 +08:00
Peter Steinberger
bd8277c248 refactor(agents): split subagent lifecycle (#113711) 2026-07-25 07:29:42 -07:00
Eugene Harold Krabs
934acf312b chore: stabilize session cost usage cache warmup test (#113460)
* test: stabilize session cost usage cache warmup

* test(infra): await cost refresh deterministically

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 07:29:18 -07:00
Peter Steinberger
f703d803cc chore(models): curate all provider model catalogs to current-generation lineups (#113681)
* chore(models): fleet-wide provider catalog curation

* fix(models): sync provider runtime catalogs and tests with curated manifests

* test(models): align venice lifecycle assertions and copilot auth default with curated catalogs

* test(models): align catalog lifecycle contract checks
2026-07-25 07:21:17 -07:00
Peter Steinberger
de916a4fe3 fix: repair tool-call transcripts when plugins block results (#113697)
* fix: preserve tool-call pairing when message hooks block results

* test: satisfy tool-result guard boolean lint

---------

Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 07:18:16 -07:00
Peter Steinberger
367ff3cea1 feat(sqlite): migrate persisted media to canonical facts and stop legacy writes (#113695)
* feat(sqlite): migrate persisted media to canonical facts and stop legacy writes

PR 3 of the media legacy retirement program — the operator-approved
canonical cutover.

- openclaw doctor --fix owns one idempotent migration: active
  transcript_events rows canonicalize to __openclaw.media (facts-first
  gap-fill, bare legacy kinds to fact.kind, transcribed indexes and
  workspace dirs onto per-fact fields) via the transcript replacement
  owner; cold plain/.zst archives rewrite through temp-file + codec
  readback + event/id verification + atomic replace; trajectory
  runtime snapshots canonicalize IN PLACE (telemetry preserved, never
  row deletion). Invalid JSON, genuinely ambiguous legacy-only sparse
  alignment, or a changed source aborts that owner without partial work;
  reruns are no-ops.
- Per-agent schema advances to v16 as a pure downgrade guard (main
  independently took v15 for board/session-sharing tables; no
  columns/tables/indexes change here, shared-state DB untouched). v15
  databases repair canonical indexes before the version assertion so
  repairable installations never strand.
- The user-turn builder stops writing top-level legacy Media* fields;
  shouldPersistStructuredMediaEntries and the aligned projection mode
  are deleted; the generic transcript append boundary canonicalizes
  every message role so SDK/mirror writers cannot mint new legacy rows.
- Internal persisted-reader legacy fallbacks are removed; the public
  SDK projection stays until retirement PR 4's window expires.

Hardening from three adversarial review rounds, each with fixture
regressions: in-place trajectory canonicalization instead of row
deletion; repair-before-assert on the v15 path; all-roles append
canonicalization; duplicate-preserving exact row rewrites; v0-v15
reopen guards; complete canonical facts bypass compact legacy
projections (PR-1 dual-write rows migrate cleanly); SQLite LIKE
underscore escaped so populated foreign databases are never claimed.

* fix(sqlite): align schema-support metadata and gates with the v16 cutover

package.json agent schema support advances to 16; verifier and board
parity fixtures run doctor migration before steady-state access (the
production guards were correct); two test-only exports removed; the
migration module registered in the doctor raw-SQLite allowlist.
2026-07-25 07:15:44 -07:00
Peter Steinberger
97c57585a1 fix: preserve distinct imported session messages (#113703)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 07:12:43 -07:00
Peter Steinberger
cb628df199 fix: recognize configured plugin dependencies by manifest id (#113691)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 07:05:44 -07:00
Peter Steinberger
d1b534d7fa docs(heartbeat): align retired config options with fixed runtime policies (#113455)
The runtime retirement already shipped: busy deferral is automatic,
reasoning payloads stay internal, the HEARTBEAT_OK ack budget is fixed at
300 chars, the Heartbeats prompt section follows cadence, and tool-error
warnings are always on. Docs still advertised skipWhenBusy, ackMaxChars,
includeReasoning, includeSystemPromptSection, and suppressToolErrorWarnings
as live options; this aligns seven pages with the fixed policies and the
strict heartbeat field list, locks the claw-profile skipWhenBusy rejection
diagnostic with a dedicated test, renames includeReasoning-era test/comments,
and canonicalizes claw add-plan workspace path assertions (macOS realpath).
2026-07-25 06:52:27 -07:00
Peter Steinberger
89984a5082 fix: preserve child process signal exit codes (#113685)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 06:51:49 -07:00
Peter Steinberger
49f223e190 fix(delivery): apply correct outbound recovery retry delays (#113700)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 06:49:33 -07:00
Peter Steinberger
4aeb426d2d fix: route skill verification through the managed proxy (#113683)
Co-authored-by: Peter Steinberger <steipete@golden-gate.local>
2026-07-25 06:39:57 -07:00
Peter Steinberger
1dcb35b204 refactor(agents): split main session recovery (#113687) 2026-07-25 13:39:15 +00:00
Peter Steinberger
46a1338918 refactor(infra): split heartbeat runner (#113668)
* refactor(infra): split heartbeat runner

* refactor(infra): keep heartbeat helpers private
2026-07-25 06:37:26 -07:00
Peter Steinberger
4c7e14f8af refactor(agents): simplify native hook relay split (#113675)
* refactor(agents): split native hook relay

* fix(agents): keep native relay contracts acyclic
2026-07-25 06:31:49 -07:00
609.sol
4e6ad11e37 fix(compaction): thread agent streamFn into safeguard summarizer (#112416)
* fix(compaction): thread agent streamFn into safeguard summarizer

The compaction safeguard summarizer invoked the model without the agent's
egress streamFn, so it fell back to the core HTTP client (completeSimple),
which builds the request from model.baseUrl. That field is empty ("") at
the core layer for OpenRouter-provider models — the real base URL is only
injected inside the provider plugin's stream function. The empty base URL
made the OpenAI SDK throw APIConnectionError, surfaced as
"Summarization failed: Connection error.", so safeguard compaction
summaries silently failed (the safeguard then preserved the verbatim
tail, masking it). Normal turns and the full/non-safeguard compaction
path were unaffected because they already thread streamFn.

Thread the agent's streamFn (the same this.agent.streamFn the core
compaction path passes into compact()) through the
session_before_compact event into summarizeViaLLM -> summarizeInStages
-> summarizeWithFallback -> summarizeChunks -> generateSummary, filling
the existing streamFn slot on the underlying summarization completion.
Minimal optional-param plumbing; safeguard tail-preservation behavior is
unchanged.

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

* fix(compaction): preserve safeguard model execution context

* test(compaction): use canonical stream type export

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 06:25:43 -07:00
Patrick Erichsen
559bc2adc8 feat(skills): support external skills.sh references (#112751) 2026-07-25 08:24:34 -05:00
Peter Steinberger
e52222cdef refactor(agents): split code mode execution (#113669)
* refactor(agents): split code mode execution

* refactor(agents): keep code mode bridge type private
2026-07-25 06:22:25 -07:00
Ahmed Tarek
8cb749ad23 fix(sessions): always protect agent primary main session from maintenance eviction (#112640)
* fix(sessions): always protect agent primary main session from maintenance eviction

capEntryCount computes maxRemovableEntries = maxEntries - preservedCount. When
protected thread/channel entries reach maxEntries, the only removable entry is
the unprotected agent:<id>:main session, so routine maintenance deletes the
operator's live TUI/webchat session out from under an in-flight run (surfacing
as "session file changed while embedded prompt lock was released"). The same
cap pressure also breaks subagent spawns.

Treat agent:<id>:main as always protected in isProtectedSessionMaintenanceEntry,
alongside existing thread/channel/topic protection.

Closes #112637

* fix(sessions): cover global primary session maintenance

* fix(sessions): preserve admitted sqlite sessions

* fix(sessions): preserve logical admission scope

* fix(sessions): align stale maintenance preflight

* test(sessions): keep maintenance preflight private

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 06:22:11 -07:00
Peter Steinberger
504e5bbf89 perf(agents): compact JSON in commitments and heartbeat prompts (#113657) 2026-07-25 06:19:01 -07:00
Peter Steinberger
71e8f6a925 refactor(infra): split session cost usage accounting (#113670) 2026-07-25 06:15:19 -07:00
ralf003
123ba75ff0 fix(agents): extract Undici cause.code for ECONNRESET/ECONNREFUSED/ETIMEDOUT (#110485)
* fix(transport): extract error code from cause.code for Undici network errors

* fix(transport): traverse nested error causes

---------

Co-authored-by: Altay <altay@hey.com>
2026-07-25 15:47:41 +03:00
Peter Steinberger
43c608e5fd refactor(agents): split native hook relay (#113626)
* refactor(agents): split native hook relay

* refactor(agents): preserve native relay API

* refactor(agents): keep relay state private

* refactor(agents): break relay type cycles
2026-07-25 05:37:54 -07:00
Peter Steinberger
4bfb26415a feat(agents): explicit per-surface agent targets + default-role materialization (#113637)
* refactor(agents): add explicit ambient target seams

* fix(doctor): materialize ambient default-agent roles

* fix(agents): satisfy dependency and docs checks

* chore: leave agent release note to release process

* test(agents): prove shared heartbeat fan-out survives doctor
2026-07-25 05:37:41 -07:00
ooiuuii
f3d94d2302 fix(mcp): retry failed tool catalogs after recovery (#111962)
* fix(mcp): retry failed tool catalogs

* fix(mcp): expose expired catalogs to combined runtimes

* fix(mcp): retry catalogs in background

* test(mcp): use tracked retry temp directory

* test(mcp): share automatic temp cleanup

* fix(mcp): preserve warm catalog snapshots

* fix(mcp): retry only failed catalog servers

* style(mcp): format retry assertion

* style(mcp): simplify catalog seed spread

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-25 05:37:16 -07:00
Peter Steinberger
b06f40a821 refactor(plugin-sdk): share ingress lifecycle fan-in (#113648)
* refactor(channels): share ingress lifecycle fan-in

* chore(plugin-sdk): refresh ingress API baseline
2026-07-25 05:34:35 -07:00
Peter Steinberger
332006bc1f test: consolidate OpenClaw test state fixtures (#113576)
* test: consolidate OpenClaw test state fixtures

* 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: use SDK test-state seam in extensions

Route bundled extension suites through the focused repo-local Plugin SDK test-state entrypoint and remove the Codex projector harness exports made stale by fixture consolidation. Keep the seam out of production builds and published package artifacts while auditing its real consumers in the full-tree deadcode scan.

* test(plugins): map test-state in package boundaries
2026-07-25 05:30:52 -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