Commit Graph
88 Commits
Author SHA1 Message Date
Wolfgang Schoenberger 9d6e8c2174 fix(stats): clarify overview token totals 2026-07-18 16:40:15 -07:00
roboomp 4ef017232e fix(stats): restricted port reclamation to stats processes
Recorded listener command lines across supported platforms and required an omp-stats-specific command identity before terminating Bun, Node, or omp holders. Unrelated runtimes now take the refusal path without receiving a signal.

Fixes #5970
2026-07-18 07:16:34 +00:00
roboomp 4010bef985 fix(stats): verified dashboard identity before port reuse
Stamped an x-omp-stats-dashboard header on dashboard responses and required it (or the models JSON-array shape) in the reuse probe, so a foreign 200 responder such as an SPA dev server catch-all is no longer mistaken for a live dashboard.

Fixes #5970
2026-07-18 07:10:54 +00:00
roboomp 477112e81d fix(stats): recovered occupied dashboard port
Reused live stats dashboards sharing the requested port and reclaimed stale Bun, Node, or omp listeners after a failed health probe. Foreign listeners now produce an ownership-specific error.

Fixes #5970
2026-07-18 07:04:01 +00:00
roboomp cc9977cce4 fix(advisor): anchored context maintenance on provider usage
- Anchored advisor compaction on provider-reported context usage (cached
  input + generated output) floored by a full local estimate including the
  advisor system prompt and tool schemas, so a near-full cached context is no
  longer undercounted by the per-message estimate.
- Rejected stale provider usage retained across advisor compaction via a
  runtime-only usage-anchor boundary recorded on the summary message.
- Recovered provider overflow by clearing only the advisor's own context at
  the current primary cursor, retrying the bounded failing batch once against
  a fresh context without replaying old primary history, and keeping later
  updates eligible.
- Threaded the selected dashboard range through the stats Recent Errors UI,
  API, and database timestamp filter before ordering and the 50-row limit.

Fixes #5282
2026-07-14 17:58:19 +00:00
can1357 1b0b18c7a6 fix(stats): handled malformed session entries to prevent sync crashes
- Coerce missing `stopReason`, token counts, and timestamps at the parser boundary to satisfy database NOT NULL constraints.
- Skip assistant entries missing essential model attribution or usage data instead of aborting the sync process.
- Filter invalid tool call blocks that lack required identifiers to ensure successful database insertion.
2026-07-12 12:42:37 +02:00
can1357 7df2ac297e fix(stats): handled legacy session entries with missing cost data
- Resolved a crash occurring when syncing legacy session files that lack usage cost breakdowns.
- Updated cost resolution to fallback to catalog pricing when stored cost is unavailable or zero.
2026-07-11 00:08:53 +02:00
can1357 c68a01f597 fix(stats): refined behavior metric extraction and filtering logic
- Adjusted yelling, profanity, and anguish criteria to reduce false-positive metrics.
- Implemented refined regex patterns for negation, blame, and noise reduction.
- Incremented the backfill key to v8 to accommodate updated signal definitions.
- Expanded test suite to validate new constraints for yelling, exclusion words, and sentiment triggers.
2026-07-06 03:55:43 +02:00
can1357 8384acb321 Merge PR #4280: perf(stats): stream session lookup and cache snapcompact JSONL reads (@metaphorics) 2026-07-05 13:25:26 +02:00
metaphorics aac5054c3f perf(stats): stream session lookup and cache snapcompact JSONL reads
getSessionEntry in packages/stats/src/parser.ts previously read the entire session file into memory and parsed every entry just to find one by ID. It now streams the file line-by-line via readLines and returns on the first matching entry, stopping I/O and parsing early. In packages/stats/src/gain-aggregator.ts, readSnapcompactRecords now stats snapcompact-savings.jsonl and caches parsed records keyed by mtimeMs and size, reusing them when the append-only journal has not changed. Cutoff filtering, per-request session:toolCallId deduplication, and project filtering are still applied per call. Verified with bun test test/gain-aggregator.test.ts in packages/stats (3 pass, 0 fail, 16 expect() calls, 1 file, 757.00ms) and bun run check:types.

