feat(05-02): replace flat budget check with policy-based gate, wire incident checks into run completion and heartbeat
- Replace flat budgetMonthlyUsd check with evaluateBudgetGate in getRunEligibilityFailure - Add projectId parameter to getRunEligibilityFailure for project-scope policy evaluation - Update all 3 call sites to pass projectId where task context is available - Wire checkAndCreateIncidents into worker-service run-finished handler for post-run incident creation - Wire autoCloseExpiredIncidents into heartbeat for window rollover cleanup (D-06) - Pass budgetService dependency to orchestration-service and worker-service via service-graph - Mark autoPauseBudgetExceededAgent as deprecated (superseded by BudgetEnforcementService)
This commit is contained in:
1 parent
feea5c1fe9
commit
4e5429929a
3 files changed
+36
-9
No files matched your search
@@ -4,6 +4,7 @@ import { getConnectorDefinition } from "./connectors";
|
||||
import type { AppDatabase } from "./database";
|
||||
import type { RunRecord } from "@shared/types";
|
||||
import type { NotificationOptions } from "./notification-service";
|
||||
import type { createBudgetEnforcementService } from "./budget-enforcement-service";
|
||||
|
||||
const runStatusSchema = z.enum(["queued", "running", "succeeded", "failed", "cancelled", "timed_out", "interrupted"]);
|
||||
export const workerMessageSchema = z.union([
|
||||
@@ -63,6 +64,7 @@ interface WorkerServiceDependencies {
|
||||
}) => void;
|
||||
processRunCompletion: (run: RunRecord, event: z.infer<typeof workerMessageSchema> & { type: "run-finished" }) => void;
|
||||
notify: (options: NotificationOptions) => void;
|
||||
budgetService?: ReturnType<typeof createBudgetEnforcementService>;
|
||||
}
|
||||
|
||||
export function createWorkerService({
|
||||
@@ -76,6 +78,7 @@ export function createWorkerService({
|
||||
dispatchRunToWorker,
|
||||
processRunCompletion,
|
||||
notify,
|
||||
budgetService,
|
||||
}: WorkerServiceDependencies) {
|
||||
const MAX_RETRY_ATTEMPTS = 2;
|
||||
const RETRY_COOLDOWN_MS = 30_000; // 30 seconds
|
||||
@@ -330,6 +333,16 @@ export function createWorkerService({
|
||||
publishDomainChanged();
|
||||
}
|
||||
|
||||
// Policy-based incident check after run completion (Phase 5)
|
||||
if (budgetService && typeof event.costUsd === "number" && Number.isFinite(event.costUsd)) {
|
||||
try {
|
||||
const task = db.getTask(run.taskId);
|
||||
budgetService.checkAndCreateIncidents(run.companyId, run.agentId, task?.projectId ?? null);
|
||||
} catch (err) {
|
||||
logger.error(`[budget] Incident check failed: ${err instanceof Error ? err.message : String(err)}`);
|
||||
}
|
||||
}
|
||||
|
||||
if ((event.status === "failed" || event.status === "timed_out") && !isQuitting() && !destroyed) {
|
||||
const retryCount = db.getTaskRetryCount(run.taskId);
|
||||
|
||||
|
||||
Reference in new issue
Block a user