blob: 54047594ceea2da615baf6c322492ee5475402e6 [file]
import { Buffer } from 'node:buffer';
import type {
AgentGraphIntentAdmissionState,
AgentGraphScheduleUpdateSource,
AgentGraphSupervisorWakeStatus,
AgentGraphTimelineMetadataSnapshot,
AgentGraphTimelineMetadataStore,
AgentRunHeader,
AgentRunStore,
RuntimeEventStore,
} from '@maka/core';
import { stableHash } from './request-shape.js';
import {
readCommittedAgentGraphProjectionWithRuns,
type AgentGraphActivationStatus,
type AgentGraphOperatorBinding,
type AgentGraphProjection,
type AgentGraphRecord,
type AgentGraphRecordFacet,
} from './stream-graph-projection.js';
export const AGENT_GRAPH_TIMELINE_SCHEMA_VERSION = 1 as const;
export const AGENT_GRAPH_TIMELINE_DEFAULT_PAGE_SIZE = 100;
export const AGENT_GRAPH_TIMELINE_MAX_PAGE_SIZE = 256;
export type AgentGraphTimelineCoverageLimitation =
| 'admission_transition_history_not_persisted'
| 'supervisor_wake_transition_history_not_persisted'
| 'reconcile_history_not_persisted';
export interface AgentGraphTimelineRunRef {
sessionId: string;
runId: string;
turnId: string;
}
interface AgentGraphTimelineEventBase {
schemaVersion: typeof AGENT_GRAPH_TIMELINE_SCHEMA_VERSION;
eventId: string;
graphId: string;
eventTime: number;
/** Deterministic reconstruction order; it is not a cross-ledger commit sequence. */
sequence: number;
}
export type AgentGraphTimelineEvent =
| (AgentGraphTimelineEventBase & {
kind: 'supervisor_turn_started';
run: AgentGraphTimelineRunRef;
wake?: { wakeId: string; attemptId: string };
})
| (AgentGraphTimelineEventBase & {
kind: 'supervisor_turn_terminal';
run: AgentGraphTimelineRunRef;
status: Extract<AgentRunHeader['status'], 'completed' | 'failed' | 'cancelled'>;
wake?: { wakeId: string; attemptId: string };
})
| (AgentGraphTimelineEventBase & {
kind: 'schedule_committed';
updateId: string;
revision: number;
source: AgentGraphScheduleUpdateSource;
workIds: string[];
stoppedTargetIds: string[];
closesGraph: boolean;
})
| (AgentGraphTimelineEventBase & {
kind: 'schedule_finished';
updateId: string;
revision: number;
source: AgentGraphScheduleUpdateSource;
resultIds: string[];
})
| (AgentGraphTimelineEventBase & {
kind: 'operator_provisioned';
provisionId: string;
workId: string;
agentId: string;
operatorId: string;
targetSessionId: string;
initialTurnId: string;
initialRunId: string;
edgeIds: string[];
})
| (AgentGraphTimelineEventBase & {
kind: 'intent_claimed';
claimId: string;
intentId: string;
operatorId: string;
activation: AgentGraphTimelineRunRef;
})
| (AgentGraphTimelineEventBase & {
kind: 'activation_started';
operatorId: string;
activation: AgentGraphTimelineRunRef;
})
| (AgentGraphTimelineEventBase & {
kind: 'record_committed';
recordId: string;
operatorId: string;
activation: AgentGraphTimelineRunRef;
facets: AgentGraphRecordFacet[];
sourceRuntimeEventId: string;
})
| (AgentGraphTimelineEventBase & {
kind: 'activation_terminal';
operatorId: string;
activation: AgentGraphTimelineRunRef;
status: Extract<AgentGraphActivationStatus, 'completed' | 'failed' | 'aborted' | 'cancelled'>;
terminalRecordId: string;
})
| (AgentGraphTimelineEventBase & {
kind: 'supervisor_wake_claimed';
wakeId: string;
snapshotVersion: string;
rootSessionId: string;
})
| (AgentGraphTimelineEventBase & {
kind: 'supervisor_wake_attempted';
wakeId: string;
attemptId: string;
turnId: string;
})
| (AgentGraphTimelineEventBase & {
kind: 'supervisor_wake_settled';
wakeId: string;
attemptId: string;
turnId: string;
status: 'delivered' | 'superseded' | 'retryable_failed';
});
export interface AgentGraphTimelineCurrentAdmission {
intentId: string;
state: AgentGraphIntentAdmissionState;
updatedAt: number;
}
export interface AgentGraphTimelineCurrentSupervisorWake {
wakeId: string;
status: AgentGraphSupervisorWakeStatus;
attemptCount: number;
updatedAt: number;
currentAttemptId?: string;
currentTurnId?: string;
}
/**
* Mutable control-plane state observed while reconstructing this page.
*
* It intentionally lives outside the pageable immutable event stream so a
* state transition cannot invalidate an already-issued historical cursor.
*/
export interface AgentGraphTimelineCurrentState {
admissions: AgentGraphTimelineCurrentAdmission[];
supervisorWakes: AgentGraphTimelineCurrentSupervisorWake[];
}
export interface AgentGraphTimelinePage {
schemaVersion: typeof AGENT_GRAPH_TIMELINE_SCHEMA_VERSION;
graphId: string;
rootSessionId: string;
events: AgentGraphTimelineEvent[];
totalEvents: number;
omittedBefore: number;
omittedAfter: number;
nextCursor?: string;
currentState: AgentGraphTimelineCurrentState;
coverage: {
runtimeRecords: 'complete';
limitations: AgentGraphTimelineCoverageLimitation[];
};
}
export interface AgentGraphTimelinePageOptions {
cursor?: string;
limit?: number;
}
export interface ReadAgentGraphTimelinePageInput {
rootSessionId: string;
graphId: string;
controlStore: AgentGraphTimelineMetadataStore;
runStore: Pick<AgentRunStore, 'listSessionRuns'>;
runtimeEventStore: Pick<RuntimeEventStore, 'readImmutableRuntimeEvents'>;
options?: AgentGraphTimelinePageOptions;
}
export interface BuildAgentGraphTimelineInput {
rootSessionId: string;
graphId: string;
metadata: AgentGraphTimelineMetadataSnapshot;
rootRuns: readonly AgentRunHeader[];
childRuns: readonly AgentRunHeader[];
projection: AgentGraphProjection;
}
type WithoutSequence<T> = T extends unknown ? Omit<T, 'sequence'> : never;
type AgentGraphTimelineEventWithoutSequence = WithoutSequence<AgentGraphTimelineEvent>;
interface PendingTimelineEvent {
event: AgentGraphTimelineEventWithoutSequence;
rank: number;
tieBreak: string;
}
const EVENT_RANK = {
supervisor_turn_started: 10,
schedule_committed: 20,
schedule_finished: 21,
operator_provisioned: 30,
intent_claimed: 40,
activation_started: 50,
record_committed: 60,
activation_terminal: 61,
supervisor_turn_terminal: 70,
supervisor_wake_claimed: 80,
supervisor_wake_attempted: 81,
supervisor_wake_settled: 82,
} as const satisfies Record<AgentGraphTimelineEvent['kind'], number>;
export async function readAgentGraphTimelinePage(
input: ReadAgentGraphTimelinePageInput,
): Promise<AgentGraphTimelinePage> {
assertIdentity(input.rootSessionId, 'root Session id');
assertIdentity(input.graphId, 'graph id');
const metadata = await input.controlStore.readAgentGraphTimelineMetadata(input.graphId);
if (metadata.graphId !== input.graphId) {
throw new Error(`Agent graph timeline metadata belongs to ${metadata.graphId}`);
}
for (const update of metadata.scheduleUpdates) {
if (update.source.sessionId !== input.rootSessionId) {
throw new Error(
`Agent graph schedule ${update.updateId} is not owned by root Session ${input.rootSessionId}`,
);
}
}
const operators: AgentGraphOperatorBinding[] = metadata.operatorProvisions.map((provision) => ({
operatorId: provision.operatorId,
sessionId: provision.targetSessionId,
}));
const [rootRuns, projected] = await Promise.all([
input.runStore.listSessionRuns(input.rootSessionId),
readCommittedAgentGraphProjectionWithRuns({
graphId: input.graphId,
operators,
runStore: input.runStore,
runtimeEventStore: input.runtimeEventStore,
}),
]);
return paginateAgentGraphTimeline(
buildAgentGraphTimeline({
rootSessionId: input.rootSessionId,
graphId: input.graphId,
metadata,
rootRuns,
childRuns: projected.runs,
projection: projected.projection,
}),
input.rootSessionId,
input.graphId,
buildAgentGraphTimelineCurrentState(metadata, input.rootSessionId, input.graphId),
input.options,
);
}
export function buildAgentGraphTimeline(
input: BuildAgentGraphTimelineInput,
): AgentGraphTimelineEvent[] {
if (input.metadata.graphId !== input.graphId || input.projection.graphId !== input.graphId) {
throw new Error('Agent graph timeline sources belong to different graphs');
}
const pending: PendingTimelineEvent[] = [];
const push = (event: AgentGraphTimelineEventWithoutSequence, tieBreak = event.eventId): void => {
pending.push({ event, rank: EVENT_RANK[event.kind], tieBreak });
};
const relevantRootRunIds = new Set(
input.metadata.scheduleUpdates.map((update) => update.source.runId),
);
const wakeAttemptIds = new Set(
input.metadata.supervisorWakes.flatMap(({ attempts }) =>
attempts.map((attempt) => attempt.attemptId),
),
);
for (const run of input.rootRuns) {
const wake =
run.agentGraphWakeId && run.agentGraphWakeAttemptId
? { wakeId: run.agentGraphWakeId, attemptId: run.agentGraphWakeAttemptId }
: undefined;
if (!relevantRootRunIds.has(run.runId) && !wakeAttemptIds.has(wake?.attemptId ?? '')) {
continue;
}
assertRunRef(run, input.rootSessionId);
const runRef = timelineRunRef(run);
push({
...eventBase(
input.graphId,
'supervisor_turn_started',
{
sessionId: run.sessionId,
runId: run.runId,
},
run.createdAt,
),
kind: 'supervisor_turn_started',
run: runRef,
...(wake ? { wake } : {}),
});
if (
run.completedAt !== undefined &&
(run.status === 'completed' || run.status === 'failed' || run.status === 'cancelled')
) {
push({
...eventBase(
input.graphId,
'supervisor_turn_terminal',
{
sessionId: run.sessionId,
runId: run.runId,
status: run.status,
},
run.completedAt,
),
kind: 'supervisor_turn_terminal',
run: runRef,
status: run.status,
...(wake ? { wake } : {}),
});
}
}
for (const update of input.metadata.scheduleUpdates) {
push({
...eventBase(
input.graphId,
'schedule_committed',
{ updateId: update.updateId },
update.committedAt,
),
kind: 'schedule_committed',
updateId: update.updateId,
revision: update.revision,
source: { ...update.source },
workIds: update.addWork.map((work) => work.workId),
stoppedTargetIds: update.stop.map((stopped) => stopped.targetId),
closesGraph: update.finish !== undefined,
});
if (update.finish) {
push({
...eventBase(
input.graphId,
'schedule_finished',
{ updateId: update.updateId },
update.committedAt,
),
kind: 'schedule_finished',
updateId: update.updateId,
revision: update.revision,
source: { ...update.source },
resultIds: [...update.finish.resultIds],
});
}
}
for (const provision of input.metadata.operatorProvisions) {
push({
...eventBase(
input.graphId,
'operator_provisioned',
{ provisionId: provision.provisionId },
provision.provisionedAt,
),
kind: 'operator_provisioned',
provisionId: provision.provisionId,
workId: provision.workId,
agentId: provision.agentId,
operatorId: provision.operatorId,
targetSessionId: provision.targetSessionId,
initialTurnId: provision.initialTurnId,
initialRunId: provision.initialRunId,
edgeIds: provision.edges.map((edge) => edge.edgeId),
});
}
const operatorSessionById = new Map(
input.metadata.operatorProvisions.map((provision) => [
provision.operatorId,
provision.targetSessionId,
]),
);
const childRunByIdentity = new Map<string, AgentRunHeader>();
for (const run of input.childRuns) {
const key = `${run.sessionId}\0${run.runId}`;
if (childRunByIdentity.has(key)) {
throw new Error(`Agent graph timeline contains duplicate AgentRun ${run.runId}`);
}
childRunByIdentity.set(key, run);
}
for (const claim of input.metadata.intentClaims) {
if (
claim.graphId !== input.graphId ||
operatorSessionById.get(claim.targetOperatorId) !== claim.targetSessionId
) {
throw new Error(`Agent graph claim ${claim.intentId} has no matching operator binding`);
}
push({
...eventBase(input.graphId, 'intent_claimed', { claimId: claim.claimId }, claim.claimedAt),
kind: 'intent_claimed',
claimId: claim.claimId,
intentId: claim.intentId,
operatorId: claim.targetOperatorId,
activation: {
sessionId: claim.targetSessionId,
runId: claim.targetRunId,
turnId: claim.targetTurnId,
},
});
const run = childRunByIdentity.get(`${claim.targetSessionId}\0${claim.targetRunId}`);
if (!run) continue;
if (run.turnId !== claim.targetTurnId) {
throw new Error(
`Agent graph activation ${claim.targetRunId} belongs to turn ${run.turnId}, expected ${claim.targetTurnId}`,
);
}
push({
...eventBase(
input.graphId,
'activation_started',
{ operatorId: claim.targetOperatorId, runId: run.runId },
run.createdAt,
),
kind: 'activation_started',
operatorId: claim.targetOperatorId,
activation: timelineRunRef(run),
});
}
const recordByRun = new Map<string, AgentGraphRecord[]>();
for (const record of input.projection.records) {
const records = recordByRun.get(record.agentRunId) ?? [];
records.push(record);
recordByRun.set(record.agentRunId, records);
push(
{
...eventBase(
input.graphId,
'record_committed',
{ recordId: record.recordId },
record.eventTime,
),
kind: 'record_committed',
recordId: record.recordId,
operatorId: record.operatorId,
activation: {
sessionId: record.sessionId,
runId: record.agentRunId,
turnId: record.source.turnId,
},
facets: [...record.facets],
sourceRuntimeEventId: record.source.runtimeEventId,
},
recordTieBreak(record),
);
}
for (const operator of input.projection.operators) {
const state = input.projection.state.operators[operator.operatorId];
if (!state) continue;
for (const activation of Object.values(state.activations)) {
const records = recordByRun.get(activation.agentRunId) ?? [];
if (activation.terminalRecordId && isTerminalActivationStatus(activation.status)) {
const terminal = records.find((record) => record.recordId === activation.terminalRecordId);
if (!terminal) {
throw new Error(
`Agent graph activation ${activation.activationId} lost its terminal record`,
);
}
push({
...eventBase(
input.graphId,
'activation_terminal',
{ terminalRecordId: activation.terminalRecordId },
terminal.eventTime,
),
kind: 'activation_terminal',
operatorId: operator.operatorId,
activation: {
sessionId: operator.sessionId,
runId: activation.agentRunId,
turnId: terminal.source.turnId,
},
status: activation.status,
terminalRecordId: activation.terminalRecordId,
});
}
}
}
for (const { wake, attempts } of input.metadata.supervisorWakes) {
if (wake.graphId !== input.graphId || wake.rootSessionId !== input.rootSessionId) {
throw new Error(`Agent graph supervisor wake ${wake.wakeId} belongs to another graph`);
}
push({
...eventBase(
input.graphId,
'supervisor_wake_claimed',
{ wakeId: wake.wakeId },
wake.createdAt,
),
kind: 'supervisor_wake_claimed',
wakeId: wake.wakeId,
snapshotVersion: wake.snapshotVersion,
rootSessionId: wake.rootSessionId,
});
for (const attempt of attempts) {
push({
...eventBase(
input.graphId,
'supervisor_wake_attempted',
{ attemptId: attempt.attemptId },
attempt.startedAt,
),
kind: 'supervisor_wake_attempted',
wakeId: attempt.wakeId,
attemptId: attempt.attemptId,
turnId: attempt.turnId,
});
if (
attempt.completedAt !== undefined &&
(attempt.status === 'delivered' ||
attempt.status === 'superseded' ||
attempt.status === 'retryable_failed')
) {
push({
...eventBase(
input.graphId,
'supervisor_wake_settled',
{ attemptId: attempt.attemptId, status: attempt.status },
attempt.completedAt,
),
kind: 'supervisor_wake_settled',
wakeId: attempt.wakeId,
attemptId: attempt.attemptId,
turnId: attempt.turnId,
status: attempt.status,
});
}
}
}
pending.sort(
(a, b) =>
a.event.eventTime - b.event.eventTime ||
a.rank - b.rank ||
a.tieBreak.localeCompare(b.tieBreak) ||
a.event.eventId.localeCompare(b.event.eventId),
);
const seen = new Set<string>();
return pending.map(({ event }, index) => {
if (seen.has(event.eventId)) {
throw new Error(`Duplicate agent graph timeline event ${event.eventId}`);
}
seen.add(event.eventId);
return { ...event, sequence: index + 1 } as AgentGraphTimelineEvent;
});
}
export function buildAgentGraphTimelineCurrentState(
metadata: AgentGraphTimelineMetadataSnapshot,
rootSessionId: string,
graphId: string,
): AgentGraphTimelineCurrentState {
if (metadata.graphId !== graphId) {
throw new Error(`Agent graph timeline metadata belongs to ${metadata.graphId}`);
}
const claimIntentIds = new Set(metadata.intentClaims.map((claim) => claim.intentId));
if (claimIntentIds.size !== metadata.intentClaims.length) {
throw new Error(`Agent graph ${graphId} has duplicate intent claims`);
}
const admissionIntentIds = new Set<string>();
const admissions = metadata.intentAdmissions.map((admission) => {
if (admission.graphId !== graphId || !claimIntentIds.has(admission.intentId)) {
throw new Error(`Agent graph admission ${admission.intentId} belongs to another graph`);
}
if (admissionIntentIds.has(admission.intentId)) {
throw new Error(`Agent graph ${graphId} has duplicate admission snapshots`);
}
admissionIntentIds.add(admission.intentId);
return {
intentId: admission.intentId,
state: admission.state,
updatedAt: admission.updatedAt,
};
});
if (admissionIntentIds.size !== claimIntentIds.size) {
throw new Error(`Agent graph ${graphId} has a missing or duplicate admission snapshot`);
}
const supervisorWakes = metadata.supervisorWakes.map(({ wake }) => {
if (wake.graphId !== graphId || wake.rootSessionId !== rootSessionId) {
throw new Error(`Agent graph supervisor wake ${wake.wakeId} belongs to another graph`);
}
return {
wakeId: wake.wakeId,
status: wake.status,
attemptCount: wake.attemptCount,
updatedAt: wake.updatedAt,
...(wake.currentAttemptId ? { currentAttemptId: wake.currentAttemptId } : {}),
...(wake.currentTurnId ? { currentTurnId: wake.currentTurnId } : {}),
};
});
admissions.sort((a, b) => a.intentId.localeCompare(b.intentId));
supervisorWakes.sort((a, b) => a.wakeId.localeCompare(b.wakeId));
return { admissions, supervisorWakes };
}
export function paginateAgentGraphTimeline(
events: readonly AgentGraphTimelineEvent[],
rootSessionId: string,
graphId: string,
currentState: AgentGraphTimelineCurrentState,
options: AgentGraphTimelinePageOptions = {},
): AgentGraphTimelinePage {
const limit = options.limit ?? AGENT_GRAPH_TIMELINE_DEFAULT_PAGE_SIZE;
if (!Number.isSafeInteger(limit) || limit < 1 || limit > AGENT_GRAPH_TIMELINE_MAX_PAGE_SIZE) {
throw new Error(
`Agent graph timeline limit must be between 1 and ${AGENT_GRAPH_TIMELINE_MAX_PAGE_SIZE}`,
);
}
let start = 0;
if (options.cursor) {
const cursor = decodeAgentGraphTimelineCursor(options.cursor);
if (cursor.graphId !== graphId) {
throw new Error('Agent graph timeline cursor belongs to another graph');
}
const index = events.findIndex(
(event) => event.eventId === cursor.eventId && event.eventTime === cursor.eventTime,
);
if (index < 0) throw new Error('Agent graph timeline cursor is stale or invalid');
start = index + 1;
}
const pageEvents = events.slice(start, start + limit).map(cloneTimelineEvent);
const omittedAfter = Math.max(0, events.length - start - pageEvents.length);
return {
schemaVersion: AGENT_GRAPH_TIMELINE_SCHEMA_VERSION,
graphId,
rootSessionId,
events: pageEvents,
totalEvents: events.length,
omittedBefore: start,
omittedAfter,
currentState: cloneTimelineCurrentState(currentState),
...(omittedAfter > 0 && pageEvents.length > 0
? { nextCursor: encodeAgentGraphTimelineCursor(graphId, pageEvents.at(-1)!) }
: {}),
coverage: {
runtimeRecords: 'complete',
limitations: [
'admission_transition_history_not_persisted',
'supervisor_wake_transition_history_not_persisted',
'reconcile_history_not_persisted',
],
},
};
}
export function encodeAgentGraphTimelineCursor(
graphId: string,
event: Pick<AgentGraphTimelineEvent, 'eventId' | 'eventTime'>,
): string {
return Buffer.from(
JSON.stringify({
schemaVersion: AGENT_GRAPH_TIMELINE_SCHEMA_VERSION,
graphId,
eventId: event.eventId,
eventTime: event.eventTime,
}),
'utf8',
).toString('base64url');
}
export function decodeAgentGraphTimelineCursor(cursor: string): {
graphId: string;
eventId: string;
eventTime: number;
} {
if (
typeof cursor !== 'string' ||
cursor.length === 0 ||
cursor.length > 2_048 ||
cursor.trim() !== cursor
) {
throw new Error('Invalid agent graph timeline cursor');
}
try {
const json = Buffer.from(cursor, 'base64url').toString('utf8');
const canonical = Buffer.from(json, 'utf8').toString('base64url');
const value = JSON.parse(json) as Record<string, unknown>;
if (
canonical !== cursor ||
Object.keys(value).sort().join(',') !== 'eventId,eventTime,graphId,schemaVersion' ||
value.schemaVersion !== AGENT_GRAPH_TIMELINE_SCHEMA_VERSION ||
typeof value.eventTime !== 'number' ||
!Number.isSafeInteger(value.eventTime) ||
value.eventTime < 0
) {
throw new Error('invalid cursor envelope');
}
return {
graphId: cursorIdentity(value.graphId),
eventId: cursorIdentity(value.eventId),
eventTime: value.eventTime,
};
} catch {
throw new Error('Invalid agent graph timeline cursor');
}
}
function eventBase(
graphId: string,
kind: AgentGraphTimelineEvent['kind'],
identity: unknown,
eventTime: number,
): Omit<AgentGraphTimelineEventBase, 'sequence'> {
if (!Number.isSafeInteger(eventTime) || eventTime < 0) {
throw new Error(`Invalid agent graph timeline timestamp for ${kind}`);
}
return {
schemaVersion: AGENT_GRAPH_TIMELINE_SCHEMA_VERSION,
eventId: `graph_timeline_${stableHash({ graphId, kind, identity }).slice('sha256:'.length, 48)}`,
graphId,
eventTime,
};
}
function timelineRunRef(run: AgentRunHeader): AgentGraphTimelineRunRef {
return {
sessionId: run.sessionId,
runId: run.runId,
turnId: run.turnId,
};
}
function assertRunRef(run: AgentRunHeader, sessionId: string): void {
if (run.sessionId !== sessionId) {
throw new Error(`AgentRun ${run.runId} belongs to ${run.sessionId}, expected ${sessionId}`);
}
}
function recordTieBreak(record: AgentGraphRecord): string {
return [
String(record.orderKey.runCreatedAt).padStart(16, '0'),
record.orderKey.operatorId,
record.orderKey.runId,
String(record.orderKey.committedEventOrdinal).padStart(12, '0'),
record.orderKey.runtimeEventId,
].join('\0');
}
function isTerminalActivationStatus(
status: AgentGraphActivationStatus,
): status is Extract<AgentGraphActivationStatus, 'completed' | 'failed' | 'aborted' | 'cancelled'> {
return status !== 'running';
}
function cloneTimelineEvent(event: AgentGraphTimelineEvent): AgentGraphTimelineEvent {
return structuredClone(event);
}
function cloneTimelineCurrentState(
currentState: AgentGraphTimelineCurrentState,
): AgentGraphTimelineCurrentState {
return {
admissions: currentState.admissions.map((admission) => ({ ...admission })),
supervisorWakes: currentState.supervisorWakes.map((wake) => ({ ...wake })),
};
}
function assertIdentity(value: string, name: string): void {
if (
!value ||
value.length > 512 ||
value.trim() !== value ||
/[\u0000-\u001f\u007f]/.test(value)
) {
throw new Error(`Invalid agent graph timeline ${name}`);
}
}
function cursorIdentity(value: unknown): string {
if (
typeof value !== 'string' ||
value.length === 0 ||
value.length > 512 ||
value.trim() !== value ||
/[\u0000-\u001f\u007f]/.test(value)
) {
throw new Error('invalid cursor identity');
}
return value;
}