Commit Graph

7354 Commits

Author SHA1 Message Date
can1357 8d60776a6f chore: bump version to 16.1.17 2026-06-24 21:11:31 +02:00
can1357 9ad17a2b49 ux(coding-agent/modes): removed hotkeys tip from welcome component
- Removed the hotkeys tip from the welcome screen UI.
2026-06-24 21:01:55 +02:00
can1357 0eb21efa1a Merge remote-tracking branch 'origin/farm/7ef98714/snapcompact-copilot-vision-gate' 2026-06-24 21:00:37 +02:00
can1357 0f2737f16e Merge remote-tracking branch 'origin/farm/e322f828/eval-agent-yield-terminal' 2026-06-24 20:59:54 +02:00
roboomp 997b2b24ff fix(session): suppressed empty-stop retry after successful yield
Trailing empty assistant 'stop' arriving after a successful 'yield'
revived the already-yielded subagent. AgentSession.agent_end maintenance
compared #assistantEndedWithSuccessfulYield(msg) against the trailing
empty-stop message — not the yield-bearing one — so the empty-stop
recovery path appended a retry reminder and scheduled agent.continue().

Track a sticky #yieldTerminationPending flag set when the yield tool
finishes without error and cleared on the next #promptWithMessage. The
agent_end routing extends the existing successful-yield branch: when the
flag is set, or the current message ended with yield, short-circuit
empty-stop / unexpected-stop / compaction continuations for the rest of
the run, so a successful yield is terminal regardless of trailing stops.