Closes #4251
2026-07-02 17:30:38 +09:00
can1357 fbf3a6eb3f feat(stats): added tool usage dashboard
- Parsed assistant `toolCall` blocks and `toolResult` messages into persisted `tool_calls` rows with one-shot historical backfill.
- Added tool aggregate queries, model breakdowns, call time-series data, and the `/api/stats/tools` dashboard endpoint.
- Added the `/#/tools` route with summary metrics, stacked calls-over-time chart, per-tool table, and model breakdown panel.
- Added end-to-end stats coverage for tool ingestion, result/error linkage, fork deduplication, incremental updates, and dashboard shaping.
2026-07-02 08:31:18 +02:00
can1357 d20e6c0829 feat: migrated service tier settings to a per-model-family architecture
- Migrated global service tier settings to a per-model-family architecture (OpenAI, Anthropic, Google).
- Implemented `ServiceTierByFamily` mapping to allow independent configuration and resolution per provider.
- Added automatic migration logic for legacy service tier and fast-mode application settings.
- Updated telemetry, session management, and task execution to support provider-specific tier resolution.
2026-06-30 04:14:48 +02:00
roboomp 7d5544493e fix(stats): skipped sync worker smoke on darwin
smokeTestSyncWorker spawned a worker via createSyncWorker on every platform, so omp --smoke-test (and the macOS signing pre-launch run in scripts/ci-macos-sign.sh) still hit the Bun-worker re-entry path the serial macOS sync default avoids. Early-return on darwin and document the carve-out.

Fixes #3733
2026-06-29 11:06:17 +00:00
roboomp 234c1919f5 fix(stats): kept worker pool for one-file syncs
Keyed the serial-parser branch off the caller-requested worker count instead of the per-pool clamp, so a one-file sync still fans out to workers when the caller (or default) asked for more than one.

Fixes #3733
2026-06-28 16:31:17 +00:00
roboomp efb96b123f fix(stats): avoided native jsonl parser trap
Replaced the stats session parser's Bun.JSONL.parseChunk path with a lenient JS line scanner so large session files do not enter the native parser before /stats launches.

Fixes #3733
2026-06-28 16:29:19 +00:00
roboomp b48d488f2c fix(stats): avoided macos stats sync worker abort
Kept the documented workers: 1 path inline and defaulted macOS stats sync to that serial parser path so /stats dashboard launches do not re-enter Bun workers on macOS.

Fixes #3733
2026-06-28 16:21:59 +00:00
can1357 fbad280b57 feat: implemented multi-advisor concurrent runtime with tui management
- Introduced comprehensive support for multiple concurrent, independently-configured advisors via `WATCHDOG.yml` files.
- Implemented a full-screen TUI overlay for managing advisor rosters, models, tools, and instructions.
- Added session-wide advisor initialization, telemetry aggregation, and named transcript isolation.
- Enhanced advisor security and observability with secret redaction in tool results and secure XML attribute encoding.
2026-06-28 12:55:09 +02:00
can1357 5a044dc0da feat: consolidated and automate changelog management
- Added `rewrite-changelog.ts` and `fix-changelogs.ts` utilities to automate the consolidation of release notes using LLM-assisted processing.
- Updated multiple internal changelog files by consolidating redundant entries and improving phrasing for readability.
- Implemented `previewLine` utility in `coding-agent` to prevent visual spillover in status rows by managing text truncation and whitespace.
- Updated `package.json` with new workflow scripts for managing package-level change histories and documentation indexes.
2026-06-27 03:08:52 +02:00
can1357 577d2a8eb8 style: biome format/organize-imports across integrated PRs 2026-06-27 02:06:38 +02:00
can1357 5a1c17c1cb Fix gain dashboard project scoping 2026-06-27 02:04:51 +02:00
David Andrews 619c0aab24 fix(stats/gain): normalize cwd before project match
matchesProject now applies normalizeProjectPath to the raw cwd before
comparing against the selected project root. Without this, a record with
cwd=/repo-worktrees/lane/src would not match the normalized project root
/repo displayed in the selector, causing project-scoped views to show
empty data for any worktree-layout cwd that normalizes to a shorter root.

