@spine-event-engine/server 2.0.0-snapshot.23 → 2.0.0-snapshot.24

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 (104) hide show
  1. package/REFERENCE.md +89 -23
  2. package/dist/bus/event-bus.d.ts +65 -100
  3. package/dist/bus/event-bus.d.ts.map +1 -1
  4. package/dist/bus/event-bus.js +46 -116
  5. package/dist/bus/event-bus.js.map +1 -1
  6. package/dist/bus/saved-dispatcher-binding.d.ts +1 -44
  7. package/dist/bus/saved-dispatcher-binding.d.ts.map +1 -1
  8. package/dist/bus/saved-dispatcher-binding.js +0 -8
  9. package/dist/bus/saved-dispatcher-binding.js.map +1 -1
  10. package/dist/context/bounded-context.d.ts +9 -10
  11. package/dist/context/bounded-context.d.ts.map +1 -1
  12. package/dist/context/bounded-context.js +64 -43
  13. package/dist/context/bounded-context.js.map +1 -1
  14. package/dist/context/entity-inbox.d.ts.map +1 -1
  15. package/dist/context/entity-inbox.js +21 -7
  16. package/dist/context/entity-inbox.js.map +1 -1
  17. package/dist/context/local-inbox-handoff.d.ts +1 -0
  18. package/dist/context/local-inbox-handoff.d.ts.map +1 -1
  19. package/dist/context/local-inbox-handoff.js +31 -1
  20. package/dist/context/local-inbox-handoff.js.map +1 -1
  21. package/dist/context/projection-handoff.d.ts.map +1 -1
  22. package/dist/context/projection-handoff.js +2 -0
  23. package/dist/context/projection-handoff.js.map +1 -1
  24. package/dist/delivery/delivery-monitor.d.ts +12 -9
  25. package/dist/delivery/delivery-monitor.d.ts.map +1 -1
  26. package/dist/delivery/delivery-monitor.js +15 -9
  27. package/dist/delivery/delivery-monitor.js.map +1 -1
  28. package/dist/delivery/delivery-ports.d.ts +6 -13
  29. package/dist/delivery/delivery-ports.d.ts.map +1 -1
  30. package/dist/delivery/delivery-run-control.d.ts +15 -0
  31. package/dist/delivery/delivery-run-control.d.ts.map +1 -1
  32. package/dist/delivery/delivery-run-control.js.map +1 -1
  33. package/dist/delivery/delivery-supervisor.d.ts +33 -5
  34. package/dist/delivery/delivery-supervisor.d.ts.map +1 -1
  35. package/dist/delivery/delivery-supervisor.js +150 -22
  36. package/dist/delivery/delivery-supervisor.js.map +1 -1
  37. package/dist/delivery/delivery.d.ts.map +1 -1
  38. package/dist/delivery/delivery.js +128 -54
  39. package/dist/delivery/delivery.js.map +1 -1
  40. package/dist/delivery/inbox-storage.d.ts +8 -11
  41. package/dist/delivery/inbox-storage.d.ts.map +1 -1
  42. package/dist/delivery/inbox-storage.js +33 -76
  43. package/dist/delivery/inbox-storage.js.map +1 -1
  44. package/dist/delivery/inbox.d.ts +9 -12
  45. package/dist/delivery/inbox.d.ts.map +1 -1
  46. package/dist/delivery/inbox.js +10 -13
  47. package/dist/delivery/inbox.js.map +1 -1
  48. package/dist/delivery/reception-observation.d.ts +56 -0
  49. package/dist/delivery/reception-observation.d.ts.map +1 -0
  50. package/dist/delivery/reception-observation.js +67 -0
  51. package/dist/delivery/reception-observation.js.map +1 -0
  52. package/dist/repository/repository.d.ts +3 -4
  53. package/dist/repository/repository.d.ts.map +1 -1
  54. package/dist/repository/repository.js +155 -166
  55. package/dist/repository/repository.js.map +1 -1
  56. package/dist/runtime/runtime.d.ts +11 -0
  57. package/dist/runtime/runtime.d.ts.map +1 -1
  58. package/dist/runtime/runtime.js +13 -0
  59. package/dist/runtime/runtime.js.map +1 -1
  60. package/dist/runtime/signal-metadata.d.ts.map +1 -1
  61. package/dist/runtime/signal-metadata.js +3 -10
  62. package/dist/runtime/signal-metadata.js.map +1 -1
  63. package/dist/runtime/signal-publisher.d.ts +11 -33
  64. package/dist/runtime/signal-publisher.d.ts.map +1 -1
  65. package/dist/runtime/signal-publisher.js +70 -55
  66. package/dist/runtime/signal-publisher.js.map +1 -1
  67. package/dist/runtime/standalone-handler-runtime.d.ts.map +1 -1
  68. package/dist/runtime/standalone-handler-runtime.js +1 -31
  69. package/dist/runtime/standalone-handler-runtime.js.map +1 -1
  70. package/dist/server/environment-delivery-worker.d.ts.map +1 -1
  71. package/dist/server/environment-delivery-worker.js +305 -5
  72. package/dist/server/environment-delivery-worker.js.map +1 -1
  73. package/dist/server/managed-server-application.d.ts +2 -2
  74. package/dist/server/managed-server-application.d.ts.map +1 -1
  75. package/dist/server/managed-server-application.js +467 -177
  76. package/dist/server/managed-server-application.js.map +1 -1
  77. package/dist/server/node-coordinator.d.ts +14 -0
  78. package/dist/server/node-coordinator.d.ts.map +1 -1
  79. package/dist/server/node-coordinator.js +266 -45
  80. package/dist/server/node-coordinator.js.map +1 -1
  81. package/dist/server/server-log.d.ts.map +1 -1
  82. package/dist/server/server-log.js +4 -0
  83. package/dist/server/server-log.js.map +1 -1
  84. package/dist/server/server.js +20 -7
  85. package/dist/server/server.js.map +1 -1
  86. package/dist/services/spine-services.d.ts.map +1 -1
  87. package/dist/services/spine-services.js +200 -72
  88. package/dist/services/spine-services.js.map +1 -1
  89. package/dist/stand/event-origin-filter.d.ts +16 -0
  90. package/dist/stand/event-origin-filter.d.ts.map +1 -0
  91. package/dist/stand/event-origin-filter.js +124 -0
  92. package/dist/stand/event-origin-filter.js.map +1 -0
  93. package/dist/stand/subscription-observer.d.ts.map +1 -1
  94. package/dist/stand/subscription-observer.js +7 -0
  95. package/dist/stand/subscription-observer.js.map +1 -1
  96. package/dist/stand/subscription-runtime.d.ts +18 -1
  97. package/dist/stand/subscription-runtime.d.ts.map +1 -1
  98. package/dist/stand/subscription-runtime.js +32 -4
  99. package/dist/stand/subscription-runtime.js.map +1 -1
  100. package/dist/testing/index.d.ts.map +1 -1
  101. package/dist/testing/index.js +2 -2
  102. package/dist/testing/index.js.map +1 -1
  103. package/dist/tsconfig.tsbuildinfo +1 -1
  104. package/package.json +15 -15
