Repository Public
1/** In-memory state of one execution of the run logic. Everything here is re-derived from step results on replay. */2import type { RunContext } from '@aos/kernel';3import type { ProviderAdapter } from '@aos/providers';4import type { Budget, DoneCriterion, Effort, Provider, ToolResult } from '@aos/shared';5import type { FileState, Tool } from '@aos/tools';6import type { ResolvedDeps } from './deps.js';7import type { PolicyRule } from './policy.js';8import type { StallDetector } from './stall.js';9import type { Transcript } from './transcript.js';1011/** Result of the `run_meta` step: the facts of the run that `RunContext` does not carry. */12export interface RunMeta {13 provider: Provider;14 model: string;15 effort: Effort | null;16 budget: Budget;17 ownerId: string;18 projectId: string | null;19 network: 'none' | 'open';20 projectNotes: string;21 /** `missions.done_criteria` when the run first started. */22 criteria: DoneCriterion[];23}2425export interface RunState {26 ctx: RunContext;27 deps: ResolvedDeps;28 meta: RunMeta;29 adapter: ProviderAdapter;30 /** Tools offered to the model, by name. */31 tools: Map<string, Tool>;32 transcript: Transcript;33 criteria: DoneCriterion[];34 criteriaConfirmed: boolean;35 /** Folded from `fileStateOut` of tool step results, in step order. */36 fileState: FileState;37 /** Allow rules created by "approve and remember" during the current tool batch (the next batch re-reads the table). */38 batchRules: PolicyRule[];39 stall: StallDetector;40 /** Milliseconds spent suspended in owner waits, measured with journaled clock readings. */41 waitedMs: number;42 /** Offloaded tool outputs, listed in the result envelope. */43 artifacts: { name: string; sha256: string }[];44 /** True during the single final turn: only `finish` is executed. */45 finalTurn: boolean;46}4748/** Durable wait whose duration is not charged against the wall-clock limit. */49export async function ownerWait<T>(st: RunState, kind: 'approval' | 'question', payload: Record<string, unknown>, timeoutSec?: number): Promise<T | { expired: true }> {50 const t0 = await st.ctx.now();51 const r = await st.ctx.wait<T>(kind, payload, timeoutSec === undefined ? undefined : { timeoutSec });52 const t1 = await st.ctx.now();53 st.waitedMs += Math.max(0, t1.getTime() - t0.getTime());54 return r;55}5657export const isExpired = (r: unknown): r is { expired: true } => typeof r === 'object' && r !== null && (r as { expired?: unknown }).expired === true;5859export function toolResult(call: { id: string; name: string }, ok: boolean, content: string, extra: Partial<Pick<ToolResult, 'artifact' | 'trust'>> = {}): ToolResult {60 return { callId: call.id, name: call.name, ok, content, artifact: extra.artifact ?? null, trust: extra.trust ?? 'tool' };61}62