Addresses codex P2 on commit 8390d278df.
2026-06-26 16:01:27 -04:00
David Andrews 8390d278df fix(stats/gain): address review feedback
- Parse minimizer JSONL once per request; derive records/unparsed/projects
  sets in a single pass instead of three separate reads+parse loops
- Use getTimeRangeConfig from aggregator.ts (export it) instead of a
  local RANGE_MS table that would drift on new range additions
- Fix startsWith project filter to be separator-aware (=== project ||
  startsWith(project+'/')) via shared matchesProject helper — prevents
  false matches on path prefix collisions across all three call sites
- Remove author-specific paths (PycharmProjects, .herdr) from
  normalizeProjectPath; replace with generic worktree-suffix regex
  covering .wt/, -wt/, .worktrees/, -worktrees/, and /.*/worktrees/
  layout patterns, keeping /.omp/wt/ drop
- Exclude snapcompact from project-scoped responses (no cwd field means
  no project filter is possible — mixing all-projects savings into a
  per-project view is misleading); global view still shows snapcompact
- Fix overall.reductionPercent to only divide minimizer+distill saved
  bytes by minimizer+distill original bytes; snapcompact has no
  originalBytes so including it in the numerator overstated the ratio
- Key unparsed command map on the full command string; command field in
  GainUnparsedCommand now stores the full string (callers truncate for
  display) to avoid merging distinct long commands sharing a 120-char
  prefix
- Fix api.ts getGainDashboardStats arg order: project before signal to
  match sibling convention; update GainRoute.tsx call site accordingly
- Add CHANGELOG entry under [Unreleased]
2026-06-26 15:27:57 -04:00
David Andrews 6ed4e4a0ba stats: gain dashboard client — project selector + unparsed commands panel
- GainRoute.tsx: project state, GainProjectSelector dropdown (113 roots),
  GainUnparsedCommandsPanel showing actual command strings + hit count + input bytes
- useHashRoute.ts: added 'gain' to VALID_SECTIONS (was falling back to 'overview')
- api.ts: getGainDashboardStats accepts optional project? param
- formatters.ts, routes.ts, App.tsx: wiring for Gain tab route
2026-06-26 04:16:38 -04:00
David Andrews 0fa4affcc4 stats: gain dashboard — project filter, unparsed commands panel
- GainUnparsedCommand type: actual command strings that had no filter match
  (replaces GainMissedSaving which grouped by filter name — not useful for tuning)
- readMinimizerUnparsedRecords(): filter==='missed' && kind==='missed', skips temp paths
- dedupeProjects(): normalize worktree sub-paths → project roots, drop ephemeral dirs
- getGainDashboardStats(range?, project?): project-scoped reads across all sources,
  top-25 unparsed commands sorted by hit count
- server.ts: ?project= query param forwarded to aggregator
- shared-types.ts: GainUnparsedCommand, GainDashboardStats.{unparsedCommands,project,projects}
2026-06-26 04:16:38 -04:00
roboomp b5769a4e10 fix(stats): dedupe forked-session entries to stop double-counting
SessionManager.fork() and createBranchedSession() deep-copy a parent's
entries into the child JSONL — same entry_id, timestamp, model,
responseId, token counts, cost. Stats keyed uniqueness on
(session_file, entry_id), so both files contributed to request, token,
and cost totals.

insertMessageStats and insertUserMessageStats now skip rows whose
(entry_id, timestamp) already exists under a different session_file
(first-write-wins). A one-shot migration on initDb, gated by the
fork_dedupe_v1 meta sentinel, collapses pre-existing duplicate rows
in messages and user_messages by keeping the lowest-id row per
(entry_id, timestamp) group.

