Commit graph

8 commits

Author SHA1 Message Date
Mikael Hugo
383e495085 feat(headless,gemini-cli): add sf headless usage + unify gemini quota path
Adds a machine-readable headless surface for live LLM-provider usage and
unifies the gemini-cli quota fetch through one helper, removing the
duplication that existed between usage-bar.js and the new package.

1. snapshotGeminiCliAccount in @singularity-forge/google-gemini-cli-provider

   - Single source of truth for { projectId, userTierId, userTierName,
     paidTier, models[] } via setupUser + retrieveUserQuota.
   - Dedups buckets per modelId, keeping the worst (lowest remainingFraction)
     so consumers always see the most-restrictive window. Code Assist
     sometimes returns multiple buckets per model; the pessimistic choice
     is what every consumer needs.
   - discoverGeminiCliModels(cwd?) wraps it for catalog-cache callers that
     only need the IDs.

2. sf headless usage subcommand

   - New src/headless-usage.ts handler. text (default) and --json output.
     Uses the package's snapshot directly — no RPC child, no jiti
     gymnastics — matching the shape of headless-uok-status / headless-doctor.
   - Wired into src/headless.ts after the doctor block.
   - Help text adds the command line.

3. usage-bar.js refactored to delegate

   - fetchGeminiUsage no longer imports gemini-cli-core directly. It calls
     snapshotGeminiCliAccount and reshapes the result into the existing
     { provider, displayName, windows[] } UI contract.
   - Eliminates the duplicate setupUser + retrieveUserQuota code path.
   - The fast existsSync(~/.gemini/oauth_creds.json) pre-flight stays
     so unauth'd users get a friendly message without paying for OAuth
     bootstrap.

4. Model registry refactor (separate track committed alongside)

   - src/resources/extensions/sf/model-registry.ts (new) consolidates
     canonical model identity, capability tier, and generation tags into
     one source of truth that auto-model-selection, benchmark-selector,
     and model-router now consume instead of maintaining parallel maps.

All 1487 tests pass (151 files); typecheck clean for both the package
and the SF extensions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 03:42:53 +02:00
Mikael Hugo
c6a3fa6a6a feat(gemini-cli): discover account models via gemini-cli-core + retry on capacity errors
Two related fixes for the google-gemini-cli provider, both motivated by today's
dogfood diagnosis: SF was pinned to a single model (gemini-3-flash-preview)
even though the AI Ultra account has access to seven (verified via the live
gemini-cli-core probe), and a transient "No capacity available for model X
on the server" was classified as `unknown` so SF gave up instead of retrying.

1. Account snapshot + model discovery in @singularity-forge/google-gemini-cli-provider

   - Add `snapshotGeminiCliAccount(cwd?)` returning { projectId, userTierId,
     userTierName, paidTier, models } where `models[]` carries each modelId
     with usedFraction, remainingFraction, and resetTime. Built on the same
     setupUser + CodeAssistServer.retrieveUserQuota path usage-bar.js
     already uses, but extracted to the dedicated package so any consumer
     (model picker, capacity diagnostics, catalog cache) can call one helper.
   - Add `discoverGeminiCliModels(cwd?)` as a thin "just the IDs" wrapper.
   - Both are best-effort: any failure (OAuth expired, no project, network)
     returns null silently — never throws.

2. SF-side cache writer at src/resources/extensions/sf/gemini-catalog.js

   - Delegates discovery to the package; only handles cache file path,
     6-hour TTL, and the session_start lifecycle hook.
   - Cache lands at .sf/runtime/model-catalog/google-gemini-cli.json with
     the same shape as the generic model-catalog-cache, so getKnownModelIds
     and the model picker pick it up transparently.
   - Wired into bootstrap/register-hooks.js session_start in parallel with
     the existing scheduleModelCatalogRefresh (the generic REST + API-key
     path can't reach gemini-cli's OAuth-only Code Assist endpoint).

3. Capacity error classification fix

   - error-classifier.js SERVER_RE now matches "no capacity (available|left)",
     "capacity (unavailable|exhausted)", and "no capacity ... on the server".
     Previously these fell through to kind=unknown, which is not transient,
     so agent-end-recovery never retried — even though the same handler
     already caps gemini-cli rate-limit backoff at 30s for exactly this
     class of transient. With the pattern matched as `server`, the existing
     retry-with-backoff path covers it.

The full extension test suite (1386 tests) passes. Typecheck clean for both
the package and the SF extensions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 03:32:35 +02:00
Mikael Hugo
0b5fa75c0d fix(lint): fix all pre-existing lint failures
- check-sf-extension-inventory.mjs: expand parseDirectRegisteredCommands()
  scan to include 7 more files (guards/inturn.js, notifications/notify.js,
  permissions/index.js, ui/usage-bar.js, commands/legacy/audit.js,
  commands/legacy/create-extension.js, commands/legacy/create-slash-command.js)
  and filter results by BASE_RUNTIME_COMMAND_NAMES to exclude doc-string false
  positives ("name" in create-slash-command.js template text)

