Commit Graph
10633 Commits
Author SHA1 Message Date
Can BölükandGitHub 4e56e8bd37 Merge pull request #3465 from cexll/local-build-pr-3428
fix(tui): keep interrupts ahead of repaint
2026-06-25 22:41:21 +02:00
can1357 5a50b047d5 Merge PR #3428: Fix active goal compaction after yield stop (@cexll) 2026-06-25 22:39:28 +02:00
can1357 3188fc6bb9 Merge remote-tracking branch 'origin/farm/371a49e5/anthropic-claude-4-5-budget-effort' 2026-06-25 22:35:22 +02:00
can1357 938489f3fd feat(coding-agent): added configurable service tier settings for subagents and advisor
- Introduced `serviceTierSubagent` and `serviceTierAdvisor` settings to allow independent service tier control for subagents and the advisor model.
- Enabled `"inherit"` mode for these settings, allowing subagents and the advisor to track the main session's live effective service tier, including dynamic toggles like `/fast`.
- Added a resolution layer to ensure service tier propagation from parent sessions to spawned task agents and evaluators.
2026-06-25 22:35:15 +02:00
roboomp 7a4cf0e30c fix(catalog): classified direct Anthropic Sonnet/Haiku 4.5 as plain budget thinking
Direct Anthropic Claude Sonnet 4.5 and Haiku 4.5 (plus their Cloudflare,
Vertex, GitLab-Duo, Copilot, OpenCode-Zen, and Bedrock cross-region passes)
were classified as anthropic-budget-effort, which made the Anthropic provider
serialize output_config.effort alongside the thinking.budget_tokens block.
Anthropic only honors output_config.effort on Opus 4.5 and adaptive (4.6+)
Messages-API models — Sonnet 4.5 and Haiku 4.5 reject every request with
HTTP 400 'This model does not support the effort parameter.', so the advisor
(and any agent on a Sonnet/Haiku 4.5 SKU) failed every turn.

inferThinkingControlMode now gates anthropic-budget-effort to
parsedModel.kind === 'opus' && semverGte(version, '4.5') on both
anthropic-messages and bedrock-converse-stream. Sonnet/Haiku 4.5 fall through
to mode: 'budget' (effort still scales the per-tier thinking budget via
ANTHROPIC_THINKING[reasoning]); Opus 4.5 keeps anthropic-budget-effort and
continues to emit output_config.effort. anthropic-budget-effort also remains
in use for Anthropic-compatible third-party backends that natively support
the field (Umans GLM 5.2).

Regenerated models.json so the 19 Sonnet/Haiku 4.5 first-party entries flip
to mode: 'budget' and the 12 Opus 4.5 entries stay on anthropic-budget-effort.

Regression tests cover both sides: anthropic-alignment.test.ts asserts the
Sonnet 4.5 wire body omits output_config and the Opus 4.5 wire body emits
output_config.effort: 'medium'.

Fixes #3497
2026-06-25 20:16:34 +00:00
github-actions[bot] 02d0ccc555 Update VOUCHED list
https://github.com/can1357/oh-my-pi/discussions/3418#discussioncomment-DC_kwDOQxs0bc4BChZk
2026-06-25 20:14:15 +00:00
can1357 2eddcf540f chore: added new names to VOUCHED list 2026-06-25 22:00:55 +02:00
can1357 af01c63e3b test(ai): updated credential access in E2E tests and CI test runner
- Updated the `ai` package E2E tests to retrieve environment variables via `e2eApiKey` to ensure they only execute when E2E testing is enabled.
- Refactored the `scripts/ci-test-ts` runner to conditionally apply the `--only-failures` flag based on provided arguments.
2026-06-25 21:50:55 +02:00
can1357 9ffaace8bc test(coding-agent): prevented sqlite database handle leaks in tests
- Track and explicitly close in-memory SQLite database handles in MCP auth tests.
- Resolved Bun GC-related crashes occurring when parallel tests finalize dangling database handles.
2026-06-25 20:59:38 +02:00
can1357 201b91199f fix(tui): corrected ellipsis type check in truncateToWidth
- Adjusted the conditional check to correctly identify string-based ellipsis inputs.
- Resolved logic for applying default ellipsis behavior when invalid or empty types are provided.