Fixes #3370
2026-06-24 14:14:25 +00:00
can1357 153fd78345 feat(stats): added token usage breakdown by agent type
- Implemented agent type classification and persistence in the database, including a backfill for legacy records.
- Added `AgentType` categorization and aggregated token usage metrics to the backend services.
- Created an `AgentTokenShare` visualization component to display usage distribution on the overview dashboard.
- Integrated agent-based tracking into existing data pipelines, view models, and testing suites.
2026-06-22 17:42:58 +02:00
can1357 f743ddc83d feat: replaced XML-style pi dialect with sigil-delimited format
- Migrated the `pi` AI dialect from legacy XML-style elements to a compact, token-frugal sigil-delimited format using `§` for calls, `""` for body fences, and `¤` for thinking.
- Implemented robust parsing for the new format, including support for incremental streaming of tool arguments and automatic escalation of body fences to prevent content collisions.
- Updated documentation, settings configurations, and test suites across the `ai` and `coding-agent` packages to ensure consistency with the new dialect rules.
- Standardized moderation category terminology in `stats` to improve clarity in reporting metrics.
2026-06-19 01:19:41 +02:00
can1357 71de9a3eb2 Merge PR #2904: fix(stats): contain wide mobile-card tables on narrow desktops (@wolfiesch) 2026-06-18 23:32:53 +02:00
can1357 f5ebab2b83 feat(utils): vendor mermaid rendering 2026-06-18 18:52:38 +02:00
Wolfgang Schoenberger 6295bc9fb4 fix(stats): contain wide mobile-card tables on narrow desktops
The `.stats-table-desktop-only` wrapper used for mobile-card tables
(Requests, Errors, Overview, Projects) lacked the `overflow-x: auto`
containment that `.stats-table-container` already has, so wide tables
spilled the page body horizontally at narrow-desktop widths (768-1023px).
Add a base rule mirroring `.stats-table-container` so these tables scroll
within their own bounds.
2026-06-17 04:12:03 -07:00
lycaon 525f4baa64 feat(stats): redesign the omp stats dashboard
Rewrite the local `omp stats` web UI on the OMP brand palette with a left nav, focused per-section views, a new Projects view, a system-aware light/dark toggle, and flicker-free navigation. Same data, endpoints, and command; the only server change is a 1h time-range bucketing fix in the aggregator.
2026-06-16 23:30:50 -06:00
can1357 3ab675a83b fix: added buffered worker inboxing and standardized worker selectors
- Added `WorkerInbox` and `installWorkerInbox(port)` to queue worker messages before bind.
- Added `consumeWorkerInbox()` to replay buffered messages and clear one active inbox.
- Added buffered inbox consumption in JS and tab worker transports before direct message handlers.
- Normalized worker selector arguments to the `__omp_worker_*` naming across workers and tests.
2026-06-15 11:59:44 +02:00
Scott Hyndmanandcan1357 83d5799dd8 fix(stats): dropped git from profanity list 2026-06-14 17:29:29 +02:00
roboomp 03bead1eac fix(auth): retried SQLITE_BUSY family and hoisted busy_timeout
Concurrent omp --session restores after an unclean shutdown crashed
in SqliteAuthCredentialStore.#initializeSchema() with
SQLITE_BUSY_RECOVERY because the multi-statement schema run installed
PRAGMA busy_timeout=5000 AFTER PRAGMA journal_mode=WAL, the first
lock-taking statement during WAL recovery. Bun's default busy_timeout
is 0, so the lock conflict surfaces immediately.

- packages/ai/src/auth-storage.ts: hoisted PRAGMA busy_timeout to a
  standalone first statement, dropped it from the multi-statement
  schema run, wrapped SqliteAuthCredentialStore.open() in a 4-attempt
  exponential-backoff retry loop on the SQLITE_BUSY family, and the
  exhausted-retry error now includes the DB path. Exported
  isSqliteBusyError(err) (matches code prefix 'SQLITE_BUSY').
