Commit Graph

3333 Commits

Author SHA1 Message Date
can1357 b91a15cbcf fix(coding-agent): ensured side-channel turns obfuscate secrets and tools
- Verified that side-channel turns maintain stable prompt cache parity with main turns.
- Applied secret and tool obfuscation to ephemeral assistant side-channel data to prevent leakage.
- Updated `Agent` and `AgentSession` test suites to validate consistency under native dialect environments.
2026-06-20 23:24:41 +02:00
can1357 64e44fd30f fix(coding-agent): preprompt / triggerContextTokens 2026-06-20 23:21:57 +02:00
DarkPhilosophy 4d6597c4a9 test(compaction): cover the AgentSession floor wiring for deflated provider usage
Mirror of the provider-anchored handoff test: a ~20k-token stored conversation
whose provider usage was deflated to 1k (as a before_provider_request compressor
would) now triggers pre-prompt compaction, proving #estimateStoredContextTokens
floors the decision through the real call-site (not just the helper math).
2026-06-20 23:21:36 +02:00
DarkPhilosophy 8c9ae9ef67 fix(compaction): exclude encrypted reasoning from the compaction floor
CI caught that flooring by the raw local estimate falsely triggers compaction on
thinking-heavy turns: estimateTokens counts the opaque thinkingSignature /
redactedThinking payloads (providers bill them on replay, #2275), but their local
byte size diverges wildly from what the provider actually charges — so a turn
with a large encrypted-reasoning blob but small provider usage would trip the
floor (broke agent-session-handoff 'provider-anchored usage' test).

estimateTokens now takes { excludeEncryptedReasoning } and the compaction floor
(#estimateStoredContextTokens) uses it: the floor counts only reliably-countable,
on-wire-compressible content (text, tool results, tool calls), while the provider
usage arm of compactionContextTokens still accounts for encrypted reasoning. This
keeps the encrypted-reasoning case provider-anchored while still flooring upward
when a before_provider_request hook compresses tool results.
2026-06-20 23:21:36 +02:00
DarkPhilosophy 7e8450192c fix(compaction): floor context tokens by local estimate so payload compression can't suppress auto-compaction
A before_provider_request extension (a context-compression proxy like Headroom,
an obfuscator, or inline snapcompact) can shrink the outgoing request below the
real stored conversation. The provider then reports deflated prompt tokens, so
the auto-compaction threshold never fires and the stored history grows unbounded
until it overflows the context window and can no longer be compacted at all.

Add compactionContextTokens(provider, storedEstimate) = max(provider, estimate)
and apply it to both the pre-prompt and post-response compaction decisions,
flooring the provider-reported tokens by the agent's own estimate of the stored
conversation. Display and cost accounting still use exact provider usage; only
the compaction trigger takes the floor.
2026-06-20 23:21:36 +02:00
can1357 b5437c2cad feat(coding-agent): improved prompt caching for ephemeral side-channel requests
- Added `buildSideRequestContext` to the `Agent` class to generate prompt-cache-friendly provider contexts.
- Updated ephemeral side-channel turns to forward the full tool catalog to maintain prompt cache hit rates.
- Injected a `developer` role reminder into ephemeral turns to instruct the model to suppress tool calls.
- Implemented automatic post-processing to strip any tool calls from ephemeral turn responses.
- Exported message and dialect helper functions in `agent-loop.ts` to support context construction.
2026-06-20 23:19:10 +02:00
can1357 60b043adb7 fix(coding-agent): fixed session history desynchronization during
- Fixed session history desynchronization during `rewind` by performing a full context rebuild after applying branch changes.
- Prevented `rewind` tool output and assistant side-channel data from polluting the prompt cache by flushing and sanitizing session state.
- Added explicit test coverage for context reconstruction and assistant message sanitization after rewind events.
2026-06-20 22:58:23 +02:00
Can Bölük 47bb5172fe Merge pull request #3138 from KamijoToma/save-command-history
feat(coding-agent): save slash command text for /btw /tan /omfg /memory /rename /move to TUI history
2026-06-20 22:39:47 +02:00
can1357 321b51517a Merge PR #3022: refactor(coding-agent): use Promise.withResolvers in AsyncDrain (@oldschoola) 2026-06-20 22:36:13 +02:00
Can Bölük 18be1f6509 Merge pull request #3090 from oldschoola/fix/batch-test-ebusy-cleanup
fix(test): migrate fs.rmSync to removeSyncWithRetries in 5 more test files
2026-06-20 22:35:07 +02:00
can1357 d8ec46eee5 fix(tiny): guard unsupportedReason access on const model-spec union (#3133 integration typecheck) 2026-06-20 22:25:29 +02:00
can1357 df581eee5f style: biome format inventory test slice (#3017 integration) 2026-06-20 22:23:18 +02:00
can1357 0f40ae3df0 test(coding-agent): drop obsolete inventory-layout assertion superseded by main's prompt reorder (#3017 integration) 2026-06-20 22:20:54 +02:00
can1357 c47b57a199 test(coding-agent): make inventoryFrom robust to prompt.md reorder
The prompt-inventory test sliced on the '# Inventory'/'ENV' markers from the
PR's merge-base prompt.md. On current main (chore: prompt reorder) the heading
is '# Tool Inventory' and the 'ENV' marker is gone, which is why the file was
deleted there. Accept either layout so the resurrected tests (incl. the SDK
'render provided tools' contract) pass after the cherry-pick.
2026-06-20 22:19:28 +02:00
can1357 9722505a2b Merge PR #3017: fix(coding-agent): handle todo paths and prompt inventory (@oldschoola)
# Conflicts:
#	packages/coding-agent/test/system-prompt-inventory.test.ts
2026-06-20 22:19:28 +02:00
can1357 ffc842ee7c fix(agent): reset promoted memory prompt on session fork
fork() reset mnemopi conversation tracking directly but skipped the shared new-transcript reset, so the folded/promoted first-turn memory stayed in #baseSystemPrompt. The next turn re-recalled and the change-detection saw no diff, taking the fallback promotion path and injecting the <memories> block twice into the forked session prompt. Route fork() through #resetMemoryContextForNewTranscript() like the other reset paths and add a regression test asserting the forked prompt contains recalled memory exactly once.
2026-06-20 22:16:58 +02:00
can1357 10ed2d4efa Merge PR #3113: fix(agent): preserve memory recall in append-only prompt cache (@roboomp) 2026-06-20 22:16:58 +02:00
can1357 1fadcdb8e3 Merge PR #3147: fix(agent): compact active goal yields (@roboomp) 2026-06-20 22:16:57 +02:00
can1357 7bf8db9215 Merge PR #2946: fix(coding-agent): show omfg dismiss hint (@wolfiesch) 2026-06-20 22:16:57 +02:00
can1357 e3dd53affc Merge PR #2862: fix(tui): keep Alt+M role models selectable over context limit (@roboomp)
# Conflicts:
#	packages/coding-agent/test/model-selector-role-badge-thinking.test.ts
2026-06-20 22:14:28 +02:00
can1357 176d0a98a0 Merge PR #2995: fix(coding-agent): clarify temporary model picker (@riverpilot) 2026-06-20 22:13:07 +02:00
can1357 d3d88ce5c3 test(coding-agent): force startInAllScope in #3099 regression so it discriminates
The #3099 test omitted the startInAllScope flag, so it passed against the
buggy baseline too (empty folder defaults to folder scope regardless). Force
the removed flag via a cast to pin the real contract: even when a caller asks
for all-projects scope on an empty folder, the picker must stay folder-scoped.
Proven: passes on head src, fails on baseline src (renders '(all projects)').
2026-06-20 22:13:01 +02:00
can1357 31bb2144e7 Merge PR #3100: fix(coding-agent): keep /resume picker scoped to the current folder (@roboomp) 2026-06-20 22:13:01 +02:00
can1357 a76de2fea8 Merge PR #3089: fix(test): migrate fs.rmSync to removeSyncWithRetries for EBUSY-safe cleanup (@oldschoola) 2026-06-20 22:12:49 +02:00
can1357 61f3b54c86 Merge PR #3086: fix(test): use TempDir for Windows-safe cleanup in settings-manager tests (@oldschoola) 2026-06-20 22:12:49 +02:00
can1357 771f93244f Merge PR #2907: fix(coding-agent): support getModel/getModels aliases in legacy extensions (@pidevxplay) 2026-06-20 22:12:49 +02:00
can1357 b128406030 Merge PR #2994: fix(catalog): clamp MiMo reasoning efforts (@riverpilot) 2026-06-20 22:12:49 +02:00
can1357 c31e7fc16e Merge PR #3145: fix(collab): chunked welcome so large session snapshots can join (@roboomp) 2026-06-20 22:12:47 +02:00
can1357 6f17533041 fix(tiny): keep tiny-models download all green by skipping load-blocked models
resolveModels("all") expanded the full TINY_LOCAL_MODELS registry, which now
includes the qwen3-1.7b entry marked unsupportedReason. loadPipeline() throws
for such specs, so the download worker reported it as failed and the bulk
command exited with "One or more tiny title models failed to download" even
when every usable model downloaded. Filter unsupported specs out of the `all`
prefetch path; explicit single-model requests are unchanged. Addresses the
unaddressed Codex P2 on PR #3133.
2026-06-20 22:12:47 +02:00
can1357 28bbe4d14f Merge PR #3133: fix(tiny): stop respawning failed local model workers (@roboomp) 2026-06-20 22:12:47 +02:00
can1357 f58750d7bf Merge PR #3118: fix(tool): resolve internal URL directories (@roboomp) 2026-06-20 22:12:47 +02:00
can1357 390ea7b82b Merge PR #3109: fix(read): render wide SQLite tables as vertical blocks (@roboomp) 2026-06-20 22:12:47 +02:00
roboomp e00483b2c1 fix(agent): compact active goal yields
Run threshold compaction maintenance when an active goal turn ends through a successful yield, while preserving the final-yield skip for non-goal completions.

Fixes #3146
2026-06-20 19:01:26 +00: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 4ff5b073e8 style: bun run fix 2026-06-20 18:34:05 +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
roboomp 39ce1b33cc fix(tiny): kept queued models retryable after crashes
Stopped treating subprocess crash notifications as model-specific inference failures. Added regression coverage proving an unrelated queued title model can spawn a replacement worker after the crashed worker faults all pending requests.

Fixes #3132
2026-06-20 13:30:22 +00:00
roboomp 9b9a6b38a7 fix(tiny): stopped respawning failed local model workers
Blocked the unsupported Qwen3 1.7B ONNX memory model before loading transformers and remembered local model execution failures so the client returns null instead of spawning another __omp_worker_tiny_inference process for the same failed model.

Fixes #3132
2026-06-20 13:24:53 +00:00
roboomp 9f77877b15 fix(tool): kept internal directory listings immutable
Flag directory resources from internal URL handlers as immutable so hashline edit anchors never key on a directory path.
2026-06-20 09:59:39 +00:00
roboomp 9da023864f fix(tool): preserved handler directory listings
Stopped routing internal URL directory reads through the filesystem tree renderer so vault:// and '/data/workspaces/can1357__oh-my-pi__3116/.omp-session/2026-06-20T09-33-10-396Z_019ee460-817c-7000-8139-f8e2927809dd/local' keep their custom navigable listings.
2026-06-20 09:53:11 +00:00
roboomp 15b9dc222c fix(tool): kept immutable search directories read only
Treat immutable internal URL directory source paths as immutable for all descendants before search emits hashline anchors.
2026-06-20 09:50:28 +00:00
roboomp b098addaf3 fix(tool): resolved internal url directories
Allow file-backed internal URL handlers to return existing directories as resources so read can list them and search/find can walk their source paths.

Fixes #3116
2026-06-20 09:44:10 +00:00
roboomp 1b197956a4 fix(agent): reset memory prompts on new transcripts
Restored and refreshed promoted memory prompts through the shared new-transcript reset path used by new sessions, handoff, branch, /btw, and cross-session switches.\n\nAdded coverage for newSession after first-turn memory recall so stale recalled memories cannot leak into the next transcript when recall returns no context.\n\nFixes #3111
2026-06-20 08:50:30 +00:00
roboomp 7d7cc1d1ba fix(agent): cleared promoted memory on session switch
Reset memory recall state before rebuilding the prompt during session switches, and clear fallback-promoted memory prompts when moving to another session.\n\nAdded a regression test that switches sessions after first-turn memory recall and verifies the next session does not receive stale memories.\n\nFixes #3111
2026-06-20 08:45:25 +00:00
roboomp 3d864fa763 fix(agent): preserved memory prompt cache
Promoted first-turn memory recall into the stable base prompt so append-only sessions do not drop the memory block on the next turn and rebuild the provider prefix.\n\nAdded a regression test covering a memory backend that recalls once before the first model request.\n\nFixes #3111
2026-06-20 08:32:48 +00:00
roboomp ed37f076ef fix(read): render wide SQLite tables as vertical blocks
The ASCII table renderer in `sqlite-reader.ts` shrank columns down to
`MIN_COLUMN_WIDTH=1` to fit the 120-cell budget. With ~20+ columns
(the reporter had 33) every multi-char cell collapsed to a lone `…`
and the final per-line `truncateToWidth(..., MAX_RENDER_WIDTH)` then
chopped the right edge — so the read tool returned a table of nothing
but ellipses with the rightmost cells missing entirely.

Bump the per-column floor to 3 (so cells always show at least two real
glyphs alongside the ellipsis) and, when the column count alone forces
the floor over budget, fall back to a per-row vertical block layout —
mirroring `psql`'s expanded display mode. Each row becomes a
`column: value` group with column names padded so colons align and
the value line truncated to the same 120-cell budget.

Fixes #3107
2026-06-20 07:55:09 +00:00
Alexander Kirilin 164176d4d4 fix(coding-agent): merge main into temp picker guidance 2026-06-20 03:27:11 -04:00
Alexander Kirilin eaf9248ec2 fix(catalog): merge main into MiMo efforts 2026-06-20 03:27:05 -04:00
can1357 b717a65fc3 feat(coding-agent): introduced prose-only thinking mode
- Added a `proseOnlyThinking` configuration setting to suppress raw code blocks in AI thinking traces.
- Implemented `formatThinkingForDisplay` utility to replace code blocks with ellipses in the UI.
- Integrated runtime toggling and live refreshing of message components via streaming reveal controllers.
- Added a live tokens-per-second indicator to the assistant thinking pulse.
- Verified logic with new unit and integration tests for thinking block presentation.
2026-06-20 08:51:15 +02:00
can1357 4947ac6ce2 feat(coding-agent/modes): added live streaming-speed indicator to thinking animation
- Added a windowed `SpeedTracker` to report average tokens-per-second during reasoning streams.
- Updated thinking animation from a dot pulse to a starburst effect with a dynamic speed badge.
- Engineered badges to fade from gray to accent color based on streaming throughput.
- Implemented automatic badge suppression during streaming lulls or for providers without live usage reporting.
- Added session-wide reset logic to prevent rate leaking between consecutive message turns.
2026-06-20 08:30:01 +02:00