forked from EduCraft/curriculum-project-hub
aaa098bb8b
Co-authored-by: Hong Jiarong <me@jrhim.com> Co-committed-by: Hong Jiarong <me@jrhim.com>
65 lines
2.6 KiB
SQL
65 lines
2.6 KiB
SQL
-- ADR-0026: append-only UsageFact ledger. AgentRun.costUsd/inputTokens/
|
|
-- outputTokens become a derived rollup cache; the truth is in UsageFact.
|
|
|
|
CREATE TABLE "UsageFact" (
|
|
"id" TEXT NOT NULL,
|
|
"runId" TEXT NOT NULL,
|
|
"occurredAt" TIMESTAMP(3) NOT NULL,
|
|
"kind" TEXT NOT NULL,
|
|
"provider" TEXT NOT NULL,
|
|
"model" TEXT,
|
|
"inputTokens" INTEGER,
|
|
"outputTokens" INTEGER,
|
|
"quantity" DECIMAL(18, 6),
|
|
"unit" TEXT,
|
|
"costUsd" DECIMAL(18, 8),
|
|
"costSource" TEXT NOT NULL,
|
|
"capabilityId" TEXT,
|
|
"correlationId" TEXT,
|
|
"metadata" JSONB NOT NULL,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
CONSTRAINT "UsageFact_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE INDEX "UsageFact_runId_occurredAt_idx" ON "UsageFact"("runId", "occurredAt");
|
|
CREATE INDEX "UsageFact_runId_kind_idx" ON "UsageFact"("runId", "kind");
|
|
CREATE INDEX "UsageFact_provider_model_occurredAt_idx"
|
|
ON "UsageFact"("provider", "model", "occurredAt");
|
|
CREATE INDEX "UsageFact_capabilityId_occurredAt_idx"
|
|
ON "UsageFact"("capabilityId", "occurredAt");
|
|
|
|
ALTER TABLE "UsageFact"
|
|
ADD CONSTRAINT "UsageFact_runId_fkey"
|
|
FOREIGN KEY ("runId") REFERENCES "AgentRun"("id")
|
|
ON DELETE CASCADE ON UPDATE CASCADE;
|
|
|
|
-- Backfill: one synthetic model_completion fact per AgentRun that has any
|
|
-- recorded usage (cost or tokens). correlationId = run id marks these as
|
|
-- backfill artefacts (real facts use an external correlation id or null).
|
|
-- Runs with no recorded usage stay fact-less and remain runsWithoutCost,
|
|
-- matching ADR-0022's "missing cost ≠ zero" rule and the pre-existing
|
|
-- migration 20260709143000_agent_run_cost_tracking's "no backfill for the
|
|
-- truly unrecorded" stance.
|
|
INSERT INTO "UsageFact" (
|
|
"id", "runId", "occurredAt", "kind", "provider", "model",
|
|
"inputTokens", "outputTokens", "costUsd", "costSource",
|
|
"correlationId", "metadata"
|
|
)
|
|
SELECT
|
|
'usagefact_backfill_' || "AgentRun"."id",
|
|
"AgentRun"."id",
|
|
COALESCE("AgentRun"."finishedAt", "AgentRun"."startedAt", CURRENT_TIMESTAMP),
|
|
'model_completion',
|
|
"AgentRun"."provider",
|
|
"AgentRun"."model",
|
|
"AgentRun"."inputTokens",
|
|
"AgentRun"."outputTokens",
|
|
"AgentRun"."costUsd",
|
|
COALESCE("AgentRun"."costSource", 'unknown'),
|
|
"AgentRun"."id",
|
|
'{}'::jsonb
|
|
FROM "AgentRun"
|
|
WHERE "AgentRun"."costUsd" IS NOT NULL
|
|
OR "AgentRun"."inputTokens" IS NOT NULL
|
|
OR "AgentRun"."outputTokens" IS NOT NULL;
|