- packages/coding-agent/src/session/agent-storage.ts: same hoist and
  the existing retry loop now uses isSqliteBusyError so
  SQLITE_BUSY_RECOVERY / _SNAPSHOT / _TIMEOUT also trigger backoff.
- Hoisted busy_timeout before journal_mode=WAL in every other shared
  SQLite open path: history-storage, autoresearch/storage,
  memories/storage, github-cache, report-tool-issue (auto-QA),
  catalog/model-cache; stats/db.ts now sets busy_timeout at all.
- packages/ai/test/auth-storage-sqlite-busy.test.ts pins the contract:
  isSqliteBusyError matches every BUSY extended code (rejects
  SQLITE_LOCKED, non-errors, strings); open() leaves the connection in
  WAL mode (proves busy_timeout ran before journal_mode); open() retries
  through synthetic SQLITE_BUSY_RECOVERY; non-BUSY errors (SQLITE_CORRUPT)
  short-circuit; exhausted retries throw an error mentioning the DB path
  with exactly 3 sleeps for a 4-attempt budget.

Fixes #2421
2026-06-12 20:17:12 +00:00
can1357 6b76463941 fix: fixed stats dashboard asset serving for bundled CLI distributions
- Fixed npm CLI bundling by invoking `generate-client-bundle.ts --generate` before build and `--reset` after.
- Added `PI_BUNDLED` handling in `packages/stats/src/server.ts` and switched bundled distributions to embedded assets.
- Decoded embedded archives via `decodeEmbeddedClientArchive` and treated legacy placeholder content as missing.
- Handled missing dashboard source/build directories as ENOENT during mtime scans to avoid startup crashes.
- Extended `--smoke-test` to start the stats server and validate dashboard HTML contains expected asset markers.
2026-06-10 10:45:31 +02:00
can1357 1b9d9d0851 refactor(catalog)!: split model catalog from pi-ai
Move bundled models, model cache/manager, thinking metadata, effort helpers,
provider descriptors/discovery, wire constants, and model identity utilities
into the new @oh-my-pi/pi-catalog package.

Update pi-ai to keep provider runtime/auth concerns, move catalog provider
metadata into CATALOG_PROVIDERS, and migrate coding-agent, agent, stats, docs,
and tests to import catalog values from pi-catalog.

Split coding-agent model registry helpers into discovery, roles, and models
config modules while preserving registry orchestration.

