Add agent runtime DB schemas and expand shared types

New schemas: agent_runtime_state, agent_wakeup_requests,
heartbeat_run_events. New migrations for runtime tables. Expand
heartbeat types with run events, wakeup reasons, and adapter state.
Add live event types. Update agent schema and shared constants.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Forgotten
2026-02-17 12:24:38 -06:00
parent 13ef123026
commit 2583bf4c43
20 changed files with 5296 additions and 5 deletions

View File

@@ -14,7 +14,7 @@ export type AgentStatus = (typeof AGENT_STATUSES)[number];
export const AGENT_CONTEXT_MODES = ["thin", "fat"] as const;
export type AgentContextMode = (typeof AGENT_CONTEXT_MODES)[number];
export const AGENT_ADAPTER_TYPES = ["process", "http"] as const;
export const AGENT_ADAPTER_TYPES = ["process", "http", "claude_local", "codex_local"] as const;
export type AgentAdapterType = (typeof AGENT_ADAPTER_TYPES)[number];
export const AGENT_ROLES = [
@@ -67,9 +67,28 @@ export type ApprovalType = (typeof APPROVAL_TYPES)[number];
export const APPROVAL_STATUSES = ["pending", "approved", "rejected", "cancelled"] as const;
export type ApprovalStatus = (typeof APPROVAL_STATUSES)[number];
export const HEARTBEAT_INVOCATION_SOURCES = ["scheduler", "manual", "callback"] as const;
export const HEARTBEAT_INVOCATION_SOURCES = [
"timer",
"assignment",
"on_demand",
"automation",
] as const;
export type HeartbeatInvocationSource = (typeof HEARTBEAT_INVOCATION_SOURCES)[number];
export const WAKEUP_TRIGGER_DETAILS = ["manual", "ping", "callback", "system"] as const;
export type WakeupTriggerDetail = (typeof WAKEUP_TRIGGER_DETAILS)[number];
export const WAKEUP_REQUEST_STATUSES = [
"queued",
"claimed",
"coalesced",
"skipped",
"completed",
"failed",
"cancelled",
] as const;
export type WakeupRequestStatus = (typeof WAKEUP_REQUEST_STATUSES)[number];
export const HEARTBEAT_RUN_STATUSES = [
"queued",
"running",
@@ -79,3 +98,13 @@ export const HEARTBEAT_RUN_STATUSES = [
"timed_out",
] as const;
export type HeartbeatRunStatus = (typeof HEARTBEAT_RUN_STATUSES)[number];
export const LIVE_EVENT_TYPES = [
"heartbeat.run.queued",
"heartbeat.run.status",
"heartbeat.run.event",
"heartbeat.run.log",
"agent.status",
"activity.logged",
] as const;
export type LiveEventType = (typeof LIVE_EVENT_TYPES)[number];

View File

@@ -13,6 +13,9 @@ export {
APPROVAL_STATUSES,
HEARTBEAT_INVOCATION_SOURCES,
HEARTBEAT_RUN_STATUSES,
WAKEUP_TRIGGER_DETAILS,
WAKEUP_REQUEST_STATUSES,
LIVE_EVENT_TYPES,
type CompanyStatus,
type AgentStatus,
type AgentContextMode,
@@ -27,6 +30,9 @@ export {
type ApprovalStatus,
type HeartbeatInvocationSource,
type HeartbeatRunStatus,
type WakeupTriggerDetail,
type WakeupRequestStatus,
type LiveEventType,
} from "./constants.js";
export type {
@@ -41,6 +47,10 @@ export type {
CostEvent,
CostSummary,
HeartbeatRun,
HeartbeatRunEvent,
AgentRuntimeState,
AgentWakeupRequest,
LiveEvent,
DashboardSummary,
ActivityEvent,
} from "./types/index.js";
@@ -53,9 +63,11 @@ export {
createAgentSchema,
updateAgentSchema,
createAgentKeySchema,
wakeAgentSchema,
type CreateAgent,
type UpdateAgent,
type CreateAgentKey,
type WakeAgent,
createProjectSchema,
updateProjectSchema,
type CreateProject,

View File

@@ -16,6 +16,7 @@ export interface Agent {
capabilities: string | null;
adapterType: AgentAdapterType;
adapterConfig: Record<string, unknown>;
runtimeConfig: Record<string, unknown>;
contextMode: AgentContextMode;
budgetMonthlyCents: number;
spentMonthlyCents: number;

View File

@@ -1,6 +1,8 @@
import type {
HeartbeatInvocationSource,
HeartbeatRunStatus,
WakeupTriggerDetail,
WakeupRequestStatus,
} from "../constants.js";
export interface HeartbeatRun {
@@ -8,12 +10,82 @@ export interface HeartbeatRun {
companyId: string;
agentId: string;
invocationSource: HeartbeatInvocationSource;
triggerDetail: WakeupTriggerDetail | null;
status: HeartbeatRunStatus;
startedAt: Date | null;
finishedAt: Date | null;
error: string | null;
wakeupRequestId: string | null;
exitCode: number | null;
signal: string | null;
usageJson: Record<string, unknown> | null;
resultJson: Record<string, unknown> | null;
sessionIdBefore: string | null;
sessionIdAfter: string | null;
logStore: string | null;
logRef: string | null;
logBytes: number | null;
logSha256: string | null;
logCompressed: boolean;
stdoutExcerpt: string | null;
stderrExcerpt: string | null;
errorCode: string | null;
externalRunId: string | null;
contextSnapshot: Record<string, unknown> | null;
createdAt: Date;
updatedAt: Date;
}
export interface HeartbeatRunEvent {
id: number;
companyId: string;
runId: string;
agentId: string;
seq: number;
eventType: string;
stream: "system" | "stdout" | "stderr" | null;
level: "info" | "warn" | "error" | null;
color: string | null;
message: string | null;
payload: Record<string, unknown> | null;
createdAt: Date;
}
export interface AgentRuntimeState {
agentId: string;
companyId: string;
adapterType: string;
sessionId: string | null;
stateJson: Record<string, unknown>;
lastRunId: string | null;
lastRunStatus: string | null;
totalInputTokens: number;
totalOutputTokens: number;
totalCachedInputTokens: number;
totalCostCents: number;
lastError: string | null;
createdAt: Date;
updatedAt: Date;
}
export interface AgentWakeupRequest {
id: string;
companyId: string;
agentId: string;
source: HeartbeatInvocationSource;
triggerDetail: WakeupTriggerDetail | null;
reason: string | null;
payload: Record<string, unknown> | null;
status: WakeupRequestStatus;
coalescedCount: number;
requestedByActorType: "user" | "agent" | "system" | null;
requestedByActorId: string | null;
idempotencyKey: string | null;
runId: string | null;
requestedAt: Date;
claimedAt: Date | null;
finishedAt: Date | null;
error: string | null;
createdAt: Date;
updatedAt: Date;
}

View File

@@ -5,6 +5,12 @@ export type { Issue, IssueComment } from "./issue.js";
export type { Goal } from "./goal.js";
export type { Approval } from "./approval.js";
export type { CostEvent, CostSummary } from "./cost.js";
export type { HeartbeatRun } from "./heartbeat.js";
export type {
HeartbeatRun,
HeartbeatRunEvent,
AgentRuntimeState,
AgentWakeupRequest,
} from "./heartbeat.js";
export type { LiveEvent } from "./live.js";
export type { DashboardSummary } from "./dashboard.js";
export type { ActivityEvent } from "./activity.js";

View File

@@ -0,0 +1,9 @@
import type { LiveEventType } from "../constants.js";
export interface LiveEvent {
id: number;
companyId: string;
type: LiveEventType;
createdAt: string;
payload: Record<string, unknown>;
}

View File

@@ -14,6 +14,7 @@ export const createAgentSchema = z.object({
capabilities: z.string().optional().nullable(),
adapterType: z.enum(AGENT_ADAPTER_TYPES).optional().default("process"),
adapterConfig: z.record(z.unknown()).optional().default({}),
runtimeConfig: z.record(z.unknown()).optional().default({}),
contextMode: z.enum(AGENT_CONTEXT_MODES).optional().default("thin"),
budgetMonthlyCents: z.number().int().nonnegative().optional().default(0),
metadata: z.record(z.unknown()).optional().nullable(),
@@ -35,3 +36,13 @@ export const createAgentKeySchema = z.object({
});
export type CreateAgentKey = z.infer<typeof createAgentKeySchema>;
export const wakeAgentSchema = z.object({
source: z.enum(["timer", "assignment", "on_demand", "automation"]).optional().default("on_demand"),
triggerDetail: z.enum(["manual", "ping", "callback", "system"]).optional(),
reason: z.string().optional().nullable(),
payload: z.record(z.unknown()).optional().nullable(),
idempotencyKey: z.string().optional().nullable(),
});
export type WakeAgent = z.infer<typeof wakeAgentSchema>;

View File

@@ -9,9 +9,11 @@ export {
createAgentSchema,
updateAgentSchema,
createAgentKeySchema,
wakeAgentSchema,
type CreateAgent,
type UpdateAgent,
type CreateAgentKey,
type WakeAgent,
} from "./agent.js";
export {