Commit Graph

15904 Commits

Author SHA1 Message Date
Vincent Koc
ee6d6e7e78 refactor(extensions): remove dead local exports (#107146) 2026-07-14 13:09:20 +08:00
Peter Steinberger
9c2dc92dd8 refactor(msteams): trim internal exports (#107148) 2026-07-13 22:01:56 -07:00
Peter Steinberger
05fb55eb7b feat: discover OpenCode and Pi sessions on paired nodes (#106941)
* feat(sessions): add opencode and pi catalogs

* fix(sessions): satisfy catalog lint

* fix(sessions): validate pi storage paths

* fix(sessions): index growing pi transcripts

* refactor(sessions): split pi path resolution

* docs(sessions): refresh catalog map

* refactor(sessions): privatize pi catalog internals

* fix(sessions): validate node catalog payloads

* fix(sessions): harden external catalog discovery

* fix(sessions): normalize catalog transcript data

* refactor(gateway): keep node scope gate compact

* fix(opencode): reject option-like session ids

* fix(sessions): align external id validation
2026-07-13 21:45:53 -07:00
Peter Steinberger
111b3a157e refactor(codex): use native SemVer floor comparison 2026-07-13 21:42:23 -07:00
Peter Steinberger
1dc9d47130 refactor(voice-call): remove dead internal exports (#107130) 2026-07-13 21:42:11 -07:00
mushuiyu886
ef25cefc8e fix(onepassword): validate audit limit strictly (#106926)
* fix(onepassword): validate audit limit strictly

* test(onepassword): strengthen audit limit coverage

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 21:37:07 -07:00
Peter Steinberger
0ecbbe2382 fix(workboard): keep dispatch inside caller workspace authority (#107087)
* fix(workboard): inherit caller workspace authority

* docs(plugin-sdk): refresh API baseline

* fix(workboard): pin restricted worker authority

* fix(workboard): avoid host git for restricted dispatch

* refactor(worktrees): extract owner matching

* refactor(workboard): reuse sdk workspace helpers

* fix(workboard): narrow cleanup owner

* refactor(workboard): clarify claim value handling

* fix(workboard): inherit caller workspace authority

* test(worktrees): use managed temp directories

* chore: keep release notes in PR body

* fix(workboard): keep internal authority helpers private
2026-07-13 21:36:26 -07:00
Peter Steinberger
80399ed19b refactor(matrix): trim internal exports (#107126) 2026-07-13 21:33:55 -07:00
Peter Steinberger
37c7de0148 refactor(ai): remove redundant tool argument finalization 2026-07-13 21:17:38 -07:00
Peter Steinberger
27f2a45c54 fix(onboarding): harden live inference handoff (#107041)
* fix(onboarding): harden live inference handoff

* fix(crestodian): preserve auto runtime probes

* fix(ci): restore current main lint gates
2026-07-13 21:15:36 -07:00
Peter Steinberger
689edddd34 fix(mattermost): restore strict test lint after refactor (#107079)
* test(mattermost): satisfy strict lint contracts

* test(mattermost): type partial response fixture
2026-07-13 21:09:35 -07:00
Peter Steinberger
c853064a42 refactor(microsoft): simplify Edge TTS output staging 2026-07-13 21:03:51 -07:00
Peter Steinberger
8d465d71b5 fix(channels): progress drafts only for long tasks, with the model's own preamble as the status headline (#106026)
* fix(channels): time-gate progress drafts and defer narration until visible

Progress drafts started immediately on the second work event, so the 5s
initial delay never filtered small fast tasks and Discord showed narrated
status for turns that finish in seconds. The gate is now purely time-based
(explicit startNow paths like approvals/patches are unchanged), and the
progress narrator no longer spends utility-model completions before the
channel draft is visible - notes buffer so the first visible narration has
full context.

Surface: src/channels/streaming.ts gate, src/auto-reply/reply/progress-narrator.ts,
Discord draft-preview wiring; test updates across discord/matrix/msteams/slack.

Refs #105872

* feat(channels): model-preamble status headline for progress drafts

In progress mode the draft's status line is now the model's own typed pre-tool
preamble whenever it is fresh (always on, no new config); utility-model
narration fills the slot only when the model has been quiet for ~20s or emits
no preamble. Preambles never start the draft early - the time gate still owns
the small-vs-big decision - and narration generation is suppressed while a
fresh preamble exists, saving utility calls. Discord and Telegram render the
headline; the opt-in streaming.progress.commentary lane and its receipt
counters are unchanged.

Refs #105872

* refactor(channels): split status-text and telegram preview helpers to honor the LOC ratchet

The LOC ratchet forbids raising baseline entries, so the headline feature's
growth is paid for with clean splits: reasoning/commentary text normalization
moves to src/channels/progress-draft-status-text.ts, Telegram progress preview
rendering to extensions/telegram/src/progress-draft-preview.ts, and small
ownership moves (formatCompactionModelRef, resolveFollowupAbortSignal, shared
CLI preamble gate, Discord preamble item-event handling) shrink the runners
back under their pins. Baseline entries lowered to exact new counts; the
compositor entry is removed (424 lines, under the 500 ceiling).

Refs #105872

* test(auto-reply): add resolveFollowupAbortSignal to the queue mock factory

The explicit ./queue.js vi.mock factory must export every binding prod touches;
the relocated resolveFollowupAbortSignal was missing and failed the whole
followup-runner suite.

Refs #105872

* fix(channels): sanitize preamble headlines and retry skipped narration

Review findings: preamble headlines now strip inline delivery directives and
reject silent-control tokens (NO_REPLY) before rendering, sharing the
commentary sanitizer; rejected input keeps the previous valid headline. The
narrator schedules cancellation-aware retries when a run is skipped for draft
invisibility or preamble freshness, so single long tool calls still narrate
and the ~20s utility filler fires without needing another event. Silent
preambles no longer stamp freshness or add narration notes.

Refs #105872

* fix(channels): bound narrator visibility polling and gate Telegram headline mode on accepted preambles

Visibility retries stop after 30 one-second attempts (turn completion has no
narrator disposal signal) and re-arm on new activity; Telegram derives its
headline-rendering state from the compositor's sanitized headline instead of
raw payload text, so directive-only or NO_REPLY preambles keep structured
tool-line rendering. Docs scope the preamble headline to Discord and Telegram.

Refs #105872

* fix(telegram): read headline state from the compositor at render time

The progressHeadlineActive mirror flag was set after pushPreambleHeadline had
already rendered, so the first valid preamble arriving after the draft opened
rendered through the structured-line path and the headline never appeared
until the next event. The renderer and formatLine now read the compositor's
sanitized hasStatusHeadline directly and the mirror flag is deleted; adds an
ordering regression test. LOC baseline lowered to the exact new count.

Refs #105872

* fix(channels): let the opt-in commentary lane own preambles and scope narration docs to Discord

With streaming.progress.commentary enabled, the status headline would replace
the documented interleaved 💬 lines for any turn with a preamble (the exact
event the lane consumes). The compositor headline now declines when the
commentary lane is enabled, preserving that lane's shipped shape, and docs
state the utility-model filler is Discord-only today (Telegram's headline is
preamble-only; it has no narrator wiring).

Refs #105872

* fix(msteams): cancel the pending progress gate at finalize

With the purely time-based gate, every fast Teams progress turn leaves a
pending 5s start timer; the SDK resets its stream id on close, so a late
timer fired renderInformativeUpdate against the closed stream and posted a
stale working card below the final answer. finalize() now cancels the gate
and the informative renderer refuses to run once final text is queued.

Refs #105872

* docs(channels): record the headline-vs-commentary ownership decision inline

Refs #105872

* style: oxfmt the late review-fix rounds

Four files from the final review-fix commits were never oxfmt-formatted and
failed the shared CI formatting step; baseline lowered for the one-line
telegram shrink.

Refs #105872

* fix(channels): harden progress draft lifecycle

* fix(channels): refresh repeated preamble items

* fix(plugin-sdk): expose progress lifecycle options

* style(auto-reply): simplify narrator reset

* docs(channels): refresh progress draft docs map

* fix(auto-reply): clear queued narrator request context

* fix(discord): cancel delayed progress gate at final

* docs: refresh plugin sdk api baseline
2026-07-13 20:55:44 -07:00
Peter Steinberger
53f6212488 test(mattermost): fix slash response mock type (#107084) 2026-07-13 20:48:34 -07:00
Peter Steinberger
c19b7d2823 refactor(mattermost): trim internal exports (#107062) 2026-07-13 20:27:52 -07:00
Peter Steinberger
604eb6af2d refactor(concurrency): use native p-limit APIs 2026-07-13 20:23:00 -07:00
Peter Steinberger
4da0eb19c5 fix(state): converge legacy startup migrations (#107002)
* fix(state): converge legacy startup migrations

Co-authored-by: Eva <eva@100yen.org>

* refactor(state): split legacy migration helpers

* fix(memory): persist legacy source acknowledgements

* fix(state): remove stale migration imports

* fix(memory): recognize numbered migration archives

* fix(matrix): downgrade archived migration residue

* fix(memory): satisfy migration lint

---------

Co-authored-by: Eva <eva@100yen.org>
2026-07-13 20:05:24 -07:00
Peter Steinberger
069616f33b feat(discord): notify agents of voice participant changes (#107004)
* feat(plugin-sdk): support keyed system event upserts

* feat(discord): notify agents of voice participant changes

* refactor(plugin-sdk): consolidate system event replacement

* fix(discord): keep voice listener dependencies acyclic

* chore: keep release changelog out of PR
2026-07-13 20:03:18 -07:00
Peter Steinberger
877af700bf feat(codex): continue paired-node Codex catalog sessions from the Control UI (#106927)
* feat(codex): continue paired-node Codex catalog sessions from the Control UI

Codex catalog rows on paired nodes were view-only. Node rows are now
continuable when the node advertises and permits the codex threads.list,
thread.turns.list, and cli.session.resume commands. Continue adopts the
session into a locked codex OpenClaw session (deterministic
harness:codex:node-session key, bounded native-history import, two-phase
initializing marker) and installs a webchat conversation binding
(codex-cli-node-session) through the new generic
bindPluginSessionConversation seam with attempt-ID guarded rollback, so
each web turn runs codex exec resume on the owning node via the existing
inbound_claim path. Local continue/archive semantics are unchanged;
archived rows are no longer offered as continuable.

* fix(plugins): serialize plugin session binds per session

Review P2: the bind rollback checked the attempt id and then awaited the
unbind, so a concurrent Continue could install a newer binding between the
two and lose it to the older attempt's rollback. All session binds for one
session key now queue through an in-process tail, so a failing attempt can
only ever roll back its own binding; the attempt-id guard stays as defense
against out-of-band rebinds.

* refactor(codex): extract node-continue and session-bind modules for the LOC ratchet

Pure movement to satisfy the changed-file TypeScript size ratchet: the
paired-node continue flow moves to session-catalog-node-continue.ts and
session-catalog-node-adoption.ts, catalog paging/parsing helpers to
session-catalog-parsing.ts, the Control UI session-bind seam to
session-conversation-binding.ts (+ session-key helpers), and the internal
conversation-id/channel-prefix helpers to utils. transcript-mirror.ts is
restored to main byte-for-byte; the node history builder constructs a plain
CodexThread (only id is required) instead of widening signatures.

* fix(plugins): satisfy preserve-caught-error in the session-bind rollback

* fix(codex): gate node continue on operator.admin and resume by CLI session id

Second review round: (1) bound node turns pass canMutateCodexHost only for
owners/admins, while sessions.catalog.continue is operator.write — a
write-scoped Control UI client could adopt a node session whose every turn
would then be rejected. The gateway now forwards the caller's scopes to the
provider (SessionCatalogContinueProviderParams.clientScopes) and codex fails
node continues closed without operator.admin, before the dedupe join so a
non-admin cannot ride an admin's in-flight operation. (2) The node binding
stored the app-server threadId, but codex exec resume takes the CLI session
id and forked threads share a session tree where the two differ; the binding
now prefers record.sessionId.

* fix(codex): defer node-session restore until the binding is durable

Third review round: continuing an archived adopted node session unarchived
it before the gateway installed the conversation binding, so a failed bind
left a visible session with no node routing. The unarchive now rides
afterConversationBound; finalizeNodeAdoptedSession already covers both the
initializing and finalized marker states, so the eager restore helper is
deleted.
2026-07-13 19:54:31 -07:00
Peter Steinberger
7f73f6e66e test(qa-lab): refresh CLI dispatch expectations (#107018) 2026-07-13 19:36:17 -07:00
Peter Steinberger
44fcbc612d refactor(qa-lab): trim dead export surface (#107016)
* refactor(qa-lab): narrow report and config exports

* refactor(qa-lab): keep live test seams private

* refactor(qa-lab): remove dead runtime wrappers

* chore(deadcode): refresh QA Lab export baseline
2026-07-13 19:32:13 -07:00
Peter Steinberger
6e067f7662 test: restore moving-main quality gates (#106972)
* test(agents): preserve caught abort cause

* refactor(browser): privatize route handler type

* test(lint): cover browser route override
2026-07-13 19:06:30 -07:00
Peter Steinberger
25a18b2d8e refactor(bonjour): use native ciao platform handling 2026-07-13 19:04:16 -07:00
Peter Steinberger
b828692089 refactor(webhooks): use native Zod schemas 2026-07-13 18:50:14 -07:00
Peter Steinberger
56e9d3b05f refactor(browser): scope async route lint exception 2026-07-13 18:37:46 -07:00
Peter Steinberger
b9c4815403 refactor(config): add canonical group-policy scope-tree resolver and migrate the first six channels (#106846)
* feat(config): add canonical group-policy scope-tree resolver

* chore(plugin-sdk): refresh API baseline hash for scope-tree exports

* refactor(channels): migrate googlechat, imessage, and whatsapp group policy onto the scope tree

* chore(plugin-sdk): refresh API baseline hash for groups scope-tree builder

* refactor(channels): migrate line, qqbot, and mattermost group policy onto the scope tree

* chore(plugin-sdk): refresh API baseline hash for case-insensitive scope key helper

* chore(plugin-sdk): refresh API baseline hash after rebase onto current main

* chore(plugin-sdk): refresh API baseline hash after rebase

* chore(plugin-sdk): refresh API baseline hash after rebase

* chore(plugin-sdk): refresh API baseline hash after rebase
2026-07-13 18:24:52 -07:00
Peter Steinberger
3442825e6b refactor(browser): use Express 5 async routes 2026-07-13 18:21:52 -07:00
sunlit-deng
7aa1aacb8e fix(reef): prevent oversized guard responses from consuming memory (#106439)
* fix(reef): bound guard provider response reads

* test(reef): strengthen guard response bound proof

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 18:02:11 -07:00
Marcus Castro
0934c445d3 refactor(whatsapp): use retryAsync for outbound delivery retries (#105579)
* refactor(whatsapp): reuse shared outbound retry runtime

* refactor(whatsapp): narrow outbound retry classification

* refactor(whatsapp): remove obsolete sleep export
2026-07-13 21:19:32 -03:00
zw-xysk
bdd060a40c fix(slack): add 30s timeout to directory client API calls (#106643)
* fix(slack): add 30s timeout to directory client API calls

* fix(slack): bound directory lookups

* fix(slack): reject delayed lookup retries

* fix(slack): preserve directory timeout contract

* fix(slack): keep lookup policy internal

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 17:07:41 -07:00
Peter Steinberger
f693ac1b65 refactor(config): share canonical deep merge 2026-07-13 17:06:26 -07:00
Leon-SK668
5864fa2dbf fix(onepassword): preserve Unicode in audit reason truncation (#106424)
* fix(onepassword): preserve Unicode in audit reason truncation

* test(onepassword): strengthen Unicode audit boundary proof

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-13 17:01:14 -07:00
Vincent Koc
cb705226ff test(telegram): avoid promise executor return (#106900) 2026-07-14 07:38:48 +08:00
Peter Steinberger
d361b4ccb8 feat(reef): headless openclaw reef CLI for agent-driven registration and pairing
Adds a non-interactive command surface (openclaw reef register|status|friend code|request|list|remove) so an agent can claim a handle and manage guarded friendships when its owner asks, without the interactive wizard. --json emits machine-readable output for automation. Registration is crash-safe and idempotent: guard defaults are provider-coupled, the full config is validated before the single-use magic-link token is consumed, a duplicate-handle claim recovers by proving key ownership and reconciling the relay's request policy, the exchanged session is cached scoped to relay+email (never printed) so reruns recover, one state dir is pinned to one identity, and friend removal revokes both the pin and the allowlist entry. Manifest gains commandAliases/onCommands so the CLI resolves; docs cover the agent-driven path.
2026-07-13 16:23:13 -07:00
Peter Steinberger
33f4856875 refactor(telegram): privatize pure helper surface (#106892) 2026-07-14 00:21:51 +01:00
Marcus Castro
3f94c647f7 refactor(whatsapp): reuse SDK tool result helper (#105574)
* refactor(whatsapp): reuse SDK agent-tool utilities

* fix(whatsapp): preserve call audio cleanup errors
2026-07-13 20:19:59 -03:00
Vincent Koc
b952394bd0 fix(ci): heal current main blockers 2026-07-13 16:10:55 -07:00
Peter Steinberger
d5a9602b41 refactor(browser): privatize proxy request type (#106883) 2026-07-14 00:08:22 +01:00
Marcus Castro
3079ac27b2 fix(whatsapp): honor mediaUrls precedence in channel payloads (#105576)
* fix(whatsapp): align channel media payload precedence

* fix(whatsapp): unify reply payload media precedence

* refactor(whatsapp): reuse media URL normalization
2026-07-13 20:07:09 -03:00
Galin Iliev
93bad8de2a fix: restore GitHub Copilot turns and account context limits (#106198)
* fix: restore GitHub Copilot runtime routing

Refs #106170

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6053811e-f081-436b-8741-54c5cab6c016

* fix: bind Copilot metadata to resolved credentials

Refs #106170

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 6053811e-f081-436b-8741-54c5cab6c016

* refactor: split Copilot runtime helpers

* fix: satisfy Copilot runtime static gates

* fix: satisfy Copilot runtime lint

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Galin Iliev <galin.iliev@microsoft.com>
2026-07-13 16:04:34 -07:00
Peter Steinberger
055f6649f9 fix(web-readability): resolve relative article links 2026-07-13 15:49:57 -07:00
Vincent Koc
9f06eb23e8 refactor(googlechat): privatize monitor access helpers (#106871) 2026-07-14 06:44:42 +08:00
Peter Steinberger
2e0f6d5304 fix: recover browser routing and Discord voice context 2026-07-13 23:38:56 +01:00
Peter Steinberger
5c9e09af3a style(codex): format prompt projection 2026-07-13 15:32:59 -07:00
Peter Steinberger
51fece4960 fix(codex): preserve failure-path ownership 2026-07-13 15:32:59 -07:00
Peter Steinberger
323a9fbe29 refactor(codex): split app server run attempt 2026-07-13 15:32:59 -07:00
Peter Steinberger
4319ddbe8c feat(control-ui): import Codex and Claude Code memory (#106406)
* feat(control-ui): import coding assistant memory

* test(migrate): clean memory import temp dirs

* chore: move memory import note to PR body

* build: refresh memory import generated artifacts

* fix(control-ui): complete memory import checks

* build(control-ui): localize memory recovery labels

* fix(control-ui): harden memory import recovery

* refactor(migrate): keep memory import surfaces bounded

* fix(control-ui): use canonical agent row type

* fix(codex): drop dead migration type exports

* fix(migrate): restrict imported memory permissions

* fix(control-ui): preserve memory import recovery state

* fix(control-ui): retain memory import results

* build(control-ui): preserve translation memory history

* fix(control-ui): bind memory import state to agent

* fix(control-ui): unlock memory import after refresh

* test(gateway): preserve memory method suffix

* fix(migrate): bind reviewed memory imports

* fix(migrate): make memory imports retry-safe

* perf(ui): keep memory import lazy

* build: refresh generated artifacts after rebase

* chore: keep migration runtime within LOC guard

* build: refresh Swift protocol model
2026-07-13 15:30:06 -07:00
Peter Steinberger
4568606490 refactor(telegram): privatize doctor helpers (#106861) 2026-07-13 15:29:06 -07:00
Peter Steinberger
95da05ddce fix(oc-path): preserve JSONC insertion formatting 2026-07-13 15:25:53 -07:00
Peter Steinberger
dc8ef09bbe refactor(diagnostics-otel): keep extracted helpers private 2026-07-13 15:25:11 -07:00