Commit Graph
6 Commits
Author SHA1 Message Date
ZacharyZhang-NY 6da0a58769 refactor(db): group database domain modules 2026-04-22 19:24:25 -04:00
ZacharyZhang-NY a69fbb053b Codemod db pass-through calls: messages + runs + approvals + company (C1 part 2/3)
Rewrite ~376 call sites for messages, runs, approvalsMod, and company
domains and delete the corresponding pass-through methods on
AppDatabase / AppDatabaseBase. Structural type references
(ReturnType<HandlerDeps["db"]["getRun"]>) and SweepStaleReviewsDeps-style
mocks are updated to route through the owning sub-module.
2026-04-20 13:20:15 -04:00
ZacharyZhang-NY 14dc9a4897 refactor(cost): single writer for cost_entries, finishRun reads SUM
Cost was written through three independent paths: worker-runner shipped
`finalUsage.costUsd` in run-finished -> finishRun wrote `runs.cost_usd`,
`tasks.cost_usd += costUsd`, `agents.spent_monthly_usd += costUsd`, and
inserted a per-run aggregate row in cost_entries. CostWriter
additionally inserted per-message rows in cost_entries from main. Any
CostWriter failure created silent drift between `SUM(cost_entries)`
(read by budget enforcement) and `runs.cost_usd` (read by the UI).

Make CostWriter the single writer, finishRun the single reader.

- Add `db.recordCostEntry(...)` as the first-class insert path for
  per-message cost rows. CostWriter calls it; tests call it directly.
- Remove the aggregate INSERT from finishRun. finishRun now reads
  `SELECT COALESCE(SUM(amount_usd), 0) FROM cost_entries WHERE run_id=?
  AND unattributed=0` and writes that as the authoritative run total to
  runs.cost_usd, tasks.cost_usd, and agents.spent_monthly_usd.
- Drop `costUsd` from `finishRun` input, the worker `run-finished`
  ChildMessage shape, the automation `RunFinishedEvent` type, and every
  caller + test fixture. Cost is owned by the per-message path.
- worker-runner stops extracting `usage.cost.total` — token counts stay
  for session accumulation, cost comes from pi-ai via CostWriter.
- run-finished-helpers now gates budget incident checks on
  `event.status === "succeeded"` instead of a cost field that no longer
  exists on the event.
- automation-run-completion fires `budget_threshold` on every succeeded
  run (post-run spent_monthly_usd already reflects the SUM path).
- Update budget tests to write a `recordCostEntry` before `finishRun`
  to simulate the per-message cost path; drop `costUsd` from cross-
  subsystem, edge-case-budget, database, and related fixtures.

One writer, one reader, one source of truth. No drift.
2026-04-17 15:04:22 -04:00
ZacharyZhang-NY 5547c29491 update 2026-04-17 14:03:56 -04:00
ZacharyZhang-NY e7e43bd0a6 fix(fireworks): route Fireworks models through resolveModel everywhere
pi-ai's getModel/getModels does not know about the Fireworks providers
(fireworks, fireworks-firepass); both live under our local model-resolver
because Fireworks speaks the Anthropic-compat endpoint with Bearer auth
at https://api.fireworks.ai/inference, not pi-ai's built-in catalog.

Three call sites were still hitting pi-ai directly and failing silently
for Fireworks:

1. connector-model-policy.ts — listProviderModels() caught the pi-ai
   throw and returned []. The "Fire Pass (CEO runtime)" card in the
   Team Models onboarding step therefore showed "暂无模型 / 已启用 0/0",
   blocking users on Fire Pass from continuing onboarding.

2. worker/worker-runner.ts — getModel() threw mid-run when the selected
   connector was Fireworks, so the worker could never actually execute
   an agent turn against Fire Pass or the curated Fireworks model set.
   Now uses resolveModel() + the Fireworks-specific Bearer header from
   resolveExtraStreamHeaders() so streamSimple hits the correct endpoint
   with the correct auth.

3. agent-runtime/cost-writer.ts — cost observation silently wrote
   amount_usd=null for Fireworks runs because getModel() threw inside
   the try/catch. Now resolves via resolveModel() so the Fireworks
   curated contextWindow/maxTokens are visible to calculateCost().

Verification: pnpm typecheck 0 / pnpm lint 0-0 / pnpm build:verify 0-0
/ pnpm test:unit 508/508.
2026-04-17 09:51:38 -04:00
ZacharyZhang-NY cad17b4d45 fix(credentials): close resolver switch and guard missing provider/auth
- credential-resolver.resolve: throw explicit CREDENTIAL_INVALID when
  the connector has no auth schema, and add a default branch so the
  switch has a definitive return path for every auth kind
- credential-resolver api_key branch: guard definition.provider being
  unset before calling pi-ai's getEnvApiKey
- cost-writer: only attempt cost lookup when definition.provider is
  defined; adapter-only connectors still write an unattributed row
2026-04-17 01:28:37 -04:00