- 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.
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.
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.
- 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.
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
- 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.
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.
- 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.
- 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.
- 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`.
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.
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.
- 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.
- 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.
- 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.
- 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.
- 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.
- Added user-message behavior metric extraction and parsing for yelling/profanity/drama counts.
- Added behavior persistence and aggregate reads by extending syncSessionFile, DB schema, and query APIs.
- Added behavior dashboard support with new shared types, /api/stats/behavior route, and client views.
- Changed cost summary/chart rendering by removing per-chart 14/30/90-day filters and trend card behavior.
- Added tests for computeUserMessageMetrics edge cases like empty text, case, thresholds, and punctuation.
- Moved tailwindcss from devDependencies to dependencies for shared client styling usage.
- Added optional time-range parameters to stats API endpoints and client requests.
- Added dashboard time-range selector controls and wired range updates to stats refresh.
- Implemented range normalization and cutoff calculation for dashboard stat aggregation.
- Updated DB queries to support optional cutoffs and unlimited mode for `range=all`.
- Added tests for 24h, 7d, all, and unknown-range fallback filtering behavior.
- Updated Codex model pricing data to include non-zero input/output/cacheRead rates.
- Added generate-models fallback to copy billable OpenAI costs into bundled openai-codex models.
- Added catalog-cost helpers to fallback openai-codex pricing to openai and compute token totals.
- Added regression tests for openai-codex cost parity and db backfill, and documented the fix in changelog.
- Added an explicit `Plugin` type import to the cost chart component.
- Updated `makeBarLabelPlugin` to return `Plugin<"bar">` for clearer Chart.js typing.
- New Costs tab with bar chart (All Models) and line chart (By Model)
- Toggle between 14d / 30d / 90d time ranges, filtered client-side
- Bar chart shows cost value on top of each bar
- Line chart uses straight lines with always-visible data points
- Summary cards: total 30d cost, avg/day, top model, trend vs prior period
- Backend: getCostTimeSeries() query grouped by day x model x provider
- All cost values displayed as whole dollar amounts (Math.round)
- Migrated all package tsconfig files to extend tsconfig.workspace.json for unified TypeScript configuration across monorepo.
- Consolidated build and check scripts across 10+ packages to use biome for linting/formatting with separate type checking via tsgo.
- Renamed build scripts from build:native and build:binary to build for simplified command naming across packages/natives and packages/coding-agent.
- Refactored CI workflow to invoke bun tasks instead of inline shell scripts, reducing workflow complexity by 40+ lines.
- Removed sync-exports.ts and repro-stuck.ts scripts; deleted path aliases from tsconfig.base.json in favor of workspace-based configuration.
- Updated turbo.json with new task definitions (check:types, lint, fmt, fix) and removed build:native/embed:native tasks.
- Introduced parseSessionEntriesLenient function that skips over malformed JSON lines and continues parsing valid entries. Updated parseSessionFile to use lenient parsing instead of throwing on parse errors. Updated getSessionEntry to use lenient parsing for robustness when reading session files.
Fixes#273
listSessionFiles() only performed a flat readdir, missing subtask JSONL
files nested inside artifact subdirectories. Switch to recursive readdir
to discover .jsonl files at any depth.
Also fix extractFolderFromPath() to derive the project folder via
path.relative from the sessions root instead of regex on basename, which
returned the artifact directory name for nested paths.
Fixes#250
- Consolidated @oh-my-pi/pi-utils subpath imports into single package root import across 100+ files.
- Moved tryParseJson utility from local web scrapers module to @oh-my-pi/pi-utils package for centralized JSON parsing.
- Renamed loadSkillsFromDir to scanSkillsFromDir and refactored skill discovery to use fs.promises.readdir instead of glob-based approach.
- Replaced custom parseJSON with tryParseJson across discovery modules for consistent error handling.
- Removed emitCustomToolSessionEvent method and cleanupSshResources function, consolidating shutdown logic into dispose method.
- Updated glob pattern construction to use GlobBuilder with literal_separator(true) for improved path handling.
- Enhanced GitLab Duo model mapping to support canonical model IDs with fallback lookup.
- Simplified Anthropic auth resolution from 4-tier to 3-tier priority system.
- Fixed artifact manager cache invalidation by validating session file before reuse.
- Improved JSONL parsing in stats package with streaming parser and error handling.
- Migrated embedded client archive from base64 constant to lazy-loaded text file for reduced bundle size.
- Refactored extractEmbeddedClientArchive() to accept archiveBytes parameter, decoupling archive loading from extraction logic.
- Optimized getLatestMtime() to use parallel Promise.allSettled() instead of sequential awaits for improved performance.
- Replaced Buffer.from().toString('base64') with btoa() for base64 encoding in clipboard module.
- Updated Tailwind CSS import from 'tailwindcss' to '@tailwindcss/node' package.
- Added '@tailwindcss/node' version 4 as a dependency in package.json.
- Simplified Tailwind compiler configuration by replacing custom loadStylesheet handler with onDependency callback.
- Added `recursive` option to GlobOptions to control whether simple glob patterns match recursively by default (true).
- Changed glob pattern behavior to always apply recursive matching for simple patterns instead of requiring explicit `**/` prefix.
- Improved symlink handling in glob file type filters to resolve symlink targets and match based on their actual type (file/dir).
- Enhanced skill discovery in coding-agent to use dual-pass glob approach with deduplication and improved extension module detection.
- Implemented dynamic Tailwind CSS compilation in stats package by extracting actual class names from source files instead of building with empty candidates.
- Refactored Tailwind stylesheet imports to use centralized `tailwindcss/index.css` import with custom stylesheet loader callback.
- Updated dependency versions across root, ai, coding-agent, stats, and tui packages.
- Pinned @sinclair/typebox to 0.34.48.
- Migrated stats Tailwind build from PostCSS plugin usage to Tailwind v4 compile() API and emitted a standalone styles.css.
- Switched discovery helpers to native glob scanning for faster gitignore-aware file/module discovery.
- Added startup timing markers around model selection and skill discovery in sdk initialization.
Generate a tar.gz bundle from stats dist/client during binary builds, embed it into the compiled binary, and extract/serve it at runtime in compiled mode instead of reading //root/client directly.
Updated CI and build:binary flow to generate/reset the embedded bundle around compilation.
Fixes#61
- Added real-time OAuth provider authentication validation with visual status indicators (checking, valid, invalid).
- Added `validateAuth` and `requestRender` options to OAuthSelectorComponent for custom authentication validation and UI refresh callbacks.
- Changed OAuth provider selector to display live authentication status instead of static login state.
- Updated logout flow to refresh OAuth provider authentication state before showing selector.