Commit Graph

139 Commits

Author SHA1 Message Date
can1357 20d19e8002 test: replaced blind sleeps with shared fixtures and condition polling
- Shared immutable model registries and auth storage via beforeAll/afterAll.
- Swapped fixed-delay settle sleeps for predicate polling and signals.
- Stubbed network/timers to drop wall-clock waits in registry and history tests.
- Added resetDisplay invalidation tests and startup-timing breakdown lines.
2026-06-06 22:09:04 +02:00
can1357 5004ba057f feat(auth-broker): added encrypted local snapshot cache
- Added AES-GCM cache for at-rest broker snapshots keyed on token, with URL as additional data.
- Added `onSnapshot` hook to RemoteAuthCredentialStore for persisting applied snapshots.
- Exposed cache read/write and TTL defaults through the coding-agent re-exports.
- Added `getAuthBrokerSnapshotCachePath` with `OMP_AUTH_BROKER_SNAPSHOT_CACHE` override.
2026-06-05 11:09:47 +02:00
can1357 52b3d90400 Merge remote-tracking branch 'origin/farm/87e6f6ee/fix-edit-renderer-enametoolong' 2026-06-04 18:35:39 +02:00
can1357 c4c2e43f35 chore: reformat 2026-06-04 18:33:36 +02:00
roboomp 9e3173da4e fix(utils): normalized paths before indentation length guard
- Moved the overlong-component guard to run after resolveFilePath so syntactically noisy but valid paths like long/../src/file.ts still honor editorconfig rules.
- Added a regression test that proves normalized paths with an eliminated overlong component resolve the configured tab width.

Fixes #1872
2026-06-04 16:32:02 +00:00
can1357 0ddc5b3804 Merge remote-tracking branch 'origin/farm/87e6f6ee/fix-edit-renderer-enametoolong' into main2 2026-06-04 18:31:05 +02:00
roboomp a27e0add5f fix(utils): made editorconfig discovery resilient to malformed paths
- Tightened parseCachedEditorConfig to absorb any FsError, not just
  ENOENT. Editorconfig lookup is best-effort indentation hinting; an
  unreadable .editorconfig (ENAMETOOLONG, ENOTDIR, EACCES, ELOOP,
  EINVAL, …) means "no usable config here", not a fatal condition for
  callers like the edit renderer.
- Added a path-component length gate (NAME_MAX = 255 bytes) in
  getIndentation that short-circuits to the default tab width before
  any syscall. Renderers can hand arbitrary strings into replaceTabs
  (e.g. a malformed edit tool call whose file_path is gibberish);
  attempting to open <dir>/.editorconfig for a 500-byte component
  would otherwise crash the TUI with an uncaught ENAMETOOLONG.
- Added regression tests covering both safety nets.

Fixes #1872
2026-06-04 16:27:55 +00:00
roboomp 72f41f333e fix(utils): swallow editorconfig probe errors to keep TUI rendering safe
parseCachedEditorConfig caught only ENOENT, so an oversized path segment
(e.g. a 2KiB garbage string emitted by a hallucinating model) blew up
the renderer with an uncaught ENAMETOOLONG from fs.readFileSync. The
editorconfig probe is best-effort — there is no useful difference
between 'file missing' and 'open() refused for any other reason' from
the renderer's perspective. Catch every error, cache the miss so we do
not re-probe the same bogus path on every redraw, and add a regression
test that exercises the 2KiB-segment path through getIndentation.

Fixes #1871
2026-06-04 16:24:59 +00:00
Can Bölük a6997b1b7f Merge branch 'main' into fix/session-accent-light-contrast 2026-06-04 06:28:21 +03:00
can1357 1379772628 refactor(utils): consolidate color utilities into pi-utils
Move the color math added for the session-accent fix into the shared
@oh-my-pi/pi-utils color module instead of a coding-agent-local file:

- colorLuma, relativeLuminance, and hslToHex now live in
  packages/utils/src/color.ts (hslToHex lifted out of session-color.ts).
