源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
Dependency audit / audit (push) Canceled after 0s
CI / plan (push) Canceled after 0s
Gitoxide helper admission / macos-latest (push) Canceled after 0s
Gitoxide helper admission / ubuntu-latest (push) Canceled after 0s
Gitoxide helper admission / windows-latest (push) Canceled after 0s
Runtime Host peer admission / quality (push) Canceled after 0s
Windows recovery / windows_recovery (push) Canceled after 0s
CI / heavy (push) Canceled after 0s
CI / test (push) Canceled after 0s
Dependency audit / audit (push) Canceled after 0s
CI / plan (push) Canceled after 0s
Gitoxide helper admission / macos-latest (push) Canceled after 0s
Gitoxide helper admission / ubuntu-latest (push) Canceled after 0s
Gitoxide helper admission / windows-latest (push) Canceled after 0s
Runtime Host peer admission / quality (push) Canceled after 0s
Windows recovery / windows_recovery (push) Canceled after 0s
CI / heavy (push) Canceled after 0s
CI / test (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { isPartialRuntimeEvent, isTerminalRuntimeEvent } from '@maka/core/runtime-event';
|
||||
import type {
|
||||
AgentRunEvent,
|
||||
AgentRunHeader,
|
||||
AgentRunEventType,
|
||||
AgentRunStore,
|
||||
} from '@maka/core/agent-run';
|
||||
import type { RuntimeEvent } from '@maka/core/runtime-event';
|
||||
import type { RuntimeEventStore } from '@maka/core/runtime-event-store';
|
||||
import {
|
||||
classifyRuntimeEventTerminalFact,
|
||||
type RuntimeEventTerminalFact,
|
||||
} from './runtime-event-read-model.js';
|
||||
|
||||
export type TerminalAgentRunStatus = Extract<
|
||||
AgentRunHeader['status'],
|
||||
'completed' | 'failed' | 'cancelled'
|
||||
>;
|
||||
|
||||
export type TerminalRuntimeLedgerClassification =
|
||||
| {
|
||||
kind: 'fact';
|
||||
fact: RuntimeEventTerminalFact;
|
||||
terminalEvents: readonly RuntimeEvent[];
|
||||
}
|
||||
| {
|
||||
kind: 'none';
|
||||
terminalEvents: readonly RuntimeEvent[];
|
||||
}
|
||||
| {
|
||||
kind: 'incomplete_single_terminal';
|
||||
terminalEvent: RuntimeEvent;
|
||||
terminalEvents: readonly RuntimeEvent[];
|
||||
}
|
||||
| {
|
||||
kind: 'ambiguous';
|
||||
terminalEvents: readonly RuntimeEvent[];
|
||||
};
|
||||
|
||||
export function classifyTerminalRuntimeLedger(
|
||||
run: AgentRunHeader,
|
||||
events: readonly RuntimeEvent[],
|
||||
): TerminalRuntimeLedgerClassification {
|
||||
const terminalEvents = matchingTerminalRuntimeEvents(run, events);
|
||||
if (terminalEvents.length === 0) {
|
||||
return { kind: 'none', terminalEvents };
|
||||
}
|
||||
if (terminalEvents.length > 1) {
|
||||
return { kind: 'ambiguous', terminalEvents };
|
||||
}
|
||||
|
||||
const fact = classifyRuntimeEventTerminalFact(run, events).fact;
|
||||
if (fact) {
|
||||
return { kind: 'fact', fact, terminalEvents };
|
||||
}
|
||||
return {
|
||||
kind: 'incomplete_single_terminal',
|
||||
terminalEvent: terminalEvents[0]!,
|
||||
terminalEvents,
|
||||
};
|
||||
}
|
||||
|
||||
export interface CommitTerminalRunWithRuntimeFactInput {
|
||||
runStore: AgentRunStore;
|
||||
runtimeEventStore: RuntimeEventStore;
|
||||
newId: () => string;
|
||||
sessionId: string;
|
||||
runId: string;
|
||||
turnId: string;
|
||||
status: TerminalAgentRunStatus;
|
||||
ts: number;
|
||||
terminalEvent: RuntimeEvent;
|
||||
failureClass?: string;
|
||||
failureMessage?: string;
|
||||
traceWriteError?: string;
|
||||
abortSource?: string;
|
||||
runEventData?: Record<string, unknown>;
|
||||
runEventMessage?: string;
|
||||
existingEvents?: readonly Pick<AgentRunEvent, 'type'>[];
|
||||
}
|
||||
|
||||
export async function commitTerminalRunWithRuntimeFact(
|
||||
input: CommitTerminalRunWithRuntimeFactInput,
|
||||
): Promise<void> {
|
||||
if (isPartialRuntimeEvent(input.terminalEvent)) {
|
||||
throw new Error('terminal RuntimeEvent must be final before terminal run header');
|
||||
}
|
||||
const terminalStatus = terminalRunStatusFromRuntimeEvent(input.terminalEvent);
|
||||
if (!terminalStatus) {
|
||||
throw new Error('terminal RuntimeEvent must carry a terminal status');
|
||||
}
|
||||
if (terminalStatus !== input.status) {
|
||||
throw new Error(
|
||||
`terminal RuntimeEvent status ${input.terminalEvent.status} cannot commit ${input.status} run header`,
|
||||
);
|
||||
}
|
||||
if (
|
||||
input.terminalEvent.sessionId !== input.sessionId ||
|
||||
input.terminalEvent.runId !== input.runId ||
|
||||
input.terminalEvent.turnId !== input.turnId
|
||||
) {
|
||||
throw new Error('terminal RuntimeEvent identity does not match run header commit');
|
||||
}
|
||||
await input.runtimeEventStore.ensureTerminalRuntimeEventDurable(
|
||||
input.sessionId,
|
||||
input.runId,
|
||||
input.terminalEvent,
|
||||
);
|
||||
|
||||
await commitTerminalRunProjection(input);
|
||||
}
|
||||
|
||||
async function commitTerminalRunProjection(
|
||||
input: CommitTerminalRunWithRuntimeFactInput,
|
||||
): Promise<void> {
|
||||
const failureClass = input.status === 'failed' ? (input.failureClass ?? 'unknown') : undefined;
|
||||
const abortSource = input.status === 'cancelled' ? input.abortSource : undefined;
|
||||
await input.runStore.updateRun(
|
||||
input.sessionId,
|
||||
input.runId,
|
||||
{
|
||||
status: input.status,
|
||||
updatedAt: input.ts,
|
||||
completedAt: input.ts,
|
||||
...(failureClass ? { failureClass } : {}),
|
||||
...(input.failureMessage ? { failureMessage: input.failureMessage } : {}),
|
||||
...(input.traceWriteError ? { traceWriteError: input.traceWriteError } : {}),
|
||||
...(abortSource ? { abortSource } : {}),
|
||||
},
|
||||
{ durable: true },
|
||||
);
|
||||
|
||||
if (hasTerminalAgentRunEvent(input.existingEvents ?? [])) return;
|
||||
const data = terminalRunEventData(input.status, failureClass, input.runEventData);
|
||||
await input.runStore.appendEvent(
|
||||
input.sessionId,
|
||||
input.runId,
|
||||
{
|
||||
type: terminalAgentRunEventType(input.status),
|
||||
id: input.newId(),
|
||||
runId: input.runId,
|
||||
sessionId: input.sessionId,
|
||||
turnId: input.turnId,
|
||||
ts: input.ts,
|
||||
...(input.runEventMessage ? { message: input.runEventMessage } : {}),
|
||||
...(Object.keys(data).length > 0 ? { data } : {}),
|
||||
},
|
||||
{ durable: true },
|
||||
);
|
||||
}
|
||||
|
||||
export interface CommitOrCreateTerminalRunFactInput
|
||||
extends Omit<CommitTerminalRunWithRuntimeFactInput, 'status' | 'terminalEvent'> {
|
||||
/** Runs after the terminal durability barrier, before the header commit. */
|
||||
afterTerminalDurable?: () => Promise<void>;
|
||||
terminalEvent?: RuntimeEvent;
|
||||
allowHeaderCommitFailure?: boolean;
|
||||
fallbackStatus: TerminalAgentRunStatus;
|
||||
fallbackInvocationId: string;
|
||||
fallbackFailureClass?: string;
|
||||
fallbackFailureMessage?: string;
|
||||
}
|
||||
|
||||
export interface CommitOrCreateTerminalRunFactResult {
|
||||
terminalEvent: RuntimeEvent;
|
||||
status: TerminalAgentRunStatus;
|
||||
failureClass?: string;
|
||||
createdTerminalEvent: boolean;
|
||||
headerCommitted: boolean;
|
||||
headerCommitError?: unknown;
|
||||
}
|
||||
|
||||
export async function commitOrCreateTerminalRunFact(
|
||||
input: CommitOrCreateTerminalRunFactInput,
|
||||
): Promise<CommitOrCreateTerminalRunFactResult> {
|
||||
const createdTerminalEvent = !input.terminalEvent;
|
||||
const effectiveAbortSource =
|
||||
input.fallbackStatus === 'cancelled' ? (input.abortSource ?? 'user_stop') : input.abortSource;
|
||||
const terminalEvent =
|
||||
input.terminalEvent ??
|
||||
buildSyntheticTerminalRuntimeEvent({
|
||||
id: input.newId(),
|
||||
invocationId: input.fallbackInvocationId,
|
||||
run: {
|
||||
sessionId: input.sessionId,
|
||||
runId: input.runId,
|
||||
turnId: input.turnId,
|
||||
},
|
||||
status: input.fallbackStatus,
|
||||
ts: input.ts,
|
||||
...(input.fallbackFailureClass ? { failureClass: input.fallbackFailureClass } : {}),
|
||||
...(effectiveAbortSource ? { abortSource: effectiveAbortSource } : {}),
|
||||
...((input.fallbackFailureMessage ?? input.failureMessage)
|
||||
? { message: input.fallbackFailureMessage ?? input.failureMessage }
|
||||
: {}),
|
||||
});
|
||||
const status = terminalRunStatusFromRuntimeEvent(terminalEvent);
|
||||
if (!status) {
|
||||
throw new Error('terminal RuntimeEvent must carry a terminal status');
|
||||
}
|
||||
if (isPartialRuntimeEvent(terminalEvent)) {
|
||||
throw new Error('terminal RuntimeEvent must be final before terminal run header');
|
||||
}
|
||||
if (
|
||||
terminalEvent.sessionId !== input.sessionId ||
|
||||
terminalEvent.runId !== input.runId ||
|
||||
terminalEvent.turnId !== input.turnId
|
||||
) {
|
||||
throw new Error('terminal RuntimeEvent identity does not match run header commit');
|
||||
}
|
||||
const failureClass =
|
||||
status === 'failed'
|
||||
? (runtimeEventFailureClass(terminalEvent) ?? input.failureClass ?? 'unknown')
|
||||
: undefined;
|
||||
await input.runtimeEventStore.ensureTerminalRuntimeEventDurable(
|
||||
input.sessionId,
|
||||
input.runId,
|
||||
terminalEvent,
|
||||
);
|
||||
// Between the terminal durability barrier and the header commit: the one
|
||||
// point where "the terminal fact is durable" is true and nothing else has
|
||||
// been projected yet. Callers that must order a crash boundary against
|
||||
// the barrier itself hang it here (#2313 corruption recovery, where the
|
||||
// claimed event's own write never ran).
|
||||
await input.afterTerminalDurable?.();
|
||||
let headerCommitted = false;
|
||||
let headerCommitError: unknown;
|
||||
try {
|
||||
await commitTerminalRunProjection({
|
||||
...input,
|
||||
terminalEvent,
|
||||
status,
|
||||
...(failureClass ? { failureClass } : {}),
|
||||
...(effectiveAbortSource ? { abortSource: effectiveAbortSource } : {}),
|
||||
});
|
||||
headerCommitted = true;
|
||||
} catch (error) {
|
||||
if (!input.allowHeaderCommitFailure) throw error;
|
||||
headerCommitError = error;
|
||||
}
|
||||
return {
|
||||
terminalEvent,
|
||||
status,
|
||||
...(failureClass ? { failureClass } : {}),
|
||||
createdTerminalEvent,
|
||||
headerCommitted,
|
||||
...(headerCommitError !== undefined ? { headerCommitError } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
export interface BuildSyntheticTerminalRuntimeEventInput {
|
||||
id: string;
|
||||
invocationId: string;
|
||||
run: Pick<AgentRunHeader, 'runId' | 'sessionId' | 'turnId'>;
|
||||
status: TerminalAgentRunStatus;
|
||||
ts: number;
|
||||
failureClass?: string;
|
||||
abortSource?: string;
|
||||
recoveryReason?: string;
|
||||
diagnostic?: Record<string, unknown>;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export function buildSyntheticTerminalRuntimeEvent(
|
||||
input: BuildSyntheticTerminalRuntimeEventInput,
|
||||
): RuntimeEvent {
|
||||
const failureClass = input.status === 'failed' ? (input.failureClass ?? 'unknown') : undefined;
|
||||
const abortSource = input.status === 'cancelled' ? input.abortSource : undefined;
|
||||
return {
|
||||
id: input.id,
|
||||
invocationId: input.invocationId,
|
||||
runId: input.run.runId,
|
||||
sessionId: input.run.sessionId,
|
||||
turnId: input.run.turnId,
|
||||
ts: input.ts,
|
||||
partial: false,
|
||||
role: 'system',
|
||||
author: 'system',
|
||||
status: input.status === 'cancelled' ? 'aborted' : input.status,
|
||||
...(failureClass
|
||||
? {
|
||||
content: {
|
||||
kind: 'error',
|
||||
code: failureClass,
|
||||
reason: failureClass,
|
||||
message: input.message ?? failureClass,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
actions: {
|
||||
endInvocation: true,
|
||||
stateDelta: {
|
||||
...(input.recoveryReason ? { recovered: true, recoveryReason: input.recoveryReason } : {}),
|
||||
...(input.diagnostic ?? {}),
|
||||
...(failureClass ? { failureClass } : {}),
|
||||
...(abortSource ? { abortSource } : {}),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export interface BuildRecoveredTerminalRuntimeEventInput {
|
||||
id: string;
|
||||
run: Pick<AgentRunHeader, 'runId' | 'sessionId' | 'turnId' | 'invocationId'>;
|
||||
status: TerminalAgentRunStatus;
|
||||
ts: number;
|
||||
invocationId?: string;
|
||||
failureClass?: string;
|
||||
abortSource?: string;
|
||||
recoveryReason: string;
|
||||
diagnostic?: Record<string, unknown>;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export function buildRecoveredTerminalRuntimeEvent(
|
||||
input: BuildRecoveredTerminalRuntimeEventInput,
|
||||
): RuntimeEvent {
|
||||
return buildSyntheticTerminalRuntimeEvent({
|
||||
id: input.id,
|
||||
invocationId: input.run.invocationId ?? input.invocationId ?? `recovery-${input.run.runId}`,
|
||||
run: input.run,
|
||||
ts: input.ts,
|
||||
status: input.status,
|
||||
...(input.failureClass ? { failureClass: input.failureClass } : {}),
|
||||
...(input.status === 'cancelled' ? { abortSource: input.abortSource ?? 'unknown' } : {}),
|
||||
recoveryReason: input.recoveryReason,
|
||||
...(input.diagnostic ? { diagnostic: input.diagnostic } : {}),
|
||||
...(input.message ? { message: input.message } : {}),
|
||||
});
|
||||
}
|
||||
|
||||
export function hasTerminalAgentRunEvent(events: readonly Pick<AgentRunEvent, 'type'>[]): boolean {
|
||||
return events.some(
|
||||
(event) =>
|
||||
event.type === 'run_completed' ||
|
||||
event.type === 'run_failed' ||
|
||||
event.type === 'run_cancelled',
|
||||
);
|
||||
}
|
||||
|
||||
function terminalAgentRunEventType(status: TerminalAgentRunStatus): AgentRunEventType {
|
||||
if (status === 'cancelled') return 'run_cancelled';
|
||||
if (status === 'failed') return 'run_failed';
|
||||
return 'run_completed';
|
||||
}
|
||||
|
||||
function terminalRunEventData(
|
||||
status: TerminalAgentRunStatus,
|
||||
failureClass: string | undefined,
|
||||
runEventData: Record<string, unknown> | undefined,
|
||||
): Record<string, unknown> {
|
||||
return {
|
||||
...(status === 'failed' && failureClass ? { failureClass } : {}),
|
||||
...(runEventData ?? {}),
|
||||
};
|
||||
}
|
||||
|
||||
function runtimeEventFailureClass(event: RuntimeEvent): string | undefined {
|
||||
const stateDelta = event.actions?.stateDelta;
|
||||
if (typeof stateDelta?.failureClass === 'string' && stateDelta.failureClass.length > 0) {
|
||||
return stateDelta.failureClass;
|
||||
}
|
||||
if (event.content?.kind === 'error') {
|
||||
return event.content.code ?? event.content.reason;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function terminalRunStatusFromRuntimeEvent(
|
||||
event: RuntimeEvent,
|
||||
): TerminalAgentRunStatus | undefined {
|
||||
if (event.status === 'completed') return 'completed';
|
||||
if (event.status === 'failed') return 'failed';
|
||||
if (event.status === 'aborted' || event.status === 'cancelled') return 'cancelled';
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function effectiveRunHeaderFromTerminalFact(
|
||||
run: AgentRunHeader,
|
||||
fact: RuntimeEventTerminalFact,
|
||||
): AgentRunHeader {
|
||||
const completedAt = run.completedAt ?? fact.terminalEvent.ts;
|
||||
const base = { ...run };
|
||||
delete base.failureClass;
|
||||
delete base.failureMessage;
|
||||
delete base.abortSource;
|
||||
return {
|
||||
...base,
|
||||
status: fact.runStatus,
|
||||
updatedAt: Math.max(run.updatedAt, completedAt),
|
||||
completedAt,
|
||||
...(fact.runStatus === 'failed' && fact.failureClass
|
||||
? { failureClass: fact.failureClass }
|
||||
: {}),
|
||||
...(fact.runStatus === 'failed' && run.failureMessage
|
||||
? { failureMessage: run.failureMessage }
|
||||
: {}),
|
||||
...(fact.runStatus === 'cancelled' && fact.abortSource
|
||||
? { abortSource: fact.abortSource }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
||||
export function terminalRunHeaderMatchesFact(
|
||||
run: AgentRunHeader,
|
||||
fact: RuntimeEventTerminalFact,
|
||||
): boolean {
|
||||
if (run.status !== fact.runStatus) return false;
|
||||
if (fact.runStatus === 'failed' && run.failureClass !== fact.failureClass) return false;
|
||||
if (fact.runStatus === 'cancelled' && run.abortSource !== fact.abortSource) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function matchingTerminalRuntimeEvents(
|
||||
run: AgentRunHeader,
|
||||
events: readonly RuntimeEvent[],
|
||||
): RuntimeEvent[] {
|
||||
return events.filter(
|
||||
(event) =>
|
||||
!isPartialRuntimeEvent(event) &&
|
||||
event.sessionId === run.sessionId &&
|
||||
event.runId === run.runId &&
|
||||
event.turnId === run.turnId &&
|
||||
isTerminalRuntimeEvent(event),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user