File size: 2,992 Bytes
d197cf3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | import type {
AdmittedRunContext,
PreparedAgentRunAdmission,
} from "../agents/admitted-run-context.js";
import { parseExecutionIdentityAdmissionToken } from "./execution-identity-admission.js";
export type ExecutionOwnerBindingResult =
| "disabled"
| "bound"
| "already-bound"
| "mismatch"
| "missing";
export function isRetainedExecutionOwnerBinding(
result: ExecutionOwnerBindingResult | undefined,
): result is "bound" | "already-bound" {
return result === "bound" || result === "already-bound";
}
type ExecutionOwnerBinding = Readonly<{
contextId: string;
executionId: string;
}>;
/** Extracts only an admitted exact identity; operational run correlation cannot bind owner rows. */
export function executionOwnerBindingFromAdmission(
admitted: AdmittedRunContext,
): ExecutionOwnerBinding | undefined {
if (!admitted.executionIdentityToken) {
return undefined;
}
const token = parseExecutionIdentityAdmissionToken(admitted.executionIdentityToken);
if (token.runId !== admitted.operationalRunInstance.runId) {
throw new Error("owner execution binding disagrees with the admitted run");
}
return { contextId: token.contextId, executionId: token.executionId };
}
export function classifyExecutionOwnerBinding(
current: { contextId: string | null; executionId: string | null },
binding: ExecutionOwnerBinding,
): Exclude<ExecutionOwnerBindingResult, "disabled" | "bound" | "missing"> | "unbound" {
if (current.contextId === null && current.executionId === null) {
return "unbound";
}
return current.contextId === binding.contextId && current.executionId === binding.executionId
? "already-bound"
: "mismatch";
}
/** Adds one exact owner write after admission resolves, never inside the admission callback. */
export function withPostAdmissionExecutionOwnerBinding(
prepared: PreparedAgentRunAdmission,
bind: (context: AdmittedRunContext) => void,
): PreparedAgentRunAdmission {
let bound = false;
return Object.freeze({
...prepared,
admit: async (runtimeKind, runtimeInstanceId) => {
const admitted = await prepared.admit(runtimeKind, runtimeInstanceId);
if (!bound) {
bound = true;
bind(admitted);
}
return admitted;
},
});
}
/** Requires both exact admission and actual execution start, in either runtime order. */
export function createExecutionStartedOwnerBinding(bind: (context: AdmittedRunContext) => void): {
onPostAdmission: (context: AdmittedRunContext) => void;
onExecutionStarted: () => void;
} {
let admitted: AdmittedRunContext | undefined;
let executionStarted = false;
let bound = false;
const bindIfReady = () => {
if (bound || !admitted || !executionStarted) {
return;
}
bound = true;
bind(admitted);
};
return {
onPostAdmission: (context) => {
admitted = context;
bindIfReady();
},
onExecutionStarted: () => {
executionStarted = true;
bindIfReady();
},
};
}
|