@moxt-ai/mobius 0.0.411 → 0.0.413

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.
Files changed (26) hide show
  1. package/dist/{chunk-EX66DFKM.js → chunk-CODQ63O2.js} +2 -2
  2. package/dist/{chunk-EX66DFKM.js.map → chunk-CODQ63O2.js.map} +1 -1
  3. package/dist/{chunk-6BQX2L5A.js → chunk-RROKC2HZ.js} +105 -49
  4. package/dist/{chunk-6BQX2L5A.js.map → chunk-RROKC2HZ.js.map} +3 -3
  5. package/dist/{cli-4QU22MGP.js → cli-F67ZNI2N.js} +3 -3
  6. package/dist/cli.js +2 -2
  7. package/dist/engine/runtime/command/registry/interactions.d.ts.map +1 -1
  8. package/dist/engine/runtime/command/registry/interactions.js +11 -2
  9. package/dist/engine/runtime/command/registry/interactions.js.map +1 -1
  10. package/dist/engine/runtime/command/registry/prompt.d.ts.map +1 -1
  11. package/dist/engine/runtime/command/registry/prompt.js +8 -7
  12. package/dist/engine/runtime/command/registry/prompt.js.map +1 -1
  13. package/dist/engine/session/api/session-layer.d.ts.map +1 -1
  14. package/dist/engine/session/api/session-layer.js +12 -4
  15. package/dist/engine/session/api/session-layer.js.map +1 -1
  16. package/dist/engine/session/prompt/prompt-lifecycle.d.ts +9 -3
  17. package/dist/engine/session/prompt/prompt-lifecycle.d.ts.map +1 -1
  18. package/dist/engine/session/prompt/prompt-lifecycle.js +33 -9
  19. package/dist/engine/session/prompt/prompt-lifecycle.js.map +1 -1
  20. package/dist/engine/session/turn/execution-receipts.d.ts +41 -8
  21. package/dist/engine/session/turn/execution-receipts.d.ts.map +1 -1
  22. package/dist/engine/session/turn/execution-receipts.js +48 -25
  23. package/dist/engine/session/turn/execution-receipts.js.map +1 -1
  24. package/dist/engine.js +2 -2
  25. package/package.json +2 -2
  26. /package/dist/{cli-4QU22MGP.js.map → cli-F67ZNI2N.js.map} +0 -0
