Commit Graph
7546 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 9e656c7421 test(omp): align session-title casing tests with main's reconcileTitleCasing
Upstream main 52b8fb156 changed normalizeGeneratedTitle to reconcile a generated title's casing against the user's message instead of forcing Title Case, and updated the tiny-text unit tests but not the title-generator/role-thinking integration suites. The rebase surfaced their stale Title-Case expectations as CI failures. Update the 6 expectations to the reconciled output; no production code change.
2026-06-26 21:46:42 +02:00
Tommaso Fontana 902fc6390e chore(omp): reconcile ssh:// CHANGELOG under [Unreleased] after main rebase
The rebase split the ssh:// entries: Added merged into the new [Unreleased] but the Fixed bullets landed under the released [16.1.23] section (where main's release script had moved the old [Unreleased] Fixed anchor). Moved the ssh:// Fixed bullets back under [Unreleased]; main's 16.1.23 and other released sections are verbatim.
2026-06-26 20:47:47 +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 b83a67a740 chore(omp): reconcile ssh:// CHANGELOG under [Unreleased] after main rebase
The rebase auto-merged the ssh:// Added/Fixed bullets into the released [16.1.20] section (where main's release script had moved the old [Unreleased] content they were anchored to). Moved them back under [Unreleased]; main's 16.1.20/21/22 sections are untouched.
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 51779aeefd chore: bump version to 16.1.23
Fixed a non-deterministic gc-cli archive test: archive-me and keep-recent
shared ageDays:90, so their mtimes tied within a millisecond on fast CI and
the retainNewestGlobal:1 'keep newest' pick fell back to readdir order,
archiving the wrong session. Give keep-recent ageDays:60 (still cold-eligible,
unambiguously newer).
2026-06-26 18:43:32 +02:00
can1357 011f036ef5 chore: bump version to 16.1.23 2026-06-26 18:29:01 +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 d7f05ac640 fix(catalog): scoped CoreWeave catalog metadata 2026-06-26 17:12:01 +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
can1357 4af09a6030 feat(ai): implemented stall detection for thinking-loop streaming
- Integrated progress-lexicon analysis to identify and warn on low-information lexical stalls during reasoning.
- Enhanced loop stream processing to strip summarizer titles before performing analytical checks.
- Introduced CONCRETE_ANCHOR pattern and windowed state management to improve detection of novel reasoning references.
- Refactored the test suite to use a standardized feed function for chunked streams and added coverage for specific stall scenarios.
2026-06-26 17:00:25 +02: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
arg3t 033f0aab23 test(coding-agent): tolerate wrapped MCP job-control comment 2026-06-26 07:05:56 -07:00
can1357 6ecdb5637d Merge remote-tracking branch 'origin/farm/c4e0cc3d/fix-windows-mcp-conhost-windows' 2026-06-26 15:56:22 +02: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
can1357 44368e3459 test(coding-agent): removed tests using source-grep patterns
- Removed multiple test files and cases that relied on brittle source string matching for validation.
- Updated project architecture documentation to explicitly prohibit source-grep style testing patterns.
- Eliminated legacy reproduction tests for issues that reached project maturity.
2026-06-26 15:51:34 +02:00
can1357 c39b655ae7 feat: implemented -q and -x flags for in-process grep
- Added support for `--quiet` (`-q`) and `--line-regexp` (`-x`) to the `grep` builtin.
- Enabled short-circuiting behavior for `-q` to suppress output and return early on the first match.
- Configured exit status logic to prioritize successful matches over error states when using `-q`.
- Added integration tests to verify correct exit status codes and line anchoring behavior.
2026-06-26 15:47:24 +02: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