@spine-event-engine/server 2.0.0-snapshot.22 → 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.
- package/README.md +104 -7
- package/REFERENCE.md +272 -31
- package/dist/agent/agent-admission.d.ts +80 -0
- package/dist/agent/agent-admission.d.ts.map +1 -0
- package/dist/agent/agent-admission.js +127 -0
- package/dist/agent/agent-admission.js.map +1 -0
- package/dist/agent/agent-ai-binding.d.ts +24 -0
- package/dist/agent/agent-ai-binding.d.ts.map +1 -0
- package/dist/agent/agent-ai-binding.js +48 -0
- package/dist/agent/agent-ai-binding.js.map +1 -0
- package/dist/agent/agent-ai-runtime.d.ts +76 -0
- package/dist/agent/agent-ai-runtime.d.ts.map +1 -0
- package/dist/agent/agent-ai-runtime.js +1269 -0
- package/dist/agent/agent-ai-runtime.js.map +1 -0
- package/dist/agent/agent-execution-capacity.d.ts +43 -0
- package/dist/agent/agent-execution-capacity.d.ts.map +1 -0
- package/dist/agent/agent-execution-capacity.js +147 -0
- package/dist/agent/agent-execution-capacity.js.map +1 -0
- package/dist/agent/agent-execution-fault.d.ts +18 -0
- package/dist/agent/agent-execution-fault.d.ts.map +1 -0
- package/dist/agent/agent-execution-fault.js +31 -0
- package/dist/agent/agent-execution-fault.js.map +1 -0
- package/dist/agent/agent-execution-session.d.ts +103 -0
- package/dist/agent/agent-execution-session.d.ts.map +1 -0
- package/dist/agent/agent-execution-session.js +238 -0
- package/dist/agent/agent-execution-session.js.map +1 -0
- package/dist/agent/agent-history.d.ts +148 -0
- package/dist/agent/agent-history.d.ts.map +1 -0
- package/dist/agent/agent-history.js +340 -0
- package/dist/agent/agent-history.js.map +1 -0
- package/dist/agent/agent-interaction-audit.d.ts +58 -0
- package/dist/agent/agent-interaction-audit.d.ts.map +1 -0
- package/dist/agent/agent-interaction-audit.js +114 -0
- package/dist/agent/agent-interaction-audit.js.map +1 -0
- package/dist/agent/agent-interaction-events.d.ts +40 -0
- package/dist/agent/agent-interaction-events.d.ts.map +1 -0
- package/dist/agent/agent-interaction-events.js +129 -0
- package/dist/agent/agent-interaction-events.js.map +1 -0
- package/dist/agent/agent-mcp-budget.d.ts +125 -0
- package/dist/agent/agent-mcp-budget.d.ts.map +1 -0
- package/dist/agent/agent-mcp-budget.js +566 -0
- package/dist/agent/agent-mcp-budget.js.map +1 -0
- package/dist/agent/agent-mcp-host.d.ts +125 -0
- package/dist/agent/agent-mcp-host.d.ts.map +1 -0
- package/dist/agent/agent-mcp-host.js +15 -0
- package/dist/agent/agent-mcp-host.js.map +1 -0
- package/dist/agent/agent-mcp-runtime.d.ts +199 -0
- package/dist/agent/agent-mcp-runtime.d.ts.map +1 -0
- package/dist/agent/agent-mcp-runtime.js +621 -0
- package/dist/agent/agent-mcp-runtime.js.map +1 -0
- package/dist/agent/agent-model-selection.d.ts +129 -0
- package/dist/agent/agent-model-selection.d.ts.map +1 -0
- package/dist/agent/agent-model-selection.js +342 -0
- package/dist/agent/agent-model-selection.js.map +1 -0
- package/dist/agent/agent-read-runtime.d.ts +70 -0
- package/dist/agent/agent-read-runtime.d.ts.map +1 -0
- package/dist/agent/agent-read-runtime.js +320 -0
- package/dist/agent/agent-read-runtime.js.map +1 -0
- package/dist/agent/agent-revisions.d.ts +35 -0
- package/dist/agent/agent-revisions.d.ts.map +1 -0
- package/dist/agent/agent-revisions.js +133 -0
- package/dist/agent/agent-revisions.js.map +1 -0
- package/dist/agent/agent-scheduler.d.ts +99 -0
- package/dist/agent/agent-scheduler.d.ts.map +1 -0
- package/dist/agent/agent-scheduler.js +398 -0
- package/dist/agent/agent-scheduler.js.map +1 -0
- package/dist/bus/command-bus.d.ts +62 -0
- package/dist/bus/command-bus.d.ts.map +1 -1
- package/dist/bus/command-bus.js +51 -2
- package/dist/bus/command-bus.js.map +1 -1
- package/dist/bus/event-bus.d.ts +101 -2
- package/dist/bus/event-bus.d.ts.map +1 -1
- package/dist/bus/event-bus.js +74 -13
- package/dist/bus/event-bus.js.map +1 -1
- package/dist/bus/saved-dispatcher-binding.d.ts +53 -0
- package/dist/bus/saved-dispatcher-binding.d.ts.map +1 -0
- package/dist/bus/saved-dispatcher-binding.js +27 -0
- package/dist/bus/saved-dispatcher-binding.js.map +1 -0
- package/dist/context/bounded-context.d.ts +45 -12
- package/dist/context/bounded-context.d.ts.map +1 -1
- package/dist/context/bounded-context.js +306 -86
- package/dist/context/bounded-context.js.map +1 -1
- package/dist/context/entity-inbox.d.ts.map +1 -1
- package/dist/context/entity-inbox.js +21 -7
- package/dist/context/entity-inbox.js.map +1 -1
- package/dist/context/local-inbox-handoff.d.ts +1 -0
- package/dist/context/local-inbox-handoff.d.ts.map +1 -1
- package/dist/context/local-inbox-handoff.js +31 -1
- package/dist/context/local-inbox-handoff.js.map +1 -1
- package/dist/context/projection-handoff.d.ts.map +1 -1
- package/dist/context/projection-handoff.js +2 -0
- package/dist/context/projection-handoff.js.map +1 -1
- package/dist/context/tenant-index.d.ts +25 -0
- package/dist/context/tenant-index.d.ts.map +1 -1
- package/dist/context/tenant-index.js +45 -1
- package/dist/context/tenant-index.js.map +1 -1
- package/dist/delivery/delivery-monitor.d.ts +12 -9
- package/dist/delivery/delivery-monitor.d.ts.map +1 -1
- package/dist/delivery/delivery-monitor.js +15 -9
- package/dist/delivery/delivery-monitor.js.map +1 -1
- package/dist/delivery/delivery-ports.d.ts +6 -13
- package/dist/delivery/delivery-ports.d.ts.map +1 -1
- package/dist/delivery/delivery-run-control.d.ts +15 -0
- package/dist/delivery/delivery-run-control.d.ts.map +1 -1
- package/dist/delivery/delivery-run-control.js.map +1 -1
- package/dist/delivery/delivery-supervisor.d.ts +33 -5
- package/dist/delivery/delivery-supervisor.d.ts.map +1 -1
- package/dist/delivery/delivery-supervisor.js +150 -22
- package/dist/delivery/delivery-supervisor.js.map +1 -1
- package/dist/delivery/delivery.d.ts.map +1 -1
- package/dist/delivery/delivery.js +128 -54
- package/dist/delivery/delivery.js.map +1 -1
- package/dist/delivery/inbox-storage.d.ts +8 -11
- package/dist/delivery/inbox-storage.d.ts.map +1 -1
- package/dist/delivery/inbox-storage.js +33 -76
- package/dist/delivery/inbox-storage.js.map +1 -1
- package/dist/delivery/inbox.d.ts +9 -12
- package/dist/delivery/inbox.d.ts.map +1 -1
- package/dist/delivery/inbox.js +10 -13
- package/dist/delivery/inbox.js.map +1 -1
- package/dist/delivery/reception-observation.d.ts +56 -0
- package/dist/delivery/reception-observation.d.ts.map +1 -0
- package/dist/delivery/reception-observation.js +67 -0
- package/dist/delivery/reception-observation.js.map +1 -0
- package/dist/entity/entity.d.ts +82 -3
- package/dist/entity/entity.d.ts.map +1 -1
- package/dist/entity/entity.js +121 -22
- package/dist/entity/entity.js.map +1 -1
- package/dist/handler/generated-handler-registry.js +8 -3
- package/dist/handler/generated-handler-registry.js.map +1 -1
- package/dist/handler/handler-metadata.d.ts +17 -1
- package/dist/handler/handler-metadata.d.ts.map +1 -1
- package/dist/handler/handler-metadata.js +10 -4
- package/dist/handler/handler-metadata.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/repository/commit-fence.d.ts +11 -0
- package/dist/repository/commit-fence.d.ts.map +1 -1
- package/dist/repository/commit-fence.js +13 -0
- package/dist/repository/commit-fence.js.map +1 -1
- package/dist/repository/repository.d.ts +221 -13
- package/dist/repository/repository.d.ts.map +1 -1
- package/dist/repository/repository.js +2323 -134
- package/dist/repository/repository.js.map +1 -1
- package/dist/runtime/runtime.d.ts +11 -0
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +13 -0
- package/dist/runtime/runtime.js.map +1 -1
- package/dist/runtime/signal-metadata.d.ts.map +1 -1
- package/dist/runtime/signal-metadata.js +3 -10
- package/dist/runtime/signal-metadata.js.map +1 -1
- package/dist/runtime/signal-publisher.d.ts +14 -30
- package/dist/runtime/signal-publisher.d.ts.map +1 -1
- package/dist/runtime/signal-publisher.js +75 -47
- package/dist/runtime/signal-publisher.js.map +1 -1
- package/dist/runtime/standalone-handler-runtime.d.ts +7 -0
- package/dist/runtime/standalone-handler-runtime.d.ts.map +1 -1
- package/dist/runtime/standalone-handler-runtime.js +118 -11
- package/dist/runtime/standalone-handler-runtime.js.map +1 -1
- package/dist/server/environment-delivery-worker.d.ts.map +1 -1
- package/dist/server/environment-delivery-worker.js +305 -5
- package/dist/server/environment-delivery-worker.js.map +1 -1
- package/dist/server/managed-server-application.d.ts +2 -2
- package/dist/server/managed-server-application.d.ts.map +1 -1
- package/dist/server/managed-server-application.js +467 -177
- package/dist/server/managed-server-application.js.map +1 -1
- package/dist/server/node-coordinator.d.ts +14 -0
- package/dist/server/node-coordinator.d.ts.map +1 -1
- package/dist/server/node-coordinator.js +266 -45
- package/dist/server/node-coordinator.js.map +1 -1
- package/dist/server/server-log.d.ts.map +1 -1
- package/dist/server/server-log.js +4 -0
- package/dist/server/server-log.js.map +1 -1
- package/dist/server/server.d.ts +9 -0
- package/dist/server/server.d.ts.map +1 -1
- package/dist/server/server.js +33 -8
- package/dist/server/server.js.map +1 -1
- package/dist/services/spine-services.d.ts.map +1 -1
- package/dist/services/spine-services.js +200 -72
- package/dist/services/spine-services.js.map +1 -1
- package/dist/stand/event-origin-filter.d.ts +16 -0
- package/dist/stand/event-origin-filter.d.ts.map +1 -0
- package/dist/stand/event-origin-filter.js +124 -0
- package/dist/stand/event-origin-filter.js.map +1 -0
- package/dist/stand/subscription-observer.d.ts.map +1 -1
- package/dist/stand/subscription-observer.js +7 -0
- package/dist/stand/subscription-observer.js.map +1 -1
- package/dist/stand/subscription-runtime.d.ts +18 -1
- package/dist/stand/subscription-runtime.d.ts.map +1 -1
- package/dist/stand/subscription-runtime.js +32 -4
- package/dist/stand/subscription-runtime.js.map +1 -1
- package/dist/testing/index.d.ts +57 -1
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +88 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +15 -13
package/README.md
CHANGED
|
@@ -82,10 +82,12 @@ for the exact contract.
|
|
|
82
82
|
|
|
83
83
|
An `@Assign`, `@Command`, `@React`, or `@Subscribe` handler may return its
|
|
84
84
|
usual result directly or through exactly one built-in `Promise<T>` layer. Its
|
|
85
|
-
|
|
85
|
+
in-memory Entity draft remains active until that promise settles. Nested `Promise<Promise<T>>`
|
|
86
86
|
results and structural or imported thenable lookalikes are rejected during handler
|
|
87
|
-
analysis.
|
|
88
|
-
|
|
87
|
+
analysis. Storage writes happen in separate short operations after the handler succeeds.
|
|
88
|
+
A failed handler leaves previous persisted state unchanged and
|
|
89
|
+
suppresses produced output. An external HTTP request or other side effect may
|
|
90
|
+
already have happened.
|
|
89
91
|
|
|
90
92
|
Handler return declarations can use native unions for one of several results,
|
|
91
93
|
or fixed tuples for several ordered results. For example,
|
|
@@ -129,7 +131,11 @@ class TaskAssignee {
|
|
|
129
131
|
Place the primary handler decorator first for readability. Reversing the two
|
|
130
132
|
decorators has the same behavior.
|
|
131
133
|
|
|
132
|
-
Process Managers
|
|
134
|
+
Process Managers have protected read-only `select()` during a handler. Agents use
|
|
135
|
+
the generated `select(query).read()` form with the same actor, tenant, and
|
|
136
|
+
1,000-state limits. Aggregates do not expose handler-scoped queries.
|
|
137
|
+
|
|
138
|
+
For Process Manager's schema-and-columns query form:
|
|
133
139
|
|
|
134
140
|
```ts
|
|
135
141
|
import { EntityQuery, type EntityColumn } from "@spine-event-engine/core";
|
|
@@ -167,11 +173,11 @@ These reads are eventually consistent. `limit()` may not exceed 1,000, and
|
|
|
167
173
|
`all()` can be expensive for a large read model; prefer a targeted, ordered,
|
|
168
174
|
bounded query.
|
|
169
175
|
|
|
170
|
-
The Entity type identifies its
|
|
176
|
+
The Entity type identifies its Bounded Context among those registered with the same
|
|
171
177
|
`Server`. For example, an order process can query a product in a catalogue
|
|
172
|
-
|
|
178
|
+
Bounded Context without naming that Bounded Context. An Entity in another Bounded Context must allow
|
|
173
179
|
queries (`query` or `full` visibility). Registering the same Entity type in two
|
|
174
|
-
|
|
180
|
+
Bounded Contexts causes a startup error.
|
|
175
181
|
|
|
176
182
|
The [Orders example](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/orders/README.md#cross-context-order-review)
|
|
177
183
|
shows this in an Event handler and includes a runnable integration test.
|
|
@@ -185,6 +191,97 @@ for the complete tenant rules and empty-result behavior.
|
|
|
185
191
|
Use `EntityQuery.all(...)` when every predicate must match and
|
|
186
192
|
`EntityQuery.either(...)` when any branch may match.
|
|
187
193
|
|
|
194
|
+
## Draft with an Agent
|
|
195
|
+
|
|
196
|
+
An Agent is a stateful Entity that can ask a model for help while handling a
|
|
197
|
+
Command or Event. For example, a support Agent drafts a reply from ticket facts
|
|
198
|
+
and emits an Event for a person to review. It keeps provider credentials out of
|
|
199
|
+
the handler and records the model interaction. Like other Entities, its ID and
|
|
200
|
+
state are declared in Proto and its handlers use generated registration.
|
|
201
|
+
|
|
202
|
+
An Agent can read its recorded interactions and emitted domain Events through
|
|
203
|
+
its repository. See the [Agent execution reference](REFERENCE.md#agent-execution)
|
|
204
|
+
for history methods, paging, and recovery behavior.
|
|
205
|
+
|
|
206
|
+
Declare the Agent ID and state in Proto, with `option (entity).kind = ENTITY;`
|
|
207
|
+
on the state. The [Support example](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/support/README.md) includes
|
|
208
|
+
complete [domain Protos](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/support/proto/spine/examples/support/states.proto),
|
|
209
|
+
[a model definition](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/support/src/model.ts), and
|
|
210
|
+
[an Agent implementation](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/support/src/index.ts).
|
|
211
|
+
|
|
212
|
+
The handler invokes a typed model operation, updates its draft only on success,
|
|
213
|
+
and emits a domain outcome. This abbreviated declaration uses the example's
|
|
214
|
+
actual generated messages:
|
|
215
|
+
|
|
216
|
+
<!-- prettier-ignore-start -->
|
|
217
|
+
|
|
218
|
+
<!-- docs-snippet-path: examples/support/src/index.ts -->
|
|
219
|
+
|
|
220
|
+
```ts
|
|
221
|
+
import { create } from "@bufbuild/protobuf";
|
|
222
|
+
import { Agent, Assign } from "@spine-event-engine/server";
|
|
223
|
+
import type { DraftSupportReply } from "../generated/spine/examples/support/commands_pb.js";
|
|
224
|
+
import {
|
|
225
|
+
SupportReplySuggestedSchema,
|
|
226
|
+
SupportReplyFailedSchema,
|
|
227
|
+
type SupportReplySuggested,
|
|
228
|
+
type SupportReplyFailed,
|
|
229
|
+
} from "../generated/spine/examples/support/events_pb.js";
|
|
230
|
+
import { SupportDraftStateSchema } from "../generated/spine/examples/support/states_pb.js";
|
|
231
|
+
import type { SupportTicketId } from "../generated/spine/examples/support/types_pb.js";
|
|
232
|
+
import { draftSupportReply } from "./model.js";
|
|
233
|
+
|
|
234
|
+
/** Proposes support replies for a person's review. */
|
|
235
|
+
class SupportDraftAgent extends Agent<SupportTicketId, typeof SupportDraftStateSchema> {
|
|
236
|
+
/**
|
|
237
|
+
* Drafts a reply from the submitted ticket facts.
|
|
238
|
+
*
|
|
239
|
+
* @param command Ticket facts and an explicit conversation.
|
|
240
|
+
* @returns The proposed reply or a recorded failure outcome.
|
|
241
|
+
*/
|
|
242
|
+
@Assign
|
|
243
|
+
async draft(command: DraftSupportReply): Promise<SupportReplySuggested | SupportReplyFailed> {
|
|
244
|
+
if (command.conversation === undefined || command.request === undefined)
|
|
245
|
+
throw new TypeError("A draft requires ticket facts and a conversation.");
|
|
246
|
+
const result = await this.ai.invoke(draftSupportReply, {
|
|
247
|
+
call: "draft-support-reply",
|
|
248
|
+
conversation: command.conversation,
|
|
249
|
+
input: command,
|
|
250
|
+
});
|
|
251
|
+
const outcome = {
|
|
252
|
+
id: this.id,
|
|
253
|
+
request: command.request,
|
|
254
|
+
conversation: command.conversation,
|
|
255
|
+
operation: result.operationId,
|
|
256
|
+
};
|
|
257
|
+
if (!result.ok) return create(SupportReplyFailedSchema, outcome);
|
|
258
|
+
this.update((state) =>
|
|
259
|
+
Object.assign(state, {
|
|
260
|
+
id: this.id,
|
|
261
|
+
request: command.request,
|
|
262
|
+
conversation: command.conversation,
|
|
263
|
+
reply: result.value,
|
|
264
|
+
}),
|
|
265
|
+
);
|
|
266
|
+
return create(SupportReplySuggestedSchema, { ...outcome, reply: result.value });
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
<!-- prettier-ignore-end -->
|
|
272
|
+
|
|
273
|
+
Configure the registry outside the Entity. The Bounded Context requires persisted System
|
|
274
|
+
Events, and the Agent registration supplies its code revision and permitted
|
|
275
|
+
capabilities. The [example Bounded Context factory](https://github.com/SpineEventEngine/spine-ts/blob/master/examples/support/src/index.ts)
|
|
276
|
+
assembles these settings with the generated handler registry. A server-wide
|
|
277
|
+
`withAi()` default can be supplied when building Bounded Contexts through `Server`;
|
|
278
|
+
Bounded Context configuration can provide its registry directly.
|
|
279
|
+
|
|
280
|
+
Posting a Command awaits acceptance. Model work and the resulting domain Event
|
|
281
|
+
arrive asynchronously afterward. The handling operation can await a model without
|
|
282
|
+
keeping a database transaction open. See the [Agent execution reference](REFERENCE.md#agent-execution)
|
|
283
|
+
for defaults, recovery and retained history.
|
|
284
|
+
|
|
188
285
|
## Native lifecycle and routing
|
|
189
286
|
|
|
190
287
|
`Server.run()` is the standalone process form: it handles `SIGINT`/`SIGTERM`
|
package/REFERENCE.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# @spine-event-engine/server reference
|
|
2
2
|
|
|
3
|
-
This reference gives
|
|
4
|
-
server contracts. For an introduction and examples, start with the
|
|
3
|
+
This reference gives coding agents the detailed server contracts. For an introduction and examples, start with the
|
|
5
4
|
[server README](README.md).
|
|
6
5
|
|
|
7
6
|
## Testing entry point
|
|
@@ -238,11 +237,13 @@ route registration API.
|
|
|
238
237
|
|
|
239
238
|
Handlers may return their established result directly or through exactly one built-in `Promise<T>`.
|
|
240
239
|
Nested promises and structural or imported thenable lookalikes are rejected during handler analysis.
|
|
241
|
-
The
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
240
|
+
The in-memory Entity draft remains active until that promise settles. Storage
|
|
241
|
+
writes use separate short operations after the handler succeeds; a rejected
|
|
242
|
+
handler leaves no partial persisted state or produced signals, but cannot undo
|
|
243
|
+
external side effects. Process Managers may use their protected read-only query
|
|
244
|
+
surface for eventually consistent Entity state during a handler. Agents expose
|
|
245
|
+
the generated `select(query).read()` form under the same handler scope and
|
|
246
|
+
limits. Aggregates must not use these reads for invariants.
|
|
246
247
|
|
|
247
248
|
`select(schema, columns)` supports `byId`, typed `where`, `orderBy`,
|
|
248
249
|
`limit`, `read`, `findById`, and `all`. A Process Manager query returns at most
|
|
@@ -329,10 +330,11 @@ A command-input `@Command` method is a command substitution receptor: it is
|
|
|
329
330
|
the one effective receptor for that Command type (instead of an `@Assign`),
|
|
330
331
|
commits its Entity state before its one-or-more returned Commands are detached
|
|
331
332
|
for in-process produced-command enqueue, and receives an optional `CommandContext`.
|
|
332
|
-
|
|
333
|
-
Projection repositories reject command-input substitutions and event- or
|
|
333
|
+
Process Manager and Agent repositories support `@Command` handlers. Aggregate
|
|
334
|
+
and Projection repositories reject command-input substitutions and event- or
|
|
334
335
|
rejection-input command reactions during generated metadata ingestion and
|
|
335
|
-
repository construction.
|
|
336
|
+
repository construction. Agents reject `@Subscribe`, including Entity-state
|
|
337
|
+
Apply handlers, at generation and runtime registration.
|
|
336
338
|
Event- and rejection-input `@Command` methods remain Event- or
|
|
337
339
|
rejection-to-command reactions on Event Bus.
|
|
338
340
|
|
|
@@ -542,6 +544,11 @@ handler registry for classes registered with `add(EntityClass)`;
|
|
|
542
544
|
`buildAsync()` performs that discovery and assembly. `build()` remains for
|
|
543
545
|
explicit `Repository` registration. A built context contains `CommandBus`,
|
|
544
546
|
`EventBus`, `Stand`, repositories, and its storage lifecycle.
|
|
547
|
+
Trusted server-side code can call `context.getRepository(EntityClass)` to obtain
|
|
548
|
+
the already registered repository for that exact constructor. The lookup does
|
|
549
|
+
not create a repository or read Entity state; an absent class or closing
|
|
550
|
+
Bounded Context fails explicitly. Application code must authorize users before
|
|
551
|
+
exposing repository reads through a client bridge.
|
|
545
552
|
|
|
546
553
|
Generated writer output is an unversioned receiver collection and records
|
|
547
554
|
command substitutions explicitly. The ingestor rejects retired versioned
|
|
@@ -615,8 +622,10 @@ configuration and Datastore custom record storage registered for
|
|
|
615
622
|
`SubscriptionRecord` are used by the registry. The registry uses one
|
|
616
623
|
record-storage handle, while the context closes the registry.
|
|
617
624
|
|
|
618
|
-
`Entity` is the state base class. `Aggregate`, `Projection`,
|
|
619
|
-
`ProcessManager` identify the
|
|
625
|
+
`Entity` is the state base class. `Aggregate`, `Projection`,
|
|
626
|
+
`ProcessManager`, and `Agent` identify the four entity families. Agent state
|
|
627
|
+
declares canonical Proto kind `ENTITY` and uses the same Spine `Version`.
|
|
628
|
+
Handler decorators are
|
|
620
629
|
`@Assign`, `@Command`, `@React`, and `@Subscribe`. A command-accepting
|
|
621
630
|
handler uses `@Throws(GeneratedRejection)` to declare its possible domain
|
|
622
631
|
rejections. Write the primary handler decorator first and `@Throws` immediately
|
|
@@ -633,6 +642,173 @@ zero. A dispatch that produces Events or changes state or lifecycle advances it
|
|
|
633
642
|
once; no-op and rejected dispatches do not. Repositories restore and persist the
|
|
634
643
|
full Version, including its timestamp, across current state, history, and Stand.
|
|
635
644
|
|
|
645
|
+
## Agent execution
|
|
646
|
+
|
|
647
|
+
Agents extend `Agent<Id, typeof StateSchema>`. The state declares Proto kind
|
|
648
|
+
`ENTITY`; IDs, state, Version, validation and routing use the normal Entity
|
|
649
|
+
contracts. Agents accept `@Assign`, `@React` and `@Command`, including declared
|
|
650
|
+
rejections as inputs. They reject `@Subscribe` and Entity-state Apply handlers.
|
|
651
|
+
The Agent runs only after an accepted signal. A model response or timer cannot
|
|
652
|
+
start a new autonomous Entity loop.
|
|
653
|
+
|
|
654
|
+
### Configuration
|
|
655
|
+
|
|
656
|
+
Register a factory-created `AiRegistry`, enable `persistSystemEvents()`, and
|
|
657
|
+
configure `agentCodeRevision` plus `ai.models` for each Agent repository. Use
|
|
658
|
+
an empty `models` array when that Agent has no model calls. Readiness requires
|
|
659
|
+
indexed Agent history and execution storage from the selected provider.
|
|
660
|
+
The [Support Bounded Context](../../examples/support/src/index.ts) uses generated
|
|
661
|
+
registration with these options.
|
|
662
|
+
|
|
663
|
+
Configuration has these scopes:
|
|
664
|
+
|
|
665
|
+
| Scope | Setting | Effect |
|
|
666
|
+
| --------------- | ---------------------------------------- | ------------------------------------------------------------------------ |
|
|
667
|
+
| Server | `Server.withAi(registry)` | Default registry for Bounded Context builders assembled by that server. |
|
|
668
|
+
| Bounded Context | `BoundedContextBuilder.withAi(registry)` | Explicit registry replacing the server default for that Bounded Context. |
|
|
669
|
+
| Repository | `ai.defaultModels` | Generation and decision defaults before the registry's defaults. |
|
|
670
|
+
| Repository | `ai.allowedModels` | Deployment references the Agent may use. |
|
|
671
|
+
| Repository | `ai.resolveModel` | Optional accepted-source choice before the Agent handler. |
|
|
672
|
+
| Repository | `ai.authorizeSelection` | Authorizes explicit choices and staged preference changes. |
|
|
673
|
+
| Repository | `ai.invocationLimits` | Limits that can narrow the registry's whole-signal limits. |
|
|
674
|
+
| Instance | `this.ai.select(kind, ref)` | A saved preference applied to later accepted signals. |
|
|
675
|
+
|
|
676
|
+
A prebuilt Bounded Context already has its registry; adding it to a server does not
|
|
677
|
+
reconfigure it. An instance preference takes precedence over its repository
|
|
678
|
+
default, which takes precedence over the effective registry default. Passing
|
|
679
|
+
`undefined` to `select` restores inheritance. Selection must satisfy the
|
|
680
|
+
repository policy and `authorizeSelection` callback; it cannot extend the
|
|
681
|
+
repository's allowed deployments. The current signal keeps its original selection.
|
|
682
|
+
|
|
683
|
+
`resolveModel(kind, scope, sourceMessage, control)` can choose a registered
|
|
684
|
+
deployment from a detached copy of the original accepted Command or Event
|
|
685
|
+
payload. A concrete result overrides preference and default precedence for that
|
|
686
|
+
signal; `undefined` preserves it. This allows an Agent without a configured
|
|
687
|
+
default to start after a deployment is appended to the bound registry. The
|
|
688
|
+
runtime checks repository allowlists, capabilities and `authorizeSelection`
|
|
689
|
+
before saving the selection and connection identity. A saved selection is reused
|
|
690
|
+
on continuation. Resolver and authorization callbacks receive linked cancellation
|
|
691
|
+
and the smaller of the invocation deadline and registry hook timeout. An
|
|
692
|
+
effective `this.ai.select()` change, including reset to inheritance, is
|
|
693
|
+
authorized before the Entity transition and preference Events commit; a no-op
|
|
694
|
+
change skips that callback.
|
|
695
|
+
|
|
696
|
+
Model registrations resolve a credential-free connection identity and authorize
|
|
697
|
+
use for the original actor, tenant, Agent and source signal. Connection callbacks
|
|
698
|
+
can obtain an API key, refreshed token, cloud credential or local model handle
|
|
699
|
+
through application code. The optional adapter supplies a guarded fetch function
|
|
700
|
+
for provider construction. Spine does not implement a provider's login flow.
|
|
701
|
+
See [adapter configuration](../ai-vercel-ax/README.md).
|
|
702
|
+
|
|
703
|
+
### Acceptance and completion
|
|
704
|
+
|
|
705
|
+
Before acknowledging Agent intake, the runtime saves the original signal,
|
|
706
|
+
recipient, selected handlers and code/schema/policy revisions. The scheduler
|
|
707
|
+
processes one accepted signal at a time per Agent instance, under a provider
|
|
708
|
+
claim. Different instances can run concurrently within configured limits.
|
|
709
|
+
Bounded Contexts using the same registry object share its capacity within the process.
|
|
710
|
+
Signals beyond the bounded in-memory waiting queue remain durably pending.
|
|
711
|
+
Waiting before a fresh execution starts precedes its deadline. Once execution
|
|
712
|
+
starts, recovery continues with the saved deadline and counts. The same deadline
|
|
713
|
+
bounds an awaited application handler. Expiry or Bounded Context shutdown ends that wait
|
|
714
|
+
and prevents late handler results from changing Entity state or emitting signals;
|
|
715
|
+
it cannot stop arbitrary application JavaScript or undo external effects.
|
|
716
|
+
|
|
717
|
+
Newly accepted work supplies its repository and tenant to prompt discovery.
|
|
718
|
+
Periodic discovery reads tenant pages and constructs repository scopes as they
|
|
719
|
+
are needed. It retains at most one page of 16 tenants, four periodic scan scopes,
|
|
720
|
+
and 64 scopes awaiting a prompt scan. A turn requests at most one tenant page
|
|
721
|
+
and reads at most four pending-work pages. It does not load the complete tenant
|
|
722
|
+
catalog or retain a scan position for every tenant.
|
|
723
|
+
|
|
724
|
+
A sweep finishes before another begins. The next starts no earlier than five
|
|
725
|
+
seconds after the preceding sweep started, measured by `Time`; longer sweeps
|
|
726
|
+
restart after completion. This lets discovery reach tenants near the end of a
|
|
727
|
+
large catalog and find later admissions on the next sweep. Periodic scans keep
|
|
728
|
+
their turn during new arrivals, including while execution capacity is full.
|
|
729
|
+
A pending catalog request does not block prompt scans of known scopes.
|
|
730
|
+
|
|
731
|
+
Bounded Context shutdown stops waiting for discovery reads even if a provider ignores
|
|
732
|
+
cancellation. Late results cannot submit work or restart scanning. Built-in
|
|
733
|
+
adapters use their available cancellation and timeout controls; detaching the
|
|
734
|
+
scheduler does not guarantee cancellation of an already issued native request.
|
|
735
|
+
|
|
736
|
+
The signal's matching handlers share one Entity draft. Each handler can await
|
|
737
|
+
`this.ai.invoke()` through the protected Spine facade. Calls in one handler must
|
|
738
|
+
be sequential and finish before it returns. Requests, results and
|
|
739
|
+
validation failures are saved as the operation progresses. The final accepted
|
|
740
|
+
state, Version, history and outgoing Command obligations are committed under the
|
|
741
|
+
same execution claim. Emitted domain Events enter immutable Agent history but are
|
|
742
|
+
not stored as delivery obligations. A no-op still completes its execution record. Waiting for
|
|
743
|
+
a provider does not hold a database transaction open.
|
|
744
|
+
|
|
745
|
+
Recovery compares the registered handler, schema and policy with accepted work.
|
|
746
|
+
A saved named call can reuse its result; changing that call's input or prepared
|
|
747
|
+
request is a mismatch, not a new attempt. Domain code should derive its decisions
|
|
748
|
+
from accepted signals and recorded reads. Arbitrary external effects performed
|
|
749
|
+
by handler code are outside the model/tool journal.
|
|
750
|
+
|
|
751
|
+
After completion, emitted domain Events are handed once to the Bounded Context's
|
|
752
|
+
normal EventBus. The Agent does not track Event recipients, retry a failed handoff,
|
|
753
|
+
or replay Event delivery after restart. Immutable Agent history remains readable
|
|
754
|
+
independently of EventBus delivery. Saved outgoing Commands retain their original
|
|
755
|
+
IDs and recipient bindings for recovery without rerunning the producing handler
|
|
756
|
+
or model. Generated repository and standalone Command receivers provide the
|
|
757
|
+
required binding metadata; matching raw custom Command dispatchers without it
|
|
758
|
+
are rejected.
|
|
759
|
+
|
|
760
|
+
### Retained history
|
|
761
|
+
|
|
762
|
+
Every Agent records conversations, System Events and its emitted domain Events.
|
|
763
|
+
The paired System Context EventStore also keeps System Events. Agent history
|
|
764
|
+
reads use dedicated repository indexes for that instance and tenant, rather than
|
|
765
|
+
scanning the Bounded Context-wide stores. Memory storage lasts for the process; choose a
|
|
766
|
+
persistent provider when records must survive process termination.
|
|
767
|
+
|
|
768
|
+
| Protected method | Returned `HistoryPage.items` |
|
|
769
|
+
| ------------------------------ | ------------------------------------------------------------------------------ |
|
|
770
|
+
| `fullHistory(request)` | `AgentHistoryEntry` oneof: conversation record, System Event, or domain Event. |
|
|
771
|
+
| `conversationHistory(request)` | `ConversationRecord` for the required `conversation` ID. |
|
|
772
|
+
| `systemEventHistory(request)` | Original System Event envelopes. |
|
|
773
|
+
| `domainEventHistory(request)` | Original domain Event envelopes emitted by this Agent. |
|
|
774
|
+
|
|
775
|
+
All methods return newest entries first. A request supplies positive `pageSize`
|
|
776
|
+
and an optional opaque cursor; `nextCursor` continues toward older entries.
|
|
777
|
+
There is no fixed 100-item or page-byte ceiling. Reads made during a handler count
|
|
778
|
+
toward any configured invocation limits for recorded reads and recovery data. Ordering
|
|
779
|
+
uses the full Spine `Time` timestamp, category and existing record ID. There is
|
|
780
|
+
no repository-managed history counter. Cursors cannot be transferred across
|
|
781
|
+
Agents, tenants, categories or conversations.
|
|
782
|
+
|
|
783
|
+
Recording has no off switch, expiry policy or Agent-specific purge operation.
|
|
784
|
+
Archive and logical deletion retain the history. General physical Entity deletion
|
|
785
|
+
is a separate feature; this API does not introduce it. Authentication callbacks do not become conversation records. Hidden model
|
|
786
|
+
reasoning is not part of the audit API. The records describe the supplied
|
|
787
|
+
requests, received supported content, tool calls and admitted outcomes.
|
|
788
|
+
|
|
789
|
+
Use `BlackBox.readAgentHistory(AgentClass, id, request)` to inspect full
|
|
790
|
+
history in an application test. `BlackBox.readSystemEvents(ids)` reads the paired
|
|
791
|
+
System store by exact Event IDs. See the [testing reference](../testing/REFERENCE.md)
|
|
792
|
+
and [complete support tests](../../examples/support/test/support-blackbox.test.ts).
|
|
793
|
+
|
|
794
|
+
For a trusted application bridge, `context.getRepository(AgentClass)` returns
|
|
795
|
+
the registered Agent `Repository`, which exposes
|
|
796
|
+
`agentHistory(id, scope)` with the same four history methods and page contracts.
|
|
797
|
+
The scope is explicit: pass `{}` in a single-tenant Bounded Context or
|
|
798
|
+
`{ tenantId }` in a multitenant Bounded Context. The repository also exposes
|
|
799
|
+
`agentExecution(id, sourceCommandOrEventId, scope)` for the exact recorded phase:
|
|
800
|
+
`accepted`, `active`, `completed-pending-commands`, `completed`, or `terminated`.
|
|
801
|
+
An absent record returns `undefined`; it does not establish completion. These
|
|
802
|
+
reads use indexed storage without restoring an Agent. The application bridge
|
|
803
|
+
must authorize access before calling either method; actor metadata does not
|
|
804
|
+
grant read permission.
|
|
805
|
+
|
|
806
|
+
If a selected model's `authorizeUse` callback explicitly returns `false` at
|
|
807
|
+
Agent claim time, the execution becomes `terminated` with one
|
|
808
|
+
`AgentInvocationTerminated` System Event carrying `MODEL_USE_DENIED`. No Agent
|
|
809
|
+
handler runs and no application-domain result Event is emitted. Callback
|
|
810
|
+
exceptions and infrastructure failures remain distinct from this denial.
|
|
811
|
+
|
|
636
812
|
## Signals, validation, and rejection behavior
|
|
637
813
|
|
|
638
814
|
`CommandBus` validates every accepted command from Proto validation options
|
|
@@ -646,18 +822,18 @@ UUIDs; fixed IDs belong only to existing source envelopes retained through the
|
|
|
646
822
|
normal origin chain.
|
|
647
823
|
|
|
648
824
|
An application handler throws a generated core `RejectionThrowable` for a
|
|
649
|
-
domain rejection declared with `@Throws`. The repository
|
|
650
|
-
|
|
825
|
+
domain rejection declared with `@Throws`. The repository discards the unaccepted
|
|
826
|
+
draft and output, retaining the previous state, Version and lifecycle; it schedules the typed rejection event independently. Command service
|
|
651
827
|
acknowledgement remains an accepted `Ack`. Rejection-event posting can be
|
|
652
828
|
unobserved by inactive, full, or closed subscriptions and a posting failure is
|
|
653
829
|
an internal diagnostic, not a retry guarantee.
|
|
654
830
|
|
|
655
831
|
Every domain context has an internal paired System Context. Domain events use
|
|
656
832
|
the domain `EventBus` and domain `EventStore`. System events use only the
|
|
657
|
-
System Context `EventBus`, so they never enter the domain EventStore.
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
and notifies without appending. Schemas may come from an external dispatcher or
|
|
833
|
+
System Context `EventBus`, so they never enter the domain EventStore.
|
|
834
|
+
`persistSystemEvents()` enables the paired System Context's separate storage.
|
|
835
|
+
Bounded Contexts with Agents must enable it. For other Bounded Contexts it is optional; without
|
|
836
|
+
it, the bus validates, dispatches and notifies without appending. Schemas may come from an external dispatcher or
|
|
661
837
|
a registered internal repository producer. A producer-only schema is not
|
|
662
838
|
thereby an external dispatch route.
|
|
663
839
|
|
|
@@ -681,6 +857,21 @@ a starting time, and has no durable operation identity, progress, Inbox
|
|
|
681
857
|
catch-up delivery, restart, resumption, or historical/live coordination. It is
|
|
682
858
|
not JVM-equivalent Projection catch-up.
|
|
683
859
|
|
|
860
|
+
Event Topics accept `include_all` or equality filters on the complete
|
|
861
|
+
`context.past_message` Origin. The filter value must be a valid packed
|
|
862
|
+
`spine.core.Origin`; other Event field paths, operators, ID filters, empty
|
|
863
|
+
filter trees, and malformed values are rejected. Existing composite-filter
|
|
864
|
+
limits apply. This is the immediate previous signal, not any ancestor in a
|
|
865
|
+
causal chain. Tenant isolation remains independent of the filter.
|
|
866
|
+
|
|
867
|
+
Origin filters use Protobuf value equality for the entire supported message,
|
|
868
|
+
including actor context and grand-origin. Packed `Any` payloads retain their
|
|
869
|
+
exact type URL and bytes. Expected Origins with unknown fields in their nested
|
|
870
|
+
message structure are unsupported and rejected; actual Origins with such
|
|
871
|
+
unknown fields cannot match. This avoids silently ignoring fields while keeping
|
|
872
|
+
the same equality semantics as Spine JVM for supported filters. The same rule
|
|
873
|
+
applies to direct and stored subscription definitions.
|
|
874
|
+
|
|
684
875
|
Active subscription streams and queues are process-local. `Stand` serves
|
|
685
876
|
authoritative queries from current state and Entity subscriptions observe
|
|
686
877
|
committed `EntityStateChanged` messages on the paired System Context EventBus,
|
|
@@ -706,7 +897,8 @@ group of complete server replicas when the framework handles process shutdown.
|
|
|
706
897
|
and installs no process signal handlers; that host closes the returned handle.
|
|
707
898
|
Both require a positive safe-integer
|
|
708
899
|
`processCount` and an ESM `moduleUrl`; it never derives a process count from
|
|
709
|
-
the machine. Its optional `host` and required
|
|
900
|
+
the machine. Its optional `host` and required `port` (zero selects an OS-assigned
|
|
901
|
+
port) bind the public
|
|
710
902
|
Coordinator listener. Every child executes that same module and calls the
|
|
711
903
|
module's `createServer({ host: "127.0.0.1", port: 0 })`. The child reports its
|
|
712
904
|
actual loopback endpoint only after its local readiness gates settle. The parent
|
|
@@ -725,11 +917,24 @@ inspect CPU availability and does not constrain the application's independently
|
|
|
725
917
|
chosen `DeliveryStrategy` or shard count. Direct `Server.run()` and browser
|
|
726
918
|
hosting remain independent of managed Node deployment.
|
|
727
919
|
|
|
920
|
+
Managed close drains Delivery before cancelling subscription relays. Child listeners
|
|
921
|
+
remain available through relay cancellation, and final child close follows relay
|
|
922
|
+
cleanup. A failed cleanup phase can be retried. Private child acknowledgement
|
|
923
|
+
and process reaping retain their finite process-control graces. A permanently
|
|
924
|
+
blocked application effect can keep explicit close pending.
|
|
925
|
+
|
|
728
926
|
If no child is READY, Command and Query return gRPC `UNAVAILABLE`. The
|
|
729
927
|
Coordinator does not enter application intake and does not retry the selected
|
|
730
928
|
call on a sibling child. Subscription fan-out follows current READY members;
|
|
731
929
|
later and replacement members attach the retained subscription before managed
|
|
732
930
|
admission.
|
|
931
|
+
Each native child sends a response-only successful activation ACK after its
|
|
932
|
+
listener attaches. The Coordinator waits for every required child ACK before
|
|
933
|
+
emitting one ACK with the logical public subscription ID and Topic; a child
|
|
934
|
+
failure before readiness cancels admitted siblings. Business updates do not
|
|
935
|
+
serve as readiness signals, and later joining children do not emit another
|
|
936
|
+
logical ACK. An ACK confirms attachment, not durable replay or delivery of
|
|
937
|
+
future updates.
|
|
733
938
|
|
|
734
939
|
`ServerOptions` is native-only: it configures contexts, resources, services,
|
|
735
940
|
and the native listener. It has no `browser` option and the root package does
|
|
@@ -844,12 +1049,15 @@ absent or elapsed (`keepUntil <= now`). Delivery skips per-record mutation check
|
|
|
844
1049
|
and deletion attempts for rows whose deadline is still in the future. Cleanup
|
|
845
1050
|
and retained-row duplicate recognition use the same applicable clock. Eligible
|
|
846
1051
|
rows still receive final time and shard checks before deletion.
|
|
847
|
-
Direct local storage
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
1052
|
+
Direct local storage checks the supplied delivered status and deadline again,
|
|
1053
|
+
then deletes by ID while the operation is active. It does not re-read the stored
|
|
1054
|
+
row or compare its snapshot, and the shard session is not checked again after
|
|
1055
|
+
deletion. A row changed between the checks and deletion can therefore be
|
|
1056
|
+
removed. Cancellation stops subsequent cleanup attempts; deletions already
|
|
1057
|
+
completed remain. The remote adapter sends a separate bounded removal request,
|
|
1058
|
+
without an atomic compare-and-delete guarantee from this client. Pending,
|
|
1059
|
+
retryable, non-delivered, and still-protected rows are skipped by cleanup. There
|
|
1060
|
+
is no additional retention configuration, timer, or scheduler.
|
|
853
1061
|
|
|
854
1062
|
`BoundedContextBuilder.withDeliveryStrategy(strategy)` snapshots a validated
|
|
855
1063
|
immutable strategy for its Entity Inbox; the default is one shard. For example,
|
|
@@ -863,7 +1071,7 @@ const context = BoundedContext.singleTenant("Tasks")
|
|
|
863
1071
|
.build();
|
|
864
1072
|
```
|
|
865
1073
|
|
|
866
|
-
Aggregate commands and Process Manager commands/events derive their target shard
|
|
1074
|
+
Aggregate commands and Process Manager or Agent commands/events derive their target shard
|
|
867
1075
|
internally and persist their envelope in the target Entity Inbox before any
|
|
868
1076
|
handler runs. Local intake can directly drain the persisted Inbox in the
|
|
869
1077
|
current request path. Attached `ServerEnvironment` ports acknowledge admission
|
|
@@ -878,6 +1086,11 @@ before source client/storage. `DeliverySource` is not configured on
|
|
|
878
1086
|
durable supervisor state, topology failover, exactly-once effects, or automatic
|
|
879
1087
|
retry of unknown remote mutations.
|
|
880
1088
|
|
|
1089
|
+
Direct `DeliverySupervisor.close({ graceMs })` stops new admission and source
|
|
1090
|
+
activity. Its `graceMs` defaults to 30,000 ms and bounds active-work grace and
|
|
1091
|
+
release cleanup separately. After those waits, close may still await entered
|
|
1092
|
+
work that has not settled; it is not a hard total close deadline.
|
|
1093
|
+
|
|
881
1094
|
Each Inbox read is bounded to one page. That bound does not limit the total
|
|
882
1095
|
pending work: an active drain continues from the last row read until that scan
|
|
883
1096
|
ends. It restarts from the beginning only if the completed scan delivered
|
|
@@ -898,11 +1111,39 @@ the remote server.
|
|
|
898
1111
|
`DeliveryMonitor` is an instantiable, customizable policy seam exposing
|
|
899
1112
|
asynchronous continuation, start/completion, failed-reception, pickup-failure,
|
|
900
1113
|
and already-picked hooks.
|
|
901
|
-
`FailedReception` supplies
|
|
902
|
-
`repeatDispatching()`
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
1114
|
+
`FailedReception` supplies `markDelivered()` and immediate
|
|
1115
|
+
`repeatDispatching()` actions for failed processing. The default marks a failed
|
|
1116
|
+
reception delivered; independent targets continue. A custom monitor may repeat
|
|
1117
|
+
the dispatch and is consulted again if that attempt fails. Monitor and selected
|
|
1118
|
+
action errors propagate. A successful handler followed by a failed acknowledgement
|
|
1119
|
+
retries acknowledgement up to three times without deliberately rerunning the
|
|
1120
|
+
handler. Exhausted acknowledgement leaves the row pending and does not call the
|
|
1121
|
+
reception monitor. A custom reception action that completes normally completes
|
|
1122
|
+
delivery and the enclosing stage acknowledges the row. An action that rejects
|
|
1123
|
+
propagates its error and leaves the row `TO_DELIVER`. `markDelivered()` does not
|
|
1124
|
+
mean domain processing succeeded.
|
|
1125
|
+
Managed repository replay sends actual handler failures to the monitor while
|
|
1126
|
+
storage and replay infrastructure errors propagate. A direct `onMessage` callback
|
|
1127
|
+
is treated as the endpoint. Handler effects and acknowledgement are separate,
|
|
1128
|
+
so a crash between them may redeliver.
|
|
1129
|
+
The framework adds no persisted attempts, quarantine, dead-letter, receipt, or
|
|
1130
|
+
marker policy. The supervisor rescans pending shards every 10 seconds by default;
|
|
1131
|
+
the stale-session threshold is separately 60 seconds.
|
|
1132
|
+
After a failed finite run, release-generated remote observations of that shard
|
|
1133
|
+
are held locally until the next periodic rescan, preventing an immediate
|
|
1134
|
+
self-triggered retry loop. Explicit notifications remain admissible. A newly
|
|
1135
|
+
enqueued remote row on that shard may wait for the next rescan; other shards
|
|
1136
|
+
continue, and other processes may each attempt the failed row before applying
|
|
1137
|
+
local suppression. This timing is not a delivery deadline.
|
|
1138
|
+
|
|
1139
|
+
`BoundedContext.close()` stops external admission, drains accepted framework
|
|
1140
|
+
work, and then closes buses, subscriptions, Stands, and repository bindings.
|
|
1141
|
+
Cleanup failures are aggregated and may be retried. A committed Entity Event,
|
|
1142
|
+
reactor or Process Manager Event, and System Event receives one first-publication
|
|
1143
|
+
attempt; a contained failure is logged and does not schedule publication again.
|
|
1144
|
+
Persisted System Events use a separate fixed storage group. Command acceptance
|
|
1145
|
+
alone does not promise recipient completion. Processing retries for Inbox rows
|
|
1146
|
+
and acknowledgement recovery remain separate Delivery behavior.
|
|
906
1147
|
|
|
907
1148
|
`Environment` resolves the Node `local` or `production` profile once from
|
|
908
1149
|
`NODE_ENV`. `ServerEnvironment` resolves configured facilities once for that
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Any } from "@bufbuild/protobuf/wkt";
|
|
2
|
+
import type { ActorContext, Command, Event } from "@spine-event-engine/proto";
|
|
3
|
+
import { type AgentAcceptedInvocation, type AgentHandlerBinding } from "@spine-event-engine/proto/generated/spine/server/agent/execution_record_pb.js";
|
|
4
|
+
import type { RegisteredHandlerMetadata } from "../handler/handler-metadata.js";
|
|
5
|
+
import type { InboxMessage } from "../delivery/inbox.js";
|
|
6
|
+
/**
|
|
7
|
+
* Complete source and selected bindings at one durable Inbox handoff.
|
|
8
|
+
*/
|
|
9
|
+
export interface AgentAdmissionInput {
|
|
10
|
+
/**
|
|
11
|
+
* Generated Agent state type.
|
|
12
|
+
*/
|
|
13
|
+
readonly stateType: string;
|
|
14
|
+
/**
|
|
15
|
+
* Canonical storage key of the typed recipient.
|
|
16
|
+
*/
|
|
17
|
+
readonly agentKey: string;
|
|
18
|
+
/**
|
|
19
|
+
* Original typed recipient from the persisted Inbox row.
|
|
20
|
+
*/
|
|
21
|
+
readonly recipientId: Any;
|
|
22
|
+
/**
|
|
23
|
+
* Original Command or Event envelope.
|
|
24
|
+
*/
|
|
25
|
+
readonly signal: {
|
|
26
|
+
readonly kind: "command";
|
|
27
|
+
readonly value: Command;
|
|
28
|
+
} | {
|
|
29
|
+
readonly kind: "event";
|
|
30
|
+
readonly value: Event;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Actor selected from the original envelope.
|
|
34
|
+
*/
|
|
35
|
+
readonly actor: ActorContext;
|
|
36
|
+
/**
|
|
37
|
+
* Original durable Inbox receipt and order.
|
|
38
|
+
*/
|
|
39
|
+
readonly inbox: InboxMessage;
|
|
40
|
+
/**
|
|
41
|
+
* Every matching handler in actual execution order.
|
|
42
|
+
*/
|
|
43
|
+
readonly handlers: readonly RegisteredHandlerMetadata[];
|
|
44
|
+
/**
|
|
45
|
+
* Application build revision supplied by Agent registration.
|
|
46
|
+
*/
|
|
47
|
+
readonly codeRevision: string;
|
|
48
|
+
/**
|
|
49
|
+
* Descriptor digest of accepted generated schemas.
|
|
50
|
+
*/
|
|
51
|
+
readonly schemaRevision: string;
|
|
52
|
+
/**
|
|
53
|
+
* Digest of effective AI policy and configuration.
|
|
54
|
+
*/
|
|
55
|
+
readonly policyRevision: string;
|
|
56
|
+
}
|
|
57
|
+
interface AgentAdmissionAccess {
|
|
58
|
+
/**
|
|
59
|
+
* Copies the exact accepted recipient and selected bindings for durable admission.
|
|
60
|
+
*
|
|
61
|
+
* @param input Routed Inbox work and registration revisions.
|
|
62
|
+
* @returns Immutable accepted invocation content.
|
|
63
|
+
*/
|
|
64
|
+
create(input: AgentAdmissionInput): AgentAcceptedInvocation;
|
|
65
|
+
/**
|
|
66
|
+
* Compares every persisted handler-binding field with current registration.
|
|
67
|
+
*
|
|
68
|
+
* @param accepted Binding saved with the original invocation.
|
|
69
|
+
* @param registered Current generated handler metadata.
|
|
70
|
+
* @param ordinal Expected position in the accepted handler order.
|
|
71
|
+
* @returns Whether current registration exactly matches the saved binding.
|
|
72
|
+
*/
|
|
73
|
+
matchesHandler(accepted: AgentHandlerBinding, registered: RegisteredHandlerMetadata, ordinal: number): boolean;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Materializes provider admission without running application handlers.
|
|
77
|
+
*/
|
|
78
|
+
export declare const AgentAdmission: AgentAdmissionAccess;
|
|
79
|
+
export {};
|
|
80
|
+
//# sourceMappingURL=agent-admission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-admission.d.ts","sourceRoot":"","sources":["../../src/agent/agent-admission.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAYL,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EAEzB,MAAM,+EAA+E,CAAC;AACvF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAChF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,GAAG,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,MAAM,EACX;QAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;KAAE,GACrD;QAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;IAEtD;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAE7B;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAE7B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,SAAS,yBAAyB,EAAE,CAAC;IAExD;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAE9B;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAEhC;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;CACjC;AAED,UAAU,oBAAoB;IAC5B;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,mBAAmB,GAAG,uBAAuB,CAAC;IAE5D;;;;;;;OAOG;IACH,cAAc,CACZ,QAAQ,EAAE,mBAAmB,EAC7B,UAAU,EAAE,yBAAyB,EACrC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;CACZ;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,oBA4C3B,CAAC"}
|