BREAKING CHANGE: @oh-my-pi/pi-ai no longer exports catalog subpaths such as
/models, /model-cache, /model-manager, /model-thinking, /effort,
/provider-models*, discovery helpers, and provider wire constants; use the
matching @oh-my-pi/pi-catalog subpaths instead.
2026-06-10 04:06:57 +02:00
can1357 dc5c93462f feat: rerouted worker subprocesses through the bundled CLI host entrypoint
- Rerouted sync, tab, js-eval, and tiny workers to re-enter CLI modes via `__omp_*` selectors.
- Adjusted `cli.ts` startup to dispatch worker entrypoints before parsing and exit 1 on uncaught errors.
- Bundled CLI as `dist/cli.js` in prepack, switching `omp` binary and published files.
- Removed explicit Bun `--compile` worker entrypoints from build/release scripts in favor of host-entry dispatch.
- Added `declareWorkerHostEntry()` and `workerHostEntry()` environment helpers and `PI_COMPILED` binary detection.
2026-06-10 03:57:31 +02:00
can1357 e831c2c758 chore: reformat 2026-05-30 18:08:51 +02:00
can1357 00bb61b054 feat(stats): added time-range-aware bucketing to model series charts
- Passed `bucketMs` to `getModelTimeSeries` and `getModelPerformanceSeries` so SQL bucketing matches the selected range.
- Added `range-meta.ts` to centralise bucket sizes, counts, tick formats, and labels per time range.
- Updated `ChartsContainer` and `ModelsTable` to use range-aware x-axis formatting and trend labels.
2026-05-17 02:15:37 +02:00
can1357 3061c47a32 chore: added robomp workspace, ignored fallow deps, cleaned up exports
- Added `python/robomp` as a workspace package alongside its nested `web` sub-package.
- Added `ignoreDependencies` in `.fallowrc.jsonc` for deps used via bin or in nested workspaces.
- Removed unused `clearTriggerStatus` export and unexported `tick` and `ByModelToggle`.
2026-05-17 01:44:13 +02:00
can1357 8499149627 fix(stats): scan service-tier prefix without materializing entries
parseSessionFile(fromOffset) still recovers the active service tier from the already-ingested prefix, but now scans only for service_tier_change entries and keeps a single current tier value instead of materializing every prefix entry. This preserves incremental sync memory behavior for large sessions.
2026-05-15 18:31:12 +02:00
can1357 be0d9d3e6c fix(stats): preserved service-tier across incremental parseSessionFile offsets
Stats sync depends on service_tier_change entries to derive priority premium requests since 69043d307 stopped folding priority-tier into per-message premiumRequests. parseSessionFile(path, fromOffset) initialized currentServiceTier to undefined per call, so an incremental resume past the tier change attributed subsequent priority OpenAI replies with premiumRequests: 0. When fromOffset > 0, parseSessionFile now replays bytes[0..start] purely to seed currentServiceTier from the latest service_tier_change before parsing the unprocessed tail. Bytes are already loaded, so no extra I/O.
2026-05-15 17:49:49 +02:00
can1357 f8ea641cdb fix(stats): ignored messages without IDs when parsing session entries
- Added message-ID checks in both assistant and user message parsers so entries without valid ids are ignored.
- This filtering prevents legacy, unlinked message records from being treated as parseable assistant or user messages.
2026-05-15 01:09:26 +02:00
can1357 f1f6516056 refactor: reorganized exports and removed obsolete helper branches
- Removed export leakage by demoting many helper and const symbols to module-local scope.
- Renamed underscore-prefixed internals and cache fields, then updated related references and `satisfies never` checks.
- Deleted obsolete logic branches and helpers, including harmony-stream interruption flow and unused benchmark runtime helpers.
- Updated Biome config and manifests by broadening lint coverage and removing an unused `@napi-rs/cli` dev dependency.
- Adjusted tests and utilities to use renamed test helpers and remove redundant private test-only helpers/locals.
2026-05-14 04:36:19 +02:00
can1357 334b6782a5 feat(stats): counted priority service-tier traffic as premium requests in usage stats
- Added `getPriorityPremiumRequests` and used it in OpenAI and OpenAI Codex providers to increment `usage.premiumRequests` when `serviceTier: "priority"` was sent.
- Combined Copilot and priority premium counts in OpenAI completions and responses usage parsing so emitted usage uses the merged premium total.
- Updated stats parsing/backfill to re-read `service_tier_change` entries and UPSERT only `premium_requests`, so historical sessions pick up priority traffic without mutating other metrics.
2026-05-13 11:31:51 +02:00
can1357 e8e2f2cd83 fix(stats): preserve pending behavior backfills 2026-05-12 16:41:28 +02:00
can1357 b468bd5abd feat(stats): show input and output token totals 2026-05-12 16:40:43 +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 f56cbbf4c6 feat(stats): added frustration metrics to stats parser and charting
- Added new frustration and revised behavior metrics across stats types, parser mappings, and UI charts.
- Reworked session sync to fan out parsing across a capped worker pool with SyncOptions progress callbacks.
- Added worker-based parse messaging and throttled TTY progress rendering in the stats sync command.
- Updated behavior scoring to strip structured content, ignore noisy prompts, and fix profanity boundary regressions.
- Expanded user message schema and migrations, then repaired assistant model/provider links during sync backfill.
- Updated worker-import guidance in AGENTS.md and recorded sync-progress/metrics updates in package changelogs.
2026-05-12 07:55:23 +02:00
can1357 a4d86a075a feat(coding-agent): added verbatim unicode rule to hashline prompt 2026-05-12 05:25:55 +02:00