Commit Graph
25 Commits
Author SHA1 Message Date
roboomp 378bc1aeca fix(collab): clip oversized arrays alongside strings in shrinkForReplication
Per #3740 review: many short strings (e.g. a tool result whose content array holds thousands of small text blocks) could sum past MAX_REPLICATED_PAYLOAD_BYTES without any individual field crossing the per-string floor, so the helper exited the truncation loop and shipped an oversized frame — the relay close/reconnect loop the helper was meant to prevent.

Replace the string-only truncation pass with a single walker that head-truncates strings AND head-clips arrays in one descent, driven by a concrete SHRINK_PASSES schedule that tightens both axes together. The final pass clamps every string to 64 B and every array to one element, so any payload converges. Add direct unit tests for shrinkForReplication covering: identity for small values, single-giant-string clamp, many-short-strings array clamp (no field above floor), and discriminator preservation on a fully-shrunk payload.
2026-06-28 17:18:10 +00:00
roboomp c577ffebdc fix(collab): cap replicated host frames so oversized entries do not loop the relay
CollabHost shipped the first entry of every snapshot-chunk batch unconditionally, and broadcast live entry/event frames verbatim, so a single multi-megabyte tool result (read/bash/search) overflowed the relay's per-frame maxPayloadLength. The relay closed the host's WebSocket with 1006 ("Received too big message"), CollabSocket treated 1006 as non-fatal and reconnected, the next guest hello triggered the same oversized send, and the host status line cycled "Collab relay connection lost, reconnecting…" indefinitely.

Add shrinkForReplication: any host->guest payload whose JSON exceeds MAX_REPLICATED_PAYLOAD_BYTES (1 MB) is deep-cloned with long strings head-truncated and an "[…N chars elided for collab session]" marker; otherwise the original reference passes through. Apply it to snapshot chunk entries, live entry broadcasts, and live event broadcasts (including large tool_execution_end results). Regression test stands up a Bun.serve relay with 8 MB maxPayloadLength and a snapshot containing a 5 MB entry; asserts the host stays connected, the snapshot train finalizes, and the guest sees the entry with the elision marker.

Fixes #3739
2026-06-28 17:10:41 +00:00
can1357 51a2a0342f test(coding-agent): implemented guest reconciliation and expanded testing for collaboration
- Introduced guest snapshot reconciliation to maintain host state consistency during session switching.
- Improved yield tool reliability by implementing incremental schema validation and strict parameter enforcement.
- Fixed a calculation edge case in the status line to prevent negative time values during activity tracking.
- Expanded the test suite with new validation for session interruption, collab state synchronization, and process error handling.
2026-06-28 09:52:44 +02:00
roboomp 9653e38526 fix(collab): close time_spent meter from guest's host-idle reconciler
Address PR review: collab guest reconciles a state frame with
isStreaming === false by stopping the loader when the host's
agent_end never reached us (typically across a reconnect). With the
new active-time meter, the same path also has to call markActivityEnd
or the per-session window stays open and time_spent ticks forever.

Extract the close logic as reconcileGuestIdleHostState so a unit test
can exercise it directly without bringing up the full host/relay
welcome train.
2026-06-27 21:07:02 +00:00
roboomp 68db2ce649 fix(tui): track active processing time for time_spent status segment
The time_spent segment rendered Date.now() - sessionStartTime, so an
idle session displayed hours of "time spent" while the agent did
nothing — the only inputs were wall-clock and the unmoving session
start.

Replace sessionStartTime with activeMs in SegmentContext and accumulate
inside StatusLineComponent across agent_start -> agent_end windows.
markActivityStart/markActivityEnd are idempotent (reentrant agent_start
events and superseded agent_end events never double-count); the segment
ticks live during an open window and freezes when the agent yields.
The session-boundary hook drops the now-meaningless wall-clock argument
and is renamed setSessionStartTime -> resetActiveTime; it zeroes the
accumulator and drops any in-flight window so /clear / fresh-session /
joined-collab paths start the meter at zero.

Fixes #3681
2026-06-27 20:50:19 +00:00
can1357 577d2a8eb8 style: biome format/organize-imports across integrated PRs 2026-06-27 02:06:38 +02:00
can1357 dda3d17edc fix(tui): mirror collab subagent badge 2026-06-27 01:40:12 +02:00
roboomp b3833452a1 fix(tui): used collab registry for subagent badge
Switched the running-subagents status badge to follow the active collab guest registry when present.
2026-06-25 20:39:24 +00:00
can1357 c6c32242e9 fix(collab): arm welcome timer over the connect phase
The chunked-welcome refactor moved welcome-timer arming into socket.onOpen,
leaving the connect phase uncovered: if the relay blackholes the WebSocket
handshake (no onOpen and no onClose), the timer never arms and /join hangs
forever. Baseline armed the 30s timeout right after connect(); restore that
so a stalled handshake still rejects the join. onOpen continues to re-arm
(resetting the budget) once the socket opens.
2026-06-20 22:12:48 +02:00
roboomp 10e1ff44c9 fix(collab): reject join when snapshot resume fails
The chunked welcome path cleared its snapshot progress timer before
writing the replica file and switching sessions. If that apply work
failed, the frame-apply catch only logged the error, leaving the
initial join promise pending with no welcome/progress timer left to
settle it.