Fixes #3492
2026-06-25 20:51:20 +02:00
can1357 53d50ce520 test(coding-agent): improved follow-up dispatch failure handling tests
- Update follow-up dispatch tests to assert error surfacing and draft recovery.
- Remove erroneous expectations that rethrow exceptions from fire-and-forget calls.
- Track error notifications via a new `showError` spy.
2026-06-25 20:48:39 +02:00
can1357 06ca03dbd8 fix(agent): release task spawn slot when progress reporting throws
In #registerSpawnJob the markRunning()/reportProgress() calls sat between
semaphore.acquire() and the try whose finally releases the slot. If progress
reporting threw there, the acquired task.maxConcurrency slot leaked and
permanently shrank subagent concurrency. Move those statements inside the try
so finally always releases. The abort-before-execution branch is unchanged
(releases once and throws before the try is entered — not a double release).

Refs #3464
2026-06-25 20:48:38 +02:00
can1357 ecd6f608e5 fix(agent): resize provider concurrency limiter in place instead of replacing it
The per-provider subagent limiter (providers.ollama-cloud.maxConcurrency)
created a fresh Semaphore whenever the configured limit changed, orphaning
in-flight slots on the old instance so a runtime or mixed limit value could
exceed the cap. getProviderSemaphore now always hands out one shared limiter
(Infinity when unlimited, so every run is still counted) and resizes it in
place. Semaphore.release() decrements before admitting, and the new
Semaphore.resize() raises the ceiling by admitting queued waiters while
lowering it drains in-flight holders without admitting past the new cap.

