Commit Graph

69027 Commits

Author SHA1 Message Date
Alix-007
3009338a9a fix(e2e): stop multi-node health checks hanging past deadline (#108065)
* fix(e2e): bound multi-node health probes

* test(e2e): track multi-node timeout temp files
2026-07-15 22:47:43 -07:00
Peter Steinberger
da59d6ade9 feat(onboarding): detect local inference providers (#108605)
* feat(onboarding): detect local inference providers

* fix(onboarding): satisfy inference choice lint

* chore(i18n): refresh onboarding locales

* chore: leave changelog to release automation

* chore(plugin-sdk): refresh API baseline

* fix(onboarding): preserve source config during local activation
2026-07-15 22:46:16 -07:00
Alix-007
5a2bc73c28 fix(qa-lab): keep suite HTTP probes within deadlines (#108064)
* fix(qa-lab): bound suite HTTP probes

* style(qa-lab): format gateway timeout proof

* test(qa-lab): pin media deadline request count
2026-07-15 22:45:30 -07:00
krissding
c924819292 fix(sessions): stop leaking file path as prompt content on read failure (#108546)
* fix(sessions): stop leaking file path as prompt content on read failure

When readFileSync fails for a valid file path, resolvePromptInput returns
the raw path string as prompt content instead of undefined. This injects
filesystem paths into the LLM context. The existing console.error warning
still fires; the caller already handles undefined returns correctly.

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

* test: cover unreadable prompt paths

* test: use tracked resource loader temp dirs

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-15 22:42:03 -07:00
Peter Steinberger
a6125b7868 perf(ci): split QA smoke into four profile parts and time tsdown invocations (#108638) 2026-07-15 22:41:02 -07:00
SunnyShu
164f33de91 fix(agents): cleanup leaked toolStartData entries on unsubscribe (#108403)
* fix(agents): cleanup leaked toolStartData entries on unsubscribe

toolStartData module-level Map only deleted entries on
handleToolExecutionEnd; crashed/aborted/unsubscribed tool executions
left leaked entries, inflating countActiveToolExecutions.

Ref: BUG-043 (local finding)
Co-Authored-By: Claude <claude@anthropic.com>

* test(agents): cover tool start cleanup on unsubscribe

* fix: sort imports in unsubscribe-tool-start test

---------

Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-15 22:40:59 -07:00
Alix-007
e60ebbc63b fix(ci): bound fallback Node downloads (#108166) 2026-07-15 22:40:39 -07:00
Peter Steinberger
bae9752c5a refactor(deadcode): enforce repository hard zero (#108641) 2026-07-15 22:40:00 -07:00
moguangyu5-design
cf8cfa8322 fix(gradium): keep isConfigured from throwing on invalid baseUrl (#108551)
* fix(gradium): keep isConfigured from throwing on invalid baseUrl

* refactor(gradium): narrow configuration validation

Co-authored-by: moguangyu5-design <moguangyu5-design@users.noreply.github.com>

---------

Co-authored-by: moguangyu5-design <moguangyu5-design@users.noreply.github.com>
Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-15 22:38:52 -07:00
wahaha1223
fbc5529fbf fix(push): parse APNs relay timeout as strict decimal (#107883)
Co-authored-by: Peter Steinberger <peter@steipete.me>
2026-07-15 22:37:37 -07:00
qingminlong
49410a2399 fix(proxy-capture): preserve small bodies with non-decimal content length (#108292)
* fix(proxy-capture): preserve small bodies with non-decimal content length

* fix(proxy-capture): align declared length guard

* fix(proxy-capture): preserve huge content lengths

* style(proxy-capture): format length guard

---------

Co-authored-by: Peter Steinberger <peter@steipete.me>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-15 22:36:39 -07:00
Alix-007
24e96bd8c1 fix(qa-lab): prevent Slack desktop bootstrap hangs (#108161)
* fix(qa-lab): bound Slack installer downloads

* fix(qa-lab): bound Slack installer retry window
2026-07-15 22:35:24 -07:00
Peter Steinberger
e7cba0e4d5 fix: provider dead exports no longer block changed checks (#108592)
* fix(ci): clean provider dead exports

* test(extensions): satisfy provider contract types

* refactor(openai): tighten provider runtime factory
2026-07-15 22:33:54 -07:00
Alix-007
527711d27c fix(crabbox): bound IMDS identity checks (#108165) 2026-07-15 22:32:29 -07:00
zengLingbiao
774cd25aa6 fix(transcript-stream): propagate non-missing filesystem errors (#106412)
* fix(transcript-stream): log stat/open errors instead of silently returning empty iterator

streamSessionTranscriptLines and streamSessionTranscriptLinesReverse
used bare catch { return; } blocks that silently swallowed all fs errors
(permission denied, I/O error, etc.) and returned empty iterators. This
made it impossible to diagnose why transcript streaming failed.

Replace catch { return; } with catch (err) { transcriptLog.warn(...); return; }
so failures are visible in diagnostics.

* fix(transcript-stream): exclude ENOENT from warning logs in stat/open catch blocks

Both streamSessionTranscriptLines and streamSessionTranscriptLinesReverse
caught all fs errors and logged warnings, but ENOENT is an expected empty-
iterator case for these best-effort readers. Filter ENOENT before logging
so missing transcripts stay silent while permission/I/O errors surface.

Added deterministic regression tests with mocked fs.promises.stat/open:
- EACCES triggers a warning in both forward and reverse directions
- ENOENT stays silent in both directions

* fix(transcript): propagate session read failures

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-15 22:29:08 -07:00
keshavbotagent
9f5609382b fix(telegram): preserve tool progress under preambles (#108394)
* fix(telegram): keep tool rows below progress preambles
* fix(telegram): preserve text tool progress under preambles
* fix(telegram): preserve memory progress under preambles

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-07-16 10:48:53 +05:30
Peter Steinberger
4b61b02d5b fix(zai): use documented thinking payload (#108633) 2026-07-15 22:18:02 -07:00
Peter Steinberger
8c95491039 fix: Claude catalog terminals bypass failed npm shims (#108627)
* fix(anthropic): prefer native Claude catalog terminals

* chore: keep release notes in PR body
2026-07-15 22:17:02 -07:00
Peter Steinberger
6bbb99b918 fix(discord): preserve forum targets for CLI plugin tools (#108628)
* fix(agents): preserve plugin delivery target

* fix(agents): prefer routable plugin target
2026-07-15 22:16:59 -07:00
Peter Steinberger
bdcf6bdfdd feat(gateway): deliver plugin approvals to paired iOS devices via APNs (#108505)
* feat(gateway): deliver plugin approvals to paired iOS devices via APNs

Generalize the exec-approval iOS push delivery into a shared driver so plugin
approvals also raise an APNs notification on paired operator devices (which iOS
mirrors to a paired Apple Watch). Reuses the operator.approvals scope gate,
direct/relay transport, and stale-registration cleanup. Wires push into both
plugin-approval origination points (the plugin.approval.request RPC and the
node.invoke policy path) alongside the existing chat forwarder; adds a
plugin.approval.* APNs payload/category with a description body truncated to
256 UTF-16-safe chars and no secret-bearing fields.

* fix(gateway): drop unused export on plugin approval push category
2026-07-15 22:12:49 -07:00
Peter Steinberger
83a4208aed fix(codex): full-auto approvals survive relay unavailability, typed failure classification, usage line after fallback (#108626)
* fix(codex): full-auto approvals survive relay unavailability, typed failure classification, usage line after fallback

- full-auto (approvalPolicy never + danger-full-access) exec approvals no
  longer get declined when the native hook relay is unreachable BEFORE
  invocation; an invoked relay's explicit deny, malformed output, or nonzero
  exit still fails closed (#107447)
- startup timeout/abort and request-timeout classification use typed error
  discriminants instead of message prose; EPIPE detection walks error causes;
  compaction keeps the message-based thread-not-found gate because codex-rs
  exposes no dedicated code (its own contract test asserts the message) and
  the generic -32600 would over-match unrelated invalid requests (#99270)
- /status keeps the Codex usage/quota line for sessions whose persisted
  agentHarnessId is codex even when the effective runtime fell back to
  OpenClaw Default; never-codex sessions remain excluded (#105184)

* chore(codex): keep startup error reason type module-local
2026-07-15 22:12:35 -07:00
Peter Steinberger
5bfcd779b1 fix(ui): local sessions show no placement icon (#108615)
* fix(ui): distinguish cloud worker sessions

* chore: defer session icon release note

* fix(ui): keep placement helper private
2026-07-15 22:05:09 -07:00
Peter Steinberger
513200125d feat(channels): render live plan checklists from typed update_plan snapshots (#108597)
* feat(channels): render live plan checklists from typed update_plan snapshots

Codex, Copilot, CLI, and embedded update_plan events now carry typed
{step, status} snapshots end to end instead of flattened strings. Slack,
Discord, Telegram, Matrix, and MS Teams render a live checklist in
progress drafts; Slack native task cards show the real plan with
position-keyed rows and id reconciliation. The embedded update_plan tool
is default-on for every model (tools.experimental.planTool: false opts
out). The shipped onPlanUpdate steps: string[] SDK field stays populated
during a deprecation window alongside the canonical planSteps.

* fix(auto-reply): align plan bridge types with SDK callback contract

* fix(auto-reply): split agent event bridge module and fix plan type boundaries

* fix(channels): satisfy oxlint on plan checklist helpers
2026-07-15 22:00:21 -07:00
Peter Steinberger
91332739f7 fix(ui): hide empty offline nodes from native session groups (#108620)
* fix(ui): hide empty offline session hosts

* chore: keep release changelog owner-only
2026-07-15 21:59:42 -07:00
Peter Steinberger
9ff855db05 fix(plugins): canonicalize plugin entry path per process to prevent duplicate register() (#108508)
On git-channel installs where both extensions/<id>/index.ts and
dist/extensions/<id>/index.js exist, two registry assemblies resolved the same
plugin id to different physical files (preferBuiltPluginArtifacts drives both the
artifact choice and the load-cache key), so the path-keyed module cache
evaluated the entry twice — two live plugin instances with separate state,
binding hooks to one and registerTool to the other. Memoize the first resolved
runtime entry path per plugin-id + real root + entry-kind so both assemblies
converge on one module instance; clear the memo on activated-runtime-state and
registry-load-cache resets so reload/install/doctor re-resolve. No-op on
dist-only installs.

Closes #107933
2026-07-15 21:58:13 -07:00
Jason (Json)
ca52d54da2 fix(onboarding): preserve OAuth across runtime defaults (#108617)
Merged via squash.

Prepared head SHA: 366fdedacf
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Reviewed-by: @fuller-stack-dev
2026-07-15 22:55:32 -06:00
Peter Steinberger
fdd1acb328 fix(ui): attach terminal tab close button to its tab (#108611)
The web terminal's per-tab close control rendered as a detached floating
square next to the tab. It now joins the tab as one surface: shared hover
background, active accent underline continuing beneath it, full tab
height, with its own rounded inner highlight on hover.
2026-07-15 21:33:25 -07:00
Peter Steinberger
61f8324682 fix(zai): use documented completion token field (#108612) 2026-07-15 21:32:49 -07:00
Peter Steinberger
c8c2b206e8 improve: speed up targeted regression suites (#108609)
* test: speed up targeted regression suites

* test: preserve subprocess startup headroom

* test: keep secops-owned auth coverage unchanged
2026-07-15 21:29:48 -07:00
Peter Steinberger
2ab4f9f370 fix(discord): resolve forum thread activity targets (#108603)
* fix(discord): resolve activity thread targets

* chore: keep changelog release-owned
2026-07-15 21:29:34 -07:00
Eden
8a141549f2 fix(line): keep group history recorded during a mention turn (#107367)
* fix(line): keep group history recorded during a mention turn

Group history cleanup ran a whole-key clear after each mention turn. Because
webhook dispatch is fire-and-forget, a plain (unmentioned) message can be
recorded while the agent is still handling a mention; the post-turn clear then
wiped the whole window, silently dropping that concurrent message from the
next turn's context.

Snapshot the identity keys the turn consumes up front and clear only those,
retaining anything recorded concurrently. The record path now stamps the LINE
message id so entries have a stable identity. Cleanup stays after the turn, so
a failed turn still leaves history intact for the retry. The snapshot/clear
helpers live in group-history.ts, next to the other group modules.

* test(line): cover group history retention when a mention turn fails

Assert that a mention turn whose processMessage throws leaves the group
history window intact (cleanup runs only after a successful turn), so the
retry still has the ambient context. Red/green verified: moving the cleanup
before the await fails this test.

* fix(line): capture consumed group history at the context read boundary

The consumed-key snapshot ran before media download and context
construction, while buildLineMessageContext copied the window later.
A plain message recorded between those awaits was included in the
turn's InboundHistory yet missing from the consumed set, so cleanup
retained it and the next mention received it twice.

Read the window and capture its identity keys in one synchronous step
in the handler (snapshotLineGroupHistory), then pass the materialized
inboundHistory into buildLineMessageContext instead of the live map.
The consumed set is now derived from the exact entries the turn reads,
so an entry is either in the context and cleared, or recorded later
and retained - there is no window where both can be true.

Regression tests park a mention turn inside context construction,
record an ambient message mid-window, and assert it stays out of that
turn's InboundHistory, survives cleanup, and is consumed exactly once
by the next mention. Red/green verified against the previous snapshot
placement.

* test(line): point history-window guardrail at group-history.ts

The group-history cleanup fix moved the createChannelHistoryWindow facade
call out of bot-message-context.ts (which now receives inboundHistory as a
parameter) into the new group-history.ts. Update the cross-channel
historyWindowFiles ledger to match, mirroring telegram's group-history-window.ts
entry already in the same list. Fixes the message-turn-guardrails 'keeps
migrated history users on the channel history window facade' assertion that
build-artifacts flagged.

* fix(line): reserve history across concurrent turns

Co-authored-by: Eden <146086744+edenfunf@users.noreply.github.com>

* test(line): complete webhook message fixtures

* test(line): use explicit token placeholders

* refactor(line): keep reservation type private

* refactor(line): render reservations through history facade

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-15 21:27:23 -07:00
Peter Steinberger
251b6f8d8c perf(ci): parallel format check and build-input-precise artifact gating (#108594) 2026-07-15 21:12:55 -07:00
Peter Steinberger
c077e801dd refactor(memory-core): split manager sync operations (#108583) 2026-07-15 21:12:22 -07:00
Josh Avant
4b7f193c9d fix: gateway-owned work fails through same-host relay (#108423)
* fix(gateway): dispatch owned runtime work in process

* fix(gateway): publish canonical approval resolutions internally

* fix(gateway): seal owned approval runtime lifecycle

* fix(gateway): keep instance runtime contracts acyclic

* fix(gateway): remove stale runtime type imports

* fix(agents): reconcile ambiguous recovery timeouts

* refactor(gateway): constrain internal approval methods

* fix(agents): route orphan recovery in process

* fix(agents): preserve aborted restores for recovery

* fix(agents): keep lifecycle waits in process

* test(agents): type lifecycle runtime mock

* test(agents): complete restored session fixture
2026-07-15 20:51:57 -07:00
Peter Steinberger
de3f7925c4 test(release): harden QA and live validation (#108589) 2026-07-15 20:45:36 -07:00
Peter Steinberger
957cc81175 test: speed up slow unit and browser coverage (#108563) 2026-07-15 19:59:16 -07:00
Peter Steinberger
7f9d519fcb fix(ci): repair provider fold validation (#108564)
* fix(ci): repair provider fold validation

* fix(qa): model debugger web entry
2026-07-15 19:49:02 -07:00
Dallin Romney
652c6444b3 fix(qa): enforce scenario lane contracts (#108539) 2026-07-15 19:48:09 -07:00
Dallin Romney
04221fc91e chore(qa): remove retired Matrix package guards (#108531) 2026-07-15 19:28:37 -07:00
Peter Steinberger
154d1277e1 fix(qa): repair package Telegram harness boundaries (#108499)
* fix(qa): keep packaged entry off private transport

* fix(qa): lazy-load private transport runtime

* fix(qa): pass relative package artifact path

* fix(qa): isolate packaged bus protocol

* fix(qa): mount package scenario catalog
2026-07-15 19:24:55 -07:00
Peter Steinberger
08ecf63bb6 fix(deadcode): resolve strict-workspace fallout from bundled plugin roots
The strict knip workspaces landed in #108547 flagged seven files. Two are
convention-resolved and become explicit entries (discord configured-state via
the package-state probes, qa-lab cli via the SDK facade basename resolver);
the other five were dead barrels/wrappers superseded by canonical modules and
are deleted (browser bridge/cdp barrels, discord timeouts wrapper, openai
register.runtime, qa-lab model-selection wrapper).
2026-07-16 03:08:17 +01:00
Peter Steinberger
d42dfed3f2 chore(codex): format usage module, fix marker import in test 2026-07-16 03:06:48 +01:00
Peter Steinberger
7864a6e6ad fix(codex): import ProviderUsageSnapshot from provider-usage 2026-07-16 03:06:47 +01:00
Peter Steinberger
7eeb1096db fix(codex): re-home app-server usage reporting on the harness seam
The deleted text provider's usage hook was the only source for the /status
Codex subscription usage line. Harnesses can now contribute an optional
usage snapshot (provider hooks keep priority; only distinct synthetic hook
owners fall through), and the codex harness reports app-server rate limits
via account/rateLimits/read with the same conversion and account identity
as before. No text provider resurrected; deadcode and SDK surface gates
clean.
2026-07-16 03:06:47 +01:00
Peter Steinberger
9c5eab471c chore(doctor): format migration tests, keep cron migration helpers module-local 2026-07-16 03:06:46 +01:00
Peter Steinberger
1491977816 test(doctor): surface the blocked-provider warning through the real route-warnings path
The preview test mocked codex-route-warnings wholesale; the consolidated
blocked-merge warning now flows through it, so the auto-merge case runs the
actual implementation once. Migration identity helpers stay module-local;
codex-route-model-ref formatting fixed.
2026-07-16 03:06:45 +01:00
Peter Steinberger
ea0fe35265 fix(codex): post-fold media route signal, drop unused migration exports
- codex media substitution keys on the registered media-understanding
  provider (image capability + default model) instead of the deleted text
  provider's synthetic auth probe; deterministic injected route in tests
- migration helper exports without production consumers are module-local;
  the blocked-provider warning assertion goes through the plan export
2026-07-16 03:06:45 +01:00
Peter Steinberger
fabdfc90db chore(protocol): regenerate Swift gateway models for agentRuntime 2026-07-16 03:06:44 +01:00
Peter Steinberger
6bcb561012 fix(codex): repair identity-fold CI fan-out
- null-vs-undefined runtime record type at the provider-move helper
- gateway models.list fixtures expect the new agentRuntime intent field
  (codex/implicit for policy-backed OpenAI routes, openclaw/implicit for
  synthetic routes without provider policy)
- split doctor cron legacy-repair into its own module to satisfy the
  max-lines gate without suppressions; callers import directly
2026-07-16 03:06:43 +01:00
Peter Steinberger
3c8269ca52 refactor(codex)!: fold the codex text provider into openai with a doctor migration
The live codex text provider was a redundant projection of the openai
catalog (exclusive provider ownership; the openai plugin's ChatGPT OAuth
discovery already serves gpt-5.6-* route-aware). Folding it:

- extensions/codex no longer registers a text provider, catalog entry, or
  synthetic text auth; provider.ts/provider-catalog.ts/provider-discovery.ts
  and the route-blind model-name heuristics are deleted; the narrow
  post-harness reasoning fallback moves to an app-server-owned module
- openai thinking policy keys on explicit selected-route provenance
  (api === openai-chatgpt-responses) instead of value-shape inference
- models.list gains an optional additive agentRuntime field (configured
  intent); session agentHarnessId remains the execution proof
- doctor --fix migrates the shipped codex/* config shape end to end:
  every model slot, provider-config merge with blocker-aware conflict
  handling, sessions, cron payloads (two-phase: runtime policy persists
  before cron refs rewrite), transcripts; migrated refs carry model-scoped
  agentRuntime.id=codex preserving the shipped wizard semantics; auto
  runtime policies normalize to codex with sibling fields preserved;
  blocked provider conflicts retain the whole legacy namespace fail-closed
  with an actionable warning
- the stale openai:default profile cleanup (#91352) was deliberately
  deferred to a follow-up after review showed it needs per-agent identity
  proofs; doctor keeps warning about unusable profiles

Fixes #105561
Fixes #84637
Fixes #90420
2026-07-16 03:06:43 +01:00