Reject the pending initial join when a welcome or snapshot-chunk apply
fails before the join has completed, preserving reconnect-time logging
for already-joined guests. Add a regression test that forces the replica
write to fail and asserts /join rejects instead of hanging.

Fixes #3144
2026-06-20 18:45:04 +00:00
roboomp 5b937511c4 fix(collab): chunked welcome so large session snapshots can join
The host used to ship the entire transcript inside a single welcome
frame, so a multi-MB session spent the guest's 30s first-welcome
timeout on the relay transfer itself: ~1.3 MB took ~3s, ~4.2 MB took
~12s, and ~13.6 MB never arrived before the guest gave up with
'timed out waiting for the host's welcome'.

Bump COLLAB_PROTO to 2 and split the welcome:

- welcome carries metadata only (header, state, agents, entryCount,
  readOnly) and lands in well under one second.
- a train of snapshot-chunk frames (SNAPSHOT_CHUNK_BYTES = 512 KB,
  oversize entries ship alone) carries the transcript. Last chunk
  flips final: true; an empty snapshot still emits one final chunk.
- the host queues welcome + chunks synchronously inside #handleHello,
  preserving the host comment's ordering invariant (later broadcast
  frames cannot interleave between them).
- the TUI guest accumulates chunks under a SNAPSHOT_PROGRESS_TIMEOUT_MS
  that resets per chunk; only after final does it write the replica
  jsonl, switchSession, and render. The first-welcome timeout still
  guards arrival of the small welcome.
- the collab-web GuestClient streams entries into the snapshot as
  chunks arrive and flips phase to 'live' on final.

Includes a contract test (in-process relay) asserting the welcome is
metadata-only, the chunk train fans the 1.5 MB synthetic transcript
across multiple frames with only the last marked final, and the
flattened entries match the source snapshot.

