depa-actor 0.1.2 → 0.2.1

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 (96) hide show
  1. package/dist/addressing.d.ts +100 -0
  2. package/dist/addressing.d.ts.map +1 -0
  3. package/dist/addressing.js +409 -0
  4. package/dist/addressing.js.map +1 -0
  5. package/dist/core/ActorSystem.d.ts +1 -1
  6. package/dist/core/ActorSystem.d.ts.map +1 -1
  7. package/dist/dispatch/ActorDispatchAdapter.d.ts +75 -18
  8. package/dist/dispatch/ActorDispatchAdapter.d.ts.map +1 -1
  9. package/dist/dispatch/ActorDispatchAdapter.js +109 -24
  10. package/dist/dispatch/ActorDispatchAdapter.js.map +1 -1
  11. package/dist/execution/commandDeque.d.ts +121 -0
  12. package/dist/execution/commandDeque.d.ts.map +1 -0
  13. package/dist/execution/commandDeque.js +415 -0
  14. package/dist/execution/commandDeque.js.map +1 -0
  15. package/dist/execution/dispatcher.d.ts +72 -0
  16. package/dist/execution/dispatcher.d.ts.map +1 -0
  17. package/dist/execution/dispatcher.js +77 -0
  18. package/dist/execution/dispatcher.js.map +1 -0
  19. package/dist/execution/index.d.ts +7 -0
  20. package/dist/execution/index.d.ts.map +1 -0
  21. package/dist/execution/index.js +4 -0
  22. package/dist/execution/index.js.map +1 -0
  23. package/dist/execution/stack.d.ts +24 -0
  24. package/dist/execution/stack.d.ts.map +1 -0
  25. package/dist/execution/stack.js +84 -0
  26. package/dist/execution/stack.js.map +1 -0
  27. package/dist/index.d.ts +21 -15
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +15 -8
  30. package/dist/index.js.map +1 -1
  31. package/dist/orchestration/index.d.ts +8 -8
  32. package/dist/orchestration/index.d.ts.map +1 -1
  33. package/dist/orchestration/index.js +6 -6
  34. package/dist/orchestration/index.js.map +1 -1
  35. package/dist/orchestration/presets/aiAgent.d.ts +2 -2
  36. package/dist/orchestration/presets/aiAgent.d.ts.map +1 -1
  37. package/dist/orchestration/recovery.d.ts +2 -2
  38. package/dist/orchestration/recovery.d.ts.map +1 -1
  39. package/dist/orchestration/reducer.d.ts +2 -2
  40. package/dist/orchestration/reducer.d.ts.map +1 -1
  41. package/dist/orchestration/reducer.js +2 -2
  42. package/dist/orchestration/reducer.js.map +1 -1
  43. package/dist/orchestration/runtimeAdapter.d.ts +3 -3
  44. package/dist/orchestration/runtimeAdapter.d.ts.map +1 -1
  45. package/dist/orchestration/scheduler.d.ts +2 -2
  46. package/dist/orchestration/scheduler.d.ts.map +1 -1
  47. package/dist/orchestration/types.d.ts +1 -1
  48. package/dist/orchestration/types.d.ts.map +1 -1
  49. package/dist/pipeline/ActorPipeline.d.ts +36 -9
  50. package/dist/pipeline/ActorPipeline.d.ts.map +1 -1
  51. package/dist/pipeline/ActorPipeline.js +26 -16
  52. package/dist/pipeline/ActorPipeline.js.map +1 -1
  53. package/dist/runtime/ActorRuntime.d.ts +2 -2
  54. package/dist/runtime/ActorRuntime.d.ts.map +1 -1
  55. package/dist/runtime/ActorRuntime.js +1 -1
  56. package/dist/runtime/ActorRuntime.js.map +1 -1
  57. package/dist-cjs/addressing.cjs +424 -0
  58. package/dist-cjs/core/ActorSystem.cjs +172 -0
  59. package/dist-cjs/core/types.cjs +10 -0
  60. package/dist-cjs/dispatch/ActorDispatchAdapter.cjs +125 -0
  61. package/dist-cjs/execution/commandDeque.cjs +430 -0
  62. package/dist-cjs/execution/dispatcher.cjs +79 -0
  63. package/dist-cjs/execution/index.cjs +24 -0
  64. package/dist-cjs/execution/stack.cjs +88 -0
  65. package/dist-cjs/index.cjs +77 -0
  66. package/dist-cjs/orchestration/index.cjs +19 -0
  67. package/dist-cjs/orchestration/presets/aiAgent.cjs +40 -0
  68. package/dist-cjs/orchestration/recovery.cjs +112 -0
  69. package/dist-cjs/orchestration/reducer.cjs +276 -0
  70. package/dist-cjs/orchestration/runtimeAdapter.cjs +14 -0
  71. package/dist-cjs/orchestration/scheduler.cjs +86 -0
  72. package/dist-cjs/orchestration/types.cjs +14 -0
  73. package/dist-cjs/package.json +3 -0
  74. package/dist-cjs/pipeline/ActorPipeline.cjs +44 -0
  75. package/dist-cjs/runtime/ActorRuntime.cjs +77 -0
  76. package/dist-cjs/runtime/completion.cjs +75 -0
  77. package/dist-cjs/runtime/indexing.cjs +34 -0
  78. package/dist-cjs/runtime/snapshot.cjs +14 -0
  79. package/package.json +9 -4
  80. package/src/addressing.ts +756 -0
  81. package/src/core/ActorSystem.ts +1 -1
  82. package/src/dispatch/ActorDispatchAdapter.ts +219 -48
  83. package/src/execution/commandDeque.ts +656 -0
  84. package/src/execution/dispatcher.ts +188 -0
  85. package/src/execution/index.ts +58 -0
  86. package/src/execution/stack.ts +130 -0
  87. package/src/index.ts +121 -16
  88. package/src/orchestration/index.ts +8 -8
  89. package/src/orchestration/presets/aiAgent.ts +2 -2
  90. package/src/orchestration/recovery.ts +2 -2
  91. package/src/orchestration/reducer.ts +3 -3
  92. package/src/orchestration/runtimeAdapter.ts +3 -3
  93. package/src/orchestration/scheduler.ts +2 -2
  94. package/src/orchestration/types.ts +1 -1
  95. package/src/pipeline/ActorPipeline.ts +104 -58
  96. package/src/runtime/ActorRuntime.ts +2 -2
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ /**
3
+ * depa-actor — Dispatch Bridge
4
+ *
5
+ * Drives the depa-processor `DispatchEngine` (all 7 strategies) from the actor
6
+ * side. The envelope → DispatchRequest adaptation and the actor `tag` overlay
7
+ * live HERE, in depa-actor — the generic `DispatchEngine` / `DispatchStrategyConfig`
8
+ * stay free of any actor (`envelope` / `tag` / `ActorSelf`) knowledge.
9
+ *
10
+ * Two orthogonal axes:
11
+ * 1. `tag` — actor's first-level route (which mailbox). Selecting a handler by
12
+ * tag is the actor system's job (`ActorDef.handlers[tag]`); a dispatch handler
13
+ * built here is slotted UNDER a tag, so tag selection happens upstream.
14
+ * `tag` is NOT a DispatchStrategyType — it is an orthogonal overlay dimension.
15
+ * 2. `strategy` — one of the 7 `DispatchStrategyType` values, used as the
16
+ * second-level resolution within the selected tag.
17
+ */
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.createDispatchHandler = createDispatchHandler;
20
+ const depa_processor_1 = require("depa-processor");
21
+ // ─── Internal helpers ────────────────────────────────────────────────
22
+ function isStrategyConfig(routes) {
23
+ return routes instanceof depa_processor_1.DispatchStrategyConfig;
24
+ }
25
+ /**
26
+ * Build a `DispatchStrategyConfig<void>` from a plain key → handler map for the
27
+ * supported key-based strategies. The map values are pre-bound to `(self, envelope)`
28
+ * by capturing the current dispatch's `self` / `envelope` via a thunk.
29
+ */
30
+ function buildKeyBasedConfig(strategy, routes, self, envelope) {
31
+ const handlerMap = new Map();
32
+ for (const [key, handler] of Object.entries(routes)) {
33
+ handlerMap.set(key, () => handler(self, envelope));
34
+ }
35
+ switch (strategy) {
36
+ case depa_processor_1.DispatchStrategyType.ROUTE_KEY:
37
+ return depa_processor_1.DispatchStrategyConfig.forRouteKeyStrategy({
38
+ handlerMap: handlerMap,
39
+ });
40
+ case depa_processor_1.DispatchStrategyType.ENUM:
41
+ return depa_processor_1.DispatchStrategyConfig.forEnumStrategy({
42
+ handlerMap,
43
+ });
44
+ case depa_processor_1.DispatchStrategyType.COMMAND_TABLE:
45
+ return depa_processor_1.DispatchStrategyConfig.forCommandStrategy({
46
+ commandConverter: (command) => handlerMap.has(command) ? command : null,
47
+ handlerExtractor: (commandEnum) => handlerMap.get(commandEnum) ?? null,
48
+ });
49
+ default:
50
+ throw new Error(`createDispatchHandler: strategy ${strategy} requires a prebuilt ` +
51
+ `DispatchStrategyConfig in 'routes' (plain key→handler maps support ` +
52
+ `ROUTE_KEY / ENUM / COMMAND_TABLE only).`);
53
+ }
54
+ }
55
+ /** Build the strategy-appropriate DispatchRequest from the envelope. */
56
+ function buildRequest(strategy, envelope, extractors) {
57
+ const input = extractors?.inputOf ? extractors.inputOf(envelope) : envelope.payload;
58
+ const routeKey = extractors?.routeKeyOf
59
+ ? extractors.routeKeyOf(envelope)
60
+ : envelope.tag;
61
+ const path = extractors?.pathOf ? extractors.pathOf(envelope) : envelope.tag;
62
+ switch (strategy) {
63
+ case depa_processor_1.DispatchStrategyType.CLASS:
64
+ return (0, depa_processor_1.createClassDispatchRequest)(input);
65
+ case depa_processor_1.DispatchStrategyType.ROUTE_KEY:
66
+ return (0, depa_processor_1.createRouteKeyDispatchRequest)(routeKey, input, false);
67
+ case depa_processor_1.DispatchStrategyType.ENUM:
68
+ return (0, depa_processor_1.createEnumDispatchRequest)(extractors?.enumOf ? extractors.enumOf(envelope) : envelope.tag, input);
69
+ case depa_processor_1.DispatchStrategyType.ROUTE_KEY_TO_ENUM:
70
+ return (0, depa_processor_1.createRouteKeyToEnumDispatchRequest)(routeKey, input);
71
+ case depa_processor_1.DispatchStrategyType.COMMAND_TABLE:
72
+ return (0, depa_processor_1.createCommandDispatchRequest)(routeKey, input);
73
+ case depa_processor_1.DispatchStrategyType.PATH:
74
+ return (0, depa_processor_1.createPathDispatchRequest)({
75
+ runtime: undefined,
76
+ request: input,
77
+ path,
78
+ });
79
+ case depa_processor_1.DispatchStrategyType.ACTION_PATH:
80
+ return (0, depa_processor_1.createActionPathDispatchRequest)({
81
+ runtime: undefined,
82
+ request: input,
83
+ action: extractors?.actionOf ? extractors.actionOf(envelope) : undefined,
84
+ path,
85
+ });
86
+ default:
87
+ throw new Error(`createDispatchHandler: unknown strategy ${String(strategy)}`);
88
+ }
89
+ }
90
+ // ─── createDispatchHandler ───────────────────────────────────────────
91
+ /**
92
+ * Creates an ActorHandler that resolves an envelope to a sub-handler via one of
93
+ * the 7 depa-processor dispatch strategies (opt-in, per-handler — DX form C / B2).
94
+ *
95
+ * Object-param signature: `{ strategy, routes, defaultHandler?, extractors? }`.
96
+ *
97
+ * Composability:
98
+ * - slot the returned handler under a `tag` in `ActorDef.handlers` → `tag` overlay
99
+ * (first-level) + `strategy` (second-level), the two axes are orthogonal.
100
+ * - the resolved sub-handler may itself be a `createPipelineHandler(...)` result,
101
+ * so dispatch and pipeline nest freely.
102
+ *
103
+ * No declarative `ActorDef.dispatch` field and no global feature flag / enableXxx
104
+ * API exist — enabling rich dispatch is expressed purely by import + composition.
105
+ */
106
+ function createDispatchHandler(params) {
107
+ const { strategy, routes, defaultHandler, extractors } = params;
108
+ return async (self, envelope) => {
109
+ const config = isStrategyConfig(routes)
110
+ ? routes
111
+ : buildKeyBasedConfig(strategy, routes, self, envelope);
112
+ const engine = new depa_processor_1.DispatchEngine();
113
+ engine.registerStrategy(config);
114
+ const request = buildRequest(strategy, envelope, extractors);
115
+ const result = await engine.dispatch(request);
116
+ if (result.isHandled()) {
117
+ // Await the sub-handler's (possibly async) side effect.
118
+ await result.getResult();
119
+ return;
120
+ }
121
+ if (defaultHandler) {
122
+ await defaultHandler(self, envelope);
123
+ }
124
+ };
125
+ }
@@ -0,0 +1,430 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultCommandDequeSelector = defaultCommandDequeSelector;
4
+ exports.createCommandDeque = createCommandDeque;
5
+ exports.createCommandDequeGroup = createCommandDequeGroup;
6
+ exports.pushBackCommand = pushBackCommand;
7
+ exports.pushFrontCommand = pushFrontCommand;
8
+ exports.popNextCommand = popNextCommand;
9
+ exports.popFrontCommand = popFrontCommand;
10
+ exports.popBackCommand = popBackCommand;
11
+ exports.pushBackCommandToGroup = pushBackCommandToGroup;
12
+ exports.pushFrontCommandToGroup = pushFrontCommandToGroup;
13
+ exports.popSelectedCommandFromGroup = popSelectedCommandFromGroup;
14
+ exports.takeNextCommandFromGroup = takeNextCommandFromGroup;
15
+ exports.drainCommandDequeFromGroup = drainCommandDequeFromGroup;
16
+ exports.drainWhereCommandDequeFromGroup = drainWhereCommandDequeFromGroup;
17
+ const DEFAULT_DEQUE_ID = 'default';
18
+ const DEFAULT_PRIORITY = 100;
19
+ class SingleCommandDeque {
20
+ state;
21
+ sequence;
22
+ now;
23
+ idFactory;
24
+ constructor(options, state, sequence = 0) {
25
+ this.state = state
26
+ ? cloneDequeState(state)
27
+ : {
28
+ id: options?.id ?? DEFAULT_DEQUE_ID,
29
+ lane: options?.lane,
30
+ priority: options?.priority ?? DEFAULT_PRIORITY,
31
+ items: [],
32
+ };
33
+ this.sequence = sequence;
34
+ this.now = options?.now;
35
+ this.idFactory = options?.idFactory;
36
+ }
37
+ get id() {
38
+ return this.state.id;
39
+ }
40
+ pushBack(command, options) {
41
+ const item = this.createItem(command, options);
42
+ this.state.items.push(item);
43
+ return item;
44
+ }
45
+ pushFront(command, options) {
46
+ const item = this.createItem(command, options);
47
+ this.state.items.unshift(item);
48
+ return item;
49
+ }
50
+ peekNext() {
51
+ return this.peekFront();
52
+ }
53
+ popNext() {
54
+ return this.popFront();
55
+ }
56
+ peekFront() {
57
+ return this.state.items[0];
58
+ }
59
+ peekBack() {
60
+ return this.state.items.at(-1);
61
+ }
62
+ popFront() {
63
+ return this.state.items.shift();
64
+ }
65
+ popBack() {
66
+ return this.state.items.pop();
67
+ }
68
+ listItems() {
69
+ return this.state.items.map((item) => ({ ...item }));
70
+ }
71
+ getItem(id) {
72
+ const item = this.state.items.find((candidate) => candidate.id === id);
73
+ return item ? { ...item } : undefined;
74
+ }
75
+ nextAfter(itemId) {
76
+ const index = this.state.items.findIndex((item) => item.id === itemId);
77
+ const item = index >= 0 ? this.state.items[index + 1] : undefined;
78
+ return item ? { ...item } : undefined;
79
+ }
80
+ prevBefore(itemId) {
81
+ const index = this.state.items.findIndex((item) => item.id === itemId);
82
+ const item = index >= 0 ? this.state.items[index - 1] : undefined;
83
+ return item ? { ...item } : undefined;
84
+ }
85
+ drain() {
86
+ const drained = this.listItems();
87
+ this.state.items.length = 0;
88
+ return drained;
89
+ }
90
+ drainWhere(predicate) {
91
+ const drained = [];
92
+ const kept = [];
93
+ for (const item of this.state.items) {
94
+ if (predicate(item)) {
95
+ drained.push({ ...item });
96
+ }
97
+ else {
98
+ kept.push(item);
99
+ }
100
+ }
101
+ this.state.items.length = 0;
102
+ this.state.items.push(...kept);
103
+ return drained;
104
+ }
105
+ hasPending() {
106
+ return this.state.items.length > 0;
107
+ }
108
+ snapshot() {
109
+ return cloneDequeState(this.state);
110
+ }
111
+ createItem(command, options) {
112
+ const nextSequence = this.sequence + 1;
113
+ this.sequence = nextSequence;
114
+ return {
115
+ id: options?.id ?? this.idFactory?.({ sequence: nextSequence, dequeId: this.state.id }) ?? `cmd-${nextSequence}`,
116
+ command,
117
+ insertedAt: options?.insertedAt ?? this.now?.() ?? Date.now(),
118
+ order: nextSequence,
119
+ };
120
+ }
121
+ }
122
+ class MultiCommandDequeGroup {
123
+ state;
124
+ selector;
125
+ now;
126
+ idFactory;
127
+ constructor(options, state) {
128
+ this.state = state
129
+ ? cloneGroupState(state)
130
+ : {
131
+ deques: {},
132
+ sequence: 0,
133
+ };
134
+ this.now = options?.now;
135
+ this.idFactory = options?.idFactory;
136
+ this.selector = options?.selector ?? defaultCommandDequeSelector;
137
+ for (const definition of options?.deques ?? []) {
138
+ this.ensureDequeState(definition);
139
+ }
140
+ }
141
+ getDeque(dequeId) {
142
+ if (!this.state.deques[dequeId]) {
143
+ this.state.deques[dequeId] = {
144
+ id: dequeId,
145
+ priority: DEFAULT_PRIORITY,
146
+ items: [],
147
+ };
148
+ }
149
+ return this.createDequeView(dequeId);
150
+ }
151
+ ensureDeque(definition) {
152
+ const state = this.ensureDequeState(definition);
153
+ return this.createDequeView(state.id);
154
+ }
155
+ pushBack(command, options) {
156
+ return this.push(command, options, 'back');
157
+ }
158
+ pushFront(command, options) {
159
+ return this.push(command, options, 'front');
160
+ }
161
+ selectNext(runtimeState, selector = this.selector) {
162
+ const selection = selector({ group: this.snapshot(), runtimeState });
163
+ if (!selection) {
164
+ return undefined;
165
+ }
166
+ return this.resolveSelection(selection);
167
+ }
168
+ popSelected(selection) {
169
+ const deque = this.state.deques[selection.dequeId];
170
+ if (!deque) {
171
+ return undefined;
172
+ }
173
+ const index = deque.items.findIndex((item) => item.id === selection.itemId);
174
+ if (index < 0) {
175
+ return undefined;
176
+ }
177
+ const [item] = deque.items.splice(index, 1);
178
+ return {
179
+ dequeId: deque.id,
180
+ itemId: item.id,
181
+ deque: cloneDequeState(deque),
182
+ item: { ...item },
183
+ };
184
+ }
185
+ takeNext(runtimeState, selector = this.selector) {
186
+ const selected = this.selectNext(runtimeState, selector);
187
+ if (!selected) {
188
+ return undefined;
189
+ }
190
+ return this.popSelected(selected);
191
+ }
192
+ drainDeque(dequeId) {
193
+ const deque = this.state.deques[dequeId];
194
+ if (!deque) {
195
+ return [];
196
+ }
197
+ const drained = deque.items.map((item) => ({ ...item }));
198
+ deque.items.length = 0;
199
+ return drained;
200
+ }
201
+ drainWhereDeque(dequeId, predicate) {
202
+ const deque = this.state.deques[dequeId];
203
+ if (!deque) {
204
+ return [];
205
+ }
206
+ const drained = [];
207
+ const kept = [];
208
+ for (const item of deque.items) {
209
+ if (predicate(item)) {
210
+ drained.push({ ...item });
211
+ }
212
+ else {
213
+ kept.push(item);
214
+ }
215
+ }
216
+ deque.items.length = 0;
217
+ deque.items.push(...kept);
218
+ return drained;
219
+ }
220
+ listDequeIds() {
221
+ return Object.keys(this.state.deques);
222
+ }
223
+ snapshot() {
224
+ return cloneGroupState(this.state);
225
+ }
226
+ push(command, options, side) {
227
+ const deque = this.ensureDequeState({
228
+ id: options.dequeId,
229
+ priority: this.state.deques[options.dequeId]?.priority ?? DEFAULT_PRIORITY,
230
+ });
231
+ const nextSequence = this.state.sequence + 1;
232
+ this.state.sequence = nextSequence;
233
+ const item = {
234
+ id: options.id ?? this.idFactory?.({ sequence: nextSequence, dequeId: deque.id }) ?? `cmd-${nextSequence}`,
235
+ command,
236
+ insertedAt: options.insertedAt ?? this.now?.() ?? Date.now(),
237
+ order: nextSequence,
238
+ };
239
+ if (side === 'front') {
240
+ deque.items.unshift(item);
241
+ }
242
+ else {
243
+ deque.items.push(item);
244
+ }
245
+ return { ...item };
246
+ }
247
+ createDequeView(dequeId) {
248
+ return {
249
+ id: dequeId,
250
+ pushBack: (command, options) => this.pushBack(command, { ...options, dequeId }),
251
+ pushFront: (command, options) => this.pushFront(command, { ...options, dequeId }),
252
+ peekNext: () => this.peekDequeFront(dequeId),
253
+ popNext: () => this.popDequeFront(dequeId),
254
+ peekFront: () => this.peekDequeFront(dequeId),
255
+ peekBack: () => this.peekDequeBack(dequeId),
256
+ popFront: () => this.popDequeFront(dequeId),
257
+ popBack: () => this.popDequeBack(dequeId),
258
+ listItems: () => this.state.deques[dequeId]?.items.map((item) => ({ ...item })) ?? [],
259
+ getItem: (id) => {
260
+ const item = this.state.deques[dequeId]?.items.find((candidate) => candidate.id === id);
261
+ return item ? { ...item } : undefined;
262
+ },
263
+ nextAfter: (itemId) => this.neighbor(dequeId, itemId, 1),
264
+ prevBefore: (itemId) => this.neighbor(dequeId, itemId, -1),
265
+ drain: () => this.drainDeque(dequeId),
266
+ drainWhere: (predicate) => this.drainWhereDeque(dequeId, predicate),
267
+ hasPending: () => (this.state.deques[dequeId]?.items.length ?? 0) > 0,
268
+ snapshot: () => cloneDequeState(this.state.deques[dequeId] ?? this.ensureDequeState({ id: dequeId, priority: DEFAULT_PRIORITY })),
269
+ };
270
+ }
271
+ peekDequeFront(dequeId) {
272
+ const item = this.state.deques[dequeId]?.items[0];
273
+ return item ? { ...item } : undefined;
274
+ }
275
+ peekDequeBack(dequeId) {
276
+ const item = this.state.deques[dequeId]?.items.at(-1);
277
+ return item ? { ...item } : undefined;
278
+ }
279
+ popDequeFront(dequeId) {
280
+ const item = this.state.deques[dequeId]?.items.shift();
281
+ return item ? { ...item } : undefined;
282
+ }
283
+ popDequeBack(dequeId) {
284
+ const item = this.state.deques[dequeId]?.items.pop();
285
+ return item ? { ...item } : undefined;
286
+ }
287
+ neighbor(dequeId, itemId, offset) {
288
+ const items = this.state.deques[dequeId]?.items;
289
+ if (!items) {
290
+ return undefined;
291
+ }
292
+ const index = items.findIndex((item) => item.id === itemId);
293
+ const item = index >= 0 ? items[index + offset] : undefined;
294
+ return item ? { ...item } : undefined;
295
+ }
296
+ resolveSelection(selection) {
297
+ const deque = this.state.deques[selection.dequeId];
298
+ const item = deque?.items.find((candidate) => candidate.id === selection.itemId);
299
+ if (!deque || !item) {
300
+ return undefined;
301
+ }
302
+ return {
303
+ dequeId: deque.id,
304
+ itemId: item.id,
305
+ deque: cloneDequeState(deque),
306
+ item: { ...item },
307
+ };
308
+ }
309
+ ensureDequeState(definition) {
310
+ const existing = this.state.deques[definition.id];
311
+ if (existing) {
312
+ if (definition.lane !== undefined) {
313
+ existing.lane = definition.lane;
314
+ }
315
+ existing.priority = definition.priority;
316
+ return existing;
317
+ }
318
+ const created = {
319
+ id: definition.id,
320
+ lane: definition.lane,
321
+ priority: definition.priority,
322
+ items: [],
323
+ };
324
+ this.state.deques[definition.id] = created;
325
+ return created;
326
+ }
327
+ }
328
+ function defaultCommandDequeSelector({ group, }) {
329
+ const candidates = Object.values(group.deques)
330
+ .filter((deque) => deque.items.length > 0)
331
+ .map((deque) => ({
332
+ dequeId: deque.id,
333
+ priority: deque.priority,
334
+ item: deque.items[0],
335
+ }));
336
+ candidates.sort((a, b) => {
337
+ if (a.priority !== b.priority) {
338
+ return a.priority - b.priority;
339
+ }
340
+ return a.item.order - b.item.order;
341
+ });
342
+ const selected = candidates[0];
343
+ return selected ? { dequeId: selected.dequeId, itemId: selected.item.id } : undefined;
344
+ }
345
+ function createCommandDeque(options, state) {
346
+ return new SingleCommandDeque(options, state, maxOrder(state?.items ?? []));
347
+ }
348
+ function createCommandDequeGroup(options, state) {
349
+ return new MultiCommandDequeGroup(options, state);
350
+ }
351
+ function pushBackCommand(state, command, options) {
352
+ const deque = createCommandDeque(options, state);
353
+ const item = deque.pushBack(command, options);
354
+ return { state: deque.snapshot(), item };
355
+ }
356
+ function pushFrontCommand(state, command, options) {
357
+ const deque = createCommandDeque(options, state);
358
+ const item = deque.pushFront(command, options);
359
+ return { state: deque.snapshot(), item };
360
+ }
361
+ function popNextCommand(state) {
362
+ const deque = createCommandDeque(undefined, state);
363
+ const item = deque.popNext();
364
+ return { state: deque.snapshot(), item };
365
+ }
366
+ function popFrontCommand(state) {
367
+ const deque = createCommandDeque(undefined, state);
368
+ const item = deque.popFront();
369
+ return { state: deque.snapshot(), item };
370
+ }
371
+ function popBackCommand(state) {
372
+ const deque = createCommandDeque(undefined, state);
373
+ const item = deque.popBack();
374
+ return { state: deque.snapshot(), item };
375
+ }
376
+ function pushBackCommandToGroup(state, command, options) {
377
+ const group = createCommandDequeGroup(options, state);
378
+ const item = group.pushBack(command, options);
379
+ return { state: group.snapshot(), item };
380
+ }
381
+ function pushFrontCommandToGroup(state, command, options) {
382
+ const group = createCommandDequeGroup(options, state);
383
+ const item = group.pushFront(command, options);
384
+ return { state: group.snapshot(), item };
385
+ }
386
+ function popSelectedCommandFromGroup(state, selection, options) {
387
+ const group = createCommandDequeGroup(options, state);
388
+ const selected = group.popSelected(selection);
389
+ return {
390
+ state: group.snapshot(),
391
+ item: selected?.item,
392
+ selection: selected,
393
+ };
394
+ }
395
+ function takeNextCommandFromGroup(state, runtimeState, options) {
396
+ const group = createCommandDequeGroup(options, state);
397
+ const selected = group.takeNext(runtimeState);
398
+ return {
399
+ state: group.snapshot(),
400
+ item: selected?.item,
401
+ selection: selected,
402
+ };
403
+ }
404
+ function drainCommandDequeFromGroup(state, dequeId, options) {
405
+ const group = createCommandDequeGroup(options, state);
406
+ const items = group.drainDeque(dequeId);
407
+ return { state: group.snapshot(), items };
408
+ }
409
+ function drainWhereCommandDequeFromGroup(state, dequeId, predicate, options) {
410
+ const group = createCommandDequeGroup(options, state);
411
+ const items = group.drainWhereDeque(dequeId, predicate);
412
+ return { state: group.snapshot(), items };
413
+ }
414
+ function cloneDequeState(state) {
415
+ return {
416
+ id: state.id,
417
+ lane: state.lane,
418
+ priority: state.priority,
419
+ items: state.items.map((item) => ({ ...item })),
420
+ };
421
+ }
422
+ function cloneGroupState(state) {
423
+ return {
424
+ deques: Object.fromEntries(Object.entries(state.deques).map(([id, deque]) => [id, cloneDequeState(deque)])),
425
+ sequence: state.sequence,
426
+ };
427
+ }
428
+ function maxOrder(items) {
429
+ return items.reduce((max, item) => Math.max(max, item.order), 0);
430
+ }
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dispatchInstructions = dispatchInstructions;
4
+ function dispatchInstructions(context, resolveHandler, options) {
5
+ const maxInstructions = options?.maxInstructions ?? Number.POSITIVE_INFINITY;
6
+ const effects = [];
7
+ const trace = [];
8
+ let executed = 0;
9
+ const finish = (stopReason, stopDetail, error) => {
10
+ options?.hooks?.onStop?.({ stopReason, stopDetail, executed });
11
+ const result = { executed, stopReason, effects, trace };
12
+ if (stopDetail !== undefined) {
13
+ result.stopDetail = stopDetail;
14
+ }
15
+ if (error !== undefined) {
16
+ result.error = error;
17
+ }
18
+ return result;
19
+ };
20
+ while (executed < maxInstructions) {
21
+ const customStop = options?.shouldStop?.({ executed });
22
+ if (customStop) {
23
+ return finish('custom', customStop);
24
+ }
25
+ const instruction = context.instructionStack.pop();
26
+ if (!instruction) {
27
+ return finish('instruction_stack_empty');
28
+ }
29
+ options?.hooks?.beforeInstruction?.({ instruction, executed });
30
+ const handler = resolveHandler(instruction.opcode);
31
+ if (!handler) {
32
+ trace.push({ instruction, result: 'missing_handler' });
33
+ options?.hooks?.afterInstruction?.({ instruction, executed, result: 'missing_handler' });
34
+ return finish('missing_handler');
35
+ }
36
+ try {
37
+ const handlerResult = handler({
38
+ runtime: context.runtime,
39
+ instruction,
40
+ instructionStack: context.instructionStack,
41
+ operandStack: context.operandStack,
42
+ });
43
+ executed += 1;
44
+ if (handlerResult?.effects) {
45
+ effects.push(...handlerResult.effects);
46
+ options?.hooks?.onHandlerEffects?.({
47
+ instruction,
48
+ effects: handlerResult.effects,
49
+ executed,
50
+ });
51
+ }
52
+ if (handlerResult?.yield) {
53
+ trace.push({ instruction, result: 'yield' });
54
+ const stopDetail = handlerResult.yieldReason;
55
+ options?.hooks?.afterInstruction?.({ instruction, executed, result: 'yield' });
56
+ return finish('yield_requested', stopDetail);
57
+ }
58
+ if (handlerResult?.stop) {
59
+ trace.push({ instruction, result: 'stop' });
60
+ const stopDetail = handlerResult.stopReason;
61
+ const stopReason = stopDetail === undefined ? 'handler_requested_stop' : 'custom';
62
+ options?.hooks?.afterInstruction?.({ instruction, executed, result: 'stop' });
63
+ return finish(stopReason, stopDetail);
64
+ }
65
+ trace.push({ instruction, result: 'ok' });
66
+ options?.hooks?.afterInstruction?.({ instruction, executed, result: 'ok' });
67
+ }
68
+ catch (error) {
69
+ trace.push({
70
+ instruction,
71
+ result: 'error',
72
+ error: error instanceof Error ? error.message : String(error),
73
+ });
74
+ options?.hooks?.afterInstruction?.({ instruction, executed, result: 'error' });
75
+ return finish('error', undefined, error);
76
+ }
77
+ }
78
+ return finish('budget_exhausted');
79
+ }
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.dispatchInstructions = exports.takeNextCommandFromGroup = exports.pushFrontCommandToGroup = exports.pushFrontCommand = exports.pushBackCommandToGroup = exports.pushBackCommand = exports.popSelectedCommandFromGroup = exports.popNextCommand = exports.popFrontCommand = exports.popBackCommand = exports.drainWhereCommandDequeFromGroup = exports.drainCommandDequeFromGroup = exports.defaultCommandDequeSelector = exports.createCommandDequeGroup = exports.createCommandDeque = exports.createOperandStack = exports.createInstructionStack = exports.createStackMachine = void 0;
4
+ var stack_js_1 = require("./stack.cjs");
5
+ Object.defineProperty(exports, "createStackMachine", { enumerable: true, get: function () { return stack_js_1.createStackMachine; } });
6
+ Object.defineProperty(exports, "createInstructionStack", { enumerable: true, get: function () { return stack_js_1.createInstructionStack; } });
7
+ Object.defineProperty(exports, "createOperandStack", { enumerable: true, get: function () { return stack_js_1.createOperandStack; } });
8
+ var commandDeque_js_1 = require("./commandDeque.cjs");
9
+ Object.defineProperty(exports, "createCommandDeque", { enumerable: true, get: function () { return commandDeque_js_1.createCommandDeque; } });
10
+ Object.defineProperty(exports, "createCommandDequeGroup", { enumerable: true, get: function () { return commandDeque_js_1.createCommandDequeGroup; } });
11
+ Object.defineProperty(exports, "defaultCommandDequeSelector", { enumerable: true, get: function () { return commandDeque_js_1.defaultCommandDequeSelector; } });
12
+ Object.defineProperty(exports, "drainCommandDequeFromGroup", { enumerable: true, get: function () { return commandDeque_js_1.drainCommandDequeFromGroup; } });
13
+ Object.defineProperty(exports, "drainWhereCommandDequeFromGroup", { enumerable: true, get: function () { return commandDeque_js_1.drainWhereCommandDequeFromGroup; } });
14
+ Object.defineProperty(exports, "popBackCommand", { enumerable: true, get: function () { return commandDeque_js_1.popBackCommand; } });
15
+ Object.defineProperty(exports, "popFrontCommand", { enumerable: true, get: function () { return commandDeque_js_1.popFrontCommand; } });
16
+ Object.defineProperty(exports, "popNextCommand", { enumerable: true, get: function () { return commandDeque_js_1.popNextCommand; } });
17
+ Object.defineProperty(exports, "popSelectedCommandFromGroup", { enumerable: true, get: function () { return commandDeque_js_1.popSelectedCommandFromGroup; } });
18
+ Object.defineProperty(exports, "pushBackCommand", { enumerable: true, get: function () { return commandDeque_js_1.pushBackCommand; } });
19
+ Object.defineProperty(exports, "pushBackCommandToGroup", { enumerable: true, get: function () { return commandDeque_js_1.pushBackCommandToGroup; } });
20
+ Object.defineProperty(exports, "pushFrontCommand", { enumerable: true, get: function () { return commandDeque_js_1.pushFrontCommand; } });
21
+ Object.defineProperty(exports, "pushFrontCommandToGroup", { enumerable: true, get: function () { return commandDeque_js_1.pushFrontCommandToGroup; } });
22
+ Object.defineProperty(exports, "takeNextCommandFromGroup", { enumerable: true, get: function () { return commandDeque_js_1.takeNextCommandFromGroup; } });
23
+ var dispatcher_js_1 = require("./dispatcher.cjs");
24
+ Object.defineProperty(exports, "dispatchInstructions", { enumerable: true, get: function () { return dispatcher_js_1.dispatchInstructions; } });