@@ -19,13 +19,13 @@ import { CommandContextSchema, ActorContextSchema, CommandIdSchema, CommandSchem
19
19
  import * as EntityLog from "@spine-event-engine/proto/generated/spine/system/server/entity_log_events_pb.js";
20
20
  import { EntityTypeNameSchema } from "@spine-event-engine/proto/generated/spine/system/server/entity_type_pb.js";
21
21
  import { EntityRecordSchema, } from "@spine-event-engine/proto/generated/spine/server/entity/entity_pb.js";
22
- import { StorageQueryPolicy, } from "@spine-event-engine/storage";
22
+ import { EventStore, StorageQueryPolicy, } from "@spine-event-engine/storage";
23
23
  import { TenantBoundary } from "@spine-event-engine/storage/provider";
24
24
  import { EntityCommitStorageFactories } from "@spine-event-engine/storage/provider";
25
25
  import { AgentHistoryStorageFactories, } from "@spine-event-engine/storage/provider";
26
26
  import { AgentExecutionStorageFactories, } from "@spine-event-engine/storage/provider";
27
27
  import { AgentHistoryEntrySchema, AgentInvocationTerminatedSchema, AgentModelSelectionChangedSchema as SelectionChangedSchema, AiModelKind, AiDiagnosticIdSchema, ModelRefSchema, ToolEffect, ConversationIdSchema, } from "@spine-event-engine/proto/agent";
28
- import { AgentInvocationKeySchema, AgentExecutionStartSchema, AgentExecutionCompletionSchema, AgentInvocationBoundsSchema, AgentInvocationStatus, AgentOutgoingSignalSchema, AgentSignalKeySchema, AgentSavedDispatchTargetSchema as SavedTargetSchema, AgentSavedRepositoryFamily, AgentSavedTargetKind, } from "@spine-event-engine/proto/generated/spine/server/agent/execution_record_pb.js";
28
+ import { AgentInvocationKeySchema, AgentExecutionStartSchema, AgentExecutionCompletionSchema, AgentInvocationBoundsSchema, AgentInvocationStatus, AgentOutgoingCommandSchema, AgentSignalKeySchema, AgentSavedDispatchTargetSchema as SavedTargetSchema, AgentSavedRepositoryFamily, AgentSavedTargetKind, } from "@spine-event-engine/proto/generated/spine/server/agent/execution_record_pb.js";
29
29
  import { registryOptions } from "@spine-event-engine/ai/spi/runtime";
30
30
  import { CommandValidationError } from "../bus/command-errors.js";
31
31
  import { SignalPublisher } from "../runtime/signal-publisher.js";
@@ -38,6 +38,7 @@ import { RoutingDeclarations } from "./routing-declarations.js";
38
38
  import { EventDispatcherOriginSchemas } from "../bus/event-dispatcher-origin-schemas.js";
39
39
  import { SavedDispatcherBindings, } from "../bus/saved-dispatcher-binding.js";
40
40
  import { Delivery } from "../delivery/delivery.js";
41
+ import { receptionObservation } from "../delivery/reception-observation.js";
41
42
  import { commitFenced } from "./commit-fence.js";
42
43
  import { AgentHistoryReads } from "../agent/agent-history.js";
43
44
  import { AgentReadRuntime } from "../agent/agent-read-runtime.js";
@@ -438,8 +439,8 @@ const RepositoryAgentReads = {
438
439
  return "accepted";
439
440
  case AgentInvocationStatus.AGENT_INVOCATION_ACTIVE:
440
441
  return "active";
441
- case AgentInvocationStatus.AGENT_INVOCATION_COMPLETED_PENDING_DELIVERY:
442
- return "completed-pending-delivery";
442
+ case AgentInvocationStatus.AGENT_INVOCATION_COMPLETED_PENDING_COMMANDS:
443
+ return "completed-pending-commands";
443
444
  case AgentInvocationStatus.AGENT_INVOCATION_COMPLETED:
444
445
  return "completed";
445
446
  case AgentInvocationStatus.AGENT_INVOCATION_TERMINATED:
@@ -2024,25 +2025,32 @@ class ProcessManagerExecutionSupport {
2024
2025
  *
2025
2026
  * @param loaded Process Manager and commit storage.
2026
2027
  * @param options Stand tenant selection.
2027
- * @param events Produced or diagnostic Events to retain when configured.
2028
- * @param emitted Domain Events emitted by an Agent, excluding the source Event.
2028
+ * @param diagnostics Input and produced Events to retain when configured.
2029
+ * @param producedEvents Delivery Events to save before current state.
2029
2030
  * @returns `true` after a successful commit or unchanged no-op.
2030
2031
  */
2031
- async commit(loaded, options, events, emitted = events) {
2032
+ async commit(loaded, options, diagnostics, producedEvents) {
2032
2033
  const version = RepositoryEntities.repositoryVersion(loaded.entity);
2033
2034
  const priorNumber = loaded.current?.version?.number ?? 0;
2034
2035
  if (version.number === priorNumber) {
2035
- await this.#appendUnchangedDiagnostics(loaded, events);
2036
- await this.#appendAgentEvents(loaded, emitted);
2036
+ await this.#appendUnchangedDiagnostics(loaded, diagnostics);
2037
+ const store = new EventStore(this.#runtime.context, this.#runtime.storageFactory);
2038
+ try {
2039
+ await store.appendAll(producedEvents);
2040
+ }
2041
+ finally {
2042
+ store.close();
2043
+ }
2044
+ await this.#appendAgentEvents(loaded, producedEvents);
2037
2045
  return true;
2038
2046
  }
2039
2047
  const entityId = loaded.entity.id;
2040
2048
  const state = RepositoryEntities.repositoryState(loaded.entity);
2041
2049
  const lifecycle = RepositoryEntities.repositoryLifecycle(loaded.entity);
2042
2050
  const deferred = await standAccess.deferUpdate(this.#runtime.stand, this.#repository.stateSchema, state, RepositoryStand.standUpdateOptions(options.tenantId, version, lifecycle), this.#repository.metadata);
2043
- await this.#storeProcessManagerRecord(loaded, entityId, events, deferred);
2044
- await this.#appendAgentEvents(loaded, emitted);
2045
- this.#notifyProcessManager(deferred, events);
2051
+ await this.#storeProcessManagerRecord(loaded, entityId, diagnostics, producedEvents, deferred);
2052
+ this.#notifyProcessManager(deferred, diagnostics);
2053
+ await this.#appendAgentEvents(loaded, producedEvents);
2046
2054
  return true;
2047
2055
  }
2048
2056
  /**
@@ -2086,13 +2094,14 @@ class ProcessManagerExecutionSupport {
2086
2094
  *
2087
2095
  * @param loaded Process Manager and commit storage.
2088
2096
  * @param entityId Process Manager identifier.
2089
- * @param events Diagnostic Events to retain when configured.
2097
+ * @param diagnostics Diagnostic Events to retain when configured.
2098
+ * @param producedEvents Delivery Events to save before current state.
2090
2099
  * @param deferred Stand update to notify or cancel.
2091
2100
  * @returns Completion after durable persistence.
2092
2101
  */
2093
- async #storeProcessManagerRecord(loaded, entityId, events, deferred) {
2102
+ async #storeProcessManagerRecord(loaded, entityId, diagnostics, producedEvents, deferred) {
2094
2103
  try {
2095
- await this.#commitProcessManagerRecord(loaded, entityId, events, deferred);
2104
+ await this.#commitProcessManagerRecord(loaded, entityId, diagnostics, producedEvents, deferred);
2096
2105
  entityStateHistoryCaches.get(loaded.entity)?.clear();
2097
2106
  }
2098
2107
  catch (error) {
@@ -2105,11 +2114,12 @@ class ProcessManagerExecutionSupport {
2105
2114
  *
2106
2115
  * @param loaded Loaded Process Manager and commit storage.
2107
2116
  * @param entityId Process Manager identifier.
2108
- * @param events Diagnostic Events to retain when configured.
2117
+ * @param diagnostics Diagnostic Events to retain when configured.
2118
+ * @param producedEvents Delivery Events to save before current state.
2109
2119
  * @param deferred Stand update containing the prepared record.
2110
2120
  * @returns Completion after the storage commit.
2111
2121
  */
2112
- #commitProcessManagerRecord(loaded, entityId, events, deferred) {
2122
+ #commitProcessManagerRecord(loaded, entityId, diagnostics, producedEvents, deferred) {
2113
2123
  const history = RepositoryStorage.historyConfiguration(this.#repository);
2114
2124
  const record = RepositoryStand.preparedRecord(this.#repository, deferred, entityId);
2115
2125
  return loaded.commits.commit({
@@ -2119,8 +2129,9 @@ class ProcessManagerExecutionSupport {
2119
2129
  next: record,
2120
2130
  ...(history.stateHistory ? { states: [record] } : {}),
2121
2131
  ...(history.processManagerEventHistory
2122
- ? { diagnostics: events.map((event) => clone(EventSchema, event)) }
2132
+ ? { diagnostics: diagnostics.map((event) => clone(EventSchema, event)) }
2123
2133
  : {}),
2134
+ events: producedEvents.map((event) => clone(EventSchema, event)),
2124
2135
  });
2125
2136
  }
2126
2137
  /**
@@ -2217,7 +2228,9 @@ const AgentExecutionRunner = {
2217
2228
  * @returns When the fenced repository operation completes.
2218
2229
  */
2219
2230
  async handleRunFailure(repository, runtime, tenantId, session, error) {
2220
- if (session.record().status === AgentInvocationStatus.AGENT_INVOCATION_COMPLETED_PENDING_DELIVERY)
2231
+ if (session.record().status ===
2232
+ AgentInvocationStatus.AGENT_INVOCATION_COMPLETED_PENDING_COMMANDS ||
2233
+ session.record().status === AgentInvocationStatus.AGENT_INVOCATION_COMPLETED)
2221
2234
  throw error;
2222
2235
  if (error instanceof AgentUncertainAttemptError) {
2223
2236
  const reason = this.hasUnresolvedToolWrite(session.record())
@@ -2248,8 +2261,8 @@ const AgentExecutionRunner = {
2248
2261
  return this.terminate(repository, runtime, tenantId, session, this.hasUnresolvedToolWrite(session.record())
2249
2262
  ? "TOOL_OUTCOME_UNKNOWN"
2250
2263
  : "MODEL_OUTCOME_UNKNOWN");
2251
- if (session.record().status === AgentInvocationStatus.AGENT_INVOCATION_COMPLETED_PENDING_DELIVERY)
2252
- return this.deliver(runtime, session);
2264
+ if (session.record().status === AgentInvocationStatus.AGENT_INVOCATION_COMPLETED_PENDING_COMMANDS)
2265
+ return this.deliverCommands(runtime, session);
2253
2266
  if (this.deadlineExpired(session.record()))
2254
2267
  return this.terminate(repository, runtime, tenantId, session, "DEADLINE_EXCEEDED");
2255
2268
  return this.execute(repository, runtime, tenantId, session);
@@ -2431,9 +2444,8 @@ const AgentExecutionRunner = {
2431
2444
  : await this.selectMissingModels(repository, runtime, session, accepted, tenantId);
2432
2445
  if (session.signal.aborted)
2433
2446
  return;
2434
- const completed = await this.completeExecution(repository, runtime, tenantId, session, loaded, accepted, handlers, entityId, record.started?.initialVersion ?? create(VersionSchema));
2435
- if (completed.status === AgentInvocationStatus.AGENT_INVOCATION_COMPLETED_PENDING_DELIVERY)
2436
- await this.deliver(runtime, session);
2447
+ const outputs = await this.completeExecution(repository, runtime, tenantId, session, loaded, accepted, handlers, entityId, record.started?.initialVersion ?? create(VersionSchema));
2448
+ await this.deliverInitial(runtime, session, outputs);
2437
2449
  },
2438
2450
  /**
2439
2451
  * Creates or rejects the draft before one conditional Entity completion.
@@ -2451,7 +2463,8 @@ const AgentExecutionRunner = {
2451
2463
  */
2452
2464
  async completeExecution(repository, runtime, tenantId, session, loaded, accepted, handlers, entityId, initialVersion) {
2453
2465
  const outputs = await this.outputsOrRejection(repository, runtime, tenantId, session, loaded.entity, accepted, handlers, entityId, initialVersion);
2454
- return this.complete(repository, runtime, tenantId, session, loaded, entityId, outputs);
2466
+ await this.complete(repository, runtime, tenantId, session, loaded, entityId, outputs);
2467
+ return outputs;
2455
2468
  },
2456
2469
  /**
2457
2470
  * Rejects a Command draft and persists only its declared rejection.
@@ -2483,22 +2496,20 @@ const AgentExecutionRunner = {
2483
2496
  }
2484
2497
  },
2485
2498
  /**
2486
- * Wraps the original rejection Event as one pending saved output.
2499
+ * Wraps the original rejection Event for one normal EventBus handoff.
2487
2500
  *
2488
2501
  * @param runtime Bounded Context storage and publication services.
2489
2502
  * @param repository Registered Entity repository for this operation.
2490
2503
  * @param command Original typed Command envelope.
2491
2504
  * @param entityId Typed recipient Entity identifier.
2492
2505
  * @param error Failure raised while processing this accepted signal.
2493
- * @returns Prepared original rejection Event for durable delivery.
2506
+ * @returns Prepared original rejection Event for one normal EventBus handoff.
2494
2507
  */
2495
2508
  rejectionOutput(runtime, repository, command, entityId, error) {
2496
- return create(AgentOutgoingSignalSchema, {
2497
- signal: {
2498
- case: "event",
2499
- value: RepositorySignals.rejectionEvent(runtime, repository, command, entityId, error),
2500
- },
2501
- });
2509
+ return {
2510
+ case: "event",
2511
+ value: RepositorySignals.rejectionEvent(runtime, repository, command, entityId, error),
2512
+ };
2502
2513
  },
2503
2514
  /**
2504
2515
  * Restores handler results and binds their declared original output envelopes.
@@ -2700,15 +2711,18 @@ const AgentExecutionRunner = {
2700
2711
  const initialVersion = record.started?.initialVersion;
2701
2712
  if (initialVersion === undefined)
2702
2713
  throw new Error("Agent completion requires its started Version.");
2714
+ const commands = outputs
2715
+ .filter((output) => output.case === "command")
2716
+ .map((output) => create(AgentOutgoingCommandSchema, { command: output.value }));
2703
2717
  record.status =
2704
- outputs.length === 0
2718
+ commands.length === 0
2705
2719
  ? AgentInvocationStatus.AGENT_INVOCATION_COMPLETED
2706
- : AgentInvocationStatus.AGENT_INVOCATION_COMPLETED_PENDING_DELIVERY;
2720
+ : AgentInvocationStatus.AGENT_INVOCATION_COMPLETED_PENDING_COMMANDS;
2707
2721
  record.completion = create(AgentExecutionCompletionSchema, {
2708
2722
  initialVersion,
2709
2723
  resultingVersion: version,
2710
2724
  preferences: [...preferences],
2711
- outgoing: [...outputs],
2725
+ commands,
2712
2726
  });
2713
2727
  return record;
2714
2728
  },
@@ -2720,9 +2734,9 @@ const AgentExecutionRunner = {
2720
2734
  */
2721
2735
  emittedHistory(outputs) {
2722
2736
  return outputs.flatMap((output) => {
2723
- if (output.signal.case !== "event" || output.signal.value.context?.rejection !== undefined)
2737
+ if (output.case !== "event" || output.value.context?.rejection !== undefined)
2724
2738
  return [];
2725
- const event = output.signal.value;
2739
+ const event = output.value;
2726
2740
  const occurredAt = event.context?.timestamp;
2727
2741
  if (occurredAt === undefined)
2728
2742
  throw new Error("Agent emitted Event requires its original timestamp.");
@@ -2839,7 +2853,7 @@ const AgentExecutionRunner = {
2839
2853
  * @param version Entity version associated with the signal.
2840
2854
  * @param signal Original domain signal or execution cancellation signal.
2841
2855
  * @param schema Generated message descriptor for the signal.
2842
- * @returns Typed original Event envelope for durable delivery.
2856
+ * @returns Typed original Event envelope for one normal EventBus handoff.
2843
2857
  */
2844
2858
  bindEventOutput(repository, runtime, source, entityId, version, signal, schema) {
2845
2859
  if (source.case !== "command" && source.case !== "event")
@@ -2852,7 +2866,7 @@ const AgentExecutionRunner = {
2852
2866
  message: AnyMessages.pack(schema, signal),
2853
2867
  context: RepositorySignals.eventContextWithProducer(metadata.context, repository, entityId, version),
2854
2868
  });
2855
- return create(AgentOutgoingSignalSchema, { signal: { case: "event", value: event } });
2869
+ return { case: "event", value: event };
2856
2870
  },
2857
2871
  /**
2858
2872
  * Creates the original Command envelope from its accepted origin.
@@ -2874,66 +2888,97 @@ const AgentExecutionRunner = {
2874
2888
  message: AnyMessages.pack(schema, signal),
2875
2889
  context: metadata.context,
2876
2890
  });
2877
- return create(AgentOutgoingSignalSchema, { signal: { case: "command", value: command } });
2891
+ return { case: "command", value: command };
2878
2892
  },
2879
2893
  /**
2880
- * Publishes saved envelopes through normal bus acceptance before marking original IDs.
2894
+ * Dispatches every emitted Event to the normal EventBus and advances saved Commands.
2881
2895
  *
2882
2896
  * @param runtime Bound normal bus acceptance callbacks.
2883
2897
  * @param session Fenced record containing pending saved envelopes.
2898
+ * @param outputs Locally produced outputs in original handler order.
2884
2899
  * @returns When the fenced repository operation completes.
2885
2900
  */
2886
- async deliver(runtime, session) {
2887
- const completed = session.record();
2888
- const key = completed.accepted?.key;
2889
- if (key === undefined)
2890
- throw new Error("Agent output delivery requires its accepted key.");
2891
- for (const [index, output] of (completed.completion?.outgoing ?? []).entries()) {
2901
+ async deliverInitial(runtime, session, outputs) {
2902
+ let commandIndex = 0;
2903
+ let failed = false;
2904
+ let firstFailure;
2905
+ for (const output of outputs) {
2906
+ try {
2907
+ if (output.case === "event") {
2908
+ await runtime.publishAgentEvent(output.value);
2909
+ }
2910
+ else {
2911
+ await this.deliverCommand(runtime, session, commandIndex);
2912
+ }
2913
+ }
2914
+ catch (error) {
2915
+ if (!failed) {
2916
+ firstFailure = error;
2917
+ failed = true;
2918
+ }
2919
+ }
2920
+ if (output.case === "command")
2921
+ commandIndex += 1;
2922
+ }
2923
+ if (failed)
2924
+ throw firstFailure;
2925
+ },
2926
+ /**
2927
+ * Retries pending saved Commands without rerunning the Agent handler.
2928
+ *
2929
+ * @param runtime Bound normal Command bus callbacks.
2930
+ * @param session Fenced record containing saved Commands.
2931
+ * @returns Completion after pending Command attempts.
2932
+ */
2933
+ async deliverCommands(runtime, session) {
2934
+ for (const [index] of (session.record().completion?.commands ?? []).entries()) {
2892
2935
  if (session.signal.aborted)
2893
2936
  return;
2894
- if (output.delivered)
2895
- continue;
2896
- const signal = output.signal;
2897
- if (signal.case !== "event" && signal.case !== "command")
2898
- throw new Error("Agent outgoing signal has no original envelope.");
2899
- const key = this.outputKey(output);
2900
- const plan = output.plan ??
2901
- (await (signal.case === "event"
2902
- ? runtime.prepareSavedEvent(signal.value)
2903
- : runtime.prepareSavedCommand(signal.value)));
2904
- if (output.plan === undefined) {
2905
- await session.update((current) => {
2906
- const pending = current.completion?.outgoing[index];
2907
- if (pending?.plan !== undefined || pending?.signal.case !== signal.case)
2908
- throw new Error("Saved Agent output changed before plan installation.");
2909
- pending.plan = plan;
2910
- return current;
2911
- });
2912
- }
2913
- if (signal.case === "event")
2914
- await runtime.publishSavedEvent(signal.value, plan);
2915
- else
2916
- await runtime.publishSavedCommand(signal.value, plan);
2917
- await session.markDelivered([key]);
2918
- runtime.recordAcceptedSaved(signal.value);
2937
+ await this.deliverCommand(runtime, session, index);
2919
2938
  }
2920
2939
  },
2921
2940
  /**
2922
- * Returns the typed original ID of one completed outgoing signal.
2941
+ * Sends one saved Command under the current claim and records its acknowledgement.
2923
2942
  *
2924
- * @param output Prepared outgoing domain signal.
2925
- * @returns Original durable key for the outgoing signal.
2943
+ * @param runtime Bound normal Command bus callbacks.
2944
+ * @param session Fenced record containing saved Commands.
2945
+ * @param index Command position in the saved completion.
2946
+ * @returns Completion after the Command is acknowledged or already delivered.
2926
2947
  */
2927
- outputKey(output) {
2928
- if (output.signal.case === "event" && output.signal.value.id !== undefined)
2929
- return create(AgentSignalKeySchema, {
2930
- id: { case: "event", value: output.signal.value.id },
2931
- });
2932
- if (output.signal.case === "command" && output.signal.value.id !== undefined)
2933
- return create(AgentSignalKeySchema, {
2934
- id: { case: "command", value: output.signal.value.id },
2948
+ async deliverCommand(runtime, session, index) {
2949
+ const output = session.record().completion?.commands[index];
2950
+ if (output === undefined || output.delivered)
2951
+ return;
2952
+ const command = output.command;
2953
+ if (command === undefined)
2954
+ throw new Error("Agent outgoing Command has no original envelope.");
2955
+ const key = this.outputKey(output);
2956
+ const plan = output.plan ?? (await runtime.prepareSavedCommand(command));
2957
+ if (output.plan === undefined) {
2958
+ await session.update((current) => {
2959
+ const pending = current.completion?.commands[index];
2960
+ if (pending === undefined ||
2961
+ pending.plan !== undefined ||
2962
+ pending.command?.id?.uuid !== command.id?.uuid)
2963
+ throw new Error("Saved Agent Command changed before plan installation.");
2964
+ pending.plan = plan;
2965
+ return current;
2935
2966
  });
2936
- throw new Error("Agent outgoing signal requires its original typed ID.");
2967
+ }
2968
+ await runtime.publishSavedCommand(command, plan);
2969
+ await session.markDelivered([key]);
2970
+ runtime.recordAcceptedSaved(command);
2971
+ },
2972
+ /**
2973
+ * Returns the typed original ID of one completed outgoing Command.
2974
+ *
2975
+ * @param output Prepared outgoing Command.
2976
+ * @returns Original durable Command ID.
2977
+ */
2978
+ outputKey(output) {
2979
+ if (output.command?.id !== undefined)
2980
+ return output.command.id;
2981
+ throw new Error("Agent outgoing Command requires its original typed ID.");
2937
2982
  },
2938
2983
  /**
2939
2984
  * Validates every stored binding against the current generated selectors.
@@ -3468,7 +3513,7 @@ class ProcessManagerCommandExecution {
3468
3513
  async #commitAndPublish(loaded, tenantOptions, intake, producedSignals) {
3469
3514
  const commands = this.#commandOutputs(intake.assignee, producedSignals);
3470
3515
  const events = this.#eventOutputs(intake.assignee, producedSignals, intake.route.entityId, RepositoryEntities.priorVersion(loaded.current));
3471
- const committed = await this.#support.commit(loaded, tenantOptions, events);
3516
+ const committed = await this.#support.commit(loaded, tenantOptions, events, events);
3472
3517
  if (!committed)
3473
3518
  return undefined;
3474
3519
  this.#publishChangedState(loaded, intake.route.entityId);
@@ -3648,7 +3693,7 @@ class ProcessManagerCommandExecution {
3648
3693
  #postEvents(events) {
3649
3694
  for (const event of events) {
3650
3695
  // spine-log-boundary: server.repository_event_follow_up
3651
- void this.#runtime.publisher.publishEvent(event);
3696
+ void this.#runtime.publisher.publishReactorEvent(event);
3652
3697
  }
3653
3698
  }
3654
3699
  }
@@ -3744,9 +3789,10 @@ class ProcessManagerEventExecution {
3744
3789
  const produced = await this.#invokeHandlers(entityId, loaded.entity, intake, tenantOptions.tenantId);
3745
3790
  const events = this.#bindProducedEvents(produced.events, entityId, RepositoryEntities.priorVersion(loaded.current));
3746
3791
  const commands = this.#bindProducedCommands(produced.commands);
3747
- const diagnostics = this.#repository.entityFamily === "agent"
3748
- ? events
3749
- : [DispatchGuards.guardedJournalEvent(this.#repository, this.#event, entityId), ...events];
3792
+ const diagnostics = [
3793
+ DispatchGuards.guardedJournalEvent(this.#repository, this.#event, entityId),
3794
+ ...events,
3795
+ ];
3750
3796
  const committed = await this.#support.commit(loaded, tenantOptions, diagnostics, events);
3751
3797
  if (!committed)
3752
3798
  return;
@@ -3944,7 +3990,7 @@ class ProcessManagerEventExecution {
3944
3990
  #postEvents(events) {
3945
3991
  for (const event of events) {
3946
3992
  // spine-log-boundary: server.process_manager_event_follow_up
3947
- void this.#runtime.publisher.publishEvent(event);
3993
+ void this.#runtime.publisher.publishReactorEvent(event);
3948
3994
  }
3949
3995
  }
3950
3996
  }
@@ -4266,7 +4312,23 @@ const EntityInvocation = {
4266
4312
  if (typeof method !== "function") {
4267
4313
  throw new TypeError(`Repository entity execution requires method "${methodName}".`);
4268
4314
  }
4269
- return Reflect.apply(method, entity, parameterCount === 2 ? [message, context] : [message]);
4315
+ let result;
4316
+ try {
4317
+ result = Reflect.apply(method, entity, parameterCount === 2 ? [message, context] : [message]);
4318
+ }
4319
+ catch (error) {
4320
+ receptionObservation.recordHandlerFailure(error);
4321
+ throw error;
4322
+ }
4323
+ if (result !== null &&
4324
+ (typeof result === "object" || typeof result === "function") &&
4325
+ typeof result.then === "function") {
4326
+ return Promise.resolve(result).catch((error) => {
4327
+ receptionObservation.recordHandlerFailure(error);
4328
+ throw error;
4329
+ });
4330
+ }
4331
+ return result;
4270
4332
  },
4271
4333
  /**
4272
4334
  * Copies a Command context or creates an empty context when absent.
@@ -8007,65 +8069,6 @@ const SavedRepositoryDispatch = {
8007
8069
  throw new Error("Saved Agent Command repository binding changed before delivery.");
8008
8070
  return { runtime, signalType: schema.typeName, recipient };
8009
8071
  },
8010
- /**
8011
- * Prepares the exact ordered Event recipients and selected generated handlers.
8012
- *
8013
- * @param repository Registered Entity repository for this operation.
8014
- * @param routing Registered generated handler routing metadata.
8015
- * @param event Original typed Event envelope.
8016
- * @returns Validated frozen Event recipient target.
8017
- */
8018
- async prepareEvent(repository, routing, event) {
8019
- const route = await repository.routeEvent(event);
8020
- return create(SavedTargetSchema, {
8021
- kind: AgentSavedTargetKind.AGENT_SAVED_REPOSITORY_EVENT,
8022
- receiverStateType: repository.stateSchema.typeName,
8023
- repositoryFamily: SavedRepositoryDispatch.family(repository),
8024
- signalType: route.messageFullTypeName,
8025
- bindingFingerprint: SavedRepositoryDispatch.fingerprint(repository, SavedRepositoryDispatch.eventHandlers(routing, event)),
8026
- recipients: route.entityIds.map((id) => InboxMessages.inboxTargetId(id, repository.idField)),
8027
- });
8028
- },
8029
- /**
8030
- * Restores the saved Event route and current generated handler metadata.
8031
- *
8032
- * @param repository Registered Entity repository for this operation.
8033
- * @param routing Registered generated handler routing metadata.
8034
- * @param event Original typed Event envelope.
8035
- * @param target Frozen recipient binding.
8036
- * @returns When the fenced repository operation completes.
8037
- */
8038
- bindEvent(repository, routing, event, target) {
8039
- const { signalType } = SavedRepositoryDispatch.requireEventBinding(repository, routing, event, target);
8040
- const entityIds = target.recipients.map((id) => SavedRepositoryDispatch.recipient(repository, id));
8041
- const route = {
8042
- entityIds,
8043
- messageFullTypeName: signalType,
8044
- invocation: "deferred",
8045
- };
8046
- return Promise.resolve(() => RepositoryDispatch.dispatchRepositoryEvent(repository, routing, event, route));
8047
- },
8048
- /**
8049
- * Checks saved Event metadata and active repository registration.
8050
- *
8051
- * @param repository Registered Entity repository for this operation.
8052
- * @param routing Registered generated handler routing metadata.
8053
- * @param event Original typed Event envelope.
8054
- * @param target Frozen recipient binding.
8055
- * @returns Registered Event route for the frozen target.
8056
- */
8057
- requireEventBinding(repository, routing, event, target) {
8058
- const packed = EntityInvocation.requireSignalMessage(event.message, "event");
8059
- const schema = RepositoryRoutes.schemaForTypeUrl(routing.eventSchemas, packed.typeUrl, "event");
8060
- const fingerprint = SavedRepositoryDispatch.fingerprint(repository, SavedRepositoryDispatch.eventHandlers(routing, event));
8061
- const runtime = repositoryRuntimes.get(repository);
8062
- if (!SavedRepositoryDispatch.matches(repository, target, AgentSavedTargetKind.AGENT_SAVED_REPOSITORY_EVENT) ||
8063
- target.signalType !== schema.typeName ||
8064
- target.bindingFingerprint !== fingerprint ||
8065
- runtime === undefined)
8066
- throw new Error("Saved Agent Event repository binding changed before delivery.");
8067
- return { runtime, signalType: schema.typeName };
8068
- },
8069
8072
  /**
8070
8073
  * Creates one internal Command binding from the repository registration.
8071
8074
  *
@@ -8080,20 +8083,6 @@ const SavedRepositoryDispatch = {
8080
8083
  bind: (command, target) => SavedRepositoryDispatch.bindCommand(repository, routing, command, target),
8081
8084
  };
8082
8085
  },
8083
- /**
8084
- * Creates one internal Event binding from the repository registration.
8085
- *
8086
- * @param repository Registered Entity repository for this operation.
8087
- * @param routing Registered generated handler routing metadata.
8088
- * @returns Saved Event binding for this registration.
8089
- */
8090
- eventBinding(repository, routing) {
8091
- return {
8092
- prepare: (event) => SavedRepositoryDispatch.prepareEvent(repository, routing, event),
8093
- matches: (target) => SavedRepositoryDispatch.matches(repository, target, AgentSavedTargetKind.AGENT_SAVED_REPOSITORY_EVENT),
8094
- bind: (event, target) => SavedRepositoryDispatch.bindEvent(repository, routing, event, target),
8095
- };
8096
- },
8097
8086
  };
8098
8087
  Object.freeze(SavedRepositoryDispatch);
8099
8088
  /**
@@ -8156,7 +8145,7 @@ const RepositoryDispatch = {
8156
8145
  },
8157
8146
  });
8158
8147
  const originAware = EventDispatcherOriginSchemas.define(dispatcher, routing.domesticEventSchemas, routing.externalEventSchemas);
8159
- return SavedDispatcherBindings.event(originAware, SavedRepositoryDispatch.eventBinding(repository, routing));
8148
+ return originAware;
8160
8149
  },
8161
8150
  /**
8162
8151
  * Creates a system-Event dispatcher for registered Entity-state subscriptions.