Fixes #3144
2026-06-20 18:33:59 +00:00
can1357 29d250fae2 feat(coding-agent): supported advisor transcript persistence
- Implemented `AdvisorTranscriptRecorder` to persist advisor sessions to append-only `__advisor.jsonl` files.
- Integrated transcript recording into agent sessions with managed flushing, atomic file switching, and synthetic turn attribution.
- Restricted advisor-kind agents by excluding them from rosters, history protocols, messaging, and interactive agent commands.
- Reserved the `__advisor` filename stem across the output manager and task registry to prevent task ID collisions.
2026-06-19 03:50:00 +02:00
Bin Jinandcan1357 e91d2cc776 feat(collab): added QR links and split web UI URL support
- Added collab.webUrl and rendered browser links as web UI wrappers whose fragments carry relay links.
- Added one-shot /collab qrcode and /collab qrcode-view commands with terminal QR rendering.
- Updated coding-agent and collab-web parsers to prefer parseable wrapper fragments while preserving legacy links.
- Added regression tests and changelog entries for split-host collab links and QR commands.
2026-06-19 01:21:21 +02:00
can1357 409196bf2e fix(coding-agent/session): fixed context usage breakdown to prefer completed in-turn anchors
- Fixed context breakdown to anchor estimates on the latest completed assistant usage message after compaction.
- Adjusted pending-context usage selection to prefer an in-turn provider anchor when available at/after cutoff.
- Added a contextUsageRevision cache token so status-line context memo invalidates after snapshot clear.
2026-06-17 12:24:20 +02:00
can1357 48decd15d7 fix(coding-agent): fixed context usage tracking to keep status and selector totals in sync
- Added context snapshot metadata to AssistantMessage for prompt and non-message token history.
- Anchored context usage calculations on assistant snapshots and computed percent numerically.
- Updated status-line, /context, selector, and interactive mode flows to share session usage totals.
- Extended status-line cache fingerprinting and invalidation for assistant usage and prompt/tool/skill changes.
2026-06-17 12:24:20 +02:00
can1357 b1c0243bab fix(coding-agent): fixed advisor auto-resume suppression for user interruptions
- Passed USER_INTERRUPT_LABEL through abort paths in collab, ACP, RPC, runtime, and SDK flows.
- Added userInitiated to synthetic continue inputs and session prompt calls.
- Suppressed advisor auto-resume during user aborts and preserved queued concerns.
- Cleared suppression on user prompts and reclaimed parked advisor cards on abort settle.
2026-06-15 20:51:56 +02:00
can1357 24c8bb24c6 feat(session): added modular session APIs and rebuilt listing/persistence behavior
- Added session-domain modules and exports for session-entries, context, listing, loader, and migrations.
- Changed persistence to async append writes plus writeTextAtomic, removing sync line APIs.
- Added compaction-aware session context rebuild with dangling tool-call cleanup.
- Added resumable session resolution with status inference, id/stem/suffix matching, and backup recovery.
2026-06-14 02:02:53 +02:00
can1357 495d49f588 refactor(coding-agent): reorganized status-line context cache usage flow
- Refactored status-line context caching to be keyed by message, tail, and window.
- Updated context usage flow to pass breakdown tokens and expose null usage when unknown.
- Adjusted context percentage handling so zero or unknown windows yield nullable values.
- Expanded status-line cache tests for usage provenance, memoization, and invalidation.
2026-06-13 18:02:08 +02:00
can1357 705750453d fix(coding-agent-turn-interrupt/queue-ux): resolved steering abort state
- Replaced queued-message interrupt flow with session abort calls on empty submit and escape.
- Removed interrupting state and notifyInterrupting teardown paths from abort handling.
- Updated AgentSession queue operations to use shared steering and follow-up queue views.
- Propagated isAborting through session state and collab payloads to suppress late updates.
2026-06-13 17:31:25 +02:00
can1357 42ffc83b5d fix: re-polled steering after yield and drained queued follow-ups after turns
- Re-polled steering at the loop yield boundary and included it in the pre-stop pending batch so late messages are processed immediately.
- Added session-side draining for stranded queued messages, scheduling an auto-continue when a prompt settles and follow-ups or steers remain.
- Added a regression test for late steering injection at yield and updated mid-turn collab prompt handling to keep steering messages in the pending display queue until consumed.
2026-06-12 17:02:42 +02:00
can1357 0d49f94418 fix(collab): switched collab links to dot-joined room secrets
- Changed the link grammar from `<roomId>#<key>` / `host[:port]/r/<roomId>#<key>` to dot-joined `<roomId>.<key>` in `formatCollabLink`/`parseCollabLink` (`packages/coding-agent/src/collab/protocol.ts`) and the collab-web mirror (`packages/collab-web/src/lib/link.ts`): RFC 3986 forbids a raw `#` inside a fragment, so strict URL stacks (macOS Foundation behind terminal click-to-open) percent-encoded the second `#`.
- Kept legacy `#`-joined links parseable via `BARE_LINK_RE` and added lenient `%23` → `#` decoding for mangled deep links.
- Updated the `ConnectScreen` placeholder, `app.tsx` deep-link comment, `DEFAULT_RELAY_URL` doc in `packages/wire`, `docs/collab.md` examples, and both package CHANGELOGs.
- Extended `crypto.test.ts` and `link.test.ts` with dot-joined, legacy-hash, and `%23`-mangled link coverage.
2026-06-12 16:47:56 +02:00
can1357 b16bfbe0f9 feat(collab-web): implemented read-only session controls and refreshed app branding metadata
- Enabled read-only mode by wiring snapshot.readOnly through AgentDrawer and Composer to block prompts and controls.
- Added read-only indicators in the header and participant titles for view-only sessions.
- Added SEO and app metadata assets by updating index.html head tags, manifest, robots.txt, and sitemap.xml.
- Updated brand presentation by adding new favicon/OG assets and switching theme tokens to new OMP colors.
2026-06-12 13:40:12 +02:00
can1357 09aa87103c feat: added read-only and write-token-based collab links for view-only sessions
- Added write-token generation and validation to distinguish writable and read-only guests.
- Added deep-link support using `https://<relay>/#<link>` with 32/48-byte collab secrets.
- Added full-link and key-only semantics where full links grant writes and key-only links are view-only.
- Added /collab view/status/stop command updates with read-only participant status and join hints.
2026-06-12 13:34:43 +02:00
can1357 8fa1f6c250 feat: added shared collab wire protocol and web guest collaboration client
- Added @oh-my-pi/pi-wire and reworked collab protocol types into shared contracts.
- Added wire-compatibility guards in coding-agent host to block unsupported events.
- Added standalone collab-web package with guest UI, mock-host tooling, and local relay.
- Added secure room-link validation, WebCrypto framing, and safer socket routing.
2026-06-12 11:54:41 +02:00
can1357 3e90371f5c feat(coding-agent): added collaborative sessions with host and guest command support
- Added AES-GCM room-key crypto, relay link parsing, and invalid-link validation.
- Added `/collab`, `/join`, and `/leave` command handling for collaborative sessions.
- Added startup `join` argument wiring to execute `/join` during interactive launch.
- Added status-line, prompt, and command-routing updates for guest/host collaboration UX.
2026-06-12 10:54:28 +02:00