- Drop the duplicate hex parser: toRgb reuses the existing hexToRgb and
  paletteToRgb returns the shared RGB type, so hex parsing lives once.
- Delete packages/coding-agent/src/utils/color.ts; theme.ts and
  session-color.ts import from @oh-my-pi/pi-utils.
- Move the color unit test into the utils package; repoint session-color
  test imports.

No behavior change to accent luminance capping.
2026-06-04 05:27:11 +02:00
can1357 5e17edf1ec refactor(coding-agent): restructured session text slicing to use unified head/tail reads
- Replaced SessionStorage readTextPrefix/readTextSuffix with readTextSlices.
- Added peekFileEnds utility to read bounded file head/tail in one handle.
- Updated session-manager list/recent reads to consume unified head/tail slices.
- Expanded storage tests for head/tail and UTF-8-boundary slice extraction.
2026-06-04 02:07:34 +02:00
can1357 e6716d086d feat(coding-agent): added lifecycle status to session picker
- Classified each session's final message as done, interrupted, aborted, error, or pending from a 32 KiB tail read.
- Rendered the status as a colored segment on the session metadata line.
- Added `peekFileTail` and `readTextSuffix` across storage backends to read file tails in one pass.
- Simplified `MemorySessionStorage` to a string array mirror with a sidecar mtime map.
2026-06-04 01:58:25 +02:00
can1357 20c019fccb refactor(cli): moved MallocStackLogging cleanup to cli entrypoint
- Removed env var deletion from utils/dirs.ts (wrong layer).
- Placed it in the CLI entrypoint so it runs before any subprocess inherits the env.
2026-05-31 16:57:22 +02:00
can1357 ad15d80031 fix(mnemosyne): corrected vector-math cosineSimilarity for bad values
- Consolidated `cosineSimilarity` in `vector-math`, removed duplicate local impls, and treated mismatch/non-finite as zero.
- Switched beam, query-cache, recall, shmr, and binary-vectors to consume shared `cosineSimilarity` from `vector-math`.
- Changed embeddings to parse `$env/$flag`, return `Float32Array`, lazily import model deps, and retry via `fetchWithRetry`.
- Added `@oh-my-pi/pi-utils` and replaced hardcoded FastEmbed cache paths with `getFastembedCacheDir`.
- Expanded truthy parsing for lowercase `y`, `true`, `yes`, and `on`, then updated optional-embedding tests for cache behavior.
- Updated binary-vectors and optional-embedding tests for NaN-safe cosine, `Float32Array`, and cache-dir expectations.
2026-05-31 05:24:52 +02:00
can1357 0986a9e605 refactor(dirs): moved malloc env scrubbing into dirs module import
- Removed `scrubProcessEnv` from procmgr and its explicit call in cli.ts.
- Scrubbing now happens automatically when `dirs.ts` is imported, eliminating the need for a manual call at startup.
2026-05-30 22:26:52 +02:00
can1357 4544db344c feat: added tiny-title generation core with worker flow and model specs
- Added `providers.tinyModel` with an `online` default and UI schema metadata; documented tiny-title updates in changelogs.
- Added tiny-title system prompt and title-text helpers to truncate input, wrap `<user-message>`, and normalize output.
- Added tiny-title model registry, local model specs, key validation, and cache-path helper.
- Added tiny-title transport/client/worker flow with spawn fallback, queued requests, ping checks, and graceful close.
- Updated `generateSessionTitle` to route by tiny-title model and race local generation against delayed online fallback.
2026-05-30 16:55:54 +02:00
roboomp bdce9cf068 feat(discovery): scan installed plugin packages for sub-discovery
Marketplace and `omp plugin link` installs write to
`<plugins>/node_modules/` rather than to `extensions:` in settings,
so the original PR still missed their sibling skills/, hooks/,
tools/, commands/, rules/, prompts/, .mcp.json sub-trees. Wire
listOmpExtensionRoots to enumerate getEnabledPlugins(cwd, { home })
in addition to CLI-injected and settings-driven roots.

