Commit Graph
5962 Commits
Author SHA1 Message Date
Tommaso Fontana dfd0fe3cfa fix(omp): reject ssh:// query/fragment and non-POSIX login shells (#3553 review)
remotePathFromUrl now rejects a URL query string or fragment, so a mistyped ssh://host/tmp/a?draft no longer silently operates on /tmp/a; a literal ?/# in a remote filename must be percent-encoded (%3F/%23).

ssh:// transfers now require a sh/bash/zsh login shell. fish can't parse the POSIX transfer snippets and csh/tcsh apply ! history expansion to the command line, so they're refused (use the ssh tool). Host-shell detection no longer misclassifies fish/csh/tcsh as sh (basename allowlist over endsWith), and HOST_INFO_VERSION is bumped to re-probe caches that stored the old classification.
2026-06-26 23:01:49 +02:00
Tommaso Fontana 8ad45254c6 fix(omp): use portable dirname in ssh write staging (#3553 review)
dirname is an operand-only POSIX utility (no options), so 'dirname -- "$t"' is non-portable on macOS/BSD (the -- is treated as an operand). The temp path is always absolute, so the end-of-options guard is unnecessary; drop it. mkdir -p -- stays (mkdir conforms to the Utility Syntax Guidelines and supports --).
2026-06-26 20:41:36 +02:00
Tommaso Fontana c425a15ef5 fix(omp): chunk oversized line-mode virtual search through native grep (#3553 review)
The >4 MiB JS fallback re-introduced regex-dialect divergence by size. Oversized line-mode virtual resources are now searched in line-boundary chunks (each <= NATIVE_GREP_MAX_FILE_BYTES) through native grep, with matched line numbers offset by each chunk's start, so RE2 dialect parity holds for all line-mode sizes. A single line larger than the cap (un-grepable) is JS-tested individually. Multiline keeps the JS fallback, since chunk boundaries would drop cross-line matches. Test now proves (?i)NEEDLE matches a >4 MiB resource.
2026-06-26 20:41:36 +02:00
Tommaso Fontana 63bd006769 fix(omp): reject malformed percent-escapes in ssh:// authority (#3553 review)
decodeOr fails open, so a bad escape (ssh://prod%ZZ, ssh://user%ZZ@prod) passed the canonical authority check (both sides equally fail-open) and reached OpenSSH literally. resolveTarget now validates the encoded authority parts (url.username, url.hostname) with a throwing decodeURIComponent up front and rejects malformed escapes, matching the path decoder's fail-closed behavior. Valid percent-encoded aliases (alice%40prod) still pass.
2026-06-26 20:41:36 +02:00
Tommaso Fontana 3117f69627 fix(omp): search >4MiB virtual resources + reject trailing-slash ssh writes (#3553 review)
- search: native grep silently skips files above NATIVE_GREP_MAX_FILE_BYTES (4 MiB), so the RE2 virtual path dropped matches for large virtual resources (history://, big artifacts). searchVirtualResources now falls back to a JS RegExp matcher for oversized content (the pre-RE2 behavior) while keeping native parity for normal sizes; buildVirtualMatches still rebuilds context/ranges.
- ssh write: a trailing-slash target (ssh://h/dir/) is now rejected before staging, so the mkdir -p parent-creation no longer leaves a directory behind on a refused write.
2026-06-26 20:41:36 +02:00
Tommaso Fontana ff756807f7 fix(omp): ranged virtual search cap + ssh write parent dirs (#3553 review)
- search: the native virtual probe capped matched-line detection at INTERNAL_TOTAL_CAP before range filtering, so a ranged virtual selector (ssh://h/log:5000-5100) over a file with >2000 earlier matches returned nothing. The probe now uses the line-count bound for ranged resources so range filtering sees every hit.
- ssh write: writeRemoteFile staged into a temp beside the destination before creating parents, so writing a new nested path failed with 'No such file or directory'. It now mkdir -p's the parent before staging, matching local write, keeping the directory/special-file refusal checks.
2026-06-26 20:41:36 +02:00
Tommaso Fontana 9dd8ed12f4 fix(omp): reject empty/stray ssh:// authority markers (#3553 review)
An empty password marker (ssh://user:@prod, ssh://:@prod) leaves url.password === '' so the truthy password check skipped it. Added a canonical-authority backstop after the explicit guards: reject any authority whose decoded rawHost differs from the canonical [user@]host[:port] WHATWG parsed. This catches empty-password (and any future stray/empty marker) while every valid authority — including percent-encoded reserved-char aliases (alice%40prod, %5Bprod%3A2222%5D) — reconstructs to exactly rawHost.
2026-06-26 20:41:36 +02:00
Tommaso Fontana 7c9342bee4 fix(omp): run virtual/remote search with the native RE2 dialect (#3553 review)
searchVirtualResources matched with JS RegExp, so an ssh:// (or other virtual) search diverged from local search for RE2-valid but JS-invalid patterns (e.g. (?i)x, [[:digit:]]) — throwing 'Invalid regex' or returning different matches even when local grep had already validated the pattern in a mixed scope. It now detects matched line numbers with native grep (the same RE2 matcher local search uses) and rebuilds the existing forward-only, range-trimmed context windows via buildVirtualMatches, so virtual/remote and local search share one dialect. Removed the now-dead JS-regex helpers (probeRegexDialect, compileVirtualRegex, searchVirtualResource{Lines,Multiline}, findLineIndex).
2026-06-26 20:41:36 +02:00
Tommaso Fontana da2bccfdf9 fix(omp): reject ssh:// URL passwords and empty userinfo (#3553 review)
resolveTarget now rejects a non-empty password (ssh://user:pass@host, ssh://:pw@host) since ssh:// uses key/agent auth (BatchMode), and a literal empty username (ssh://@host) that previously fell through to the bare-host fallback and could match a configured host. Both use the same decoded-authority comparison as the empty-port guard, so a percent-encoded alias like %40prod (decodes to @prod) is still matched.
2026-06-26 20:41:36 +02:00
Tommaso Fontana 36e82776cf fix(omp): let IPv6 ssh:// URLs reach the resolver in search (#3553 review)
search's generic glob-char guard saw the [ ] of an IPv6 authority (ssh://[::1]/etc/hosts) and threw 'Glob patterns are not supported' before the SSH handler could strip the brackets. The check now runs only on the path portion for ssh:// URLs, so IPv6 literals resolve while a glob in the remote path (ssh://host/p*) still rejects.
2026-06-26 20:41:36 +02:00
Tommaso Fontana 33a435af67 fix(omp): stat ssh:// targets before reading to reject special files (#3553 review)
resolve() ran readRemoteFile (head) before any classification, so a FIFO with no writer blocked until the 30s timeout and a device like /dev/zero streamed the whole probe. It now stats first: directory -> listing, special file (other) -> fast refusal, regular file -> read. missing/stat-failure still falls through to the read so the original remote stderr surfaces.
2026-06-26 20:41:35 +02:00
Tommaso Fontana a7d2fb3b21 fix(omp): reject ssh:// overrides on encoded configured aliases (#3553 review)
The override-rejection compared the still-encoded url.hostname, so a user/port override on a reserved-char alias (configured alice@prod addressed as ssh://bob@alice%40prod/) slipped through to the opaque target (bob@alice@prod). The guard now also compares the decoded bare host; the error names the decoded host while suggesting the correct encoded URL.
2026-06-26 20:41:35 +02:00
Tommaso Fontana ceefaf4f6b fix(omp): decode percent-encoded ssh:// username and host for the connection target (#3553 review)
The override path stored url.username/url.hostname verbatim, so ssh://user%40corp@host/ reached OpenSSH as user%40corp@host (wrong user). Decode both before building the SSHConnectionTarget. Decoding happens before buildSshTarget's leading-dash guard, so an encoded %2DoProxyCommand now decodes to -oProxyCommand and is rejected.
2026-06-26 20:41:35 +02:00
Tommaso Fontana 04bc70a8ad fix(omp): reject encoded empty ssh:// port authorities (#3553 review)
The empty-port guard compared decoded url.rawHost against the percent-encoded url.hostname/username, so ssh://prod%2Dblue:/ and ssh://u%2Dname@prod:/ slipped through. Decode both sides before comparing; a %3A alias (decoded host already ends in ':') reconstructs to 'prod::' and is still left alone.
2026-06-26 20:41:35 +02:00
Tommaso Fontana 12b966f90a fix(omp): reject empty ssh:// port (#3553 review)
An empty port (ssh://host:/path) parses with url.port === "" and slipped past the malformed-authority guard as "no port", silently using the default/configured target. resolveTarget now rejects it (raw authority retains the trailing colon; percent-encoded aliases like prod%3A keep %3A in hostname and are unaffected).
2026-06-26 20:41:35 +02:00
Tommaso Fontana f7ff11b15b fix(omp): address #3553 round-2 review feedback
- strip IPv6 URL brackets before invoking ssh (ssh://[::1]/ -> ::1)
- reject malformed/out-of-range ssh:// ports before connecting (prod:abc, host:65536)
- search requests directory metadata only (skipDirectoryListing) instead of draining a remote ls it always rejects
2026-06-26 20:41:35 +02:00
Tommaso Fontana 73c1b33fd9 fix(omp): address #3553 review feedback
- reject explicit ssh:// port 0 before connecting (Codex P2)
- keep a path-less ssh://host:port authority port out of selector peeling
- restore ResolveContext on ProtocolHandler.complete (symmetry with resolve/write)
- clarify search/read selector-parity docs + add read-side regression
2026-06-26 20:41:35 +02:00
Tommaso Fontana 3028bc4ef0 feat(omp): autocomplete ssh:// hosts and list them on bare read
- ssh handler complete() suggests the configured hosts; bare `read ssh://` resolves to an immutable host index (markdown links per host)
- thread a minimal cwd through the completion pipeline (provider basePath -> getInternalUrlSuggestions -> router.complete -> handler.complete) so project-scoped ssh.json hosts resolve like the cwd-aware bare-read path
- scoped to configured SSH-capability hosts; opaque ~/.ssh/config aliases stay usable at ssh://alias/path but are not enumerated
- local handler complete() signature updated to match (behavior preserved; the router never threaded context to it)
2026-06-26 20:41:35 +02:00
Tommaso Fontana e4ceebb258 feat(omp): list ssh:// directories via read
- `read ssh://host/dir` lists a remote directory one level deep; `ssh://host/` lists the remote root
- add statRemotePath + listRemoteDir; resolve reads first and classifies on error (directory -> one-level listing, dirs-first, dotfiles included)
- directory resources carry isDirectory + immutable and expose no sourcePath
- search refuses a virtual (no-sourcePath) directory resource instead of grepping the listing text
- writeRemoteFile refuses a directory destination and cleans up its temp on that path
2026-06-26 20:41:35 +02:00
Tommaso Fontana f9ece90853 fix(omp): harden ssh:// URL handler per PR review
- buildSshTarget rejects destinations beginning with "-" (SSH argument-injection / local RCE guard)
- gate ssh:// read/search/write at the exec approval tier; substring scan covers search's pre-expansion delimited paths and write's hashline-wrapped paths
- validate the entire materialized buffer as UTF-8 instead of only the first 8 KiB prefix
- write peels read selectors (raw/conflicts) so it targets the same file read does, and rejects line-range/malformed selectors instead of silently stripping them
- write to a uniquely named remote temp; document symlink-replacement on write as a v1 limit
2026-06-26 20:41:35 +02:00
Tommaso Fontana c63171b909 feat(omp): add ssh:// URL support to read, search, and write 2026-06-26 20:41:35 +02:00
can1357 52b8fb1565 feat(coding-agent): improved session title casing logic
- Updated `normalizeGeneratedTitle` to reconcile model-generated titles against the user's input instead of forcing title-case.
- Added logic to restore distinctive proper-noun casing (e.g., `TinyVMM`) and flatten model-generated camelCase artifacts (e.g., `dAemon`) that do not appear in the user's message.
- Ensured model-cased proper nouns that are not in the source message (e.g., `GitHub`) are preserved.
2026-06-26 20:27:40 +02:00
can1357 5d4203d52b fix(coding-agent): preserved resume scoping after PR merges 2026-06-26 17:17:43 +02:00
can1357 d07d03d2af Merge PR #3565: compact long tool loops mid-turn (@riverpilot) 2026-06-26 17:12:09 +02:00
can1357 b6b0379a3b Merge PR #3540: manual coding-agent GC command (@Kenmege)
# Conflicts:
#	packages/coding-agent/test/issue-3461-repro.test.ts
2026-06-26 17:09:24 +02:00
can1357 80c6528c93 fix(coding-agent): resolved PR 3562 merge fallout 2026-06-26 17:08:53 +02:00
can1357 40e56a6318 Merge PR #3562: resume by ID, Nix/Mermaid highlighting (@arg3t)
# Conflicts:
#	packages/coding-agent/test/issue-3461-repro.test.ts
2026-06-26 17:07:48 +02:00
Alexander Kirilin e9530895a1 Merge remote-tracking branch 'origin/main' into fix/mid-turn-auto-compaction-3525 2026-06-26 11:02:40 -04:00
Alexander Kirilin d2b6bde571 fix(agent): preserve mid-turn tool persistence order 2026-06-26 10:57:36 -04:00
can1357 55b02a568d feat(coding-agent): improved local artifact sandbox handling and path recovery
- Enabled tag-based path recovery for artifacts within the session `local://` sandbox.
- Restructured `hashline` path recovery logic to ensure preflight validation runs on resolved paths.
- Prevented ACP editor buffer routing for session `local://` sandbox artifacts.
- Added comprehensive tests covering sandbox target identification and recovery for bare file names.
2026-06-26 16:39:48 +02:00
can1357 bf110f9a18 feat(coding-agent): updated plan-mode guidance for block-level edits
- Added instructions for writing sections as cohesive multi-line blocks when performing edit operations.
- Clarified that block operations require multi-line sections to avoid falling back to standard editing behavior.
2026-06-26 16:20:05 +02:00
can1357 cf7894ffa1 Merge remote-tracking branch 'origin/farm/2a4ef5fb/use-default-role-for-fresh-startup' 2026-06-26 16:14:50 +02:00
can1357 02f870fb20 feat: supported markdown section operations for block edits
- Added tree-sitter markdown support to resolve headings into full sections in `pi-ast`.
- Enabled block operations (`SWAP.BLK`, `DEL.BLK`, `INS.BLK.POST`) on markdown headings so they encompass the entire section, including nested deeper headings.
- Updated system prompt to guide agents in using structured markdown heading edits for plans.
- Fixed `plan-mode-guard` to correctly resolve local protocol options for subagents.
2026-06-26 16:14:23 +02:00
roboomp aad2a0fa49 fix(coding-agent): honored modelRoles.default for extension-provided models on fresh launch
The createAgentSession default-role resolution ran before extension
factories registered their providers, so a default role pointing at an
extension-provided model (e.g. an openai-compat plugin's
posthog/claude-opus-4-8) returned undefined there. On a fresh launch
(no -c/--resume) the post-extension fallback went straight to
pickDefaultAvailableModel and replaced the user's configured default
with the first bundled provider default that had auth — commonly
openai/gpt-5.5 when OPENAI_API_KEY was set.

The fallback now retries resolveModelRoleValue against the
post-extension allowed-model set before pickDefaultAvailableModel, and
re-applies the role's explicit thinking selector / model host
preconnect.

Fixes #3569
2026-06-26 14:08:12 +00:00
roboomp 52d1a04652 fix(mcp): reused attached windows console for stdio wrappers
Detected whether the OMP host already owns an inheritable Windows console before resolving stdio MCP spawn flags.

Skipped CREATE_NO_WINDOW for console-attached MCP wrapper chains so cmd.exe and PowerShell grandchildren reuse the existing terminal instead of allocating visible conhost windows.

Fixes #3567
2026-06-26 13:54:10 +00:00
Alexander Kirilin ab513757f8 fix(agent): preserve tool turn before mid-run compaction 2026-06-26 09:35:24 -04:00
Alexander Kirilin e99b8c4128 docs(agent): clarify mid-turn continuation hook 2026-06-26 09:17:07 -04:00
Alexander Kirilinandcoderred bbe3d98375 fix(agent): compact long tool loops mid-turn
Co-authored-by: coderred <coderredlab@gmail.com>
2026-06-26 09:05:11 -04:00
arg3t b10cea54d7 Merge branch 'main' of https://github.com/can1357/oh-my-pi into lsp-reload-nix-highlight
# Conflicts:
#	packages/coding-agent/src/lsp/index.ts
2026-06-26 06:03:33 -07:00
can1357 415099c420 fix: stripped stale snapcompact archive state during compaction strategy migration
- Fixed stale `preserveData.snapcompact` frames leaking into context-full compaction after switching from `snapcompact` to `context-full` strategy, which inflated context usage and made sessions appear to compact prematurely.
- Added secret redaction for migrated snapcompact archive plaintext (`text`/`textHead`/`textTail`) during the snapcompact->context-full transition, while preserving opaque provider-replay state byte-identical.
- Added `archiveSourceText()` and `stripPreservedArchive()` utilities to snapcompact module for archive extraction and cleanup.
2026-06-26 14:31:50 +02:00
can1357 93b80e5b1b refactor: consolidated duplicate
- Consolidated duplicate `stripSnapcompactPreserveData` functions into `snapcompact.stripPreservedArchive`.
- Added unit tests to verify archive removal and empty state collapse behavior.
2026-06-26 14:28:49 +02:00
Can BölükandGitHub 13100cbade Merge pull request #3561 from serverinspector/fix/snapcompact-context-full-transition
fix(agent): stop stale snapcompact state leaking into context-full
2026-06-26 14:21:24 +02:00
Dr Kennedy Umege 5ea467aa3c fix: address gc review edge cases 2026-06-26 12:58:30 +01:00
arg3t e7cbe0a9fe fix(coding-agent): resolve slash resume across cwd sessions 2026-06-26 04:51:45 -07:00
arg3t 599874e255 feat(coding-agent): support resume by session id 2026-06-26 04:34:44 -07:00
arg3t e894753603 feat(tui): add mermaid rendering toggle 2026-06-26 04:34:44 -07:00
can1357 ac904fc70c fix: patched Kimi model edit mode fallback
- Added a fallback from `hashline` to `replace` mode for Kimi-family models to resolve compatibility issues.
- Introduced `PI_STRICT_EDIT_MODE` environment variable to bypass automatic model-specific edit-mode fallbacks.
- Updated `getEditVariantForModel` to perform case-insensitive matching for model variant configurations.
- Added comprehensive unit tests for edit mode resolution and settings configuration.
2026-06-26 13:17:35 +02:00
Dr Kennedy Umege 1912cf93ab fix: align gc dry-run and wal failures 2026-06-26 11:53:44 +01:00
can1357 68d7593244 chore: reorg 2026-06-26 12:24:42 +02:00
Dr Kennedy Umege 087a0a4be0 fix: tighten gc dry-run and failure status 2026-06-26 11:23:33 +01:00