- extension-manifest.json: remove 'clear' (subcommand of logs/notifications,
  never a top-level pi.registerCommand)

- packages/pi-agent-core/src/db/sf-db.ts: fix 23 noVoidTypeReturn errors
  - openDatabase: void → boolean (caller uses return value at line 5625)
  - claimEscalationOverride: void → boolean (caller checks at escalation.js:243)
  - resolveSelfFeedbackEntry: void → boolean (caller checks at self-feedback.js:387)
  - copyWorktreeDb: void → boolean (caller checks at reconcileWorktreeDb)
  - compactUokMessages: void → {before,after} (caller returns value at message-bus.js:238)
  - insertSessionTurn: void → bigint|null (caller uses id at session-recorder.js:104)
  - expireStaleMemories: void → number (caller uses count at auto-start.js:1047)
  - deleteMemorySourceRow: void → boolean (caller returns value at memory-source-store.js:107)
  - deleteMemoryEmbedding: void → boolean (caller returns value at memory-embeddings.js:328)
  - updateBacklogItemStatus: remove dead return expression (callers discard value)
  - removeBacklogItem: remove dead return expression (callers discard value)
  - updateGateCircuitBreaker: remove dead return {total,avgMs,...} (wrong-type
    code accidentally merged from getGateLatencyStats, never reachable)
  - markUokMessageRead: remove dead return true/false (callers discard value)

- Auto-fix formatting and organizeImports in ~30 source files (biome --write)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-11 04:02:31 +02:00
Mikael Hugo
d447095bd7 build: switch full build pipeline to TypeScript 7 native (tsgo)
Replace tsc with tsgo in all build scripts — 5.6x faster emit.
tsgo has full emit parity for this codebase (NodeNext, ES2022, strict).

- build:core: tsc → tsgo (root tsconfig.json)
- copy-resources.cjs: typescript/bin/tsc → @typescript/native-preview/bin/tsgo.js
- All workspace packages (agent-core, ai, coding-agent, daemon,
  google-gemini-cli-provider, native, rpc-client, tui): tsc → tsgo

Benchmarks (root project):
  tsc --project tsconfig.json: 7.7s
  tsgo --project tsconfig.json: 1.4s  (5.6x faster)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 11:58:58 +02:00
Mikael Hugo
e09eb8f899 build: add TypeScript 7 (native preview) for fast type checking
- Remove vestigial experimentalDecorators/emitDecoratorMetadata from all
  package tsconfigs (no actual decorators in source — flags were from
  pi-mono vendor copy)
- Add @typescript/native-preview for 8-10x faster type checking (measured
  4.6x on this repo: tsc 6.5s vs tsgo 1.4s)
- Fix tsconfig.extensions.json: remove baseUrl (removed in tsgo/TS7) and
  use relative paths in paths mappings — compatible with both tsc and tsgo
- Add typecheck/typecheck:extensions scripts using tsgo

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 11:53:22 +02:00
Mikael Hugo
02a4339a51 refactor: rename pi-* packages to forge-native names (Phase 1)
Rename all four packages/pi-* directories to forge-native names,
stripping the 'pi' identity and establishing forge's own:

- packages/pi-coding-agent → packages/coding-agent
- packages/pi-ai → packages/ai
- packages/pi-agent-core → packages/agent-core
- packages/pi-tui → packages/tui

Package names updated:
- @singularity-forge/pi-coding-agent → @singularity-forge/coding-agent
- @singularity-forge/pi-ai → @singularity-forge/ai
- @singularity-forge/pi-agent-core → @singularity-forge/agent-core
- @singularity-forge/pi-tui → @singularity-forge/tui

All import references, bare string references, path references,
internal variable names (_bundledPi*), and dist files updated.
@mariozechner/pi-* third-party compat aliases preserved.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-10 11:28:01 +02:00
Mikael Hugo
d895cf2a16 fix: silence OpenTelemetry diag and LogTape meta startup warnings
- Align google-gemini-cli-provider's @google/gemini-cli-core dep from
  0.40.1 → 0.41.2 to match root; npm deduplicates to a single module
  instance, so diag.setLogger is called only once (no 'overwritten' warn)
- Add logtape.meta logger config at 'warning' level to suppress LogTape's
  own 'loggers are configured' info message on every startup

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-09 21:54:26 +02:00
Mikael Hugo
9875812c1b sf snapshot: uncommitted changes after 131m inactivity 2026-05-09 02:53:47 +02:00