Refs #3464
2026-06-25 20:48:38 +02:00
can1357 ded0976af2 chore: normalize changelog after #3466 merge 2026-06-25 20:48:38 +02:00
can1357 556ced266c Merge PR #3466 into sweep 2026-06-25 20:42:31 +02:00
can1357 3721e47c51 chore: normalize changelog after PR sweep 2026-06-25 20:42:30 +02:00
can1357 88783b6e5c fix(agent): cancel in-flight auto-compaction on manual compact startup
The preserveCompaction abort path skipped abortCompaction() entirely,
so a manual /compact starting while auto-compaction was in flight no
longer cancelled it. Both passes could then appendCompaction/
replaceMessages, double-rewriting history (reachable via the RPC/
extension compact paths, whose only guard checks #compactionAbortController).
Preserve the just-installed manual controller but still abort the
auto-compaction controller. Adds regression coverage.
2026-06-25 20:42:30 +02:00
can1357 5cfea2884d Merge PR #3489 into sweep 2026-06-25 20:42:30 +02:00
pr-evalandcan1357 0fb6af9354 fix(coding-agent): keep ast_grep/ast_edit patterns in transcript summaries
Adding `paths` to the global PRIMARY_ARG_KEYS hid the pattern for the
structural tools: ast_grep ({pat,paths}) and ast_edit ({ops,paths})
rendered scope-only (e.g. `ast_grep(src/**/*.ts)`), dropping `pat`/`ops`
— the most decision-relevant argument. Drop the global `paths` key and
special-case `find` (mirroring `search`) so find/search still surface
scope while ast_grep/ast_edit keep showing their pattern via the
existing fallback. Adds regression tests for both structural tools.
2026-06-25 20:42:30 +02:00
can1357 3ba39c1ec4 Merge PR #3486 into sweep 2026-06-25 20:42:30 +02:00
can1357 0aef0b522c test(bash): resolved bash/echo paths so snapshot e2e tests pass on macOS
The two getOrCreateSnapshot e2e tests hard-coded /usr/bin/bash and
/usr/bin/echo, both absent on macOS (bash is /bin/bash, echo is
/bin/echo). The symlink then pointed at a nonexistent target so
getOrCreateSnapshot returned null, and the replay invoked a missing
echo. Since #3470 is a macOS bug, the regression tests could not run on
the affected platform. Resolve bash via Bun.env.SHELL (mirroring
bash-executor.test.ts) with a /bin/bash fallback and an existsSync skip
guard, and resolve echo via Bun.which with a /bin/echo fallback.
2026-06-25 20:42:30 +02:00
can1357 15816b03af Merge PR #3474 into sweep 2026-06-25 20:42:29 +02:00
can1357 f61fc85382 Merge PR #3477 into sweep 2026-06-25 18:53:34 +02:00
can1357 61da80d2ae Merge PR #3468 into sweep 2026-06-25 18:53:34 +02:00
can1357 2420b7e525 Merge PR #3475 into sweep 2026-06-25 18:53:12 +02:00
can1357 6890b0ffd7 Merge PR #3463 into sweep 2026-06-25 18:53:12 +02:00
roboomp d380a9e723 fix(agent): queued manual compact startup steers
Install the manual compaction abort controller before abort teardown so input routing observes session.isCompacting during the starting window.

Fixes #3485
2026-06-25 15:49:23 +00:00
roboomp 08854f9f16 style: bun run fix 2026-06-25 15:39:12 +00:00
roboomp 8f63bd60be fix(coding-agent): surfaced transcript search paths
Added scoped path summaries for find/search tool calls in concise session history rendering, with regression coverage for JSON fallback and hidden search scope.

Fixes #3482
2026-06-25 15:38:59 +00:00
roboomp d08dc7946b fix(bash): kept snapshot 0600 when rc resets umask
PR #3474 second review: previous revision ran `umask 077` only BEFORE
sourcing the rc, so a typical `.bashrc`/`.zshrc` that calls
`umask 022` reopened the world-read window between the spawned shell's
first `>|` and the JS post-spawn chmod. Snapshot file (with inlined
env-var values) lived at 0644 for the full body of the script.

Two-layer fix:
 - JS caller now pre-creates the snapshot file at 0600 with
   `fs.writeFileSync(path, "", { mode: 0o600 })` before spawning. The
   shell's `>|` (truncate) and `>>` (append) preserve the existing
   inode mode, so the file is 0600 from byte zero regardless of the
   spawned shell's umask state.
 - Script also re-applies `umask 077` after the rc source so any
   other file the script might create (none today, defensive) stays
   private even when the rc resets umask.

New e2e regression test seeds a `.bashrc` containing `umask 022` and
asserts the resulting snapshot mode `& 0o077 === 0`.
2026-06-25 15:26:26 +00:00
roboomp 8f05a29d4d fix(cli): aligned gallery state labels
Accepted displayed gallery lifecycle labels as --state aliases, rejected unknown values before rendering, and updated failed fixtures to render visibly failed states.

Fixes #3473
2026-06-25 15:22:35 +00:00
roboomp 1ab1838587 fix(tui): treated warp wsl host as windows for kitty
Bun reports process.platform as 'linux' inside WSL even when the rendering Warp is the Windows build, which lacks Kitty support and prints APC sequences as visible garbage. Detected WSL via WSL_DISTRO_NAME/WSL_INTEROP and disabled the Kitty image protocol in that case.

Refs #3471
2026-06-25 15:22:32 +00:00
roboomp de1368fd2d fix(bash): tightened snapshot perms and denied secret-shaped env vars
PR #3474 review: the new export pass writes referenced env-var values
into a snapshot file under `os.tmpdir()/omp-shell-snapshots`. On Linux
where `os.tmpdir()` is `/tmp` and the umask is the default 022, the
file ended up world-readable (0644) until postmortem cleanup. A user
rcfile defining `deploy(){ curl -H "Authorization: $GITHUB_TOKEN" ...; }`
would have its token written verbatim to that file.

Three-layer mitigation:
 - `umask 077` at the top of the snapshot script so the file is 0600
   from the first byte (the shell creates it via redirection, not JS).
 - JS caller now passes `mode: 0o700` to `mkdirSync` and chmods the
   dir + file defensively after the script exits, covering pre-existing
   dirs and exotic shells where the umask call might not take.
 - Helper denylist gained the common secret-shaped name patterns
   (`*TOKEN*`, `*SECRET*`, `*API_KEY*`, `*PASSWORD*`, `*PASSWD*`,
   `*PRIVATE_KEY*`, `*ACCESS_KEY*`, `*CREDENTIAL*`, `*SESSION_KEY*`)
   so even when the file is locked down, we don't materialise tokens
   onto disk in the first place.

Tests cover both: a new helper-level test asserts none of the secret
names (or their values) appear in the export stream, and the e2e test
now stats the snapshot file + dir and asserts `mode & 0o077 === 0`.
2026-06-25 15:19:23 +00:00
roboomp 4ab1f25503 fix(tui): recognized warp terminal capabilities
Detected Warp via TERM_PROGRAM=WarpTerminal and mapped its platform-specific image and hyperlink capabilities.

Fixes #3471
2026-06-25 15:15:04 +00:00
roboomp 77265de55e fix(bash): re-exported env vars referenced by snapshotted shell functions
generateSnapshotScript captured the user's shell functions via declare -f /
typeset -f and dropped everything except PATH on the export floor. mise
activate installs a mise() function whose body expands $__MISE_EXE; the
replay shell then ran `command "" "$@"` and died with
`command: command not found:` (exit 127). The same shape breaks asdf
shims, direnv-style helpers, and any other activation idiom that pairs a
shell function with a sidecar env var.

The snapshot script now scans captured function bodies for $VAR /
${VAR…} references and re-emits `export NAME='value'` for each name
that is currently set and not on a shell-internal denylist (PATH, HOME,
BASH_*, LC_*, …). getShellConfigFile also honours env.HOME so callers
(and tests) can target a sandboxed home — os.homedir() is cached by Bun
and ignores later process.env.HOME mutations.

Fixes #3470
2026-06-25 15:10:59 +00:00
roboomp 039c93be60 fix(tui): restore streaming steer image draft on prompt error
Wrap the streaming Enter steer dispatch in try/catch so prompt failures restore text plus pendingImages / pendingImageLinks / imageLinks and surface showError instead of losing an image-only draft.\n\nAlso remove a forbidden ReturnType<> from the follow-up image regression helper.\n\nFixes #3467
2026-06-25 13:53:00 +00:00
roboomp b0bbd872c4 fix(tui): restore followup image draft on prompt error
Snapshot pendingImageLinks alongside pendingImages at the top of handleFollowUp and wrap both the streaming and idle session.prompt dispatches in try/catch that restores text + pendingImages + pendingImageLinks + imageLinks and surfaces showError, mirroring the main submit and focused submit error paths so an image-only or text+image Ctrl+Enter draft survives dispatch rejection.\n\nFixes #3467
2026-06-25 13:47:06 +00:00
roboomp a2a217277c fix(tui): restore focused submit image draft on prompt error
Snapshot pendingImageLinks and re-seed editor.pendingImages / pendingImageLinks / imageLinks in the focused-session submit catch block so an image-only or text+image draft survives a viewSession.prompt rejection, mirroring the main controller error path.\n\nFixes #3467
2026-06-25 13:40:14 +00:00
roboomp e24b70c09a fix(tui): queued image-only streaming submits
Treat pending pasted images as submit content in the main and focused input controller paths so image-only Enter/Ctrl+Enter submissions queue instead of dropping or aborting.\n\nFixes #3467
2026-06-25 13:32:18 +00:00
roboomp 7e90e4d081 fix(agent): released ollama-cloud semaphore slot when waiter aborts
Semaphore.acquire now accepts an AbortSignal so a queued waiter that is cancelled (parent task abort, wall-clock budget elapsing) removes itself from the wait queue instead of being resolved by the next release. The provider semaphore in runSubprocess passes the run's abortSignal through, preventing aborted ollama-cloud subagents from permanently draining the provider concurrency budget.

Fixes #3464
2026-06-25 12:14:45 +00:00
ben d3060f9491 fix(tui): keep interrupts ahead of repaint 2026-06-25 20:01:06 +08:00
roboomp 80862b79da fix(agent): handled ollama-cloud task backoff
Added ollama-cloud subagent concurrency limiting, role fallback-chain inheritance, and visible empty length errors for native Ollama responses.

Fixes #3464
2026-06-25 11:57:51 +00:00
roboomp 184f6dd809 style: bun run fix 2026-06-25 11:41:56 +00:00
roboomp 8506fbdf52 fix(coding-agent): switched ctrl-z handler to SIGSTOP-self to defeat brush tokio SIGTSTP hijack
brush-core's Process::wait calls tokio::signal::unix::signal(SIGTSTP) to
detect when its children get stopped. Per tokio's documented contract,
the first call for a SignalKind permanently replaces the kernel-default
handler for the lifetime of the process. So once omp has executed any
bash tool call — even /usr/bin/true — SIGTSTP's default "stop" action
is gone, and InputController.handleCtrlZ's process.kill(0, "SIGTSTP")
gets swallowed by tokio. The TUI tore down via ui.stop() but the process
kept running in Sl+ state, leaving the user with a dead terminal that
only kill -9 could recover.

Send SIGSTOP to our own PID instead. SIGSTOP can't be caught, blocked,
or ignored — it stops the process at the kernel regardless of installed
handlers. Targeting self (not pgid=0) also leaves long-lived children
(MCP stdio servers, the persistent brush native shell) running across
the suspend, so they no longer freeze mid-IPC during a quick fg/bg
detour.

Fixes #3461
2026-06-25 11:33:35 +00:00
can1357 451af61280 chore: bump version to 16.1.19 2026-06-25 13:14:44 +02:00
can1357 c46216742b feat(hashline): implemented tag-based patch path recovery
- Automatically rebind edits to the correct file when an authored path does not exist but the filename and snapshot tag uniquely match a file read earlier in the session.
- Prevent path recovery for paths that would escalate write privileges, ensuring compatibility with read-only internal URL targets.
- Surface warning messages to the model and user upon successful path recovery to encourage correct future path usage.
2026-06-25 13:14:05 +02:00
can1357 57e9848c8c refactor(coding-agent): removed automatic file attachment for non-image paste paths
- Removed `onPasteFilePath` handler to prevent automatic background file attachment when pasting paths.
- Updated `CustomEditor` to treat non-image paths as literal text input.
- Cleaned up unused file system utilities and paste path resolution logic.
2026-06-25 12:57:54 +02:00
can1357 c03a78917a test(coding-agent): disabled fsmonitor during test repo initialization
- Added core.fsmonitor configuration to the git initialization process in test setup to prevent potential environment-specific conflicts.
2026-06-25 12:55:01 +02:00
can1357 a13c8d2698 fix(utils): prevented winston warnings when transports are disabled
- Set logger to silent mode when no transports are active to avoid "no transports" errors during log emission.
- Added a regression test to verify that disabling all transports suppresses warnings and that log output resumes after re-enabling transports.
2026-06-25 12:46:49 +02:00
can1357 2c80863e55 fix(utils): silenced logger when no transports are configured
- Added a check for empty transport arrays during logger initialization.
- Set the logger to silent mode if no transports exist to prevent unnecessary warning messages on every log emit.
2026-06-25 12:45:02 +02:00