@@ -80,7 +80,7 @@ var __callDispose = (stack, error, hasError) => {
80
80
  // package.json
81
81
  var package_default = {
82
82
  name: "@moxt-ai/mobius",
83
- version: "0.0.411",
83
+ version: "0.0.413",
84
84
  description: "Mobius CLI for pairing and running local AI agent services.",
85
85
  type: "module",
86
86
  bin: {
@@ -171,4 +171,4 @@ export {
171
171
  __callDispose,
172
172
  package_default
173
173
  };
174
- //# sourceMappingURL=chunk-EX66DFKM.js.map
174
+ //# sourceMappingURL=chunk-CODQ63O2.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../package.json"],
4
- "sourcesContent": ["{\n \"name\": \"@moxt-ai/mobius\",\n \"version\": \"0.0.411\",\n \"description\": \"Mobius CLI for pairing and running local AI agent services.\",\n \"type\": \"module\",\n \"bin\": {\n \"mobius\": \"dist/cli.js\"\n },\n \"exports\": {\n \"./engine\": {\n \"mobius-source\": \"./src/exports/engine.ts\",\n \"types\": \"./dist/exports/engine.d.ts\",\n \"default\": \"./dist/engine.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"NOTICE\",\n \"THIRD-PARTY-NOTICES.txt\"\n ],\n \"engines\": {\n \"node\": \">=22.19.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"exports\": {\n \"./engine\": {\n \"types\": \"./dist/exports/engine.d.ts\",\n \"import\": \"./dist/engine.js\",\n \"default\": \"./dist/engine.js\"\n }\n }\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/moxt-ai/mobius.git\",\n \"directory\": \"packages/cli\"\n },\n \"scripts\": {\n \"prebuild\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"build\": \"node scripts/build.ts && tsc --project tsconfig.build.json\",\n \"dev\": \"node --watch src/cli/entrypoint.ts\",\n \"pretypecheck\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"prepack\": \"pnpm build\",\n \"start\": \"node dist/cli.js\",\n \"typecheck\": \"tsc --project tsconfig.json && tsc --project tests/tsconfig.json\",\n \"pretest:controlled\": \"pnpm build\",\n \"test:controlled\": \"vitest run tests/sessions tests/runtime\",\n \"pretest:manual\": \"pnpm pretest:controlled\",\n \"test:manual\": \"vitest run tests/manual\",\n \"pretest:agents\": \"pnpm build\",\n \"test:agents\": \"vitest run tests/agents --maxWorkers=2\",\n \"pretest:pressure\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"test:pressure\": \"node tests/pressure/concurrent-sessions.mjs\"\n },\n \"dependencies\": {\n \"@agentclientprotocol/sdk\": \"^1.4.0\",\n \"@anthropic-ai/claude-agent-sdk\": \"0.3.257\",\n \"commander\": \"15.0.0\",\n \"semver\": \"^7.8.5\",\n \"undici\": \"8.12.2\",\n \"zod\": \"^4.6.7\"\n },\n \"devDependencies\": {\n \"@anthropic-ai/sdk\": \"0.122.0\",\n \"@moxt-ai/mobius-sdk\": \"workspace:*\",\n \"@moxt-ai/mobius-test\": \"workspace:*\",\n \"@types/node\": \"^24.13.5\",\n \"@types/semver\": \"^7.8.0\",\n \"@types/ws\": \"^8.18.1\",\n \"drizzle-kit\": \"1.0.0-rc.4\",\n \"drizzle-orm\": \"1.0.0-rc.4\",\n \"esbuild\": \"0.28.2\",\n \"valibot\": \"1.5.0\",\n \"ws\": \"^8.21.3\"\n },\n \"keywords\": [],\n \"author\": \"Moxt\",\n \"license\": \"Apache-2.0\",\n \"bugs\": {\n \"url\": \"https://github.com/moxt-ai/mobius/issues\"\n },\n \"homepage\": \"https://github.com/moxt-ai/mobius#readme\"\n}\n"],
4
+ "sourcesContent": ["{\n \"name\": \"@moxt-ai/mobius\",\n \"version\": \"0.0.413\",\n \"description\": \"Mobius CLI for pairing and running local AI agent services.\",\n \"type\": \"module\",\n \"bin\": {\n \"mobius\": \"dist/cli.js\"\n },\n \"exports\": {\n \"./engine\": {\n \"mobius-source\": \"./src/exports/engine.ts\",\n \"types\": \"./dist/exports/engine.d.ts\",\n \"default\": \"./dist/engine.js\"\n }\n },\n \"files\": [\n \"dist\",\n \"NOTICE\",\n \"THIRD-PARTY-NOTICES.txt\"\n ],\n \"engines\": {\n \"node\": \">=22.19.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\",\n \"exports\": {\n \"./engine\": {\n \"types\": \"./dist/exports/engine.d.ts\",\n \"import\": \"./dist/engine.js\",\n \"default\": \"./dist/engine.js\"\n }\n }\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/moxt-ai/mobius.git\",\n \"directory\": \"packages/cli\"\n },\n \"scripts\": {\n \"prebuild\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"build\": \"node scripts/build.ts && tsc --project tsconfig.build.json\",\n \"dev\": \"node --watch src/cli/entrypoint.ts\",\n \"pretypecheck\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"prepack\": \"pnpm build\",\n \"start\": \"node dist/cli.js\",\n \"typecheck\": \"tsc --project tsconfig.json && tsc --project tests/tsconfig.json\",\n \"pretest:controlled\": \"pnpm build\",\n \"test:controlled\": \"vitest run tests/sessions tests/runtime\",\n \"pretest:manual\": \"pnpm pretest:controlled\",\n \"test:manual\": \"vitest run tests/manual\",\n \"pretest:agents\": \"pnpm build\",\n \"test:agents\": \"vitest run tests/agents --maxWorkers=2\",\n \"pretest:pressure\": \"tsc --project src/engine/acp/harness/claude/upstream/tsconfig.json && tsc --project src/engine/acp/harness/pi/upstream/tsconfig.json\",\n \"test:pressure\": \"node tests/pressure/concurrent-sessions.mjs\"\n },\n \"dependencies\": {\n \"@agentclientprotocol/sdk\": \"^1.4.0\",\n \"@anthropic-ai/claude-agent-sdk\": \"0.3.257\",\n \"commander\": \"15.0.0\",\n \"semver\": \"^7.8.5\",\n \"undici\": \"8.12.2\",\n \"zod\": \"^4.6.7\"\n },\n \"devDependencies\": {\n \"@anthropic-ai/sdk\": \"0.122.0\",\n \"@moxt-ai/mobius-sdk\": \"workspace:*\",\n \"@moxt-ai/mobius-test\": \"workspace:*\",\n \"@types/node\": \"^24.13.5\",\n \"@types/semver\": \"^7.8.0\",\n \"@types/ws\": \"^8.18.1\",\n \"drizzle-kit\": \"1.0.0-rc.4\",\n \"drizzle-orm\": \"1.0.0-rc.4\",\n \"esbuild\": \"0.28.2\",\n \"valibot\": \"1.5.0\",\n \"ws\": \"^8.21.3\"\n },\n \"keywords\": [],\n \"author\": \"Moxt\",\n \"license\": \"Apache-2.0\",\n \"bugs\": {\n \"url\": \"https://github.com/moxt-ai/mobius/issues\"\n },\n \"homepage\": \"https://github.com/moxt-ai/mobius#readme\"\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,EACI,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,KAAO;AAAA,IACH,QAAU;AAAA,EACd;AAAA,EACA,SAAW;AAAA,IACP,YAAY;AAAA,MACR,iBAAiB;AAAA,MACjB,OAAS;AAAA,MACT,SAAW;AAAA,IACf;AAAA,EACJ;AAAA,EACA,OAAS;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACJ;AAAA,EACA,SAAW;AAAA,IACP,MAAQ;AAAA,EACZ;AAAA,EACA,eAAiB;AAAA,IACb,QAAU;AAAA,IACV,SAAW;AAAA,MACP,YAAY;AAAA,QACR,OAAS;AAAA,QACT,QAAU;AAAA,QACV,SAAW;AAAA,MACf;AAAA,IACJ;AAAA,EACJ;AAAA,EACA,YAAc;AAAA,IACV,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,WAAa;AAAA,EACjB;AAAA,EACA,SAAW;AAAA,IACP,UAAY;AAAA,IACZ,OAAS;AAAA,IACT,KAAO;AAAA,IACP,cAAgB;AAAA,IAChB,SAAW;AAAA,IACX,OAAS;AAAA,IACT,WAAa;AAAA,IACb,sBAAsB;AAAA,IACtB,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,EACrB;AAAA,EACA,cAAgB;AAAA,IACZ,4BAA4B;AAAA,IAC5B,kCAAkC;AAAA,IAClC,WAAa;AAAA,IACb,QAAU;AAAA,IACV,QAAU;AAAA,IACV,KAAO;AAAA,EACX;AAAA,EACA,iBAAmB;AAAA,IACf,qBAAqB;AAAA,IACrB,uBAAuB;AAAA,IACvB,wBAAwB;AAAA,IACxB,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,eAAe;AAAA,IACf,eAAe;AAAA,IACf,SAAW;AAAA,IACX,SAAW;AAAA,IACX,IAAM;AAAA,EACV;AAAA,EACA,UAAY,CAAC;AAAA,EACb,QAAU;AAAA,EACV,SAAW;AAAA,EACX,MAAQ;AAAA,IACJ,KAAO;AAAA,EACX;AAAA,EACA,UAAY;AAChB;",
6
6
  "names": []
7
7
  }
@@ -3,7 +3,7 @@ import {
3
3
  __export,
4
4
  __using,
5
5
  package_default
6
- } from "./chunk-EX66DFKM.js";
6
+ } from "./chunk-CODQ63O2.js";
7
7
 
8
8
  // src/engine/runtime/relay/runtime-revocation.ts
9
9
  var runtimeRevocationCloseCode = 1008;
@@ -20804,9 +20804,10 @@ var sessionEventPayloadSchema = external_exports.discriminatedUnion("type", [
20804
20804
  external_exports.object({ payload: lifecycleMetadataSchema, type: external_exports.literal("lifecycle-metadata") }).readonly()
20805
20805
  ]);
20806
20806
  var positionSchema = external_exports.string().regex(/^(0|[1-9][0-9]*)$/);
20807
+ var mobiusMetadataFields = { omitted: external_exports.literal(true).optional(), restated: external_exports.literal(true).optional() };
20807
20808
  var sharedSessionEventFields = {
20808
20809
  eventId: identifierStringSchema,
20809
- mobiusMetadata: external_exports.object({ omitted: external_exports.literal(true).optional() }).readonly().optional(),
20810
+ mobiusMetadata: external_exports.object(mobiusMetadataFields).readonly().optional(),
20810
20811
  recordedAt: external_exports.iso.datetime({ offset: true }),
20811
20812
  sessionGenerationId: identifierStringSchema,
20812
20813
  sessionId: identifierStringSchema
@@ -20829,7 +20830,7 @@ var wireLifecyclePayloadSchema = external_exports.object({
20829
20830
  }).passthrough().readonly();
20830
20831
  var wireEventFields = {
20831
20832
  ...sessionLiveEventFields,
20832
- mobiusMetadata: external_exports.object({ omitted: external_exports.literal(true).optional() }).passthrough().readonly().optional()
20833
+ mobiusMetadata: external_exports.object(mobiusMetadataFields).passthrough().readonly().optional()
20833
20834
  };
20834
20835
  var sessionWireEventSchema = external_exports.union([
20835
20836
  external_exports.object({
@@ -88606,8 +88607,10 @@ var PromptLifecycle = class {
88606
88607
  #recordActiveTurn;
88607
88608
  #executions;
88608
88609
  #recordLifecycle;
88609
- constructor(sink, recordLifecycle, recordActiveTurn, executions) {
88610
+ #append;
88611
+ constructor(sink, recordLifecycle, append, recordActiveTurn, executions) {
88610
88612
  this.#recordLifecycle = recordLifecycle;
88613
+ this.#append = append;
88611
88614
  this.#recordActiveTurn = recordActiveTurn;
88612
88615
  this.#executions = executions;
88613
88616
  this.#sink = sink;
@@ -88646,16 +88649,20 @@ var PromptLifecycle = class {
88646
88649
  const sessionId = recorded.sessionId;
88647
88650
  if (recorded.type === "lifecycle-metadata" && isPromptTerminal(recorded.payload)) {
88648
88651
  this.#terminal.set(recorded.payload.commandId, recorded);
88649
- const pending2 = this.#publications.get(sessionId) ?? [];
88650
- pending2.push(recorded);
88651
- this.#publications.set(sessionId, pending2);
88652
+ const pending = this.#publications.get(sessionId) ?? [];
88653
+ pending.push(recorded);
88654
+ this.#publications.set(sessionId, pending);
88652
88655
  return;
88653
88656
  }
88654
- const pending = this.#publications.get(sessionId);
88657
+ this.#publishInOrder(recorded);
88658
+ };
88659
+ /** Publishes after the Session's held terminal events, so clients receive its events in order. */
88660
+ #publishInOrder = (event) => {
88661
+ const pending = this.#publications.get(event.sessionId);
88655
88662
  if (pending !== void 0) {
88656
- pending.push(recorded);
88663
+ pending.push(event);
88657
88664
  } else {
88658
- this.#sink.publish(recorded);
88665
+ this.#sink.publish(event);
88659
88666
  }
88660
88667
  };
88661
88668
  publishTerminal = (sessionId, commandId) => {
@@ -88680,13 +88687,25 @@ var PromptLifecycle = class {
88680
88687
  }
88681
88688
  this.#queued.delete(commandId);
88682
88689
  };
88683
- replayOutcome = async (sessionId, event) => {
88690
+ recordOutcome = async (sessionId, event) => {
88684
88691
  if (event.type !== "lifecycle-metadata" || !("commandId" in event.payload)) {
88685
88692
  return;
88686
88693
  }
88687
88694
  await this.#recordLifecycle(sessionId, event);
88688
88695
  this.publishTerminal(sessionId, event.payload.commandId);
88689
88696
  };
88697
+ /**
88698
+ * Publishes again an outcome a receipt already holds, for clients that missed it. The restatement is marked, so
88699
+ * Recording and status notifications do not take it for a new outcome, and it does not settle the receipt again.
88700
+ * It keeps the time the outcome was recorded, which receivers that predate the marker report as when it ended.
88701
+ */
88702
+ restateOutcome = (sessionId, { event, recordedAt }) => {
88703
+ if (event.type !== "lifecycle-metadata" || !("commandId" in event.payload)) {
88704
+ return;
88705
+ }
88706
+ const restated = this.#append(sessionId, event, recordedAt);
88707
+ this.#publishInOrder({ ...restated, mobiusMetadata: { ...restated.mobiusMetadata, restated: true } });
88708
+ };
88690
88709
  queueChanged = async (sessionId, commandId) => {
88691
88710
  await this.#recordLifecycle(sessionId, {
88692
88711
  type: "lifecycle-metadata",
@@ -88745,10 +88764,16 @@ var PromptLifecycle = class {
88745
88764
  });
88746
88765
  };
88747
88766
  async function settleAbandonedTurn(projection, operations, cancellation) {
88748
- const outcome = operations.recordCancellationBeforeAdmission(cancellation.commandId, cancellation.sessionId);
88749
- if (outcome !== void 0) {
88750
- await projection.replayOutcome(cancellation.sessionId, outcome);
88751
- return;
88767
+ const cancelled = operations.recordCancellationBeforeAdmission(cancellation.commandId, cancellation.sessionId);
88768
+ switch (cancelled.kind) {
88769
+ case "recorded":
88770
+ await projection.recordOutcome(cancellation.sessionId, cancelled.outcome);
88771
+ return;
88772
+ case "restated":
88773
+ projection.restateOutcome(cancellation.sessionId, cancelled.outcome);
88774
+ return;
88775
+ case "unavailable":
88776
+ break;
88752
88777
  }
88753
88778
  const attemptId = operations.findUnsettledAttemptId(cancellation.commandId, cancellation.sessionId);
88754
88779
  if (attemptId === null) {
@@ -88835,12 +88860,16 @@ var cancelledBeforeStartOutcome = (commandId) => ({
88835
88860
  type: "lifecycle-metadata",
88836
88861
  payload: { kind: "prompt.completed", commandId, stopReason: "cancelled", execution: "not-started" }
88837
88862
  });
88863
+ var storedOutcome = (stored) => {
88864
+ const parsed = JSON.parse(stored);
88865
+ const event = decodeKnownSessionEventPayload(parsed);
88866
+ return event === null ? void 0 : { event, recordedAt: external_exports.object({ recordedAt: external_exports.string() }).parse(parsed).recordedAt };
88867
+ };
88838
88868
  var unexpectedStanding = (standing) => {
88839
88869
  throw new Error("Unexpected command standing", { cause: standing });
88840
88870
  };
88841
88871
  var ExecutionReceipts = class {
88842
88872
  #executions = /* @__PURE__ */ new Map();
88843
- #recoveredCommands = /* @__PURE__ */ new Set();
88844
88873
  #table;
88845
88874
  #cancellations;
88846
88875
  #closing = false;
@@ -88860,7 +88889,6 @@ var ExecutionReceipts = class {
88860
88889
  if (cancelledBeforeStart(state)) {
88861
88890
  retained.push({ commandId, sessionId: identity2.sessionId });
88862
88891
  }
88863
- this.#recoveredCommands.add(commandId);
88864
88892
  }
88865
88893
  cancellations.retain(retained);
88866
88894
  }
@@ -88881,7 +88909,6 @@ var ExecutionReceipts = class {
88881
88909
  this.#executions.set(commandId, receipt);
88882
88910
  for (const evictedCommandId of evicted) {
88883
88911
  this.#executions.delete(evictedCommandId);
88884
- this.#recoveredCommands.delete(evictedCommandId);
88885
88912
  }
88886
88913
  let activeCount = 0;
88887
88914
  for (const entry of this.#executions.values()) {
@@ -88919,10 +88946,12 @@ var ExecutionReceipts = class {
88919
88946
  beginShutdown = () => {
88920
88947
  this.#closing = true;
88921
88948
  };
88922
- outcome = (commandId) => {
88949
+ outcome = (commandId) => this.restatedOutcome(commandId)?.event;
88950
+ /** The outcome the command's receipt holds, with the time it was recorded. */
88951
+ restatedOutcome = (commandId) => {
88923
88952
  const receipt = this.#executions.get(commandId);
88924
88953
  const outcome = receipt === void 0 ? null : executionOutcome(receipt.state);
88925
- return outcome === null ? void 0 : decodeKnownSessionEventPayload(JSON.parse(outcome)) ?? void 0;
88954
+ return outcome === null ? void 0 : storedOutcome(outcome);
88926
88955
  };
88927
88956
  /** The command's delivery as these receipts know it; another Session's command reads as unknown. */
88928
88957
  delivery = (commandId, sessionId) => {
@@ -89014,22 +89043,36 @@ var ExecutionReceipts = class {
89014
89043
  return unexpectedStanding(standing);
89015
89044
  }
89016
89045
  };
89017
- /** Reserves an unseen command for cancellation before a delayed prompt can claim its identity. */
89046
+ /**
89047
+ * Reserves an unseen command for cancellation before a delayed prompt can claim its identity. A command that
89048
+ * already has an outcome keeps it, and the outcome is restated rather than recorded again.
89049
+ */
89018
89050
  recordCancellationBeforeAdmission = (commandId, sessionId) => {
89019
89051
  const standing = this.#standing(commandId, sessionId);
89020
89052
  switch (standing.kind) {
89021
89053
  case "foreign":
89022
- return void 0;
89054
+ return { kind: "unavailable" };
89023
89055
  case "retryable":
89024
- case "retained":
89025
- return this.outcome(commandId);
89056
+ case "retained": {
89057
+ const outcome2 = this.restatedOutcome(commandId);
89058
+ return outcome2 === void 0 ? { kind: "unavailable" } : { kind: "restated", outcome: outcome2 };
89059
+ }
89026
89060
  case "expired":
89027
89061
  return {
89028
- type: "lifecycle-metadata",
89029
- payload: { kind: "prompt.completed", commandId, stopReason: "cancelled" }
89062
+ kind: "restated",
89063
+ outcome: {
89064
+ event: {
89065
+ type: "lifecycle-metadata",
89066
+ payload: { kind: "prompt.completed", commandId, stopReason: "cancelled" }
89067
+ },
89068
+ recordedAt: void 0
89069
+ }
89030
89070
  };
89031
89071
  case "cancelled":
89032
- return cancelledBeforeStartOutcome(commandId);
89072
+ return {
89073
+ kind: "restated",
89074
+ outcome: { event: cancelledBeforeStartOutcome(commandId), recordedAt: void 0 }
89075
+ };
89033
89076
  case "unseen":
89034
89077
  break;
89035
89078
  default:
@@ -89053,7 +89096,7 @@ var ExecutionReceipts = class {
89053
89096
  outcome: JSON.stringify({ ...outcome, recordedAt: (/* @__PURE__ */ new Date()).toISOString() })
89054
89097
  }
89055
89098
  });
89056
- return outcome;
89099
+ return { kind: "recorded", outcome };
89057
89100
  };
89058
89101
  /**
89059
89102
  * Receipts follow their command's recorded lifecycle. `prompt.started` is recorded where the command is handed
@@ -89110,14 +89153,19 @@ var ExecutionReceipts = class {
89110
89153
  if (event === null) {
89111
89154
  continue;
89112
89155
  }
89113
- const recordedAt = restoreCancellation || outcome === null ? (/* @__PURE__ */ new Date()).toISOString() : external_exports.object({ recordedAt: external_exports.string() }).parse(JSON.parse(outcome)).recordedAt;
89114
- recovered.push({ sessionId: receipt.sessionId, event, recordedAt });
89115
- if (restoreCancellation || outcome === null) {
89116
- this.#save(commandId, {
89117
- ...receipt,
89118
- state: settledExecution(receipt.state, JSON.stringify({ ...event, recordedAt }))
89119
- });
89156
+ if (!restoreCancellation && outcome !== null) {
89157
+ const restated = storedOutcome(outcome);
89158
+ if (restated !== void 0) {
89159
+ recovered.push({ kind: "restated", sessionId: receipt.sessionId, outcome: restated });
89160
+ }
89161
+ continue;
89120
89162
  }
89163
+ const recordedAt = (/* @__PURE__ */ new Date()).toISOString();
89164
+ recovered.push({ kind: "recorded", sessionId: receipt.sessionId, event, recordedAt });
89165
+ this.#save(commandId, {
89166
+ ...receipt,
89167
+ state: settledExecution(receipt.state, JSON.stringify({ ...event, recordedAt }))
89168
+ });
89121
89169
  }
89122
89170
  return recovered;
89123
89171
  };
@@ -89136,14 +89184,13 @@ var ExecutionReceipts = class {
89136
89184
  attemptId: standing.receipt.attemptId,
89137
89185
  commandId,
89138
89186
  kind: "duplicate",
89139
- outcome: this.#recoveredCommands.has(commandId) ? this.outcome(commandId) : void 0
89187
+ state: executionOutcome(standing.receipt.state) === null ? "unsettled" : "settled"
89140
89188
  };
89141
89189
  case "expired":
89142
89190
  return standing.commandHash === commandHash ? { kind: "expired" } : { kind: "conflict" };
89143
89191
  case "retryable":
89144
89192
  this.#table.remove(commandId);
89145
89193
  this.#executions.delete(commandId);
89146
- this.#recoveredCommands.delete(commandId);
89147
89194
  return this.claimExecution(commandId, sessionId, commandJson);
89148
89195
  case "unseen":
89149
89196
  break;
@@ -89171,7 +89218,6 @@ var ExecutionReceipts = class {
89171
89218
  };
89172
89219
  close = () => {
89173
89220
  this.#executions.clear();
89174
- this.#recoveredCommands.clear();
89175
89221
  this.#cancellations.close();
89176
89222
  };
89177
89223
  };
@@ -89833,6 +89879,7 @@ function buildSessionLayer(options) {
89833
89879
  eventProjection.record(recorded);
89834
89880
  return true;
89835
89881
  },
89882
+ (sessionId, event, recordedAt) => events.append(sessionId, event, recordedAt),
89836
89883
  activeSessions.recordSessionEvent,
89837
89884
  operations
89838
89885
  );
@@ -89869,8 +89916,15 @@ function buildSessionLayer(options) {
89869
89916
  };
89870
89917
  }
89871
89918
  );
89872
- for (const { sessionId, event, recordedAt } of operations.recover()) {
89873
- sink.publish(events.append(sessionId, event, recordedAt));
89919
+ for (const recovered of operations.recover()) {
89920
+ switch (recovered.kind) {
89921
+ case "recorded":
89922
+ sink.publish(events.append(recovered.sessionId, recovered.event, recovered.recordedAt));
89923
+ break;
89924
+ case "restated":
89925
+ eventProjection.restateOutcome(recovered.sessionId, recovered.outcome);
89926
+ break;
89927
+ }
89874
89928
  }
89875
89929
  return {
89876
89930
  activeSessions,
@@ -91713,9 +91767,14 @@ var sessionCancelBeforeStartCommand = {
91713
91767
  }
91714
91768
  const turn = sessionTurns.get(message.commandId, message.sessionId);
91715
91769
  if (turn === void 0) {
91716
- const outcome = operations.recordCancellationBeforeAdmission(message.commandId, message.sessionId);
91770
+ const cancelled = operations.recordCancellationBeforeAdmission(message.commandId, message.sessionId);
91771
+ const outcome = cancelled.kind === "unavailable" ? void 0 : cancelled.kind === "restated" ? cancelled.outcome.event : cancelled.outcome;
91717
91772
  if (outcome?.type === "lifecycle-metadata" && outcome.payload.kind === "prompt.completed" && promptCompletion(outcome.payload).kind === "cancelled") {
91718
- void eventProjection.replayOutcome(message.sessionId, outcome).catch((error62) => {
91773
+ if (cancelled.kind === "restated") {
91774
+ eventProjection.restateOutcome(message.sessionId, cancelled.outcome);
91775
+ return;
91776
+ }
91777
+ void eventProjection.recordOutcome(message.sessionId, outcome).catch((error62) => {
91719
91778
  reportOperationFailure(socket, message.commandId, message.sessionId, error62);
91720
91779
  });
91721
91780
  return;
@@ -92278,18 +92337,15 @@ var sessionPromptCommand = {
92278
92337
  return;
92279
92338
  }
92280
92339
  if (receipt.kind === "duplicate") {
92281
- const outcome = receipt.outcome;
92282
- const original = context.sessionTurns.get(message.commandId, message.sessionId);
92283
92340
  send(context.socket, {
92284
92341
  kind: "session.prompt.accepted",
92285
92342
  requestId: message.commandId,
92286
92343
  sessionId: message.sessionId,
92287
- state: outcome !== void 0 ? "settled" : original?.isQueued() === true ? "queued" : "running"
92344
+ state: receipt.state === "settled" ? "settled" : context.sessionTurns.get(message.commandId, message.sessionId)?.isQueued() === true ? "queued" : "running"
92288
92345
  });
92346
+ const outcome = receipt.state === "settled" ? context.operations.restatedOutcome(message.commandId) : void 0;
92289
92347
  if (outcome !== void 0) {
92290
- void context.eventProjection.replayOutcome(message.sessionId, outcome).catch((cause) => {
92291
- console.error("Could not replay the persisted execution outcome", cause);
92292
- });
92348
+ context.eventProjection.restateOutcome(message.sessionId, outcome);
92293
92349
  }
92294
92350
  return;
92295
92351
  }
@@ -94010,4 +94066,4 @@ export {
94010
94066
  * MIT Licensed
94011
94067
  *)
94012
94068
  */
94013
- //# sourceMappingURL=chunk-6BQX2L5A.js.map
94069
+ //# sourceMappingURL=chunk-RROKC2HZ.js.map