feat(agent): budget reminders, usage while waiting, budget-exceeded status and dedupe

- tool results carry a budget reminder near limits; text before the last tool
  call is dropped as report when cut by budget/abort
- usage persisted when a run suspends, so waiting sessions show spent tokens
- task page shows budget_exceeded via business.outcome instead of completed
- budget-exceeded decisions merge by root cause (decision / schedule / goal
  template); new summaries added to investigate allowlist

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-29 01:58:28 +08:00
1 parent 4cd9ec8390
commit a00a9eaf5d
14 files changed
+205 -21

No files matched your search

@@ -218,10 +218,12 @@ export async function resolveBusiness(
}),
);
const agentIds = [...(byKind.get("agent") ?? [])];
const agents = new Map<string, { trigger: string; created_by: string | null }>();
const agents = new Map<string, { trigger: string; created_by: string | null; status: string }>();
if (agentIds.length) {
const r = await sql<{ id: string; trigger: string; created_by: string | null }>`
select id::text as id, trigger, created_by from agent_run where id::text = any(${agentIds}::text[])`.execute(db);
const r = await sql<{ id: string; trigger: string; created_by: string | null; status: string }>`
select id::text as id, trigger, created_by, status from agent_run where id::text = any(${agentIds}::text[])`.execute(
db,
);
for (const a of r.rows) agents.set(a.id, a);
}
@@ -240,6 +242,7 @@ export async function resolveBusiness(
agentCreatedBy: agent?.created_by ?? null,
fromOutbox: !!r.idempotency_key && outboxKeys.has(r.idempotency_key),
}),
...(agent ? { outcome: agent.status } : {}),
});
}
return out;