Adds an optional { home } parameter to getEnabledPlugins so the
discovery loader can pass through LoadContext.home for tempdir-rooted
tests. The getPluginsNodeModules/getPluginsPackageJson/
getPluginsLockfile helpers gain the same optional home overload so
they mirror getPluginsDir.

Per-PR review feedback: https://github.com/can1357/oh-my-pi/pull/1498
2026-05-29 06:28:33 +00:00
can1357 b4238b10d3 fix: resolved auth-gateway handling of 429 usage-limit responses
- Classified usage-limit gateway responses as `429 rate_limit_error` in auth handling paths.
- Aligned auth-gateway and pi-native key retrieval with derived `sessionId` for `getApiKey` lookups.
- Handled usage-limit auth failures by rotating credentials with retry hints and returning undefined when none available.
- Replaced stream auth checks with retryable-upstream logic for 401 and usage-limit errors before content.
- Expanded `extractRetryHint` parsing for `~`, `sec`, `ms`, and minute/hour units.
- Added coverage for classifyGatewayError, retry-hint parsing variants, and stream-auth retry edge cases.
2026-05-28 02:56:54 +02:00
can1357 6643178d6a refactor: replaced instanceof Promise checks with isPromise utility
- Imported isPromise from node:util/types in four modules.
- Replaced four instanceof Promise checks with isPromise calls for more reliable promise detection.
2026-05-27 13:02:52 +02:00
can1357 8a32eceb53 fix(utils): clamped usage durations to suppress stale negative reset countdowns
- Clamped `formatDuration` to return `0ms` for non-positive, NaN, or infinite inputs.
- Updated usage report rendering to suppress reset countdowns when `resetsAt` is absent or no longer in the future.
- Added unit tests for `formatDuration` covering clamped values and standard duration formatting.
2026-05-26 20:22:25 +02:00
can1357 82b3a83dd7 fix(utils): improved logger error serialization and transient error detection
- Added a custom JSON replacer that unwraps `Error` instances in logger output, preserving name, message, stack, cause, and enumerable fields.
- Updated uncaught-exception and unhandled-rejection logging paths to pass only `{ err }`, relying on the logger serializer for full error details.
- Extended transient socket-close matching to detect HTTP2 stream reset/refused/calm errors and added regression tests for logger error serialization behavior.
2026-05-26 08:07:08 +02:00
can1357 25cfee5bca fix(ai): validated auth-broker SSE stream responses and initial snapshot
- AuthBrokerClient now checked the response Content-Type and rejected non-SSE responses before parsing.
- It required the first parsed SSE event to be a snapshot and treated ended or truncated streams as errors.
- Added coverage for non-SSE and missing-initial-snapshot streams, and reset raw SSE state for empty events.
2026-05-25 20:28:58 +02:00
can1357 1228c96959 feat(coding-agent): added worktree list/clear CLI with orphan pruning
- Added the new `omp worktree` (`wt`) command with `list|clear`, `all/dry-run/json` options, and CLI registration.
- Added `listWorktrees`/`clearWorktrees` flows that scan worktrees, classify orphaned entries, emit JSON, and call `worktree.prune`.
- Replaced legacy path encoding with `hashPath` via `getWorktreeDir`, updating task isolation, storage keys, and PR checkout paths.
- Added bounded PR worktree path retries before `git worktree add` and updated checkout-path tests for hashed names.
2026-05-22 12:47:13 +09:00
can1357 4b6be0b0df fix(utils): preserve Windows env names with parentheses
The Bun.env scrub and filterProcessEnv used isValidEnvName (strict shell
identifier shape), which deleted standard Windows variables like
ProgramFiles(x86) and CommonProgramFiles(x86). procmgr.ts imports this
module before resolving the shell and reads Bun.env['ProgramFiles(x86)']
to find Git Bash under 32-bit Program Files, so installations that only
had Git there were no longer discovered and failed with 'No bash shell
found'.

