fix(runtime): classify run usage status
This commit is contained in:
1 parent
d971ca7929
commit
eefb515aa2
17 files changed
+308
-26
No files matched your search
@@ -29,6 +29,7 @@ function makeRun(overrides: Partial<RunRecord> = {}): RunRecord {
|
||||
model: null,
|
||||
costUsd: null,
|
||||
unattributedCost: false,
|
||||
usageStatus: "ok",
|
||||
startedAt: null,
|
||||
finishedAt: null,
|
||||
logPath: null,
|
||||
|
||||
@@ -304,6 +304,60 @@ describe("AppDatabase", () => {
|
||||
expect(db.entityCrud.getAgent(agentId).spentMonthlyUsd).toBe(12);
|
||||
});
|
||||
|
||||
it("persists explicit run usage status", () => {
|
||||
const companyId = db.company.saveCompany({
|
||||
name: "Usage Status Company",
|
||||
description: "Tracks run usage status",
|
||||
status: "active",
|
||||
});
|
||||
const workspaceId = db.workspacesMod.saveWorkspace({
|
||||
companyId,
|
||||
name: "Usage Workspace",
|
||||
localPath: "/tmp/usage-status",
|
||||
repoUrl: "",
|
||||
repoRef: "",
|
||||
isPrimary: true,
|
||||
});
|
||||
const agentId = db.agents.saveAgent({
|
||||
companyId,
|
||||
name: "Usage Agent",
|
||||
role: "Engineer",
|
||||
title: "Engineer",
|
||||
status: "active",
|
||||
reportsTo: null,
|
||||
connectorId: "openai-codex",
|
||||
workspaceId,
|
||||
model: "gpt-5",
|
||||
capabilities: "Run tasks",
|
||||
budgetMonthlyUsd: 100,
|
||||
});
|
||||
const taskId = db.tasks.saveTask({
|
||||
companyId,
|
||||
title: "Usage task",
|
||||
description: "Exercise explicit usage status.",
|
||||
assigneeAgentId: agentId,
|
||||
workspaceId,
|
||||
priority: "medium",
|
||||
status: "in_progress",
|
||||
});
|
||||
const run = db.runs.createRun({ companyId, taskId, agentId, workspaceId, connectorId: "openai-codex" });
|
||||
|
||||
db.runs.finishRun({
|
||||
runId: run.id,
|
||||
status: "failed",
|
||||
summary: null,
|
||||
errorMessage: "stream setup failed",
|
||||
exitCode: null,
|
||||
signal: null,
|
||||
model: "gpt-5",
|
||||
unattributedCost: true,
|
||||
usageStatus: "error_stop",
|
||||
});
|
||||
|
||||
expect(db.runs.getRun(run.id).usageStatus).toBe("error_stop");
|
||||
expect(db.snap.listSnapshot().runs.find((record) => record.id === run.id)?.usageStatus).toBe("error_stop");
|
||||
});
|
||||
|
||||
it("activates pending hires when the corresponding approval is granted", () => {
|
||||
const companyId = db.company.saveCompany({
|
||||
name: "Hiring Company",
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
classifyRunUsage,
|
||||
deriveLegacyRunUsageStatus,
|
||||
hasAttributableAssistantUsage,
|
||||
} from "../../src/main/run-usage-status";
|
||||
|
||||
describe("run usage status", () => {
|
||||
it("does not treat pi error EMPTY_USAGE as attributable cost", () => {
|
||||
expect(
|
||||
hasAttributableAssistantUsage({
|
||||
role: "assistant",
|
||||
stopReason: "error",
|
||||
usage: { input: 0, output: 0 },
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it("accepts normal assistant usage as attributable", () => {
|
||||
expect(
|
||||
hasAttributableAssistantUsage({
|
||||
role: "assistant",
|
||||
stopReason: "stop",
|
||||
usage: { input: 12, output: 7 },
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("keeps non-zero terminal usage attributable", () => {
|
||||
expect(
|
||||
hasAttributableAssistantUsage({
|
||||
role: "assistant",
|
||||
stopReason: "error",
|
||||
usage: { input: 12, output: 1 },
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("classifies terminal usage states explicitly", () => {
|
||||
expect(
|
||||
classifyRunUsage({
|
||||
runStatus: "failed",
|
||||
errorMessage: "stream setup failed",
|
||||
sawAttributableUsage: false,
|
||||
terminalStopReason: "error",
|
||||
}),
|
||||
).toBe("error_stop");
|
||||
|
||||
expect(
|
||||
classifyRunUsage({
|
||||
runStatus: "cancelled",
|
||||
errorMessage: null,
|
||||
sawAttributableUsage: false,
|
||||
terminalStopReason: "aborted",
|
||||
}),
|
||||
).toBe("aborted_before_usage");
|
||||
|
||||
expect(
|
||||
classifyRunUsage({
|
||||
runStatus: "failed",
|
||||
errorMessage: "prepareRun failed",
|
||||
sawAttributableUsage: false,
|
||||
terminalStopReason: null,
|
||||
}),
|
||||
).toBe("pre_first_message");
|
||||
|
||||
expect(
|
||||
classifyRunUsage({
|
||||
runStatus: "succeeded",
|
||||
errorMessage: null,
|
||||
sawAttributableUsage: true,
|
||||
terminalStopReason: null,
|
||||
}),
|
||||
).toBe("ok");
|
||||
});
|
||||
|
||||
it("maps legacy finishRun inputs into explicit usage status", () => {
|
||||
expect(deriveLegacyRunUsageStatus({ runStatus: "succeeded", unattributedCost: false })).toBe("ok");
|
||||
expect(deriveLegacyRunUsageStatus({ runStatus: "interrupted", unattributedCost: true })).toBe(
|
||||
"aborted_before_usage",
|
||||
);
|
||||
expect(deriveLegacyRunUsageStatus({ runStatus: "failed", unattributedCost: true })).toBe("pre_first_message");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user