@rowan-agent/agent 0.15.3 → 0.15.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +117 -4
- package/dist/index.js +912 -136
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3264,6 +3264,13 @@ function createPhaseExecution(config, state, phase, messageManager, toolExecutio
|
|
|
3264
3264
|
}
|
|
3265
3265
|
};
|
|
3266
3266
|
}
|
|
3267
|
+
function parallelPhaseReply(produced) {
|
|
3268
|
+
const last = [...produced].reverse().find((message) => message.role === "assistant");
|
|
3269
|
+
if (!last) return void 0;
|
|
3270
|
+
if (typeof last.content === "string") return last.content.trim() ? last : void 0;
|
|
3271
|
+
if (last.content.some((part) => part.type === "tool_use")) return void 0;
|
|
3272
|
+
return last.content.some((part) => part.type === "text" && part.text.trim()) ? last : void 0;
|
|
3273
|
+
}
|
|
3267
3274
|
async function executeParallelPhase(config, state, registry, phase, payload, instruction, context, availablePhases, instanceId, groupId, index, count, sourcePhaseId) {
|
|
3268
3275
|
const messages = [...context];
|
|
3269
3276
|
const effectivePayload = preparePhasePayload(phase.input, payload);
|
|
@@ -3305,7 +3312,12 @@ async function executeParallelPhase(config, state, registry, phase, payload, ins
|
|
|
3305
3312
|
const toolExecutionManager = createToolExecutionManager();
|
|
3306
3313
|
const execution = createPhaseExecution(config, state, phase, messageManager, toolExecutionManager, registry);
|
|
3307
3314
|
const runtime = { phase, config, state, execution, messageManager, registry, context: phaseContext };
|
|
3315
|
+
const phaseStart = messages.length;
|
|
3308
3316
|
let output = await executePhase(runtime);
|
|
3317
|
+
const reply = parallelPhaseReply(messages.slice(phaseStart));
|
|
3318
|
+
if (reply && config.onParallelPhaseOutput) {
|
|
3319
|
+
await config.onParallelPhaseOutput(reply, { mode: "parallel", instanceId, groupId, index, count, sourcePhaseId });
|
|
3320
|
+
}
|
|
3309
3321
|
if (phaseMsgId) removePhaseMessage(messages, phaseMsgId);
|
|
3310
3322
|
if (config.afterPhase) {
|
|
3311
3323
|
const extAfter = await config.afterPhase(phase.name, output);
|
|
@@ -3483,6 +3495,7 @@ async function executeOnce(input) {
|
|
|
3483
3495
|
afterPhase: input.afterPhase,
|
|
3484
3496
|
beforePrompt: input.beforePrompt,
|
|
3485
3497
|
onMessage: input.onMessage,
|
|
3498
|
+
onParallelPhaseOutput: input.onParallelPhaseOutput,
|
|
3486
3499
|
onMessageDelta: input.onMessageDelta,
|
|
3487
3500
|
onThinkingDelta: input.onThinkingDelta,
|
|
3488
3501
|
onOutcome: input.onOutcome,
|
|
@@ -4307,6 +4320,10 @@ function renderInteractionText(record) {
|
|
|
4307
4320
|
const replyStr = record.reply ?? "";
|
|
4308
4321
|
return template.replaceAll("{{prompt}}", record.prompt).replaceAll("{{answer}}", answerStr).replaceAll("{{reply}}", replyStr);
|
|
4309
4322
|
}
|
|
4323
|
+
var PARALLEL_PHASE_METADATA_KEY = "parallelPhase";
|
|
4324
|
+
function isParallelPhaseOutput(message) {
|
|
4325
|
+
return message.role === "assistant" && message.metadata?.[PARALLEL_PHASE_METADATA_KEY] !== void 0;
|
|
4326
|
+
}
|
|
4310
4327
|
function projectModelContext(input) {
|
|
4311
4328
|
const toolInteractionTexts = /* @__PURE__ */ new Map();
|
|
4312
4329
|
for (const message of input.messages) {
|
|
@@ -4322,6 +4339,7 @@ function projectModelContext(input) {
|
|
|
4322
4339
|
}
|
|
4323
4340
|
const projectedMessages = [];
|
|
4324
4341
|
for (const message of input.messages) {
|
|
4342
|
+
if (isParallelPhaseOutput(message)) continue;
|
|
4325
4343
|
if (message.role === "interaction") {
|
|
4326
4344
|
if (message.toolCallId !== void 0) {
|
|
4327
4345
|
continue;
|
|
@@ -6613,6 +6631,33 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6613
6631
|
status
|
|
6614
6632
|
});
|
|
6615
6633
|
},
|
|
6634
|
+
onParallelPhaseOutput: (message, invocation) => {
|
|
6635
|
+
const task = toolQueue.then(async () => {
|
|
6636
|
+
const active = this.executions.get(run.id);
|
|
6637
|
+
if (this.closed || controller.signal.aborted || active?.executionId !== claim.execution.executionId) return;
|
|
6638
|
+
const projected = projectAssistantMessage(message, run.agentId, run.id, 0);
|
|
6639
|
+
const committed = await this.owned.commitPhaseOutput({
|
|
6640
|
+
runId: run.id,
|
|
6641
|
+
execution: claim.execution,
|
|
6642
|
+
expectedRevision: executionRevision,
|
|
6643
|
+
message: {
|
|
6644
|
+
...projected,
|
|
6645
|
+
metadata: {
|
|
6646
|
+
...projected.metadata,
|
|
6647
|
+
[PARALLEL_PHASE_METADATA_KEY]: {
|
|
6648
|
+
groupId: invocation.groupId,
|
|
6649
|
+
instanceId: invocation.instanceId,
|
|
6650
|
+
index: invocation.index,
|
|
6651
|
+
count: invocation.count
|
|
6652
|
+
}
|
|
6653
|
+
}
|
|
6654
|
+
}
|
|
6655
|
+
});
|
|
6656
|
+
executionRevision = committed.revision;
|
|
6657
|
+
});
|
|
6658
|
+
toolQueue = task.then(() => void 0, () => void 0);
|
|
6659
|
+
return task;
|
|
6660
|
+
},
|
|
6616
6661
|
onMessageDelta: (event) => {
|
|
6617
6662
|
const active = this.executions.get(run.id);
|
|
6618
6663
|
if (this.closed || controller.signal.aborted || active?.executionId !== claim.execution.executionId) return;
|
|
@@ -6700,7 +6745,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6700
6745
|
}
|
|
6701
6746
|
}
|
|
6702
6747
|
if (this.cancellationRequested.has(run.id) || controller.signal.aborted) {
|
|
6703
|
-
const output = latestAssistant(run, result.messages,
|
|
6748
|
+
const output = latestAssistant(run, result.messages, executionContext.messages.length, true);
|
|
6704
6749
|
const reason = this.cancellationReasons.get(run.id) ?? "Agent run stopped.";
|
|
6705
6750
|
await this.owned.cancelRun({
|
|
6706
6751
|
runId: run.id,
|
|
@@ -6723,7 +6768,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6723
6768
|
const output = isToolCallInteraction ? void 0 : latestAssistant(
|
|
6724
6769
|
run,
|
|
6725
6770
|
result.messages,
|
|
6726
|
-
|
|
6771
|
+
executionContext.messages.length
|
|
6727
6772
|
);
|
|
6728
6773
|
const prompt = isToolCallInteraction ? void 0 : output ?? (result.interactions[0]?.prompt ? promptMessage(run, result.interactions[0].prompt, result.messages.length) : void 0);
|
|
6729
6774
|
await this.owned.commitInputRequired({
|
|
@@ -6741,7 +6786,7 @@ var AgentRuntime = class _AgentRuntime {
|
|
|
6741
6786
|
return;
|
|
6742
6787
|
}
|
|
6743
6788
|
if (result.type === "completed") {
|
|
6744
|
-
const output = latestAssistant(run, result.messages,
|
|
6789
|
+
const output = latestAssistant(run, result.messages, executionContext.messages.length);
|
|
6745
6790
|
await this.owned.commitOutcome({ runId: run.id, execution: claim.execution, expectedRevision: executionRevision, outcome: durableOutcome(result.outcome), ...output ? { output } : {} });
|
|
6746
6791
|
this.transientEvents.clear(run.id, claim.execution.executionId, true);
|
|
6747
6792
|
return;
|
|
@@ -7573,9 +7618,83 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7573
7618
|
eventSequence = 0;
|
|
7574
7619
|
retentionFloor = 1;
|
|
7575
7620
|
contextCompactions = /* @__PURE__ */ new Map();
|
|
7621
|
+
recorder;
|
|
7622
|
+
runReceiptKeys = /* @__PURE__ */ new Map();
|
|
7576
7623
|
constructor(options = {}) {
|
|
7577
7624
|
this.incarnation = options.incarnation ?? createId("store");
|
|
7578
7625
|
}
|
|
7626
|
+
setChangeRecorder(recorder) {
|
|
7627
|
+
this.recorder = recorder;
|
|
7628
|
+
}
|
|
7629
|
+
touchAgent(agent) {
|
|
7630
|
+
this.recorder?.onAgentUpsert(agent);
|
|
7631
|
+
}
|
|
7632
|
+
touchRun(run) {
|
|
7633
|
+
this.recorder?.onRunUpsert(run);
|
|
7634
|
+
}
|
|
7635
|
+
storeMessage(message) {
|
|
7636
|
+
this.messages.set(message.id, message);
|
|
7637
|
+
this.recorder?.onMessageInsert(message);
|
|
7638
|
+
}
|
|
7639
|
+
storeToolCall(toolCall) {
|
|
7640
|
+
this.toolCalls.set(toolCall.id, toolCall);
|
|
7641
|
+
this.recorder?.onToolCallUpsert(toolCall);
|
|
7642
|
+
}
|
|
7643
|
+
appendEvent(event) {
|
|
7644
|
+
this.events.push(event);
|
|
7645
|
+
this.recorder?.onEventAppend(event);
|
|
7646
|
+
}
|
|
7647
|
+
inferRunIdForReceipt(key, payload) {
|
|
7648
|
+
const parts = key.split(":");
|
|
7649
|
+
const prefix = parts[0];
|
|
7650
|
+
if (["queued_failure", "phase_entered", "input_required", "interaction_answer", "outcome", "cancel"].includes(prefix) && parts[1]) {
|
|
7651
|
+
return parts[1];
|
|
7652
|
+
}
|
|
7653
|
+
const match = payload.match(/^\[\s*"([^"]+)"/);
|
|
7654
|
+
if (match && match[1]) {
|
|
7655
|
+
const candidate = match[1];
|
|
7656
|
+
if (this.runs.has(candidate) || candidate.startsWith("run_") || candidate.startsWith("run-")) {
|
|
7657
|
+
return candidate;
|
|
7658
|
+
}
|
|
7659
|
+
}
|
|
7660
|
+
return void 0;
|
|
7661
|
+
}
|
|
7662
|
+
dropRunOperationReceipts(runId) {
|
|
7663
|
+
const keys = this.runReceiptKeys.get(runId);
|
|
7664
|
+
if (keys && keys.size > 0) {
|
|
7665
|
+
for (const key of keys) {
|
|
7666
|
+
this.operationReceipts.delete(key);
|
|
7667
|
+
this.recorder?.onOperationReceiptDelete(key);
|
|
7668
|
+
}
|
|
7669
|
+
this.runReceiptKeys.delete(runId);
|
|
7670
|
+
}
|
|
7671
|
+
for (const [key] of this.operationReceipts.entries()) {
|
|
7672
|
+
if (key.includes(`:${runId}:`) || key.endsWith(`:${runId}`) || key.startsWith(`phase_output:${runId}`) || key.startsWith(`tool_reserve_batch:${runId}`)) {
|
|
7673
|
+
this.operationReceipts.delete(key);
|
|
7674
|
+
this.recorder?.onOperationReceiptDelete(key);
|
|
7675
|
+
}
|
|
7676
|
+
}
|
|
7677
|
+
}
|
|
7678
|
+
compactTerminalReceipts() {
|
|
7679
|
+
let count = 0;
|
|
7680
|
+
for (const [key, receipt] of [...this.operationReceipts.entries()]) {
|
|
7681
|
+
const runId = this.inferRunIdForReceipt(key, receipt.payload);
|
|
7682
|
+
if (runId) {
|
|
7683
|
+
const run = this.runs.get(runId);
|
|
7684
|
+
if (!run || ["completed", "failed", "cancelled"].includes(run.state)) {
|
|
7685
|
+
this.operationReceipts.delete(key);
|
|
7686
|
+
const keys = this.runReceiptKeys.get(runId);
|
|
7687
|
+
if (keys) {
|
|
7688
|
+
keys.delete(key);
|
|
7689
|
+
if (keys.size === 0) this.runReceiptKeys.delete(runId);
|
|
7690
|
+
}
|
|
7691
|
+
this.recorder?.onOperationReceiptDelete(key);
|
|
7692
|
+
count += 1;
|
|
7693
|
+
}
|
|
7694
|
+
}
|
|
7695
|
+
}
|
|
7696
|
+
return count;
|
|
7697
|
+
}
|
|
7579
7698
|
static fromState(state) {
|
|
7580
7699
|
const store = new _InMemoryStore({ incarnation: state.incarnation });
|
|
7581
7700
|
for (const agent of state.agents) store.agents.set(agent.id, clone(agent));
|
|
@@ -7593,6 +7712,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7593
7712
|
clonedRun.updatedAt = createTimestamp();
|
|
7594
7713
|
store.runs.set(clonedRun.id, clonedRun);
|
|
7595
7714
|
store.appendTransition(clonedRun, "input_required", "cancelled", { reason: clonedRun.cancellationReason });
|
|
7715
|
+
store.dropRunOperationReceipts(clonedRun.id);
|
|
7596
7716
|
} else {
|
|
7597
7717
|
store.runs.set(clonedRun.id, clonedRun);
|
|
7598
7718
|
}
|
|
@@ -7601,7 +7721,18 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7601
7721
|
for (const toolCall of state.toolCalls ?? []) store.toolCalls.set(toolCall.id, clone(toolCall));
|
|
7602
7722
|
store.events.push(...clone(state.events));
|
|
7603
7723
|
for (const [key, receipt] of state.idempotency) store.idempotency.set(key, clone(receipt));
|
|
7604
|
-
for (const [key, receipt] of state.operationReceipts)
|
|
7724
|
+
for (const [key, receipt] of state.operationReceipts) {
|
|
7725
|
+
store.operationReceipts.set(key, clone(receipt));
|
|
7726
|
+
const runId = store.inferRunIdForReceipt(key, receipt.payload);
|
|
7727
|
+
if (runId) {
|
|
7728
|
+
let keys = store.runReceiptKeys.get(runId);
|
|
7729
|
+
if (!keys) {
|
|
7730
|
+
keys = /* @__PURE__ */ new Set();
|
|
7731
|
+
store.runReceiptKeys.set(runId, keys);
|
|
7732
|
+
}
|
|
7733
|
+
keys.add(key);
|
|
7734
|
+
}
|
|
7735
|
+
}
|
|
7605
7736
|
for (const [agentId, messages] of state.historySeeds ?? []) store.historySeeds.set(agentId, clone(messages));
|
|
7606
7737
|
for (const [consumerId, cursor] of state.consumerCheckpoints ?? []) store.consumerCheckpoints.set(consumerId, cursor);
|
|
7607
7738
|
for (const [agentId, sequence] of state.nextAgentSequence) store.nextAgentSequence.set(agentId, sequence);
|
|
@@ -7634,6 +7765,16 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7634
7765
|
contextCompactions: [...this.contextCompactions.entries()]
|
|
7635
7766
|
});
|
|
7636
7767
|
}
|
|
7768
|
+
exportMetadata() {
|
|
7769
|
+
return {
|
|
7770
|
+
incarnation: this.incarnation,
|
|
7771
|
+
eventSequence: this.eventSequence,
|
|
7772
|
+
nextAgentSequence: [...this.nextAgentSequence.entries()],
|
|
7773
|
+
nextReadySequence: [...this.nextReadySequence.entries()],
|
|
7774
|
+
historySeeds: [...this.historySeeds.entries()],
|
|
7775
|
+
contextCompactions: [...this.contextCompactions.entries()]
|
|
7776
|
+
};
|
|
7777
|
+
}
|
|
7637
7778
|
attachOwner(lease) {
|
|
7638
7779
|
this.owner = clone(lease);
|
|
7639
7780
|
this.ownerEpoch = Math.max(this.ownerEpoch, lease.epoch);
|
|
@@ -7656,6 +7797,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7656
7797
|
run.revision += 1;
|
|
7657
7798
|
run.updatedAt = createTimestamp();
|
|
7658
7799
|
this.appendTransition(run, "running", "failed", { failure });
|
|
7800
|
+
this.dropRunOperationReceipts(run.id);
|
|
7659
7801
|
}
|
|
7660
7802
|
}
|
|
7661
7803
|
async openOwner(input) {
|
|
@@ -7673,6 +7815,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7673
7815
|
}
|
|
7674
7816
|
if (this.owner) this.interruptOwner(this.owner.epoch);
|
|
7675
7817
|
this.dropSettledClaimReceipts();
|
|
7818
|
+
this.compactTerminalReceipts();
|
|
7676
7819
|
this.ownerEpoch += 1;
|
|
7677
7820
|
this.owner = {
|
|
7678
7821
|
ownerId: input.ownerId,
|
|
@@ -7719,6 +7862,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7719
7862
|
updatedAt: timestamp
|
|
7720
7863
|
};
|
|
7721
7864
|
this.agents.set(agent.id, agent);
|
|
7865
|
+
this.touchAgent(agent);
|
|
7722
7866
|
if (input.historySeed && input.historySeed.length > 0) this.historySeeds.set(agent.id, materializeHistorySeed(agent.id, input.historySeed));
|
|
7723
7867
|
this.nextAgentSequence.set(agent.id, 0);
|
|
7724
7868
|
this.nextReadySequence.set(agent.id, 0);
|
|
@@ -7732,6 +7876,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7732
7876
|
if (configToken !== void 0) agent.currentConfigToken = configToken;
|
|
7733
7877
|
if (configIdentity !== void 0) agent.currentConfigIdentity = configIdentity;
|
|
7734
7878
|
agent.updatedAt = createTimestamp();
|
|
7879
|
+
this.touchAgent(agent);
|
|
7735
7880
|
return clone(agent);
|
|
7736
7881
|
}
|
|
7737
7882
|
updateAgentConfigToken(lease, input) {
|
|
@@ -7744,6 +7889,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7744
7889
|
agent.currentConfigToken = input.token;
|
|
7745
7890
|
if (input.configIdentity !== void 0) agent.currentConfigIdentity = input.configIdentity;
|
|
7746
7891
|
agent.updatedAt = createTimestamp();
|
|
7892
|
+
this.touchAgent(agent);
|
|
7747
7893
|
this.writeReceipt(scope, payload, agent);
|
|
7748
7894
|
return clone(agent);
|
|
7749
7895
|
}
|
|
@@ -7765,24 +7911,48 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7765
7911
|
}
|
|
7766
7912
|
const runIds = new Set(runs.map((run) => run.id));
|
|
7767
7913
|
this.agents.delete(agent.id);
|
|
7914
|
+
this.recorder?.onAgentDelete(agent.id);
|
|
7768
7915
|
this.nextAgentSequence.delete(agent.id);
|
|
7769
7916
|
this.nextReadySequence.delete(agent.id);
|
|
7770
7917
|
this.historySeeds.delete(agent.id);
|
|
7771
|
-
for (const run of runs)
|
|
7918
|
+
for (const run of runs) {
|
|
7919
|
+
this.runs.delete(run.id);
|
|
7920
|
+
this.runReceiptKeys.delete(run.id);
|
|
7921
|
+
this.recorder?.onRunDelete(run.id);
|
|
7922
|
+
}
|
|
7772
7923
|
for (const [messageId, message] of this.messages) {
|
|
7773
|
-
if (runIds.has(message.runId))
|
|
7924
|
+
if (runIds.has(message.runId)) {
|
|
7925
|
+
this.messages.delete(messageId);
|
|
7926
|
+
this.recorder?.onMessageDelete(messageId);
|
|
7927
|
+
}
|
|
7774
7928
|
}
|
|
7775
7929
|
for (const [toolCallId, toolCall] of this.toolCalls) {
|
|
7776
|
-
if (runIds.has(toolCall.runId))
|
|
7930
|
+
if (runIds.has(toolCall.runId)) {
|
|
7931
|
+
this.toolCalls.delete(toolCallId);
|
|
7932
|
+
this.recorder?.onToolCallDelete(toolCallId);
|
|
7933
|
+
}
|
|
7777
7934
|
}
|
|
7935
|
+
const deletedEventIds = [];
|
|
7778
7936
|
for (let index = this.events.length - 1; index >= 0; index -= 1) {
|
|
7779
|
-
if (this.events[index].agentId === agent.id)
|
|
7937
|
+
if (this.events[index].agentId === agent.id) {
|
|
7938
|
+
deletedEventIds.push(this.events[index].id);
|
|
7939
|
+
this.events.splice(index, 1);
|
|
7940
|
+
}
|
|
7941
|
+
}
|
|
7942
|
+
if (deletedEventIds.length > 0) {
|
|
7943
|
+
this.recorder?.onEventsTruncate(deletedEventIds);
|
|
7780
7944
|
}
|
|
7781
7945
|
for (const [key] of this.idempotency) {
|
|
7782
|
-
if (key.includes(String(agent.id)) || [...runIds].some((runId) => key.includes(String(runId))))
|
|
7946
|
+
if (key.includes(String(agent.id)) || [...runIds].some((runId) => key.includes(String(runId)))) {
|
|
7947
|
+
this.idempotency.delete(key);
|
|
7948
|
+
this.recorder?.onIdempotencyDelete(key);
|
|
7949
|
+
}
|
|
7783
7950
|
}
|
|
7784
7951
|
for (const [key] of this.operationReceipts) {
|
|
7785
|
-
if (key.includes(String(agent.id)) || [...runIds].some((runId) => key.includes(String(runId))))
|
|
7952
|
+
if (key.includes(String(agent.id)) || [...runIds].some((runId) => key.includes(String(runId)))) {
|
|
7953
|
+
this.operationReceipts.delete(key);
|
|
7954
|
+
this.recorder?.onOperationReceiptDelete(key);
|
|
7955
|
+
}
|
|
7786
7956
|
}
|
|
7787
7957
|
}
|
|
7788
7958
|
reviseMessage(lease, input) {
|
|
@@ -7890,14 +8060,19 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7890
8060
|
run.revision += 1;
|
|
7891
8061
|
run.updatedAt = timestamp;
|
|
7892
8062
|
this.appendTransition(run, previousState, "cancelled", { reason: run.cancellationReason });
|
|
8063
|
+
this.dropRunOperationReceipts(run.id);
|
|
7893
8064
|
} else {
|
|
7894
8065
|
run.revision += 1;
|
|
7895
8066
|
run.updatedAt = timestamp;
|
|
8067
|
+
this.touchRun(run);
|
|
7896
8068
|
}
|
|
7897
8069
|
}
|
|
7898
8070
|
for (const [messageId, message] of this.messages) {
|
|
7899
8071
|
if (!affectedRunSet.has(message.runId)) continue;
|
|
7900
|
-
if (message.runId !== original.runId || message.sequenceWithinRun > original.sequenceWithinRun)
|
|
8072
|
+
if (message.runId !== original.runId || message.sequenceWithinRun > original.sequenceWithinRun) {
|
|
8073
|
+
this.messages.delete(messageId);
|
|
8074
|
+
this.recorder?.onMessageDelete(messageId);
|
|
8075
|
+
}
|
|
7901
8076
|
}
|
|
7902
8077
|
if (isSeedMessage) {
|
|
7903
8078
|
const targetIndex = seed.findIndex(({ id }) => id === original.id);
|
|
@@ -7911,10 +8086,11 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7911
8086
|
sequenceWithinRun: 0,
|
|
7912
8087
|
createdAt: timestamp
|
|
7913
8088
|
};
|
|
7914
|
-
this.
|
|
8089
|
+
this.storeMessage(revisedMessage);
|
|
7915
8090
|
this.runs.set(replacementRun.id, replacementRun);
|
|
8091
|
+
this.touchRun(replacementRun);
|
|
7916
8092
|
this.appendTransition(replacementRun, null, "queued");
|
|
7917
|
-
this.
|
|
8093
|
+
this.appendEvent({
|
|
7918
8094
|
...this.baseEvent(replacementRun),
|
|
7919
8095
|
kind: "message_revised",
|
|
7920
8096
|
message: revisedMessage,
|
|
@@ -7930,7 +8106,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7930
8106
|
affectedToolCallIds: affectedTools.map((toolCall) => toolCall.id),
|
|
7931
8107
|
...effectDigest === void 0 ? {} : { effectDigest }
|
|
7932
8108
|
};
|
|
7933
|
-
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8109
|
+
this.writeOperationReceipt(operationKey, operationPayload, result, replacementRun.id);
|
|
7934
8110
|
return clone(result);
|
|
7935
8111
|
}
|
|
7936
8112
|
commitInteractionRecord(run, interaction, status, answer, reply) {
|
|
@@ -7952,7 +8128,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
7952
8128
|
sequenceWithinRun: this.nextMessageSequence(run.id),
|
|
7953
8129
|
createdAt: now
|
|
7954
8130
|
};
|
|
7955
|
-
this.
|
|
8131
|
+
this.storeMessage(record);
|
|
7956
8132
|
this.appendMessage(run, record);
|
|
7957
8133
|
return record;
|
|
7958
8134
|
}
|
|
@@ -8001,12 +8177,13 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8001
8177
|
sequenceWithinRun: this.nextMessageSequence(waitingRun.id),
|
|
8002
8178
|
createdAt: now
|
|
8003
8179
|
};
|
|
8004
|
-
this.
|
|
8180
|
+
this.storeMessage(message);
|
|
8005
8181
|
this.appendMessage(waitingRun, message);
|
|
8006
8182
|
waitingRun.readySequence = this.nextReady(waitingRun.agentId);
|
|
8007
8183
|
waitingRun.state = "queued";
|
|
8008
8184
|
waitingRun.revision += 1;
|
|
8009
8185
|
waitingRun.updatedAt = now;
|
|
8186
|
+
this.touchRun(waitingRun);
|
|
8010
8187
|
this.appendTransition(waitingRun, "input_required", "queued");
|
|
8011
8188
|
this.writeReceipt(scope, payload, waitingRun);
|
|
8012
8189
|
return clone(waitingRun);
|
|
@@ -8028,6 +8205,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8028
8205
|
updatedAt: timestamp
|
|
8029
8206
|
};
|
|
8030
8207
|
this.runs.set(run.id, run);
|
|
8208
|
+
this.touchRun(run);
|
|
8031
8209
|
this.appendTransition(run, null, "queued");
|
|
8032
8210
|
this.writeReceipt(scope, payload, run);
|
|
8033
8211
|
return clone(run);
|
|
@@ -8070,7 +8248,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8070
8248
|
sequenceWithinRun: this.nextMessageSequence(run.id),
|
|
8071
8249
|
createdAt: createTimestamp()
|
|
8072
8250
|
};
|
|
8073
|
-
this.
|
|
8251
|
+
this.storeMessage(message);
|
|
8074
8252
|
committedMessages.push(message);
|
|
8075
8253
|
}
|
|
8076
8254
|
const execution = {
|
|
@@ -8082,10 +8260,11 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8082
8260
|
run.execution = execution;
|
|
8083
8261
|
run.revision += 1;
|
|
8084
8262
|
run.updatedAt = createTimestamp();
|
|
8263
|
+
this.touchRun(run);
|
|
8085
8264
|
for (const message of committedMessages) this.appendMessage(run, message);
|
|
8086
8265
|
this.appendTransition(run, "queued", "running");
|
|
8087
8266
|
const result = { run: clone(run), execution: clone(execution), history: this.activeHistory(run.agentId, run.agentSequence) };
|
|
8088
|
-
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8267
|
+
this.writeOperationReceipt(operationKey, operationPayload, result, run.id);
|
|
8089
8268
|
return result;
|
|
8090
8269
|
}
|
|
8091
8270
|
failQueuedRun(lease, input) {
|
|
@@ -8101,9 +8280,11 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8101
8280
|
run.failure = clone(input.failure);
|
|
8102
8281
|
run.revision += 1;
|
|
8103
8282
|
run.updatedAt = createTimestamp();
|
|
8283
|
+
this.touchRun(run);
|
|
8104
8284
|
this.appendTransition(run, "queued", "failed", { failure: input.failure });
|
|
8285
|
+
this.dropRunOperationReceipts(run.id);
|
|
8105
8286
|
const result = clone(run);
|
|
8106
|
-
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8287
|
+
this.writeOperationReceipt(operationKey, operationPayload, result, run.id);
|
|
8107
8288
|
return result;
|
|
8108
8289
|
}
|
|
8109
8290
|
commitPhaseEntered(lease, input) {
|
|
@@ -8119,10 +8300,38 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8119
8300
|
run.currentPhaseId = input.phaseId;
|
|
8120
8301
|
run.revision += 1;
|
|
8121
8302
|
run.updatedAt = createTimestamp();
|
|
8303
|
+
this.touchRun(run);
|
|
8122
8304
|
const visit2 = this.events.filter((event) => event.runId === run.id && event.kind === "phase_entered").length + 1;
|
|
8123
|
-
this.
|
|
8305
|
+
this.appendEvent(this.baseEvent(run, { kind: "phase_entered", executionId: input.execution.executionId, phaseId: input.phaseId, visit: visit2 }));
|
|
8124
8306
|
const result = clone(run);
|
|
8125
|
-
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8307
|
+
this.writeOperationReceipt(operationKey, operationPayload, result, run.id);
|
|
8308
|
+
return result;
|
|
8309
|
+
}
|
|
8310
|
+
/** Commit a parallel Phase's reply while its Run is still running. */
|
|
8311
|
+
commitPhaseOutput(lease, input) {
|
|
8312
|
+
this.assertOwner(lease);
|
|
8313
|
+
const operationKey = `phase_output:${input.message.id}`;
|
|
8314
|
+
const operationPayload = canonicalJson([input.runId, input.execution.executionId, input.expectedRevision, input.message]);
|
|
8315
|
+
const replay = this.replayOperation(operationKey, operationPayload);
|
|
8316
|
+
if (replay) return clone(replay);
|
|
8317
|
+
const run = this.requireRun(input.runId);
|
|
8318
|
+
this.assertExecution(run, input.execution, input.expectedRevision);
|
|
8319
|
+
this.assertState(run, ["running"]);
|
|
8320
|
+
if (this.messages.has(input.message.id)) throw new RuntimeError("run_state_conflict", { runId: run.id, expected: ["running"], actual: run.state });
|
|
8321
|
+
const message = {
|
|
8322
|
+
...clone(input.message),
|
|
8323
|
+
agentId: run.agentId,
|
|
8324
|
+
runId: run.id,
|
|
8325
|
+
role: "assistant",
|
|
8326
|
+
sequenceWithinRun: this.nextMessageSequence(run.id)
|
|
8327
|
+
};
|
|
8328
|
+
this.storeMessage(message);
|
|
8329
|
+
run.revision += 1;
|
|
8330
|
+
run.updatedAt = createTimestamp();
|
|
8331
|
+
this.touchRun(run);
|
|
8332
|
+
this.appendMessage(run, message);
|
|
8333
|
+
const result = clone(run);
|
|
8334
|
+
this.writeOperationReceipt(operationKey, operationPayload, result, run.id);
|
|
8126
8335
|
return result;
|
|
8127
8336
|
}
|
|
8128
8337
|
commitInputRequired(lease, input) {
|
|
@@ -8144,7 +8353,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8144
8353
|
...clone(input.prompt),
|
|
8145
8354
|
sequenceWithinRun: this.nextMessageSequence(run.id)
|
|
8146
8355
|
};
|
|
8147
|
-
this.
|
|
8356
|
+
this.storeMessage(prompt);
|
|
8148
8357
|
}
|
|
8149
8358
|
run.state = "input_required";
|
|
8150
8359
|
run.checkpoint = clone(input.checkpoint);
|
|
@@ -8159,12 +8368,13 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8159
8368
|
delete run.execution;
|
|
8160
8369
|
run.revision += 1;
|
|
8161
8370
|
run.updatedAt = createTimestamp();
|
|
8371
|
+
this.touchRun(run);
|
|
8162
8372
|
if (prompt) {
|
|
8163
8373
|
this.appendMessage(run, prompt);
|
|
8164
8374
|
}
|
|
8165
8375
|
this.appendTransition(run, "running", "input_required", { prompt, interactions, answers: run.interactionAnswers ?? {} });
|
|
8166
8376
|
const result = clone(run);
|
|
8167
|
-
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8377
|
+
this.writeOperationReceipt(operationKey, operationPayload, result, run.id);
|
|
8168
8378
|
return result;
|
|
8169
8379
|
}
|
|
8170
8380
|
answerInteraction(lease, input) {
|
|
@@ -8212,8 +8422,9 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8212
8422
|
run.state = "queued";
|
|
8213
8423
|
this.appendTransition(run, "input_required", "queued");
|
|
8214
8424
|
}
|
|
8425
|
+
this.touchRun(run);
|
|
8215
8426
|
const result = clone(run);
|
|
8216
|
-
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8427
|
+
this.writeOperationReceipt(operationKey, operationPayload, result, run.id);
|
|
8217
8428
|
return result;
|
|
8218
8429
|
}
|
|
8219
8430
|
reserveToolCall(lease, input) {
|
|
@@ -8287,17 +8498,18 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8287
8498
|
sequenceWithinRun: this.nextMessageSequence(run.id),
|
|
8288
8499
|
createdAt: timestamp
|
|
8289
8500
|
};
|
|
8290
|
-
for (const toolCall of toolCalls) this.
|
|
8291
|
-
this.
|
|
8501
|
+
for (const toolCall of toolCalls) this.storeToolCall(toolCall);
|
|
8502
|
+
this.storeMessage(requestMessage);
|
|
8292
8503
|
run.revision += 1;
|
|
8293
8504
|
run.updatedAt = timestamp;
|
|
8505
|
+
this.touchRun(run);
|
|
8294
8506
|
this.appendMessage(run, requestMessage);
|
|
8295
8507
|
for (const toolCall of toolCalls) this.appendToolTransition(run, { from: null, to: "pending" }, toolCall);
|
|
8296
8508
|
const result = {
|
|
8297
8509
|
run: clone(run),
|
|
8298
8510
|
toolCalls: toolCalls.map((toolCall) => clone(toolCall))
|
|
8299
8511
|
};
|
|
8300
|
-
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8512
|
+
this.writeOperationReceipt(operationKey, operationPayload, result, run.id);
|
|
8301
8513
|
return result;
|
|
8302
8514
|
}
|
|
8303
8515
|
startToolCall(lease, input) {
|
|
@@ -8312,13 +8524,14 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8312
8524
|
if (toolCall.state !== "pending") throw new RuntimeError("run_state_conflict", { runId: run.id, expected: ["running"], actual: run.state });
|
|
8313
8525
|
toolCall.state = "running";
|
|
8314
8526
|
toolCall.executionId = input.execution.executionId;
|
|
8315
|
-
toolCall.executionId = input.execution.executionId;
|
|
8316
8527
|
toolCall.updatedAt = createTimestamp();
|
|
8528
|
+
this.storeToolCall(toolCall);
|
|
8317
8529
|
run.revision += 1;
|
|
8318
8530
|
run.updatedAt = toolCall.updatedAt;
|
|
8531
|
+
this.touchRun(run);
|
|
8319
8532
|
this.appendToolTransition(run, { from: "pending", to: "running" }, toolCall);
|
|
8320
8533
|
const result = { run: clone(run), toolCall: clone(toolCall) };
|
|
8321
|
-
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8534
|
+
this.writeOperationReceipt(operationKey, operationPayload, result, run.id);
|
|
8322
8535
|
return result;
|
|
8323
8536
|
}
|
|
8324
8537
|
suspendToolCall(lease, input) {
|
|
@@ -8335,11 +8548,13 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8335
8548
|
}
|
|
8336
8549
|
toolCall.state = "pending";
|
|
8337
8550
|
toolCall.updatedAt = createTimestamp();
|
|
8551
|
+
this.storeToolCall(toolCall);
|
|
8338
8552
|
run.revision += 1;
|
|
8339
8553
|
run.updatedAt = toolCall.updatedAt;
|
|
8554
|
+
this.touchRun(run);
|
|
8340
8555
|
this.appendToolTransition(run, { from: "running", to: "pending" }, toolCall);
|
|
8341
8556
|
const result = { run: clone(run), toolCall: clone(toolCall) };
|
|
8342
|
-
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8557
|
+
this.writeOperationReceipt(operationKey, operationPayload, result, run.id);
|
|
8343
8558
|
return result;
|
|
8344
8559
|
}
|
|
8345
8560
|
commitToolResult(lease, input) {
|
|
@@ -8371,15 +8586,17 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8371
8586
|
sequenceWithinRun: this.nextMessageSequence(run.id),
|
|
8372
8587
|
createdAt: createTimestamp()
|
|
8373
8588
|
};
|
|
8374
|
-
this.
|
|
8589
|
+
this.storeMessage(message);
|
|
8375
8590
|
toolCall.state = input.state;
|
|
8376
8591
|
toolCall.result = durableResult;
|
|
8377
8592
|
toolCall.resultMessageId = resultMessageId;
|
|
8378
8593
|
if (input.state === "indeterminate") toolCall.reason = input.reason;
|
|
8379
8594
|
else delete toolCall.reason;
|
|
8380
8595
|
toolCall.updatedAt = message.createdAt;
|
|
8596
|
+
this.storeToolCall(toolCall);
|
|
8381
8597
|
run.revision += 1;
|
|
8382
8598
|
run.updatedAt = message.createdAt;
|
|
8599
|
+
this.touchRun(run);
|
|
8383
8600
|
this.appendToolTransition(run, { from, to: input.state }, toolCall);
|
|
8384
8601
|
this.appendMessage(run, message);
|
|
8385
8602
|
if (input.state === "indeterminate") {
|
|
@@ -8400,10 +8617,12 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8400
8617
|
delete run.execution;
|
|
8401
8618
|
run.revision += 1;
|
|
8402
8619
|
run.updatedAt = createTimestamp();
|
|
8620
|
+
this.touchRun(run);
|
|
8403
8621
|
this.appendTransition(run, "running", "failed", { failure });
|
|
8622
|
+
this.dropRunOperationReceipts(run.id);
|
|
8404
8623
|
}
|
|
8405
8624
|
const result = { run: clone(run), toolCall: clone(toolCall) };
|
|
8406
|
-
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8625
|
+
this.writeOperationReceipt(operationKey, operationPayload, result, run.id);
|
|
8407
8626
|
return result;
|
|
8408
8627
|
}
|
|
8409
8628
|
commitOutcome(lease, input) {
|
|
@@ -8421,7 +8640,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8421
8640
|
if (nextState === "failed" && !input.failure) throw new TypeError("failed Run requires a failure");
|
|
8422
8641
|
const output = input.output ? { ...clone(input.output), sequenceWithinRun: this.nextMessageSequence(run.id) } : void 0;
|
|
8423
8642
|
if (output) {
|
|
8424
|
-
this.
|
|
8643
|
+
this.storeMessage(output);
|
|
8425
8644
|
this.appendMessage(run, output);
|
|
8426
8645
|
}
|
|
8427
8646
|
run.state = nextState;
|
|
@@ -8433,9 +8652,10 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8433
8652
|
delete run.interactionAnswers;
|
|
8434
8653
|
run.revision += 1;
|
|
8435
8654
|
run.updatedAt = createTimestamp();
|
|
8655
|
+
this.touchRun(run);
|
|
8436
8656
|
this.appendTransition(run, "running", nextState, { outcome: input.outcome, failure: input.failure, output });
|
|
8657
|
+
this.dropRunOperationReceipts(run.id);
|
|
8437
8658
|
const result = clone(run);
|
|
8438
|
-
this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8439
8659
|
return result;
|
|
8440
8660
|
}
|
|
8441
8661
|
cancelRun(lease, input) {
|
|
@@ -8455,7 +8675,6 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8455
8675
|
}
|
|
8456
8676
|
if (["completed", "failed", "cancelled"].includes(run.state)) {
|
|
8457
8677
|
const result2 = clone(run);
|
|
8458
|
-
if (input.expectedRevision !== void 0) this.writeOperationReceipt(operationKey, operationPayload, result2);
|
|
8459
8678
|
return result2;
|
|
8460
8679
|
}
|
|
8461
8680
|
const from = run.state;
|
|
@@ -8470,7 +8689,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8470
8689
|
for (const toolCall of activeToolCalls) this.interruptToolCall(run, toolCall, input.reason ?? "The Run was cancelled.");
|
|
8471
8690
|
if (input.output && (typeof input.output.content === "string" ? input.output.content.length > 0 : input.output.content.length > 0)) {
|
|
8472
8691
|
const output = { ...clone(input.output), sequenceWithinRun: this.nextMessageSequence(run.id) };
|
|
8473
|
-
this.
|
|
8692
|
+
this.storeMessage(output);
|
|
8474
8693
|
this.appendMessage(run, output);
|
|
8475
8694
|
}
|
|
8476
8695
|
if (run.openInteractions && run.openInteractions.length > 0) {
|
|
@@ -8493,9 +8712,10 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8493
8712
|
delete run.interactionAnswers;
|
|
8494
8713
|
run.revision += 1;
|
|
8495
8714
|
run.updatedAt = createTimestamp();
|
|
8715
|
+
this.touchRun(run);
|
|
8496
8716
|
this.appendTransition(run, from, "failed", { failure });
|
|
8717
|
+
this.dropRunOperationReceipts(run.id);
|
|
8497
8718
|
const result2 = clone(run);
|
|
8498
|
-
if (input.expectedRevision !== void 0) this.writeOperationReceipt(operationKey, operationPayload, result2);
|
|
8499
8719
|
return result2;
|
|
8500
8720
|
}
|
|
8501
8721
|
run.state = "cancelled";
|
|
@@ -8506,9 +8726,10 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8506
8726
|
delete run.interactionAnswers;
|
|
8507
8727
|
run.revision += 1;
|
|
8508
8728
|
run.updatedAt = createTimestamp();
|
|
8729
|
+
this.touchRun(run);
|
|
8509
8730
|
this.appendTransition(run, from, "cancelled", { reason: input.reason });
|
|
8731
|
+
this.dropRunOperationReceipts(run.id);
|
|
8510
8732
|
const result = clone(run);
|
|
8511
|
-
if (input.expectedRevision !== void 0) this.writeOperationReceipt(operationKey, operationPayload, result);
|
|
8512
8733
|
return result;
|
|
8513
8734
|
}
|
|
8514
8735
|
snapshotRun(lease, runId) {
|
|
@@ -8589,6 +8810,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8589
8810
|
const previous = this.consumerCheckpoints.get(input.consumerId);
|
|
8590
8811
|
if (previous !== void 0 && next <= this.parseCursor(previous)) return;
|
|
8591
8812
|
this.consumerCheckpoints.set(input.consumerId, input.cursor);
|
|
8813
|
+
this.recorder?.onConsumerCheckpointUpsert(input.consumerId, input.cursor);
|
|
8592
8814
|
}
|
|
8593
8815
|
compact(lease, input = {}) {
|
|
8594
8816
|
this.assertOwner(lease);
|
|
@@ -8622,11 +8844,15 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8622
8844
|
}
|
|
8623
8845
|
const deletedEvents = deleteThrough >= this.retentionFloor ? this.events.filter((event) => this.parseCursor(event.cursor) <= deleteThrough) : [];
|
|
8624
8846
|
if (deleteThrough >= this.retentionFloor) {
|
|
8847
|
+
const deletedEventIds = this.events.filter((event) => this.parseCursor(event.cursor) <= deleteThrough).map((event) => event.id);
|
|
8625
8848
|
this.events.splice(0, this.events.length, ...this.events.filter((event) => this.parseCursor(event.cursor) > deleteThrough));
|
|
8626
8849
|
this.retentionFloor = deleteThrough + 1;
|
|
8850
|
+
this.recorder?.onRetentionFloorChange(this.retentionFloor);
|
|
8851
|
+
this.recorder?.onEventsTruncate(deletedEventIds);
|
|
8627
8852
|
for (const [consumerId, cursor] of this.consumerCheckpoints) {
|
|
8628
8853
|
if (this.parseCursor(cursor) < this.retentionFloor - 1) {
|
|
8629
8854
|
this.consumerCheckpoints.delete(consumerId);
|
|
8855
|
+
this.recorder?.onConsumerCheckpointDelete(consumerId);
|
|
8630
8856
|
}
|
|
8631
8857
|
}
|
|
8632
8858
|
}
|
|
@@ -8635,11 +8861,21 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8635
8861
|
const deletedRunIds = deletableRuns.map((run) => run.id);
|
|
8636
8862
|
const deletedRunSet = new Set(deletedRunIds);
|
|
8637
8863
|
const deletedTools = [...this.toolCalls.values()].filter((tool) => deletedRunSet.has(tool.runId));
|
|
8638
|
-
for (const runId of deletedRunIds)
|
|
8864
|
+
for (const runId of deletedRunIds) {
|
|
8865
|
+
this.runs.delete(runId);
|
|
8866
|
+
this.runReceiptKeys.delete(runId);
|
|
8867
|
+
this.recorder?.onRunDelete(runId);
|
|
8868
|
+
}
|
|
8639
8869
|
for (const [messageId, message] of this.messages) {
|
|
8640
|
-
if (deletedRunSet.has(message.runId))
|
|
8870
|
+
if (deletedRunSet.has(message.runId)) {
|
|
8871
|
+
this.messages.delete(messageId);
|
|
8872
|
+
this.recorder?.onMessageDelete(messageId);
|
|
8873
|
+
}
|
|
8874
|
+
}
|
|
8875
|
+
for (const tool of deletedTools) {
|
|
8876
|
+
this.toolCalls.delete(tool.id);
|
|
8877
|
+
this.recorder?.onToolCallDelete(tool.id);
|
|
8641
8878
|
}
|
|
8642
|
-
for (const tool of deletedTools) this.toolCalls.delete(tool.id);
|
|
8643
8879
|
return {
|
|
8644
8880
|
deletedRunIds,
|
|
8645
8881
|
deletedToolCallIds: deletedTools.map((tool) => tool.id),
|
|
@@ -8661,7 +8897,10 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8661
8897
|
return receipt.result;
|
|
8662
8898
|
}
|
|
8663
8899
|
writeReceipt(scope, payload, result) {
|
|
8664
|
-
|
|
8900
|
+
const key = encodeIdempotencyScope(this.incarnation, scope);
|
|
8901
|
+
const receipt = { payload, result: clone(result) };
|
|
8902
|
+
this.idempotency.set(key, receipt);
|
|
8903
|
+
this.recorder?.onIdempotencyUpsert(key, receipt);
|
|
8665
8904
|
}
|
|
8666
8905
|
replayOperation(key, payload) {
|
|
8667
8906
|
const receipt = this.operationReceipts.get(key);
|
|
@@ -8669,8 +8908,19 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8669
8908
|
if (receipt.payload !== payload) throw new Error(`Idempotency payload conflict for ${key}.`);
|
|
8670
8909
|
return receipt.result;
|
|
8671
8910
|
}
|
|
8672
|
-
writeOperationReceipt(key, payload, result) {
|
|
8673
|
-
|
|
8911
|
+
writeOperationReceipt(key, payload, result, runId) {
|
|
8912
|
+
const receipt = { payload, result: clone(result) };
|
|
8913
|
+
this.operationReceipts.set(key, receipt);
|
|
8914
|
+
const resolvedRunId = runId ?? this.inferRunIdForReceipt(key, payload);
|
|
8915
|
+
if (resolvedRunId) {
|
|
8916
|
+
let keys = this.runReceiptKeys.get(resolvedRunId);
|
|
8917
|
+
if (!keys) {
|
|
8918
|
+
keys = /* @__PURE__ */ new Set();
|
|
8919
|
+
this.runReceiptKeys.set(resolvedRunId, keys);
|
|
8920
|
+
}
|
|
8921
|
+
keys.add(key);
|
|
8922
|
+
}
|
|
8923
|
+
this.recorder?.onOperationReceiptUpsert(key, receipt);
|
|
8674
8924
|
}
|
|
8675
8925
|
/**
|
|
8676
8926
|
* A Claim receipt exists for idempotent replay of one live Execution Attempt
|
|
@@ -8678,7 +8928,11 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8678
8928
|
* one history snapshot per Agent instead of one per Attempt.
|
|
8679
8929
|
*/
|
|
8680
8930
|
dropClaimReceipt(execution) {
|
|
8681
|
-
if (execution)
|
|
8931
|
+
if (execution) {
|
|
8932
|
+
const key = `claim:${execution.executionId}`;
|
|
8933
|
+
this.operationReceipts.delete(key);
|
|
8934
|
+
this.recorder?.onOperationReceiptDelete(key);
|
|
8935
|
+
}
|
|
8682
8936
|
}
|
|
8683
8937
|
/**
|
|
8684
8938
|
* A new owner fences the Execution Attempts of the previous one, so no Claim
|
|
@@ -8694,6 +8948,7 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8694
8948
|
for (const key of [...this.operationReceipts.keys()]) {
|
|
8695
8949
|
if (key.startsWith("claim:") && !liveExecutions.has(key.slice("claim:".length))) {
|
|
8696
8950
|
this.operationReceipts.delete(key);
|
|
8951
|
+
this.recorder?.onOperationReceiptDelete(key);
|
|
8697
8952
|
}
|
|
8698
8953
|
}
|
|
8699
8954
|
}
|
|
@@ -8732,14 +8987,16 @@ var InMemoryStore = class _InMemoryStore {
|
|
|
8732
8987
|
};
|
|
8733
8988
|
const from = toolCall.state;
|
|
8734
8989
|
const to = from === "running" ? "indeterminate" : "failed";
|
|
8735
|
-
this.
|
|
8990
|
+
this.storeMessage(message);
|
|
8736
8991
|
toolCall.state = to;
|
|
8737
8992
|
toolCall.result = durableResult;
|
|
8738
8993
|
toolCall.resultMessageId = message.id;
|
|
8739
8994
|
if (to === "indeterminate") toolCall.reason = reason;
|
|
8740
8995
|
toolCall.updatedAt = message.createdAt;
|
|
8996
|
+
this.storeToolCall(toolCall);
|
|
8741
8997
|
run.revision += 1;
|
|
8742
8998
|
run.updatedAt = message.createdAt;
|
|
8999
|
+
this.touchRun(run);
|
|
8743
9000
|
this.appendToolTransition(run, { from, to }, toolCall);
|
|
8744
9001
|
this.appendMessage(run, message);
|
|
8745
9002
|
}
|
|
@@ -8840,6 +9097,7 @@ ${record.summary}`,
|
|
|
8840
9097
|
if (existing?.id === record.id) return clone(existing);
|
|
8841
9098
|
const next = clone(record);
|
|
8842
9099
|
this.contextCompactions.set(record.agentId, next);
|
|
9100
|
+
this.recorder?.onContextCompactionUpsert(record.agentId, next);
|
|
8843
9101
|
return clone(next);
|
|
8844
9102
|
}
|
|
8845
9103
|
activeHistory(agentId, beforeSequence) {
|
|
@@ -8849,7 +9107,7 @@ ${record.summary}`,
|
|
|
8849
9107
|
].map((message) => ({ ...message, messageRevision: message.messageRevision ?? 0 })));
|
|
8850
9108
|
}
|
|
8851
9109
|
appendMessage(run, message) {
|
|
8852
|
-
this.
|
|
9110
|
+
this.appendEvent(this.baseEvent(run, {
|
|
8853
9111
|
kind: "message_committed",
|
|
8854
9112
|
message
|
|
8855
9113
|
}));
|
|
@@ -8865,13 +9123,14 @@ ${record.summary}`,
|
|
|
8865
9123
|
...to === "failed" && options?.failure ? { failure: options.failure } : {},
|
|
8866
9124
|
...to === "cancelled" && options?.reason ? { reason: options.reason } : {}
|
|
8867
9125
|
};
|
|
8868
|
-
this.
|
|
9126
|
+
this.touchRun(run);
|
|
9127
|
+
this.appendEvent(transition);
|
|
8869
9128
|
}
|
|
8870
9129
|
appendToolTransition(run, transition, toolCall) {
|
|
8871
|
-
this.
|
|
9130
|
+
this.appendEvent(this.baseEvent(run, {
|
|
8872
9131
|
kind: "tool_state_changed",
|
|
8873
9132
|
transition,
|
|
8874
|
-
toolCall
|
|
9133
|
+
toolCall: clone(toolCall)
|
|
8875
9134
|
}));
|
|
8876
9135
|
}
|
|
8877
9136
|
baseEvent(run, extra) {
|
|
@@ -8944,6 +9203,9 @@ var MemoryOwnedStore = class {
|
|
|
8944
9203
|
async commitPhaseEntered(input) {
|
|
8945
9204
|
return this.store.commitPhaseEntered(this.lease, input);
|
|
8946
9205
|
}
|
|
9206
|
+
async commitPhaseOutput(input) {
|
|
9207
|
+
return this.store.commitPhaseOutput(this.lease, input);
|
|
9208
|
+
}
|
|
8947
9209
|
async commitInputRequired(input) {
|
|
8948
9210
|
return this.store.commitInputRequired(this.lease, input);
|
|
8949
9211
|
}
|
|
@@ -9244,6 +9506,94 @@ var CURRENT_SCHEMA_SQL = `
|
|
|
9244
9506
|
CREATE INDEX runs_active_idx ON runs (agent_id, state, agent_sequence);
|
|
9245
9507
|
CREATE INDEX run_events_sequence_idx ON run_events (sequence);
|
|
9246
9508
|
`;
|
|
9509
|
+
var ChangeTracker = class {
|
|
9510
|
+
upsertedAgents = /* @__PURE__ */ new Map();
|
|
9511
|
+
deletedAgentIds = /* @__PURE__ */ new Set();
|
|
9512
|
+
upsertedRuns = /* @__PURE__ */ new Map();
|
|
9513
|
+
deletedRunIds = /* @__PURE__ */ new Set();
|
|
9514
|
+
insertedMessages = /* @__PURE__ */ new Map();
|
|
9515
|
+
deletedMessageIds = /* @__PURE__ */ new Set();
|
|
9516
|
+
upsertedToolCalls = /* @__PURE__ */ new Map();
|
|
9517
|
+
deletedToolCallIds = /* @__PURE__ */ new Set();
|
|
9518
|
+
appendedEvents = [];
|
|
9519
|
+
truncatedEventIds = /* @__PURE__ */ new Set();
|
|
9520
|
+
upsertedIdempotency = /* @__PURE__ */ new Map();
|
|
9521
|
+
deletedIdempotencyScopes = /* @__PURE__ */ new Set();
|
|
9522
|
+
upsertedOperationReceipts = /* @__PURE__ */ new Map();
|
|
9523
|
+
deletedOperationReceiptKeys = /* @__PURE__ */ new Set();
|
|
9524
|
+
upsertedConsumerCheckpoints = /* @__PURE__ */ new Map();
|
|
9525
|
+
deletedConsumerCheckpoints = /* @__PURE__ */ new Set();
|
|
9526
|
+
upsertedContextCompactions = /* @__PURE__ */ new Map();
|
|
9527
|
+
retentionFloorChanged;
|
|
9528
|
+
onAgentUpsert(agent) {
|
|
9529
|
+
this.deletedAgentIds.delete(agent.id);
|
|
9530
|
+
this.upsertedAgents.set(agent.id, agent);
|
|
9531
|
+
}
|
|
9532
|
+
onAgentDelete(agentId) {
|
|
9533
|
+
this.upsertedAgents.delete(agentId);
|
|
9534
|
+
this.deletedAgentIds.add(agentId);
|
|
9535
|
+
}
|
|
9536
|
+
onRunUpsert(run) {
|
|
9537
|
+
this.deletedRunIds.delete(run.id);
|
|
9538
|
+
this.upsertedRuns.set(run.id, run);
|
|
9539
|
+
}
|
|
9540
|
+
onRunDelete(runId) {
|
|
9541
|
+
this.upsertedRuns.delete(runId);
|
|
9542
|
+
this.deletedRunIds.add(runId);
|
|
9543
|
+
}
|
|
9544
|
+
onMessageInsert(message) {
|
|
9545
|
+
this.deletedMessageIds.delete(message.id);
|
|
9546
|
+
this.insertedMessages.set(message.id, message);
|
|
9547
|
+
}
|
|
9548
|
+
onMessageDelete(messageId) {
|
|
9549
|
+
this.insertedMessages.delete(messageId);
|
|
9550
|
+
this.deletedMessageIds.add(messageId);
|
|
9551
|
+
}
|
|
9552
|
+
onToolCallUpsert(toolCall) {
|
|
9553
|
+
this.deletedToolCallIds.delete(toolCall.id);
|
|
9554
|
+
this.upsertedToolCalls.set(toolCall.id, toolCall);
|
|
9555
|
+
}
|
|
9556
|
+
onToolCallDelete(toolCallId) {
|
|
9557
|
+
this.upsertedToolCalls.delete(toolCallId);
|
|
9558
|
+
this.deletedToolCallIds.add(toolCallId);
|
|
9559
|
+
}
|
|
9560
|
+
onEventAppend(event) {
|
|
9561
|
+
this.appendedEvents.push(event);
|
|
9562
|
+
}
|
|
9563
|
+
onEventsTruncate(deletedEventIds) {
|
|
9564
|
+
for (const id of deletedEventIds) this.truncatedEventIds.add(id);
|
|
9565
|
+
}
|
|
9566
|
+
onIdempotencyUpsert(scope, receipt) {
|
|
9567
|
+
this.deletedIdempotencyScopes.delete(scope);
|
|
9568
|
+
this.upsertedIdempotency.set(scope, receipt);
|
|
9569
|
+
}
|
|
9570
|
+
onIdempotencyDelete(scope) {
|
|
9571
|
+
this.upsertedIdempotency.delete(scope);
|
|
9572
|
+
this.deletedIdempotencyScopes.add(scope);
|
|
9573
|
+
}
|
|
9574
|
+
onOperationReceiptUpsert(key, receipt) {
|
|
9575
|
+
this.deletedOperationReceiptKeys.delete(key);
|
|
9576
|
+
this.upsertedOperationReceipts.set(key, receipt);
|
|
9577
|
+
}
|
|
9578
|
+
onOperationReceiptDelete(key) {
|
|
9579
|
+
this.upsertedOperationReceipts.delete(key);
|
|
9580
|
+
this.deletedOperationReceiptKeys.add(key);
|
|
9581
|
+
}
|
|
9582
|
+
onConsumerCheckpointUpsert(consumerId, cursor) {
|
|
9583
|
+
this.deletedConsumerCheckpoints.delete(consumerId);
|
|
9584
|
+
this.upsertedConsumerCheckpoints.set(consumerId, cursor);
|
|
9585
|
+
}
|
|
9586
|
+
onConsumerCheckpointDelete(consumerId) {
|
|
9587
|
+
this.upsertedConsumerCheckpoints.delete(consumerId);
|
|
9588
|
+
this.deletedConsumerCheckpoints.add(consumerId);
|
|
9589
|
+
}
|
|
9590
|
+
onContextCompactionUpsert(agentId, record) {
|
|
9591
|
+
this.upsertedContextCompactions.set(agentId, record);
|
|
9592
|
+
}
|
|
9593
|
+
onRetentionFloorChange(floor) {
|
|
9594
|
+
this.retentionFloorChanged = floor;
|
|
9595
|
+
}
|
|
9596
|
+
};
|
|
9247
9597
|
var SqliteStore = class {
|
|
9248
9598
|
database;
|
|
9249
9599
|
archiveRoot;
|
|
@@ -9252,6 +9602,25 @@ var SqliteStore = class {
|
|
|
9252
9602
|
mirroredAgents = /* @__PURE__ */ new Set();
|
|
9253
9603
|
closed = false;
|
|
9254
9604
|
configured = false;
|
|
9605
|
+
cachedMemory;
|
|
9606
|
+
cachedOwner;
|
|
9607
|
+
isLegacyState = false;
|
|
9608
|
+
stmtUpsertAgent;
|
|
9609
|
+
stmtDeleteAgent;
|
|
9610
|
+
stmtUpsertRun;
|
|
9611
|
+
stmtDeleteRun;
|
|
9612
|
+
stmtInsertMessage;
|
|
9613
|
+
stmtDeleteMessage;
|
|
9614
|
+
stmtUpsertToolCall;
|
|
9615
|
+
stmtDeleteToolCall;
|
|
9616
|
+
stmtInsertEvent;
|
|
9617
|
+
stmtDeleteEvent;
|
|
9618
|
+
stmtUpsertIdempotency;
|
|
9619
|
+
stmtDeleteIdempotency;
|
|
9620
|
+
stmtUpsertCheckpoint;
|
|
9621
|
+
stmtDeleteCheckpoint;
|
|
9622
|
+
stmtUpdateMeta;
|
|
9623
|
+
stmtUpdateState;
|
|
9255
9624
|
constructor(filename = ":memory:") {
|
|
9256
9625
|
this.database = new Database(filename, { create: true, readwrite: true, strict: true });
|
|
9257
9626
|
this.archiveRoot = filename === ":memory:" ? join6(tmpdir2(), `rowan-context-archives-${crypto.randomUUID()}`) : join6(dirname7(resolve8(filename)), "context-archives");
|
|
@@ -9272,7 +9641,26 @@ var SqliteStore = class {
|
|
|
9272
9641
|
}
|
|
9273
9642
|
const replay = ownerLease(row);
|
|
9274
9643
|
this.writeOwner({ ...row, expires_at: now + input.leaseMs });
|
|
9275
|
-
|
|
9644
|
+
const newLease2 = { ...replay, expiresAt: new Date(now + input.leaseMs).toISOString() };
|
|
9645
|
+
if (!this.cachedMemory || this.cachedOwner?.epoch !== replay.epoch) {
|
|
9646
|
+
const state2 = this.readState();
|
|
9647
|
+
const memory2 = InMemoryStore.fromState(state2);
|
|
9648
|
+
memory2.attachOwner(newLease2);
|
|
9649
|
+
const tracker2 = new ChangeTracker();
|
|
9650
|
+
memory2.setChangeRecorder(tracker2);
|
|
9651
|
+
try {
|
|
9652
|
+
memory2.dropSettledClaimReceipts();
|
|
9653
|
+
memory2.compactTerminalReceipts();
|
|
9654
|
+
} finally {
|
|
9655
|
+
memory2.setChangeRecorder(void 0);
|
|
9656
|
+
}
|
|
9657
|
+
this.ensureTableBackedStorage(memory2, tracker2, this.isLegacyState);
|
|
9658
|
+
this.cachedMemory = memory2;
|
|
9659
|
+
} else {
|
|
9660
|
+
this.cachedMemory.attachOwner(newLease2);
|
|
9661
|
+
}
|
|
9662
|
+
this.cachedOwner = newLease2;
|
|
9663
|
+
return newLease2;
|
|
9276
9664
|
}
|
|
9277
9665
|
const state = this.readState();
|
|
9278
9666
|
const memory = InMemoryStore.fromState(state);
|
|
@@ -9291,22 +9679,42 @@ var SqliteStore = class {
|
|
|
9291
9679
|
released_epoch: row.released_epoch
|
|
9292
9680
|
};
|
|
9293
9681
|
this.writeOwner(next);
|
|
9294
|
-
|
|
9295
|
-
this.persistState(memory.exportState());
|
|
9296
|
-
return {
|
|
9682
|
+
const newLease = {
|
|
9297
9683
|
ownerId: input.ownerId,
|
|
9298
9684
|
token,
|
|
9299
9685
|
epoch,
|
|
9300
9686
|
expiresAt: new Date(now + input.leaseMs).toISOString()
|
|
9301
9687
|
};
|
|
9688
|
+
memory.attachOwner(newLease);
|
|
9689
|
+
const tracker = new ChangeTracker();
|
|
9690
|
+
memory.setChangeRecorder(tracker);
|
|
9691
|
+
try {
|
|
9692
|
+
memory.dropSettledClaimReceipts();
|
|
9693
|
+
memory.compactTerminalReceipts();
|
|
9694
|
+
} finally {
|
|
9695
|
+
memory.setChangeRecorder(void 0);
|
|
9696
|
+
}
|
|
9697
|
+
this.ensureTableBackedStorage(memory, tracker, this.isLegacyState);
|
|
9698
|
+
this.cachedMemory = memory;
|
|
9699
|
+
this.cachedOwner = newLease;
|
|
9700
|
+
return newLease;
|
|
9302
9701
|
});
|
|
9303
9702
|
return new SqliteOwnedStore(this, lease);
|
|
9304
9703
|
}
|
|
9305
9704
|
close() {
|
|
9306
9705
|
if (this.closed) return;
|
|
9307
9706
|
this.closed = true;
|
|
9707
|
+
this.cachedMemory = void 0;
|
|
9708
|
+
this.cachedOwner = void 0;
|
|
9308
9709
|
this.database.close();
|
|
9309
9710
|
}
|
|
9711
|
+
exportState() {
|
|
9712
|
+
if (this.cachedMemory) {
|
|
9713
|
+
return this.cachedMemory.exportState();
|
|
9714
|
+
}
|
|
9715
|
+
const state = this.readState();
|
|
9716
|
+
return InMemoryStore.fromState(state).exportState();
|
|
9717
|
+
}
|
|
9310
9718
|
/** Filesystem location owned by this Store for one Agent's readable archive. */
|
|
9311
9719
|
contextArchiveDir(agentId) {
|
|
9312
9720
|
return join6(this.archiveRoot, String(agentId));
|
|
@@ -9347,6 +9755,9 @@ var SqliteStore = class {
|
|
|
9347
9755
|
async commitPhaseEntered(lease, input) {
|
|
9348
9756
|
return this.invoke(lease, (store, current) => store.commitPhaseEntered(current, input));
|
|
9349
9757
|
}
|
|
9758
|
+
async commitPhaseOutput(lease, input) {
|
|
9759
|
+
return this.invoke(lease, (store, current) => store.commitPhaseOutput(current, input));
|
|
9760
|
+
}
|
|
9350
9761
|
async commitInputRequired(lease, input) {
|
|
9351
9762
|
return this.invoke(lease, (store, current) => store.commitInputRequired(current, input));
|
|
9352
9763
|
}
|
|
@@ -9388,31 +9799,7 @@ var SqliteStore = class {
|
|
|
9388
9799
|
}
|
|
9389
9800
|
async listEvents(lease, input = {}) {
|
|
9390
9801
|
this.assertOpen();
|
|
9391
|
-
return this.
|
|
9392
|
-
this.requireMatchingOwner(lease, true);
|
|
9393
|
-
const retentionRow = this.database.query(
|
|
9394
|
-
"SELECT value FROM runtime_meta WHERE key = ?"
|
|
9395
|
-
).get(RETENTION_FLOOR_KEY);
|
|
9396
|
-
const retentionFloor = Math.max(1, Number(retentionRow?.value ?? "1"));
|
|
9397
|
-
const after = input.after ? parseEventCursor(lease, input.after) : retentionFloor - 1;
|
|
9398
|
-
if (input.after && after < retentionFloor - 1) {
|
|
9399
|
-
throw new RuntimeError("invalid_cursor", { cursorType: "event", reason: "expired" });
|
|
9400
|
-
}
|
|
9401
|
-
if (input.after) {
|
|
9402
|
-
const latest = this.database.query(
|
|
9403
|
-
"SELECT max(sequence) AS sequence FROM run_events"
|
|
9404
|
-
).get();
|
|
9405
|
-
const waterline = latest.sequence ?? 0;
|
|
9406
|
-
if (after > waterline) {
|
|
9407
|
-
throw new RuntimeError("invalid_cursor", { cursorType: "event", reason: "beyond_waterline" });
|
|
9408
|
-
}
|
|
9409
|
-
if (after === waterline) return [];
|
|
9410
|
-
}
|
|
9411
|
-
const rows = this.database.query(
|
|
9412
|
-
"SELECT payload_json FROM run_events ORDER BY sequence"
|
|
9413
|
-
).all();
|
|
9414
|
-
return rows.map((row) => JSON.parse(row.payload_json)).filter((event) => parseEventCursor(lease, event.cursor) > after);
|
|
9415
|
-
});
|
|
9802
|
+
return this.read(lease, (memory) => memory.listEvents(lease, input));
|
|
9416
9803
|
}
|
|
9417
9804
|
async openConsumer(lease, consumerId) {
|
|
9418
9805
|
return this.invoke(lease, (store, current) => store.openConsumer(current, consumerId), false);
|
|
@@ -9436,7 +9823,12 @@ var SqliteStore = class {
|
|
|
9436
9823
|
const row = this.requireMatchingOwner(lease, false);
|
|
9437
9824
|
const expiresAt = Date.now() + leaseMs;
|
|
9438
9825
|
this.writeOwner({ ...row, expires_at: expiresAt });
|
|
9439
|
-
|
|
9826
|
+
const nextLease = { ...lease, expiresAt: new Date(expiresAt).toISOString() };
|
|
9827
|
+
if (this.cachedOwner && this.cachedOwner.token === lease.token) {
|
|
9828
|
+
this.cachedOwner = nextLease;
|
|
9829
|
+
this.cachedMemory?.attachOwner(nextLease);
|
|
9830
|
+
}
|
|
9831
|
+
return nextLease;
|
|
9440
9832
|
});
|
|
9441
9833
|
}
|
|
9442
9834
|
async sealAndReleaseOwner(lease) {
|
|
@@ -9447,27 +9839,75 @@ var SqliteStore = class {
|
|
|
9447
9839
|
if (row.owner_id !== lease.ownerId || row.owner_token !== lease.token || row.epoch !== lease.epoch) {
|
|
9448
9840
|
throw ownershipLost2(lease, row);
|
|
9449
9841
|
}
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9842
|
+
if (!this.cachedMemory || this.cachedOwner?.epoch !== lease.epoch) {
|
|
9843
|
+
this.cachedMemory = InMemoryStore.fromState(this.readState());
|
|
9844
|
+
this.cachedOwner = lease;
|
|
9845
|
+
}
|
|
9846
|
+
const tracker = new ChangeTracker();
|
|
9847
|
+
this.cachedMemory.setChangeRecorder(tracker);
|
|
9848
|
+
try {
|
|
9849
|
+
this.cachedMemory.attachOwner(lease);
|
|
9850
|
+
this.cachedMemory.interruptOwner(lease.epoch, "The Runtime owner was sealed.");
|
|
9851
|
+
} finally {
|
|
9852
|
+
this.cachedMemory.setChangeRecorder(void 0);
|
|
9853
|
+
}
|
|
9854
|
+
this.persistChanges(tracker, this.cachedMemory);
|
|
9855
|
+
this.mirrorChanges(tracker);
|
|
9454
9856
|
this.writeOwner({ ...row, owner_id: null, owner_token: null, expires_at: null, released_epoch: lease.epoch });
|
|
9857
|
+
this.cachedMemory = void 0;
|
|
9858
|
+
this.cachedOwner = void 0;
|
|
9455
9859
|
});
|
|
9456
9860
|
}
|
|
9457
|
-
|
|
9861
|
+
read(lease, operation) {
|
|
9862
|
+
this.assertOpen();
|
|
9863
|
+
this.requireMatchingOwner(lease, true);
|
|
9864
|
+
if (!this.cachedMemory || this.cachedOwner?.epoch !== lease.epoch) {
|
|
9865
|
+
this.cachedMemory = InMemoryStore.fromState(this.readState());
|
|
9866
|
+
this.cachedMemory.attachOwner(lease);
|
|
9867
|
+
this.cachedOwner = lease;
|
|
9868
|
+
} else {
|
|
9869
|
+
this.cachedMemory.attachOwner(lease);
|
|
9870
|
+
}
|
|
9871
|
+
return operation(this.cachedMemory);
|
|
9872
|
+
}
|
|
9873
|
+
write(lease, operation) {
|
|
9458
9874
|
this.assertOpen();
|
|
9459
9875
|
return this.immediateTransaction(() => {
|
|
9460
9876
|
this.requireMatchingOwner(lease, true);
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
this.
|
|
9877
|
+
if (!this.cachedMemory || this.cachedOwner?.epoch !== lease.epoch) {
|
|
9878
|
+
this.cachedMemory = InMemoryStore.fromState(this.readState());
|
|
9879
|
+
this.cachedMemory.attachOwner(lease);
|
|
9880
|
+
this.cachedOwner = lease;
|
|
9881
|
+
} else {
|
|
9882
|
+
this.cachedMemory.attachOwner(lease);
|
|
9883
|
+
}
|
|
9884
|
+
const tracker = new ChangeTracker();
|
|
9885
|
+
this.cachedMemory.setChangeRecorder(tracker);
|
|
9886
|
+
let result;
|
|
9887
|
+
try {
|
|
9888
|
+
result = operation(this.cachedMemory);
|
|
9889
|
+
} catch (error) {
|
|
9890
|
+
this.cachedMemory.setChangeRecorder(void 0);
|
|
9891
|
+
this.cachedMemory = void 0;
|
|
9892
|
+
throw error;
|
|
9893
|
+
}
|
|
9894
|
+
this.cachedMemory.setChangeRecorder(void 0);
|
|
9895
|
+
try {
|
|
9896
|
+
this.persistChanges(tracker, this.cachedMemory);
|
|
9897
|
+
this.mirrorChanges(tracker);
|
|
9898
|
+
} catch (error) {
|
|
9899
|
+
this.cachedMemory = void 0;
|
|
9900
|
+
throw error;
|
|
9467
9901
|
}
|
|
9468
9902
|
return result;
|
|
9469
9903
|
});
|
|
9470
9904
|
}
|
|
9905
|
+
invoke(lease, operation, persist = true) {
|
|
9906
|
+
if (persist) {
|
|
9907
|
+
return this.write(lease, (memory) => operation(memory, lease));
|
|
9908
|
+
}
|
|
9909
|
+
return this.read(lease, (memory) => operation(memory, lease));
|
|
9910
|
+
}
|
|
9471
9911
|
ensureSchema() {
|
|
9472
9912
|
const catalog = this.catalog();
|
|
9473
9913
|
if (catalog.length > 0 && !this.isCurrentSchema(catalog)) {
|
|
@@ -9484,7 +9924,7 @@ var SqliteStore = class {
|
|
|
9484
9924
|
this.database.run("INSERT INTO runtime_meta (key, value) VALUES (?, ?)", [RETENTION_FLOOR_KEY, "1"]);
|
|
9485
9925
|
const state = new InMemoryStore();
|
|
9486
9926
|
this.database.run("INSERT INTO runtime_owner (singleton, epoch) VALUES (?, ?)", [STATE_ROW, 0]);
|
|
9487
|
-
this.database.run("INSERT INTO runtime_state (singleton, state_json) VALUES (?, ?)", [STATE_ROW, JSON.stringify(state.
|
|
9927
|
+
this.database.run("INSERT INTO runtime_state (singleton, state_json) VALUES (?, ?)", [STATE_ROW, JSON.stringify(state.exportMetadata())]);
|
|
9488
9928
|
});
|
|
9489
9929
|
return;
|
|
9490
9930
|
}
|
|
@@ -9523,13 +9963,267 @@ var SqliteStore = class {
|
|
|
9523
9963
|
readState() {
|
|
9524
9964
|
const row = this.database.query("SELECT state_json FROM runtime_state WHERE singleton = ?").get(STATE_ROW);
|
|
9525
9965
|
if (!row) throw new RuntimeError("store_unavailable", { operation: "read_state", retryable: false, reason: "runtime_state row is missing" });
|
|
9526
|
-
|
|
9966
|
+
const parsed = JSON.parse(row.state_json);
|
|
9967
|
+
if (parsed.agents && Array.isArray(parsed.agents)) {
|
|
9968
|
+
this.isLegacyState = true;
|
|
9969
|
+
return parsed;
|
|
9970
|
+
}
|
|
9971
|
+
this.isLegacyState = false;
|
|
9972
|
+
return this.loadTableBackedState(parsed);
|
|
9973
|
+
}
|
|
9974
|
+
loadTableBackedState(metadata) {
|
|
9975
|
+
const agentRows = this.database.query(
|
|
9976
|
+
"SELECT id, metadata_json, config_token, config_identity, created_at, activated_at, updated_at FROM agents ORDER BY created_at"
|
|
9977
|
+
).all();
|
|
9978
|
+
const agents = agentRows.map((row) => ({
|
|
9979
|
+
id: row.id,
|
|
9980
|
+
...row.metadata_json ? { metadata: JSON.parse(row.metadata_json) } : {},
|
|
9981
|
+
...row.config_token ? { currentConfigToken: row.config_token } : {},
|
|
9982
|
+
...row.config_identity ? { currentConfigIdentity: row.config_identity } : {},
|
|
9983
|
+
createdAt: row.created_at,
|
|
9984
|
+
...row.activated_at ? { activatedAt: row.activated_at } : {},
|
|
9985
|
+
updatedAt: row.updated_at
|
|
9986
|
+
}));
|
|
9987
|
+
const runRows = this.database.query("SELECT payload_json FROM runs").all();
|
|
9988
|
+
const runs = runRows.map((r) => JSON.parse(r.payload_json));
|
|
9989
|
+
const messageRows = this.database.query("SELECT payload_json FROM messages ORDER BY run_id, sequence_within_run").all();
|
|
9990
|
+
const messages = messageRows.map((m) => JSON.parse(m.payload_json));
|
|
9991
|
+
const toolRows = this.database.query("SELECT payload_json FROM tool_calls").all();
|
|
9992
|
+
const toolCalls = toolRows.map((t) => JSON.parse(t.payload_json));
|
|
9993
|
+
const eventRows = this.database.query("SELECT payload_json FROM run_events ORDER BY sequence").all();
|
|
9994
|
+
const events = eventRows.map((e) => JSON.parse(e.payload_json));
|
|
9995
|
+
const idempotencyRows = this.database.query("SELECT scope, payload_json, result_json FROM idempotency").all();
|
|
9996
|
+
const idempotency = [];
|
|
9997
|
+
const operationReceipts = [];
|
|
9998
|
+
for (const row of idempotencyRows) {
|
|
9999
|
+
const receipt = { payload: row.payload_json, result: JSON.parse(row.result_json) };
|
|
10000
|
+
if (row.scope.startsWith("operation:")) {
|
|
10001
|
+
operationReceipts.push([row.scope.slice("operation:".length), receipt]);
|
|
10002
|
+
} else {
|
|
10003
|
+
idempotency.push([row.scope, receipt]);
|
|
10004
|
+
}
|
|
10005
|
+
}
|
|
10006
|
+
const cpRows = this.database.query("SELECT consumer_id, sequence FROM consumer_checkpoints").all();
|
|
10007
|
+
const consumerCheckpoints = cpRows.map((r) => [r.consumer_id, `${metadata.incarnation}:${r.sequence}`]);
|
|
10008
|
+
const retentionRow = this.database.query("SELECT value FROM runtime_meta WHERE key = ?").get(RETENTION_FLOOR_KEY);
|
|
10009
|
+
const retentionFloor = Math.max(1, Number(retentionRow?.value ?? metadata.retentionFloor ?? "1"));
|
|
10010
|
+
return {
|
|
10011
|
+
incarnation: metadata.incarnation,
|
|
10012
|
+
agents,
|
|
10013
|
+
runs,
|
|
10014
|
+
messages,
|
|
10015
|
+
toolCalls,
|
|
10016
|
+
events,
|
|
10017
|
+
idempotency,
|
|
10018
|
+
operationReceipts,
|
|
10019
|
+
historySeeds: metadata.historySeeds ?? [],
|
|
10020
|
+
consumerCheckpoints,
|
|
10021
|
+
retentionFloor,
|
|
10022
|
+
nextAgentSequence: metadata.nextAgentSequence ?? [],
|
|
10023
|
+
nextReadySequence: metadata.nextReadySequence ?? [],
|
|
10024
|
+
eventSequence: metadata.eventSequence ?? 0,
|
|
10025
|
+
contextCompactions: metadata.contextCompactions ?? []
|
|
10026
|
+
};
|
|
10027
|
+
}
|
|
10028
|
+
ensureTableBackedStorage(memory, tracker, isLegacy) {
|
|
10029
|
+
if (isLegacy) {
|
|
10030
|
+
this.writeFullStateToTables(memory);
|
|
10031
|
+
this.isLegacyState = false;
|
|
10032
|
+
} else {
|
|
10033
|
+
this.persistChanges(tracker, memory);
|
|
10034
|
+
this.mirrorChanges(tracker);
|
|
10035
|
+
}
|
|
10036
|
+
}
|
|
10037
|
+
getStmtUpsertAgent() {
|
|
10038
|
+
return this.stmtUpsertAgent ??= this.database.prepare(
|
|
10039
|
+
`INSERT INTO agents (id, metadata_json, config_token, config_identity, created_at, activated_at, updated_at)
|
|
10040
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
10041
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
10042
|
+
metadata_json = excluded.metadata_json,
|
|
10043
|
+
config_token = excluded.config_token,
|
|
10044
|
+
config_identity = excluded.config_identity,
|
|
10045
|
+
activated_at = excluded.activated_at,
|
|
10046
|
+
updated_at = excluded.updated_at`
|
|
10047
|
+
);
|
|
10048
|
+
}
|
|
10049
|
+
getStmtDeleteAgent() {
|
|
10050
|
+
return this.stmtDeleteAgent ??= this.database.prepare("DELETE FROM agents WHERE id = ?");
|
|
10051
|
+
}
|
|
10052
|
+
getStmtUpsertRun() {
|
|
10053
|
+
return this.stmtUpsertRun ??= this.database.prepare(
|
|
10054
|
+
`INSERT INTO runs (id, agent_id, agent_sequence, state, revision, payload_json, created_at, updated_at)
|
|
10055
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
10056
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
10057
|
+
state = excluded.state,
|
|
10058
|
+
revision = excluded.revision,
|
|
10059
|
+
payload_json = excluded.payload_json,
|
|
10060
|
+
updated_at = excluded.updated_at`
|
|
10061
|
+
);
|
|
10062
|
+
}
|
|
10063
|
+
getStmtDeleteRun() {
|
|
10064
|
+
return this.stmtDeleteRun ??= this.database.prepare("DELETE FROM runs WHERE id = ?");
|
|
10065
|
+
}
|
|
10066
|
+
getStmtInsertMessage() {
|
|
10067
|
+
return this.stmtInsertMessage ??= this.database.prepare(
|
|
10068
|
+
`INSERT INTO messages (id, run_id, sequence_within_run, payload_json, created_at)
|
|
10069
|
+
VALUES (?, ?, ?, ?, ?)
|
|
10070
|
+
ON CONFLICT(id) DO UPDATE SET payload_json = excluded.payload_json`
|
|
10071
|
+
);
|
|
10072
|
+
}
|
|
10073
|
+
getStmtDeleteMessage() {
|
|
10074
|
+
return this.stmtDeleteMessage ??= this.database.prepare("DELETE FROM messages WHERE id = ?");
|
|
10075
|
+
}
|
|
10076
|
+
getStmtUpsertToolCall() {
|
|
10077
|
+
return this.stmtUpsertToolCall ??= this.database.prepare(
|
|
10078
|
+
`INSERT INTO tool_calls (id, run_id, execution_id, state, payload_json)
|
|
10079
|
+
VALUES (?, ?, ?, ?, ?)
|
|
10080
|
+
ON CONFLICT(id) DO UPDATE SET state = excluded.state, payload_json = excluded.payload_json`
|
|
10081
|
+
);
|
|
10082
|
+
}
|
|
10083
|
+
getStmtDeleteToolCall() {
|
|
10084
|
+
return this.stmtDeleteToolCall ??= this.database.prepare("DELETE FROM tool_calls WHERE id = ?");
|
|
10085
|
+
}
|
|
10086
|
+
getStmtInsertEvent() {
|
|
10087
|
+
return this.stmtInsertEvent ??= this.database.prepare(
|
|
10088
|
+
"INSERT INTO run_events (id, run_id, payload_json, created_at) VALUES (?, ?, ?, ?)"
|
|
10089
|
+
);
|
|
10090
|
+
}
|
|
10091
|
+
getStmtDeleteEvent() {
|
|
10092
|
+
return this.stmtDeleteEvent ??= this.database.prepare("DELETE FROM run_events WHERE id = ?");
|
|
10093
|
+
}
|
|
10094
|
+
getStmtUpsertIdempotency() {
|
|
10095
|
+
return this.stmtUpsertIdempotency ??= this.database.prepare(
|
|
10096
|
+
`INSERT INTO idempotency (scope, payload_json, result_json)
|
|
10097
|
+
VALUES (?, ?, ?)
|
|
10098
|
+
ON CONFLICT(scope) DO UPDATE SET payload_json = excluded.payload_json, result_json = excluded.result_json`
|
|
10099
|
+
);
|
|
9527
10100
|
}
|
|
9528
|
-
|
|
9529
|
-
this.database.
|
|
10101
|
+
getStmtDeleteIdempotency() {
|
|
10102
|
+
return this.stmtDeleteIdempotency ??= this.database.prepare("DELETE FROM idempotency WHERE scope = ?");
|
|
9530
10103
|
}
|
|
9531
|
-
|
|
9532
|
-
this.
|
|
10104
|
+
getStmtUpsertCheckpoint() {
|
|
10105
|
+
return this.stmtUpsertCheckpoint ??= this.database.prepare(
|
|
10106
|
+
`INSERT INTO consumer_checkpoints (consumer_id, sequence, event_id, updated_at)
|
|
10107
|
+
VALUES (?, ?, ?, ?)
|
|
10108
|
+
ON CONFLICT(consumer_id) DO UPDATE SET sequence = excluded.sequence, updated_at = excluded.updated_at`
|
|
10109
|
+
);
|
|
10110
|
+
}
|
|
10111
|
+
getStmtDeleteCheckpoint() {
|
|
10112
|
+
return this.stmtDeleteCheckpoint ??= this.database.prepare("DELETE FROM consumer_checkpoints WHERE consumer_id = ?");
|
|
10113
|
+
}
|
|
10114
|
+
getStmtUpdateMeta() {
|
|
10115
|
+
return this.stmtUpdateMeta ??= this.database.prepare(
|
|
10116
|
+
"INSERT INTO runtime_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value"
|
|
10117
|
+
);
|
|
10118
|
+
}
|
|
10119
|
+
getStmtUpdateState() {
|
|
10120
|
+
return this.stmtUpdateState ??= this.database.prepare(
|
|
10121
|
+
"UPDATE runtime_state SET state_json = ? WHERE singleton = ?"
|
|
10122
|
+
);
|
|
10123
|
+
}
|
|
10124
|
+
persistChanges(tracker, memory) {
|
|
10125
|
+
for (const agent of tracker.upsertedAgents.values()) {
|
|
10126
|
+
this.getStmtUpsertAgent().run(
|
|
10127
|
+
agent.id,
|
|
10128
|
+
agent.metadata === void 0 ? null : JSON.stringify(agent.metadata),
|
|
10129
|
+
agent.currentConfigToken ?? null,
|
|
10130
|
+
agent.currentConfigIdentity ?? null,
|
|
10131
|
+
agent.createdAt,
|
|
10132
|
+
agent.activatedAt ?? null,
|
|
10133
|
+
agent.updatedAt
|
|
10134
|
+
);
|
|
10135
|
+
}
|
|
10136
|
+
for (const agentId of tracker.deletedAgentIds) {
|
|
10137
|
+
this.getStmtDeleteAgent().run(agentId);
|
|
10138
|
+
}
|
|
10139
|
+
for (const run of tracker.upsertedRuns.values()) {
|
|
10140
|
+
this.getStmtUpsertRun().run(
|
|
10141
|
+
run.id,
|
|
10142
|
+
run.agentId,
|
|
10143
|
+
run.agentSequence,
|
|
10144
|
+
run.state,
|
|
10145
|
+
run.revision,
|
|
10146
|
+
JSON.stringify(run),
|
|
10147
|
+
run.createdAt,
|
|
10148
|
+
run.updatedAt
|
|
10149
|
+
);
|
|
10150
|
+
}
|
|
10151
|
+
for (const runId of tracker.deletedRunIds) {
|
|
10152
|
+
this.getStmtDeleteRun().run(runId);
|
|
10153
|
+
}
|
|
10154
|
+
for (const message of tracker.insertedMessages.values()) {
|
|
10155
|
+
this.getStmtInsertMessage().run(
|
|
10156
|
+
message.id,
|
|
10157
|
+
message.runId,
|
|
10158
|
+
message.sequenceWithinRun,
|
|
10159
|
+
JSON.stringify(message),
|
|
10160
|
+
message.createdAt
|
|
10161
|
+
);
|
|
10162
|
+
}
|
|
10163
|
+
for (const messageId of tracker.deletedMessageIds) {
|
|
10164
|
+
this.getStmtDeleteMessage().run(messageId);
|
|
10165
|
+
}
|
|
10166
|
+
for (const toolCall of tracker.upsertedToolCalls.values()) {
|
|
10167
|
+
this.getStmtUpsertToolCall().run(
|
|
10168
|
+
toolCall.id,
|
|
10169
|
+
toolCall.runId,
|
|
10170
|
+
toolCall.executionId,
|
|
10171
|
+
toolCall.state,
|
|
10172
|
+
JSON.stringify(toolCall)
|
|
10173
|
+
);
|
|
10174
|
+
}
|
|
10175
|
+
for (const toolCallId of tracker.deletedToolCallIds) {
|
|
10176
|
+
this.getStmtDeleteToolCall().run(toolCallId);
|
|
10177
|
+
}
|
|
10178
|
+
for (const event of tracker.appendedEvents) {
|
|
10179
|
+
this.getStmtInsertEvent().run(
|
|
10180
|
+
event.id,
|
|
10181
|
+
event.runId,
|
|
10182
|
+
JSON.stringify(event),
|
|
10183
|
+
event.createdAt
|
|
10184
|
+
);
|
|
10185
|
+
}
|
|
10186
|
+
for (const eventId of tracker.truncatedEventIds) {
|
|
10187
|
+
this.getStmtDeleteEvent().run(eventId);
|
|
10188
|
+
}
|
|
10189
|
+
for (const [scope, receipt] of tracker.upsertedIdempotency) {
|
|
10190
|
+
this.getStmtUpsertIdempotency().run(
|
|
10191
|
+
scope,
|
|
10192
|
+
receipt.payload,
|
|
10193
|
+
JSON.stringify(receipt.result)
|
|
10194
|
+
);
|
|
10195
|
+
}
|
|
10196
|
+
for (const scope of tracker.deletedIdempotencyScopes) {
|
|
10197
|
+
this.getStmtDeleteIdempotency().run(scope);
|
|
10198
|
+
}
|
|
10199
|
+
for (const [key, receipt] of tracker.upsertedOperationReceipts) {
|
|
10200
|
+
this.getStmtUpsertIdempotency().run(
|
|
10201
|
+
`operation:${key}`,
|
|
10202
|
+
receipt.payload,
|
|
10203
|
+
JSON.stringify(receipt.result)
|
|
10204
|
+
);
|
|
10205
|
+
}
|
|
10206
|
+
for (const key of tracker.deletedOperationReceiptKeys) {
|
|
10207
|
+
this.getStmtDeleteIdempotency().run(`operation:${key}`);
|
|
10208
|
+
}
|
|
10209
|
+
for (const [consumerId, cursor] of tracker.upsertedConsumerCheckpoints) {
|
|
10210
|
+
this.getStmtUpsertCheckpoint().run(
|
|
10211
|
+
consumerId,
|
|
10212
|
+
Number(String(cursor).split(":").at(-1)),
|
|
10213
|
+
null,
|
|
10214
|
+
(/* @__PURE__ */ new Date()).toISOString()
|
|
10215
|
+
);
|
|
10216
|
+
}
|
|
10217
|
+
for (const consumerId of tracker.deletedConsumerCheckpoints) {
|
|
10218
|
+
this.getStmtDeleteCheckpoint().run(consumerId);
|
|
10219
|
+
}
|
|
10220
|
+
if (tracker.retentionFloorChanged !== void 0) {
|
|
10221
|
+
this.getStmtUpdateMeta().run(RETENTION_FLOOR_KEY, String(tracker.retentionFloorChanged));
|
|
10222
|
+
}
|
|
10223
|
+
this.getStmtUpdateState().run(JSON.stringify(memory.exportMetadata()), STATE_ROW);
|
|
10224
|
+
}
|
|
10225
|
+
writeFullStateToTables(memory) {
|
|
10226
|
+
const state = memory.exportState();
|
|
9533
10227
|
this.database.run(
|
|
9534
10228
|
"INSERT INTO runtime_meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value",
|
|
9535
10229
|
[RETENTION_FLOOR_KEY, String(Math.max(1, state.retentionFloor ?? 1))]
|
|
@@ -9538,57 +10232,149 @@ var SqliteStore = class {
|
|
|
9538
10232
|
this.database.run(`DELETE FROM ${table}`);
|
|
9539
10233
|
}
|
|
9540
10234
|
for (const agent of state.agents) {
|
|
9541
|
-
this.
|
|
9542
|
-
|
|
9543
|
-
|
|
10235
|
+
this.getStmtUpsertAgent().run(
|
|
10236
|
+
agent.id,
|
|
10237
|
+
agent.metadata === void 0 ? null : JSON.stringify(agent.metadata),
|
|
10238
|
+
agent.currentConfigToken ?? null,
|
|
10239
|
+
agent.currentConfigIdentity ?? null,
|
|
10240
|
+
agent.createdAt,
|
|
10241
|
+
agent.activatedAt ?? null,
|
|
10242
|
+
agent.updatedAt
|
|
9544
10243
|
);
|
|
9545
10244
|
}
|
|
9546
10245
|
for (const run of state.runs) {
|
|
9547
|
-
this.
|
|
9548
|
-
|
|
9549
|
-
|
|
10246
|
+
this.getStmtUpsertRun().run(
|
|
10247
|
+
run.id,
|
|
10248
|
+
run.agentId,
|
|
10249
|
+
run.agentSequence,
|
|
10250
|
+
run.state,
|
|
10251
|
+
run.revision,
|
|
10252
|
+
JSON.stringify(run),
|
|
10253
|
+
run.createdAt,
|
|
10254
|
+
run.updatedAt
|
|
9550
10255
|
);
|
|
9551
10256
|
}
|
|
9552
10257
|
for (const message of state.messages) {
|
|
9553
|
-
this.
|
|
9554
|
-
|
|
9555
|
-
|
|
10258
|
+
this.getStmtInsertMessage().run(
|
|
10259
|
+
message.id,
|
|
10260
|
+
message.runId,
|
|
10261
|
+
message.sequenceWithinRun,
|
|
10262
|
+
JSON.stringify(message),
|
|
10263
|
+
message.createdAt
|
|
9556
10264
|
);
|
|
9557
10265
|
}
|
|
9558
10266
|
for (const toolCall of state.toolCalls) {
|
|
9559
|
-
this.
|
|
9560
|
-
|
|
9561
|
-
|
|
10267
|
+
this.getStmtUpsertToolCall().run(
|
|
10268
|
+
toolCall.id,
|
|
10269
|
+
toolCall.runId,
|
|
10270
|
+
toolCall.executionId,
|
|
10271
|
+
toolCall.state,
|
|
10272
|
+
JSON.stringify(toolCall)
|
|
9562
10273
|
);
|
|
9563
10274
|
}
|
|
9564
10275
|
for (const event of state.events) {
|
|
9565
|
-
this.
|
|
9566
|
-
|
|
9567
|
-
|
|
10276
|
+
this.getStmtInsertEvent().run(
|
|
10277
|
+
event.id,
|
|
10278
|
+
event.runId,
|
|
10279
|
+
JSON.stringify(event),
|
|
10280
|
+
event.createdAt
|
|
9568
10281
|
);
|
|
9569
10282
|
}
|
|
9570
10283
|
for (const [scope, receipt] of state.idempotency) {
|
|
9571
|
-
this.
|
|
9572
|
-
|
|
9573
|
-
|
|
10284
|
+
this.getStmtUpsertIdempotency().run(
|
|
10285
|
+
scope,
|
|
10286
|
+
receipt.payload,
|
|
10287
|
+
JSON.stringify(receipt.result)
|
|
9574
10288
|
);
|
|
9575
10289
|
}
|
|
9576
10290
|
for (const [scope, receipt] of state.operationReceipts) {
|
|
9577
|
-
this.
|
|
9578
|
-
|
|
9579
|
-
|
|
10291
|
+
this.getStmtUpsertIdempotency().run(
|
|
10292
|
+
`operation:${scope}`,
|
|
10293
|
+
receipt.payload,
|
|
10294
|
+
JSON.stringify(receipt.result)
|
|
9580
10295
|
);
|
|
9581
10296
|
}
|
|
9582
10297
|
for (const [consumerId, cursor] of state.consumerCheckpoints ?? []) {
|
|
9583
|
-
this.
|
|
9584
|
-
|
|
9585
|
-
|
|
10298
|
+
this.getStmtUpsertCheckpoint().run(
|
|
10299
|
+
consumerId,
|
|
10300
|
+
Number(String(cursor).split(":").at(-1)),
|
|
10301
|
+
null,
|
|
10302
|
+
(/* @__PURE__ */ new Date()).toISOString()
|
|
9586
10303
|
);
|
|
9587
10304
|
}
|
|
9588
|
-
this.
|
|
10305
|
+
this.getStmtUpdateState().run(JSON.stringify(memory.exportMetadata()), STATE_ROW);
|
|
10306
|
+
this.mirrorInitialState(state);
|
|
10307
|
+
}
|
|
10308
|
+
mirrorChanges(tracker) {
|
|
10309
|
+
for (const agentId of tracker.deletedAgentIds) {
|
|
10310
|
+
const idStr = String(agentId);
|
|
10311
|
+
rmSync(join6(this.archiveRoot, idStr), { recursive: true, force: true });
|
|
10312
|
+
this.mirroredEventIds.delete(idStr);
|
|
10313
|
+
this.mirroredCompactionIds.delete(idStr);
|
|
10314
|
+
this.mirroredAgents.delete(idStr);
|
|
10315
|
+
}
|
|
10316
|
+
for (const agent of tracker.upsertedAgents.values()) {
|
|
10317
|
+
const idStr = String(agent.id);
|
|
10318
|
+
this.mirroredAgents.add(idStr);
|
|
10319
|
+
const archiveDir = join6(this.archiveRoot, idStr);
|
|
10320
|
+
const toolDir = join6(archiveDir, "tool-results");
|
|
10321
|
+
mkdirSync(toolDir, { recursive: true, mode: 448 });
|
|
10322
|
+
chmodSync(archiveDir, 448);
|
|
10323
|
+
chmodSync(toolDir, 448);
|
|
10324
|
+
}
|
|
10325
|
+
if (tracker.appendedEvents.length > 0) {
|
|
10326
|
+
mkdirSync(this.archiveRoot, { recursive: true, mode: 448 });
|
|
10327
|
+
chmodSync(this.archiveRoot, 448);
|
|
10328
|
+
const eventsByAgent = /* @__PURE__ */ new Map();
|
|
10329
|
+
for (const event of tracker.appendedEvents) {
|
|
10330
|
+
const agentId = String(event.agentId);
|
|
10331
|
+
let list = eventsByAgent.get(agentId);
|
|
10332
|
+
if (!list) {
|
|
10333
|
+
list = [];
|
|
10334
|
+
eventsByAgent.set(agentId, list);
|
|
10335
|
+
}
|
|
10336
|
+
list.push(event);
|
|
10337
|
+
}
|
|
10338
|
+
for (const [agentId, events] of eventsByAgent) {
|
|
10339
|
+
const archiveDir = join6(this.archiveRoot, agentId);
|
|
10340
|
+
const toolDir = join6(archiveDir, "tool-results");
|
|
10341
|
+
mkdirSync(toolDir, { recursive: true, mode: 448 });
|
|
10342
|
+
chmodSync(archiveDir, 448);
|
|
10343
|
+
chmodSync(toolDir, 448);
|
|
10344
|
+
const sessionPath = join6(archiveDir, "session.jsonl");
|
|
10345
|
+
try {
|
|
10346
|
+
chmodSync(sessionPath, 384);
|
|
10347
|
+
} catch {
|
|
10348
|
+
}
|
|
10349
|
+
const known = this.mirroredEventIds.get(agentId) ?? /* @__PURE__ */ new Set();
|
|
10350
|
+
const newEvents = events.filter((e) => !known.has(String(e.id)));
|
|
10351
|
+
if (newEvents.length > 0) {
|
|
10352
|
+
const lines = newEvents.map((e) => JSON.stringify({ schemaVersion: 1, kind: "rowan_event", event: e }) + "\n").join("");
|
|
10353
|
+
appendFileSync(sessionPath, lines, { encoding: "utf8", mode: 384 });
|
|
10354
|
+
chmodSync(sessionPath, 384);
|
|
10355
|
+
for (const e of newEvents) known.add(String(e.id));
|
|
10356
|
+
this.mirroredEventIds.set(agentId, known);
|
|
10357
|
+
}
|
|
10358
|
+
}
|
|
10359
|
+
}
|
|
10360
|
+
if (tracker.upsertedContextCompactions.size > 0) {
|
|
10361
|
+
for (const [agentId, record] of tracker.upsertedContextCompactions) {
|
|
10362
|
+
const idStr = String(agentId);
|
|
10363
|
+
const archiveDir = join6(this.archiveRoot, idStr);
|
|
10364
|
+
const sessionPath = join6(archiveDir, "session.jsonl");
|
|
10365
|
+
const knownCompactions = this.mirroredCompactionIds.get(idStr) ?? /* @__PURE__ */ new Set();
|
|
10366
|
+
if (!knownCompactions.has(record.id)) {
|
|
10367
|
+
const line = JSON.stringify({ schemaVersion: 1, kind: "context_compacted", record }) + "\n";
|
|
10368
|
+
appendFileSync(sessionPath, line, { encoding: "utf8", mode: 384 });
|
|
10369
|
+
chmodSync(sessionPath, 384);
|
|
10370
|
+
knownCompactions.add(record.id);
|
|
10371
|
+
this.mirroredCompactionIds.set(idStr, knownCompactions);
|
|
10372
|
+
}
|
|
10373
|
+
}
|
|
10374
|
+
}
|
|
9589
10375
|
}
|
|
9590
10376
|
/** Append the semantic durable event mirror and remove deleted Agent sidecars. */
|
|
9591
|
-
|
|
10377
|
+
mirrorInitialState(state) {
|
|
9592
10378
|
mkdirSync(this.archiveRoot, { recursive: true, mode: 448 });
|
|
9593
10379
|
chmodSync(this.archiveRoot, 448);
|
|
9594
10380
|
const currentAgents = new Set(state.agents.map((agent) => String(agent.id)));
|
|
@@ -9740,6 +10526,9 @@ var SqliteOwnedStore = class {
|
|
|
9740
10526
|
commitPhaseEntered(input) {
|
|
9741
10527
|
return this.store.commitPhaseEntered(this.lease, input);
|
|
9742
10528
|
}
|
|
10529
|
+
commitPhaseOutput(input) {
|
|
10530
|
+
return this.store.commitPhaseOutput(this.lease, input);
|
|
10531
|
+
}
|
|
9743
10532
|
commitInputRequired(input) {
|
|
9744
10533
|
return this.store.commitInputRequired(this.lease, input);
|
|
9745
10534
|
}
|
|
@@ -9805,19 +10594,6 @@ function ownerLease(row) {
|
|
|
9805
10594
|
expiresAt: new Date(row.expires_at).toISOString()
|
|
9806
10595
|
};
|
|
9807
10596
|
}
|
|
9808
|
-
function parseEventCursor(lease, cursor) {
|
|
9809
|
-
const value = String(cursor);
|
|
9810
|
-
const separator = value.lastIndexOf(":");
|
|
9811
|
-
const incarnation = separator < 0 ? "" : value.slice(0, separator);
|
|
9812
|
-
const sequence = separator < 0 ? "" : value.slice(separator + 1);
|
|
9813
|
-
const token = String(lease.token);
|
|
9814
|
-
const ownerSuffix = `:${lease.epoch}:${lease.ownerId}`;
|
|
9815
|
-
const expectedIncarnation = token.endsWith(ownerSuffix) ? token.slice(0, -ownerSuffix.length) : "";
|
|
9816
|
-
if (incarnation !== expectedIncarnation || !/^\d+$/.test(sequence)) {
|
|
9817
|
-
throw new RuntimeError("invalid_cursor", { cursorType: "event", reason: "wrong_store" });
|
|
9818
|
-
}
|
|
9819
|
-
return Number(sequence);
|
|
9820
|
-
}
|
|
9821
10597
|
function ownershipLost2(lease, row) {
|
|
9822
10598
|
return new RuntimeError("runtime_ownership_lost", {
|
|
9823
10599
|
reason: row.epoch > lease.epoch ? "epoch_advanced" : row.owner_id ? "released" : "released",
|