The unsafe cases for native execve are '=' or NUL in names and NUL in
values, not parentheses. Introduce isSafeEnvName covering exactly those
cases and use it for the in-place Bun.env scrub and the spawn-env
filter. Keep isValidEnvName (strict) for dotenv parsing, where strict
shell-identifier shape is the right contract.
2026-05-17 13:43:00 +02:00
Vilmos Nebehaj 98405e16de fix(utils): ignore unsafe dotenv entries 2026-05-17 13:43:00 +02:00
can1357 189b9a6d35 fix(ai): addressed stream auth retries by replaying start events after 401
- Buffered `start` events until after the first replay-unsafe event and replayed them on auth failure.
- Retried stream requests with refreshed credentials when `onAuthError` returned a new key for gateway and pi-native.
- Added 401 error-status parsing for assistant errors and updated stream-auth tests for start+401 retry behavior.
- Added `AuthRetryFailure` helpers and status extraction types to propagate auth-retry metadata through stream attempts.
2026-05-17 13:13:32 +02:00
can1357 75f34d1815 feat(utils): added configurable logger transport switching for headless services
- Added a new `setTransports` logger API to swap console and file winston transports at runtime.
- Refactored logger transport creation to lazily build rotating file logs via a shared directory helper.
- Updated auth-broker serve startup/shutdown to use structured logger output and switch to console-only logs for its headless runtime.
2026-05-17 04:19:38 +02:00
can1357 cd981ae0e6 feat(utils): install ID generation 2026-05-17 01:31:16 +02:00
can1357 c3f5a60c22 feat(auth): added auth-broker for remote credential vault
- Added `AuthBrokerClient`, `RemoteAuthCredentialStore`, `AuthBrokerRefresher`, and `startAuthBroker` server in `packages/ai/src/auth-broker`.
- Renamed `AuthCredentialStore` class to `SqliteAuthCredentialStore`; extracted `AuthCredentialStore` as a persistence interface.
- Added `exportSnapshot`, `forceRefreshCredentialById`, `disableCredentialById`, and `upsertCredential` to `AuthStorage` for broker wire protocol.
- Added `omp auth-broker` CLI subcommand (serve, token, login, logout, import, status) and `discoverAuthStorage` broker-mode path keyed on `OMP_AUTH_BROKER_URL`.
2026-05-16 20:44:07 +02:00
can1357 39f34ada70 feat: added pure-JS sanitizeText
- Migrated sanitizeText from pi-natives to pi-utils as a pure-JS implementation, removing the native dependency across all call sites.
2026-05-16 20:12:26 +02:00
can1357 7282d92bf4 fix: normalized line-ending handling for text and TUI output flows
- Unified line-ending normalization to `replace(/\r\n?/g, "\\n")` in editor, scraper, benchmark, and utils modules.
- Added terminal-aware line sanitization in code-cell rendering to collapse inline carriage returns and avoid overwrite corruption.
- Tightened editor and paste sanitizers to trim control characters consistently after CR normalization.
2026-05-15 23:46:23 +02:00
can1357 361a40dc43 refactor(coding-agent): replaced reverse/find usage with last-item array helpers
- Updated plan-mode and hindsight session state lookups to use Array.findLast for selecting the latest assistant or user message.
- Updated postmortem callback iteration to use Array.toReversed before mapping cleanup callbacks.
2026-05-15 14:46:54 +02:00
can1357 1b47cd3042 feat(ai): fetch overrides
- Introduced `FetchImpl` type with optional `preconnect` to accept non-Bun fetch implementations without type errors.
- Applied the new type across all providers and `StreamOptions.fetch`.
- Added tests verifying fetch override routing for openai-completions, openai-responses, and fetchWithRetry.
2026-05-15 09:16:38 +02:00
can1357 1b76b60b17 feat(ai/providers): added configurable fetch overrides to AI provider request paths
- Introduced a `fetch` option on `StreamOptions` and threaded it through providers to let callers supply a custom request transport.
- Updated provider clients and direct HTTP calls across Anthropic, OpenAI, Azure, Google, GitLab Duo, Gemini CLI, Ollama, and Codex flows to use the injected fetch implementation.
- Extended retry helper options to accept a fetch override and preserved preconnect support from the selected fetch function.
2026-05-15 09:07:34 +02:00
can1357 1a77322a4d fix(hashline): adjusted hashline anchor rejection messaging and guidance
- Updated the hashline mismatch error to describe anchor mismatches against the current file.
- Rewrote hashline tool instructions to clarify insert payload rules, anchor usage, and avoidance of fabricated hashes.
- Expanded stale-edit detection and tests to recognize the revised anchor-mismatch rejection wording.
2026-05-14 07:06:42 +02:00
can1357 12115e4cdf fix(utils): excluded ASCII replacements inside HTML comments
- Added an HTML comment state tracker to prompt formatting.
- Updated ASCII symbol replacement to skip substitutions inside `<!-- ... -->` comment blocks across lines.
- Added tests that preserved comment text while converting symbols outside comments.
2026-05-14 06:40:50 +02:00
can1357 6eda70aada refactor: replaced abortableSleep with scheduler.wait and fetchWithRetry
- Removed local `abortableSleep` in favour of Node's built-in `scheduler.wait` from `node:timers/promises`.
- Consolidated per-provider retry/fetch loops into a shared `fetchWithRetry` utility in `packages/utils`.
- Moved `extractHttpStatusFromError`, `isRetryableError`, and related helpers out of `packages/ai` into `packages/utils`.
- Deleted `extractRetryDelay` in favour of `extractRetryHint` with unified header and body parsing.
2026-05-13 16:40:58 +02:00
can1357 a733390462 feat: added issue:// and pr:// handlers with sqlite cache ttl refresh
- Added issue:// and pr:// URL handlers for single lookups and list queries with query filters.
- Added a SQLite-backed GitHub cache with soft/hard TTLs, stale hits, and background stale refresh.
- Removed issue_view and pr_view tool operations, inputs, and docs, requiring reads via issue:// and pr:// URLs.
- Added github-cache and issue-pr-protocol tests with temporary cache DB setup and OMP_GITHUB_CACHE_DB teardown.
2026-05-13 04:04:45 +02:00
can1357 c27d007828 feat(docs): added NEVER/AVOID guidance to agent/tool/system prompts
- Standardized prompt templates across agents, tools, system, memory, and compaction to NEVER/AVOID wording.
- Reinforced policy language to ban edits/builds, state changes, and unsolicited JSON/code or filler output.
- Renamed stripRfc2119Bold to normalizeRfc2119, mapped NEVER/AVOID aliases, and skipped inline-code replacements.
- Updated the unreleased changelog to document the prompt-terminology migration.
2026-05-13 03:10:39 +02:00
can1357 b8d238b4ee docs(docs): documented RFC2119 terms to stay uppercase without bold
- Removed markdown bold from RFC 2119 MUST/SHOULD/REQUIRED across agent, tool, system, compaction, and memory prompts.
- Updated SKILL guidance to require uppercase RFC 2119 terms without bold emphasis.
- Renamed `boldRfc2119Keywords` to `stripRfc2119Bold` and made prompt formatting strip `**keyword**` markers.
- Preserved substantive prompt instruction wording while switching emphasis-only formatting in markdown templates.
2026-05-13 03:05:32 +02:00
can1357 1cb451a071 fix(workers): replaced file-URL import pattern with compiled-binary-aware spawn
- Replaced `with { type: "file" }` worker imports with `isCompiledBinary()` hybrid: literal string for `--compile` static analysis, `new URL(import.meta.url)` for dev portability.
- Added worker entrypoints as explicit `--compile` args in `build-binary.ts` so Bun emits them into bunfs.
- Added `smokeTestSyncWorker` and `omp --smoke-test` to catch silent worker-load failures in compiled binaries (fixes #1011, #1027).
- Added `isCompiledBinary()` utility to `@oh-my-pi/pi-utils` detecting bunfs path markers.
2026-05-12 16:40:15 +02:00
can1357 32e1b41889 feat(coding-agent): added prompt markers to system prompt assembly
- Added explicit prompt markers and wrappers across system templates, including `[env]`, `[role]`, `[coop]`, `[closure]`, and `[now]`.
- Removed `renderTemplate` and `sectionSeparator` flows, deleted `task/template.ts`, and switched to per-task `renderSubagentUserPrompt` rendering.
- Updated system prompt assembly to `shortenPath`-normalize `cwd`, append rendered now metadata, and preserve trailing `[now]` blocks.
- Removed legacy template tests and added prompt-composition tests for ordered `[contract]`->`[project]`->`[now]` blocks and context-only system placement.
- Reworked shared prompt utilities by collapsing consecutive blank lines and removing obsolete `OPENING_HBS`/`LIST_ITEM` helper behavior.
2026-05-10 12:27:45 +02:00
can1357 9f386dd6e5 feat(ai,coding-agent): raw SSE diagnostics + steady-state idle watchdog
Adds an opt-in onSseEvent callback across HTTP-streaming providers (Anthropic, OpenAI Responses/Completions, Azure OpenAI Responses, OpenAI Codex SSE, Google Gemini CLI, GitLab Duo, Kimi, Synthetic) so callers can inspect raw SSE frames without altering parsed output. Provider fetch wrapping only tees response bodies when an observer is wired; standalone packages/ai consumers without onSseEvent are not penalized.

Adds streamIdleTimeoutMs (env: PI_STREAM_IDLE_TIMEOUT_MS, with PI_OPENAI_STREAM_IDLE_TIMEOUT_MS as a backward-compatible alias). Anthropic now enforces a steady-state idle watchdog (default 120s) in addition to the first-event watchdog. OpenAI Responses, Azure Responses, and Codex (SSE + WebSocket) gain a semantic-progress predicate so response.in_progress-style keepalives no longer keep stalled tool calls alive forever.

Adds a coding-agent debug-panel raw SSE viewer backed by a per-session bounded buffer (1000 records / 512KB) that AgentSession populates unconditionally so users can post-hoc inspect a stuck stream from the TUI.
2026-05-10 04:53:41 +02:00
can1357 903b8f03a5 fix(utils): scrubbed macOS malloc logging env vars at startup
- Added a new `scrubProcessEnv` helper in `procmgr` to remove macOS malloc logging variables from `process.env` before spawning.
- Invoked the helper at coding-agent CLI startup so bun sub-processes no longer inherit the problematic environment.
- This prevented the recurring `MallocStackLogging` warning from appearing in child process stderr output.
2026-05-07 15:45:44 +02:00
can1357 9672139228 feat: added shared readSseEvents utility for Anthropic SSE parsing
- Added `readSseEvents` and `ServerSentEvent` exports in utils for reusable SSE stream parsing.
- Replaced Anthropic's local SSE parser with shared `readSseEvents(response.body, signal)` decoding.
- Updated abort handling in agent stream loop to race an `ABORTED` sentinel with `responseIterator.next()`.
- Expanded stream tests for `readSseEvents` parsing of CRLF, comments, split UTF-8 chunks, and trailing events.
2026-05-07 00:08:06 +02:00
Can Bölük dd6a9b4e54 Merge pull request #933 from Parsifa1/fix-python-gateway
fix(coding-agent): fix share lib error for python gateway
2026-05-06 18:54:28 +02:00
can1357 3f40cb0570 fix(coding-agent): isolate python gateway state 2026-05-06 18:14:00 +02:00
Parsifa1 1b2b8f0991 fix(coding-agent): fix share lib error for python gateway
also fix correct position for python-gateway/ for xdg spec
2026-05-06 18:08:48 +02:00
can1357 ba2affae7f fix(coding-agent): restore path alias equivalence
Fixes #935
2026-05-06 17:23:33 +02:00
can1357 a4c8586f82 fix(coding-agent): preserve junction project paths
Fixes #935
2026-05-06 17:13:11 +02:00