Fixes #3389
2026-06-24 17:08:49 +00:00
can1357 a4dbe6396c style: biome organize-imports on merged test files (#3193, #3312) 2026-06-24 19:03:32 +02:00
can1357 ff2280e6ee chore(changelog): normalize [Unreleased] after merge sweep (fix-changelogs --since baseline; dedup #3258) 2026-06-24 18:46:00 +02:00
can1357 9b3c193dfd Merge PR #1681: fix(coding-agent): expose hashline edit path to extensions (@roboomp)
# Conflicts:
#	packages/coding-agent/test/extensions-runner.test.ts
2026-06-24 18:42:35 +02:00
roboomp 714051d795 fix(catalog,coding-agent): disable vision on non-personal copilot endpoints
GitHub Copilot's /models response advertises supports.vision = true for
Claude/GPT chat models on every host, but only the canonical personal
endpoint (https://api.githubcopilot.com) actually accepts image inputs;
the business (api.business.githubcopilot.com) and enterprise
(copilot-api.{domain}) hosts respond '400 vision is not supported'.
snapcompact then injected rasterized transcript frames after compaction
and permanently broke every business-Copilot session.

- Catalog discovery (githubCopilotModelManagerOptions.mapModel) now
  forces input=['text'] whenever the resolved baseUrl is not the
  canonical personal-Copilot host, so the upstream's vision flag is
  honoured only where it actually works.
- mergeDynamicModel honours the dynamic input value (instead of
  OR-upgrading with the bundled reference) when the merged baseUrl
  differs from the bundled one, so a bundled spec pinned to the
  personal host can no longer taint a business-resolved merge.
- snapcompact-inline's canSendImages helper short-circuits the
  rasterizer for any github-copilot model whose baseUrl is non-personal,
  catching stale cached specs that still advertise vision.
- Helper isPersonalGitHubCopilotBaseUrl exported from
  pi-catalog/wire/github-copilot so catalog and coding-agent share one
  canonical check.

Regression coverage in github-copilot-model-limits.test.ts (vision
endpoint policy + full merge) and snapcompact-inline.test.ts (#3387
business/enterprise case).

Fixes #3387
2026-06-24 16:27:14 +00:00
can1357 b1e31b7f7d docs(changelog): dropped unbacked resize-replay claim
This PR tails appended JSONL and collapses compacted history; it does not
touch the resize/SIGWINCH replay path, so the changelog should not claim it.
2026-06-24 18:26:20 +02:00
can1357 6988178f64 test(session-storage): used a top-level FileSessionStorage import
Replaced the inline await import() calls with a top-level import per the
repo's no-inline-imports rule.
2026-06-24 18:26:20 +02:00
can1357 9c56956631 fix(tui): kept recent turns visible when collapsing remote compactions
With collapseCompactedHistory the live display fell into the LLM compaction
branch, which skips the firstKeptEntryId..compaction turns whenever an OpenAI
remote-compaction replacementHistory payload is present. That payload feeds the
provider only and is not rendered, so a remotely-compacted session showed just
the summary plus post-compaction rows, hiding recent turns that were visible
before. Emit the kept SessionEntry rows in transcript mode regardless. Adds a
regression.
2026-06-24 18:26:20 +02:00
can1357 fa5024caa4 fix(tui): guarded transcript sentinel reads against mid-poll unlink
The append fast-path opened the session file for sentinel comparison and
recompute without a guard, so a file unlinked/rotated between #refresh's
statSync and the sentinel read threw out of the 250ms poll timer (no catch),
risking a TUI crash. Treat sentinel read/recompute failures as non-appendable
and fall back to the guarded full reload. Adds a fake-timer regression.
2026-06-24 18:26:20 +02:00
can1357 c04747c5ac Merge PR #3259: fix(tui): reduce large transcript stalls (@roboomp) 2026-06-24 18:26:19 +02:00
omp-eval 78e469088d test(agent): decouple snapcompact skip test from provider-dependent LLM fallback
The "skips snapcompact entirely" case asserted .rejects.toThrow() on
session.compact(), but after the maxFrames<1 skip the manual /compact path
falls through to the LLM summarizer whose outcome is provider/network
dependent (resolves when a summary lands, rejects only without
credentials/network). In a sandbox it resolves and blows the 5s default
timeout. Tolerate either outcome and pin only the deterministic skip
contract (snapcompact.compact not invoked + the kept-history notice), with
a generous explicit timeout. Addresses chatgpt-codex P2 review on #3249.
2026-06-24 18:26:19 +02:00
can1357 3117a20ab9 Merge PR #3249: fix(agent): size snapcompact maxFrames by the live model window (@roboomp) 2026-06-24 18:26:19 +02:00
can1357 ef67f685ac Merge PR #3380: fix(coding-agent): clamp auto thinking to undefined for models without controllable effort (@roboomp) 2026-06-24 18:26:19 +02:00
can1357 0f072cbcc1 Merge PR #3315: fix(welcome): replace stale ? shortcut with /hotkeys in tips panel (@oldschoola) 2026-06-24 18:26:18 +02:00
can1357 a7a17e8dc1 Merge PR #3376: fix(tui): theme-aware welcome tip line for light-theme legibility (@roboomp) 2026-06-24 18:26:18 +02:00
can1357 ee57c07371 Merge PR #3377: fix(settings): prevent numeric config values from crashing settings UI (@roboomp) 2026-06-24 18:26:18 +02:00
can1357 b56a7524af Merge PR #3385: fix(coding-agent): restore TUI focus to live editor-slot owner when a fullscreen overlay closes (@roboomp) 2026-06-24 18:26:18 +02:00
can1357 8c76b45c3b Merge PR #3381: fix(coding-agent): honor app.message.followUp chord in ask prompt-style editor (@roboomp) 2026-06-24 18:26:18 +02:00
can1357 35ec85c034 test: cover central slash-command history recording + secret skip (#3148) 2026-06-24 18:26:17 +02:00
can1357 d88d9bd6d8 Merge PR #3352: fix: store slash commands in input history (@oldschoola) 2026-06-24 18:26:17 +02:00
can1357 d4d7fed0cc Merge PR #3384: fix(tui): attach pasted file paths as local refs (@roboomp) 2026-06-24 18:26:17 +02:00
can1357 345bdc32e1 test(usage): cover TUI aggregate provider-notes-once and per-limit dedup
renderUsageReports (command-controller) carried the #3268 dedup contract
with no regression test; the PR's added CLI test asserts the opposite
(per-limit CLI rendering shows the note twice). Export renderUsageReports
and add a real regression through it: two accounts sharing one window group
render a provider-wide UsageReport.note once and an identical per-limit note
once. Verified failing on the pre-fix flatMap form (0 and 2 occurrences) and
passing on head (1 and 1).
2026-06-24 18:26:17 +02:00
can1357 01ef63fbd0 Merge PR #3312: fix(usage): dedup provider-wide notes and add report-level notes field (@oldschoola) 2026-06-24 18:26:17 +02:00
can1357 b1e0ba41eb Merge PR #3289: fix(tui): include tiered Codex usage limits (@riverpilot) 2026-06-24 18:26:16 +02:00
can1357 a34f4fc129 Merge PR #3345: fix(tui): @-path autocomplete on Windows for paths outside cwd (@oldschoola) 2026-06-24 18:23:50 +02:00
can1357 4d71beb0df Merge PR #3344: fix(tui): stop OSC 11 poll from wiping text selection (@oldschoola) 2026-06-24 18:23:49 +02:00
can1357 ca31872f29 test(cli): cover backslash runtime-path normalization in profile-alias POSIX fields 2026-06-24 18:23:49 +02:00
can1357 5d49862eaf Merge PR #3346: fix(cli): profile-alias installer produces correct paths for POSIX shells on Windows (@oldschoola) 2026-06-24 18:23:48 +02:00
can1357 d0f5dba066 Merge PR #3379: fix(tools): stream tool downloads without Bun.write Response (@roboomp) 2026-06-24 18:23:48 +02:00
can1357 07f4ac698c Merge PR #3383: fix(memory): scope mnemopi entity extraction to user turns (@roboomp) 2026-06-24 18:23:48 +02:00
can1357 2b42f19456 Merge PR #3232: fix(agent): clamp provider context images (@roboomp) 2026-06-24 18:23:48 +02:00
can1357 df8c773fae Merge PR #3245: fix(cli): register marketplace plugin installs (@roboomp) 2026-06-24 18:23:47 +02:00
can1357 63dc80073b Merge PR #3292: fix(cli): keep tiny-model downloads alive (@roboomp) 2026-06-24 18:23:47 +02:00
roboomp 1b24e0044a fix(coding-agent): restore focus to the live editor-slot owner when a fullscreen overlay closes
When /settings (or the Extensions/Agents dashboard) is open and a tool
approval prompt fires, ExtensionUiController.showHookSelector swaps the
editor out of editorContainer for the HookSelectorComponent. On exit,
the overlay's done() called overlayHandle.hide() + setFocus(editor),
both pointing at the editor captured as preFocus when the overlay
opened — now no longer mounted. The visible approval prompt then sat
unreachable: Up/Down/Enter/Esc routed to the unmounted editor and only
Ctrl+C escaped (issue #3349).

SelectorController now exposes focusActiveEditorArea(), which restores
focus to editorContainer.children[0] (the live slot owner) or falls
back to the editor. Wired into showSettingsSelector, showExtensionsDashboard,
and showAgentsDashboard close paths after overlay.hide().

Tests: unit test verifying focusActiveEditorArea picks the live slot
owner; TUI overlay-focus regression pinning the post-fix contract plus
a 'pre-fix snapshot' test pinning the broken pre-fix behavior so the
restore-from-preFocus assumption can't silently change.

Fixes #3349
2026-06-24 14:24:15 +00:00
roboomp 4f20d10454 fix(tui): attached pasted file paths
Converted bracketed non-image filesystem path pastes into session-local attachment references while preserving the existing image path flow.

Added regression coverage for editor routing and controller local file attachment behavior.

Fixes #3360
2026-06-24 14:21:45 +00:00
roboomp f97e05a1c4 fix(memory): scope mnemopi extraction to user turns
- Added an extractText override to pi-mnemopi remember paths so stored content and mined facts can use different text.
- Routed coding-agent mnemopi retention to store the full transcript while extracting only user-authored turns.
- Tightened deterministic Instruction extraction to require an explicit I/you subject.

Fixes #3372
2026-06-24 14:21:26 +00:00
roboomp 3e502a38bc style: bun run fix 2026-06-24 14:12:42 +00:00
roboomp b0e07f52d2 fix(coding-agent): clamped auto thinking to undefined for models without controllable effort
Devin provider models (devin-agent) advertise reasoning: true but no
thinking.efforts metadata — Cascade selects effort by routing to sibling
model ids, not a wire param. getSupportedEfforts(model) therefore returns
[]. clampAutoThinkingEffort previously short-circuited that empty supported
list by returning the requested effort as-is, so the auto-thinking
classifier-resolved level (e.g. low) reached stream.ts:1163 where
requireSupportedEffort threw 'Thinking effort low is not supported by
devin/<id>. Supported efforts: '. In --print mode the user saw the error
text; in the TUI it was silently swallowed, producing the reported
'working then empty response' symptom.

Returns undefined when supported is empty so the result mirrors
clampThinkingLevelForModel's behavior on the same shape (the explicit
--thinking low / high paths already worked because of this). Updates
classifyDifficulty's return type to Effort | undefined and threads through
to the existing #applyAutoThinkingLevel undefined-effort early-return.
#applyAutoThinkingLevel also short-circuits the classifier call up front
for these models — there is no effort to pick.

Fixes #3356
2026-06-24 14:12:18 +00:00
roboomp bd06c5dd4e fix(coding-agent): honor app.message.followUp chord in ask prompt-style editor
The ask tool's "Other (type your own)" free-text input is a prompt-style
HookEditorComponent. The hook-style branch already called matchesAppFollowUp
(Ctrl+Q / Ctrl+Enter) so Windows Terminal users — which can't deliver a
distinct Ctrl+Enter (#1903 / fixed by #1905) — had a working chord on the
main editor, hook editors, and the agent dashboard. The prompt-style branch
did not, so Ctrl+Q was unbound and Ctrl+Enter fell through to Editor as a
newline that WT silently swallowed: pressing Ctrl+Enter did nothing.

#handlePromptStyleInput now checks matchesAppFollowUp before the rest of
the dispatch (mirroring #handleHookStyleInput), so plain Enter remains the
primary submit and the chord is a secondary submit for cross-terminal
muscle memory. The prompt-style hint now reads "enter or ctrl+q submit"
so the fallback is discoverable.

Fixes #3353
2026-06-24 14:12:05 +00:00
roboomp 44f3632cff fix(tools): bounded tool asset downloads
Stream fetched tool assets to disk under the existing download abort signal instead of passing the Response object to Bun.write. Remove partial files when a stalled body is aborted and cover completed plus stalled downloads with regression tests.

Fixes #3369
2026-06-24 14:11:39 +00:00
roboomp e261848293 fix(settings): coerced rendered settings values
Coerced malformed YAML-derived settings values to strings before they reach settings row truncation. Added regression coverage for numeric enum display values.

Fixes #3338
2026-06-24 13:53:06 +00:00
roboomp 4bcb9b5fe9 style: bun run fix 2026-06-24 13:44:47 +00:00
roboomp de87923add fix(tui): theme-aware welcome tip line for light-theme legibility
The welcome 'Tip:' line hardcoded #b48cff (label) and #9ccfff (body)
with an additional \x1b[2m dim on the body, ignoring the active theme.
On any light theme this dropped the body to ~1.5:1 contrast on a white
background (WCAG AA needs >=4.5:1), making the line effectively
invisible. Switching between light variants did not help because the
colors were not theme-derived.

renderWelcomeTip in packages/coding-agent/src/modes/components/welcome.ts
now paints the label through theme.fg('customMessageLabel', ...) and the
body through theme.fg('muted', ...), drops the manual dim, and wraps the
whole line with theme.italic(...). Both tokens are tuned per theme, so
the line stays vivid on dark backgrounds and readable on light ones
(e.g. light theme's customMessageLabel #7e57c2 = 5.21:1 on white).

A regression test pins the contract: dark/light themes must produce
different bytes for the same tip, and no manual \x1b[2m may remain.

Fixes #3337
2026-06-24 13:44:21 +00:00
oldschoola cbbdfda2ce fix: normalize tabs in usage notes rendering
Address P2 review: sanitizeText preserves \t which can create visual
holes in rendered output. Add .replace(/\t/g, '  ') to provider-wide
and per-limit notes in usage-report.ts and usage-cli.ts, matching the
TUI path which already uses replaceTabs().
2026-06-23 16:02:26 -07:00
oldschoola 04c3199511 fix(usage): normalize newlines in provider notes before rendering
sanitizeText preserves newlines (\n) which break TUI line layout when
injected into a single rendered row. All notes rendering sites now
replace \r\n sequences with spaces before sanitization:

- command-controller.ts: provider-wide notes (line 1591) + per-group
  notes (line 1666)
- usage-report.ts: provider-wide notes (line 58) + per-limit notes
  (line 90, previously completely unsanitized)
- usage-cli.ts: provider-wide notes (line 455)
2026-06-23 16:02:26 -07:00
oldschoola 12511ca004 fix(usage): sanitize provider notes in usage-report and usage-cli
Apply sanitizeText to provider notes in the shared usage-report
renderer and the CLI usage output, matching the sanitization added
to command-controller.ts. Prevents tabs/newlines/control characters
in provider notes from breaking terminal rendering.
2026-06-23 16:02:25 -07:00