@effect-agent/platform-node 0.1.0-beta.44 → 0.1.0-beta.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/NodeDurableAgentRuntime-Ceye0Exk.d.mts +170 -0
- package/dist/NodeDurableAgentRuntime.d.mts +2 -0
- package/dist/NodeDurableAgentRuntime.mjs +217 -0
- package/dist/NodeDurableAgentRuntime.mjs.map +1 -0
- package/dist/NodeDurableHost.d.mts +120 -0
- package/dist/NodeDurableHost.mjs +90 -0
- package/dist/NodeDurableHost.mjs.map +1 -0
- package/dist/NodeScheduling.d.mts +22 -0
- package/dist/NodeScheduling.mjs +59 -0
- package/dist/NodeScheduling.mjs.map +1 -0
- package/dist/NodeSubscriptions.d.mts +27 -0
- package/dist/NodeSubscriptions.mjs +103 -0
- package/dist/NodeSubscriptions.mjs.map +1 -0
- package/dist/NodeWakeScheduler-DWdHIhWA.d.mts +27 -0
- package/dist/NodeWakeScheduler.d.mts +2 -0
- package/dist/NodeWakeScheduler.mjs +61 -0
- package/dist/NodeWakeScheduler.mjs.map +1 -0
- package/dist/NodeWorkflow.d.mts +27 -0
- package/dist/NodeWorkflow.mjs +159 -0
- package/dist/NodeWorkflow.mjs.map +1 -0
- package/dist/index.d.mts +6 -283
- package/dist/index.mjs +6 -436
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/package.json +1 -1
- package/src/{layers.ts → NodeDurableAgentRuntime.ts} +142 -60
- package/src/{host.ts → NodeDurableHost.ts} +103 -102
- package/src/{scheduling.ts → NodeScheduling.ts} +7 -5
- package/src/{subscriptions.ts → NodeSubscriptions.ts} +17 -13
- package/src/{wake-scheduler.ts → NodeWakeScheduler.ts} +3 -2
- package/src/NodeWorkflow.ts +258 -0
- package/src/index.ts +5 -5
- package/dist/index.mjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type SubmissionId } from "@effect-agent/core/Identifiers";
|
|
2
2
|
import {
|
|
3
3
|
CurrentToolFailureObserver,
|
|
4
4
|
RunContextPreparationPassthrough,
|
|
@@ -7,38 +7,47 @@ import {
|
|
|
7
7
|
type RunContextPreparation,
|
|
8
8
|
type RunCostEstimator,
|
|
9
9
|
type RunToolFailureObserver,
|
|
10
|
-
} from "@effect-agent/engine";
|
|
10
|
+
} from "@effect-agent/engine/RunOptions";
|
|
11
|
+
import { scheduleStoreLayer } from "@effect-agent/storage-sqlite/SqliteScheduleStore";
|
|
11
12
|
import {
|
|
12
|
-
threadStoreLayer,
|
|
13
|
-
scheduleStoreLayer,
|
|
14
13
|
SqliteStorageConfig,
|
|
15
14
|
SqliteStorageConfigValue,
|
|
15
|
+
} from "@effect-agent/storage-sqlite/SqliteStorageConfig";
|
|
16
|
+
import { type SqliteStorageFailpointHandler } from "@effect-agent/storage-sqlite/SqliteStorageFailpoint";
|
|
17
|
+
import { submissionLedgerLayer } from "@effect-agent/storage-sqlite/SqliteSubmissionLedger";
|
|
18
|
+
import {
|
|
19
|
+
threadStoreLayer,
|
|
16
20
|
storageFailpointLayer,
|
|
17
|
-
submissionLedgerLayer,
|
|
18
|
-
type SqliteStorageFailpointHandler,
|
|
19
21
|
type SqliteStorageInitializationError,
|
|
20
|
-
} from "@effect-agent/storage-sqlite";
|
|
22
|
+
} from "@effect-agent/storage-sqlite/SqliteThreadStore";
|
|
23
|
+
import {
|
|
24
|
+
type AgentRegistration,
|
|
25
|
+
type ResolvedBinding,
|
|
26
|
+
} from "@effect-agent/thread/AgentRegistration";
|
|
21
27
|
import {
|
|
22
|
-
type ScheduleStore,
|
|
23
|
-
type ThreadStore,
|
|
24
|
-
type WakeScheduler,
|
|
25
|
-
DEFAULT_OWNERSHIP_LEASE_DURATION,
|
|
26
|
-
DeploymentId,
|
|
27
28
|
DurableAgentRuntime,
|
|
28
29
|
DurableRuntimeConfig,
|
|
30
|
+
} from "@effect-agent/thread/DurableAgentRuntime";
|
|
31
|
+
import {
|
|
29
32
|
DurableRuntimeFailpoint,
|
|
30
|
-
|
|
33
|
+
type DurableRuntimeFailpointHandler,
|
|
34
|
+
} from "@effect-agent/thread/DurableFailpoint";
|
|
35
|
+
import { DeploymentId, ProducerId } from "@effect-agent/thread/Records";
|
|
36
|
+
import { type ScheduleStore } from "@effect-agent/thread/Schedule";
|
|
37
|
+
import {
|
|
38
|
+
DEFAULT_OWNERSHIP_LEASE_DURATION,
|
|
31
39
|
ReleaseOwnershipRequest,
|
|
32
40
|
SubmissionLedger,
|
|
33
|
-
ToolReconciler,
|
|
34
|
-
type DurableRuntimeFailpointHandler,
|
|
35
41
|
type OwnershipToken,
|
|
36
|
-
} from "@effect-agent/thread";
|
|
42
|
+
} from "@effect-agent/thread/SubmissionLedger";
|
|
43
|
+
import { type ThreadStore } from "@effect-agent/thread/ThreadStore";
|
|
44
|
+
import { ToolReconciler } from "@effect-agent/thread/ToolReconciler";
|
|
45
|
+
import { type WakeScheduler } from "@effect-agent/thread/WakeScheduler";
|
|
37
46
|
import { NodeCrypto } from "@effect/platform-node";
|
|
38
47
|
import { SqliteClient } from "@effect/sql-sqlite-node";
|
|
39
48
|
import { Context, type Crypto, Duration, Effect, Layer, Ref, Schema } from "effect";
|
|
40
49
|
|
|
41
|
-
import { NodeWakeSchedulerConfig, nodeWakeSchedulerLayer } from "./
|
|
50
|
+
import { NodeWakeSchedulerConfig, nodeWakeSchedulerLayer } from "./NodeWakeScheduler.ts";
|
|
42
51
|
|
|
43
52
|
const PositiveMillis = Schema.Int.check(Schema.isGreaterThan(0));
|
|
44
53
|
const NonNegativeMillis = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
|
|
@@ -62,8 +71,8 @@ export class NodePlatformConfigError extends Schema.TaggedError<NodePlatformConf
|
|
|
62
71
|
* construction, exposed as a typed service). Every cadence is in milliseconds and every bound is
|
|
63
72
|
* finite; `workerConcurrency` caps how many worker loops `NodeDurableHost.runWorkers` drives.
|
|
64
73
|
*/
|
|
65
|
-
export class
|
|
66
|
-
"@effect-agent/platform-node/
|
|
74
|
+
export class NodeDurableAgentRuntimeConfigValue extends Schema.Class<NodeDurableAgentRuntimeConfigValue>(
|
|
75
|
+
"@effect-agent/platform-node/NodeDurableAgentRuntimeConfigValue",
|
|
67
76
|
)({
|
|
68
77
|
/** SQLite database file backing BOTH the Thread Log and the Submission Ledger. */
|
|
69
78
|
filename: Schema.NonEmptyString,
|
|
@@ -90,17 +99,17 @@ export class NodeDurableRuntimeConfigValue extends Schema.Class<NodeDurableRunti
|
|
|
90
99
|
}) {}
|
|
91
100
|
|
|
92
101
|
/** Explicit configuration authority for the assembled Node durable runtime. */
|
|
93
|
-
export class
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
>()("@effect-agent/platform-node/
|
|
102
|
+
export class NodeDurableAgentRuntimeConfig extends Context.Service<
|
|
103
|
+
NodeDurableAgentRuntimeConfig,
|
|
104
|
+
NodeDurableAgentRuntimeConfigValue
|
|
105
|
+
>()("@effect-agent/platform-node/NodeDurableAgentRuntimeConfig") {}
|
|
97
106
|
|
|
98
107
|
/**
|
|
99
|
-
* Raw (unvalidated) construction options for `
|
|
108
|
+
* Raw (unvalidated) construction options for `NodeDurableAgentRuntime.layer`. Optional fields default
|
|
100
109
|
* to the documented production values; everything is schema-decoded into
|
|
101
|
-
* `
|
|
110
|
+
* `NodeDurableAgentRuntimeConfigValue` before any resource opens (deployment §5 gate 1).
|
|
102
111
|
*/
|
|
103
|
-
export interface
|
|
112
|
+
export interface NodeDurableAgentRuntimeOptions<
|
|
104
113
|
ContextError = never,
|
|
105
114
|
ContextRequirements = never,
|
|
106
115
|
AuthorizationError = never,
|
|
@@ -161,25 +170,25 @@ export interface NodeDurableRuntimeOptions<
|
|
|
161
170
|
}
|
|
162
171
|
|
|
163
172
|
/** Built-in construction failures. `layer` also preserves supplied service Layers' errors. */
|
|
164
|
-
export type
|
|
173
|
+
export type NodeDurableAgentRuntimeInitializationError =
|
|
165
174
|
| NodePlatformConfigError
|
|
166
175
|
| SqliteStorageInitializationError;
|
|
167
176
|
|
|
168
|
-
/** The services `
|
|
169
|
-
export type
|
|
177
|
+
/** The services `NodeDurableAgentRuntime.layer` provides. */
|
|
178
|
+
export type NodeDurableAgentRuntimeServices =
|
|
170
179
|
| DurableAgentRuntime
|
|
171
180
|
| SubmissionLedger
|
|
172
181
|
| ThreadStore
|
|
173
182
|
| ScheduleStore
|
|
174
183
|
| WakeScheduler
|
|
175
184
|
| DurableRuntimeConfig
|
|
176
|
-
|
|
|
185
|
+
| NodeDurableAgentRuntimeConfig;
|
|
177
186
|
|
|
178
|
-
const decodeConfigValue = Schema.decodeUnknownEffect(
|
|
187
|
+
const decodeConfigValue = Schema.decodeUnknownEffect(NodeDurableAgentRuntimeConfigValue);
|
|
179
188
|
|
|
180
189
|
const configFromOptions = (
|
|
181
|
-
options: Omit<
|
|
182
|
-
): Effect.Effect<
|
|
190
|
+
options: Omit<NodeDurableAgentRuntimeOptions, "runContext" | "toolAuthorization">,
|
|
191
|
+
): Effect.Effect<NodeDurableAgentRuntimeConfigValue, NodePlatformConfigError> =>
|
|
183
192
|
decodeConfigValue({
|
|
184
193
|
filename: options.filename,
|
|
185
194
|
deploymentId: options.deploymentId,
|
|
@@ -204,27 +213,30 @@ const configFromOptions = (
|
|
|
204
213
|
);
|
|
205
214
|
|
|
206
215
|
/** SQLite storage configuration derived from the single validated Node configuration. */
|
|
207
|
-
const sqliteStorageConfigLayer: Layer.Layer<
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
216
|
+
const sqliteStorageConfigLayer: Layer.Layer<
|
|
217
|
+
SqliteStorageConfig,
|
|
218
|
+
never,
|
|
219
|
+
NodeDurableAgentRuntimeConfig
|
|
220
|
+
> = Layer.effect(SqliteStorageConfig)(
|
|
221
|
+
Effect.gen(function* () {
|
|
222
|
+
const config = yield* NodeDurableAgentRuntimeConfig;
|
|
223
|
+
|
|
224
|
+
return SqliteStorageConfigValue.make({
|
|
225
|
+
observationPollInterval: config.observationPollInterval,
|
|
226
|
+
busyTimeout: config.busyTimeout,
|
|
227
|
+
ownershipLeaseDuration: config.ownershipLeaseDuration,
|
|
228
|
+
verifyOnOpen: config.verifyOnOpen,
|
|
229
|
+
});
|
|
230
|
+
}),
|
|
231
|
+
);
|
|
220
232
|
|
|
221
233
|
/** Thread coordinator configuration derived from the single validated Node configuration. */
|
|
222
234
|
const durableRuntimeConfigLayer = (
|
|
223
235
|
estimateCostMicrousd: RunCostEstimator | undefined,
|
|
224
|
-
): Layer.Layer<DurableRuntimeConfig, never,
|
|
236
|
+
): Layer.Layer<DurableRuntimeConfig, never, NodeDurableAgentRuntimeConfig> =>
|
|
225
237
|
Layer.effect(DurableRuntimeConfig)(
|
|
226
238
|
Effect.gen(function* () {
|
|
227
|
-
const config = yield*
|
|
239
|
+
const config = yield* NodeDurableAgentRuntimeConfig;
|
|
228
240
|
|
|
229
241
|
return DurableRuntimeConfig.make({
|
|
230
242
|
deploymentId: config.deploymentId,
|
|
@@ -241,10 +253,10 @@ const durableRuntimeConfigLayer = (
|
|
|
241
253
|
const wakeSchedulerConfigLayer: Layer.Layer<
|
|
242
254
|
NodeWakeSchedulerConfig,
|
|
243
255
|
never,
|
|
244
|
-
|
|
256
|
+
NodeDurableAgentRuntimeConfig
|
|
245
257
|
> = Layer.effect(NodeWakeSchedulerConfig)(
|
|
246
258
|
Effect.gen(function* () {
|
|
247
|
-
const config = yield*
|
|
259
|
+
const config = yield* NodeDurableAgentRuntimeConfig;
|
|
248
260
|
|
|
249
261
|
return { scanInterval: Duration.millis(config.wakeScanInterval) };
|
|
250
262
|
}),
|
|
@@ -373,7 +385,7 @@ export const ownershipDrainLayer: Layer.Layer<SubmissionLedger, never, Submissio
|
|
|
373
385
|
* verified during construction: an incompatible database file fails the Layer with
|
|
374
386
|
* `SqliteStorageCompatibilityError` before anything is mutated (DEPLOY-008).
|
|
375
387
|
*/
|
|
376
|
-
export class
|
|
388
|
+
export class NodeDurableAgentRuntime {
|
|
377
389
|
/** Validated configuration Layer; fails typed when the supplied options are out of bounds. */
|
|
378
390
|
static configLayer<
|
|
379
391
|
ContextError = never,
|
|
@@ -381,14 +393,14 @@ export class NodeDurableRuntime {
|
|
|
381
393
|
AuthorizationError = never,
|
|
382
394
|
AuthorizationRequirements = never,
|
|
383
395
|
>(
|
|
384
|
-
options:
|
|
396
|
+
options: NodeDurableAgentRuntimeOptions<
|
|
385
397
|
ContextError,
|
|
386
398
|
ContextRequirements,
|
|
387
399
|
AuthorizationError,
|
|
388
400
|
AuthorizationRequirements
|
|
389
401
|
>,
|
|
390
|
-
): Layer.Layer<
|
|
391
|
-
return Layer.effect(
|
|
402
|
+
): Layer.Layer<NodeDurableAgentRuntimeConfig, NodePlatformConfigError> {
|
|
403
|
+
return Layer.effect(NodeDurableAgentRuntimeConfig)(configFromOptions(options));
|
|
392
404
|
}
|
|
393
405
|
|
|
394
406
|
/** The full DN runtime stack over one SQLite file. */
|
|
@@ -398,20 +410,82 @@ export class NodeDurableRuntime {
|
|
|
398
410
|
AuthorizationError = never,
|
|
399
411
|
AuthorizationRequirements = never,
|
|
400
412
|
>(
|
|
401
|
-
options:
|
|
413
|
+
options: NodeDurableAgentRuntimeOptions<
|
|
402
414
|
ContextError,
|
|
403
415
|
ContextRequirements,
|
|
404
416
|
AuthorizationError,
|
|
405
417
|
AuthorizationRequirements
|
|
406
418
|
>,
|
|
407
419
|
): Layer.Layer<
|
|
408
|
-
|
|
409
|
-
|
|
420
|
+
NodeDurableAgentRuntimeServices,
|
|
421
|
+
NodeDurableAgentRuntimeInitializationError | ContextError | AuthorizationError,
|
|
410
422
|
Exclude<ContextRequirements | AuthorizationRequirements, Crypto.Crypto>
|
|
411
423
|
> {
|
|
412
|
-
return
|
|
424
|
+
return NodeDurableAgentRuntime.assemble(DurableAgentRuntime.layerWithServices, options);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/** Own typed executable registrations for every worker using this Node runtime. */
|
|
428
|
+
static layerRegistered<
|
|
429
|
+
const Entries extends ReadonlyArray<AgentRegistration>,
|
|
430
|
+
ContextError = never,
|
|
431
|
+
ContextRequirements = never,
|
|
432
|
+
AuthorizationError = never,
|
|
433
|
+
AuthorizationRequirements = never,
|
|
434
|
+
>(
|
|
435
|
+
registrations: Entries,
|
|
436
|
+
options: NodeDurableAgentRuntimeOptions<
|
|
437
|
+
ContextError,
|
|
438
|
+
ContextRequirements,
|
|
439
|
+
AuthorizationError,
|
|
440
|
+
AuthorizationRequirements
|
|
441
|
+
>,
|
|
442
|
+
) {
|
|
443
|
+
return NodeDurableAgentRuntime.assemble(
|
|
444
|
+
DurableAgentRuntime.layerRegistered(registrations),
|
|
445
|
+
options,
|
|
446
|
+
);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/** Construct from registrations already resolved within the enclosing application Scope. */
|
|
450
|
+
static layerWithBindings<
|
|
451
|
+
ContextError = never,
|
|
452
|
+
ContextRequirements = never,
|
|
453
|
+
AuthorizationError = never,
|
|
454
|
+
AuthorizationRequirements = never,
|
|
455
|
+
>(
|
|
456
|
+
bindings: ReadonlyArray<ResolvedBinding>,
|
|
457
|
+
options: NodeDurableAgentRuntimeOptions<
|
|
458
|
+
ContextError,
|
|
459
|
+
ContextRequirements,
|
|
460
|
+
AuthorizationError,
|
|
461
|
+
AuthorizationRequirements
|
|
462
|
+
>,
|
|
463
|
+
) {
|
|
464
|
+
return NodeDurableAgentRuntime.assemble(
|
|
465
|
+
DurableAgentRuntime.layerWithBindings(bindings),
|
|
466
|
+
options,
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
private static assemble<
|
|
471
|
+
RuntimeError,
|
|
472
|
+
RuntimeRequirements,
|
|
473
|
+
ContextError,
|
|
474
|
+
ContextRequirements,
|
|
475
|
+
AuthorizationError,
|
|
476
|
+
AuthorizationRequirements,
|
|
477
|
+
>(
|
|
478
|
+
runtimeLayer: Layer.Layer<DurableAgentRuntime, RuntimeError, RuntimeRequirements>,
|
|
479
|
+
options: NodeDurableAgentRuntimeOptions<
|
|
480
|
+
ContextError,
|
|
481
|
+
ContextRequirements,
|
|
482
|
+
AuthorizationError,
|
|
483
|
+
AuthorizationRequirements
|
|
484
|
+
>,
|
|
485
|
+
) {
|
|
486
|
+
const assembled = Layer.unwrap(
|
|
413
487
|
Effect.map(configFromOptions(options), (config) => {
|
|
414
|
-
const nodeConfigLayer = Layer.succeed(
|
|
488
|
+
const nodeConfigLayer = Layer.succeed(NodeDurableAgentRuntimeConfig)(config);
|
|
415
489
|
|
|
416
490
|
const infrastructure = Layer.mergeAll(
|
|
417
491
|
sqliteStorageConfigLayer,
|
|
@@ -443,7 +517,7 @@ export class NodeDurableRuntime {
|
|
|
443
517
|
),
|
|
444
518
|
);
|
|
445
519
|
|
|
446
|
-
return
|
|
520
|
+
return runtimeLayer.pipe(
|
|
447
521
|
Layer.provideMerge(
|
|
448
522
|
Layer.mergeAll(ports, durableRuntimeConfigLayer(options.estimateCostMicrousd)),
|
|
449
523
|
),
|
|
@@ -466,5 +540,13 @@ export class NodeDurableRuntime {
|
|
|
466
540
|
);
|
|
467
541
|
}),
|
|
468
542
|
);
|
|
543
|
+
|
|
544
|
+
const runtime: Layer.Layer<
|
|
545
|
+
NodeDurableAgentRuntimeServices,
|
|
546
|
+
Layer.Error<typeof assembled>,
|
|
547
|
+
Layer.Services<typeof assembled>
|
|
548
|
+
> = assembled;
|
|
549
|
+
|
|
550
|
+
return runtime;
|
|
469
551
|
}
|
|
470
552
|
}
|
|
@@ -1,17 +1,20 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ThreadId, type SubmissionId } from "@effect-agent/core/Identifiers";
|
|
2
|
+
import {
|
|
3
|
+
type IntegrityReport,
|
|
4
|
+
type ObligationReport,
|
|
5
|
+
type ObligationThresholds,
|
|
6
|
+
type RecoveryExplanation,
|
|
7
|
+
type RetryCommand,
|
|
8
|
+
} from "@effect-agent/thread/Admin";
|
|
2
9
|
import {
|
|
3
|
-
compileRegistrations,
|
|
4
10
|
type AgentRegistration,
|
|
11
|
+
type ResolvedBinding,
|
|
12
|
+
type DurableBindingFailure,
|
|
13
|
+
} from "@effect-agent/thread/AgentRegistration";
|
|
14
|
+
import {
|
|
5
15
|
DurableAgentRuntime,
|
|
6
|
-
type AbortCommand,
|
|
7
|
-
type AbortIntent,
|
|
8
|
-
type CanonicalRecordEnvelope,
|
|
9
|
-
type ThreadNotMaterialized,
|
|
10
|
-
type ThreadStoreError,
|
|
11
16
|
type DurableAbortFailure,
|
|
12
17
|
type DurableAwaitFailure,
|
|
13
|
-
type ResolvedBinding,
|
|
14
|
-
type DurableBindingFailure,
|
|
15
18
|
type DurableExplainFailure,
|
|
16
19
|
type DurableObserveOptions,
|
|
17
20
|
type DurableObligationFailure,
|
|
@@ -21,26 +24,29 @@ import {
|
|
|
21
24
|
type DurableSubmitOptions,
|
|
22
25
|
type DurableVerifyFailure,
|
|
23
26
|
type DurableWorkerFailure,
|
|
24
|
-
type IntegrityReport,
|
|
25
|
-
type ObligationReport,
|
|
26
|
-
type ObligationThresholds,
|
|
27
|
-
type OperationDenied,
|
|
28
27
|
type Receipt,
|
|
29
|
-
type RecoveryExplanation,
|
|
30
28
|
type RecoveryReport,
|
|
31
|
-
|
|
29
|
+
} from "@effect-agent/thread/DurableAgentRuntime";
|
|
30
|
+
import { type OperationDenied } from "@effect-agent/thread/OperationAuthorizer";
|
|
31
|
+
import { type CanonicalRecordEnvelope } from "@effect-agent/thread/Records";
|
|
32
|
+
import {
|
|
33
|
+
type AbortCommand,
|
|
34
|
+
type AbortIntent,
|
|
32
35
|
type Settlement,
|
|
33
|
-
} from "@effect-agent/thread";
|
|
34
|
-
import {
|
|
36
|
+
} from "@effect-agent/thread/SubmissionLedger";
|
|
37
|
+
import {
|
|
38
|
+
type ThreadNotMaterialized,
|
|
39
|
+
type ThreadStoreError,
|
|
40
|
+
} from "@effect-agent/thread/ThreadStore";
|
|
35
41
|
import { type Stream, Context, type Crypto, Effect, Layer, Ref, Schema } from "effect";
|
|
36
42
|
|
|
37
43
|
import {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
type
|
|
41
|
-
type
|
|
42
|
-
type
|
|
43
|
-
} from "./
|
|
44
|
+
NodeDurableAgentRuntime,
|
|
45
|
+
NodeDurableAgentRuntimeConfig,
|
|
46
|
+
type NodeDurableAgentRuntimeInitializationError,
|
|
47
|
+
type NodeDurableAgentRuntimeOptions,
|
|
48
|
+
type NodeDurableAgentRuntimeServices,
|
|
49
|
+
} from "./NodeDurableAgentRuntime.ts";
|
|
44
50
|
|
|
45
51
|
/**
|
|
46
52
|
* Admission is not open on this host: it is shutting down (deployment §6 step 1, DEPLOY-005).
|
|
@@ -50,75 +56,74 @@ export class AdmissionClosed extends Schema.TaggedError<AdmissionClosed>()("Admi
|
|
|
50
56
|
message: Schema.String,
|
|
51
57
|
}) {}
|
|
52
58
|
|
|
53
|
-
const makeHost = (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const config = yield* NodeDurableRuntimeConfig;
|
|
59
|
+
const makeHost = Effect.gen(function* () {
|
|
60
|
+
const runtime = yield* DurableAgentRuntime;
|
|
61
|
+
const config = yield* NodeDurableAgentRuntimeConfig;
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
// Startup gate (deployment §5, plan §host): configuration decoding and storage compatibility
|
|
64
|
+
// already gated this Layer's dependencies; the last gate before admission opens is recovering
|
|
65
|
+
// EVERY nonterminal Submission. Work needing a live Agent Binding is reported `deferred` and
|
|
66
|
+
// stays a visible obligation for `runWorkers`; lanes durably blocked on an Unknown Outcome are
|
|
67
|
+
// reported `unknown` and wait for the authorized `resolveUnknown` path (DUR-017) — they consume
|
|
68
|
+
// no worker permit while the settlement obligation stays owed.
|
|
69
|
+
const startupRecovery = yield* runtime.runRecovery;
|
|
65
70
|
|
|
66
|
-
|
|
71
|
+
const admission = yield* Ref.make(true);
|
|
67
72
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
// Shutdown step 1 (DEPLOY-005): admission closes before the ownership drain in the runtime
|
|
74
|
+
// Layer below releases claims and before the stores close in reverse acquisition order.
|
|
75
|
+
yield* Effect.addFinalizer(() => Ref.set(admission, false));
|
|
71
76
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
const requireAdmission: Effect.Effect<void, AdmissionClosed> = Ref.get(admission).pipe(
|
|
78
|
+
Effect.flatMap((open) =>
|
|
79
|
+
open
|
|
80
|
+
? Effect.void
|
|
81
|
+
: Effect.fail(
|
|
82
|
+
AdmissionClosed.make({ message: "The host is shutting down; admission is closed." }),
|
|
83
|
+
),
|
|
84
|
+
),
|
|
85
|
+
);
|
|
81
86
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
const submit = <InputSchema extends Schema.Top>(
|
|
88
|
+
agent: DurableSubmitAgent<InputSchema>,
|
|
89
|
+
input: InputSchema["Type"],
|
|
90
|
+
options: DurableSubmitOptions,
|
|
91
|
+
): Effect.Effect<
|
|
92
|
+
Receipt,
|
|
93
|
+
AdmissionClosed | DurableSubmitFailure,
|
|
94
|
+
InputSchema["EncodingServices"]
|
|
95
|
+
> => requireAdmission.pipe(Effect.andThen(runtime.submit(agent, input, options)));
|
|
91
96
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
const runWorkers = <A, E, R>(worker: Effect.Effect<A, E, R>): Effect.Effect<void, E, R> =>
|
|
98
|
+
Effect.forEach(
|
|
99
|
+
Array.from({ length: config.workerConcurrency }, (_, index) => index),
|
|
100
|
+
() => worker,
|
|
101
|
+
{ concurrency: "unbounded", discard: true },
|
|
102
|
+
);
|
|
98
103
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
+
// S2 multi-binding pool: every claimed head resolves its exact registered Binding through
|
|
105
|
+
// the host's exact registrations, so one bounded
|
|
106
|
+
// pool serves parent and child lanes — the spec §12 smallest-pool suspension/wakeup proof
|
|
107
|
+
// runs `workerConcurrency: 1` over exactly this loop.
|
|
108
|
+
const runResolvedWorkers = runWorkers(runtime.runResolvedWorker);
|
|
104
109
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
});
|
|
110
|
+
return NodeDurableHost.of({
|
|
111
|
+
startupRecovery,
|
|
112
|
+
admissionOpen: Ref.get(admission),
|
|
113
|
+
submit,
|
|
114
|
+
awaitSettlement: runtime.awaitSettlement,
|
|
115
|
+
observe: runtime.observe,
|
|
116
|
+
abort: runtime.abort,
|
|
117
|
+
explain: runtime.explain,
|
|
118
|
+
explainThread: runtime.explainThread,
|
|
119
|
+
verify: runtime.verify,
|
|
120
|
+
retry: runtime.retry,
|
|
121
|
+
wake: runtime.wake,
|
|
122
|
+
scanObligations: runtime.scanObligations,
|
|
123
|
+
runWorkers,
|
|
124
|
+
runResolvedWorkers,
|
|
121
125
|
});
|
|
126
|
+
});
|
|
122
127
|
|
|
123
128
|
/**
|
|
124
129
|
* Operational host lifecycle for the DN runtime (deployment §2/§5/§6).
|
|
@@ -210,57 +215,53 @@ export class NodeDurableHost extends Context.Service<
|
|
|
210
215
|
AuthorizationRequirements = never,
|
|
211
216
|
>(
|
|
212
217
|
registrations: Entries,
|
|
213
|
-
options:
|
|
218
|
+
options: NodeDurableAgentRuntimeOptions<
|
|
214
219
|
ContextError,
|
|
215
220
|
ContextRequirements,
|
|
216
221
|
AuthorizationError,
|
|
217
222
|
AuthorizationRequirements
|
|
218
223
|
>,
|
|
219
224
|
) {
|
|
220
|
-
return
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
),
|
|
224
|
-
).pipe(Layer.provide(NodeCrypto.layer));
|
|
225
|
+
return NodeDurableHost.layer.pipe(
|
|
226
|
+
Layer.provideMerge(NodeDurableAgentRuntime.layerRegistered(registrations, options)),
|
|
227
|
+
);
|
|
225
228
|
}
|
|
226
229
|
|
|
227
230
|
/**
|
|
228
|
-
* Host gates over an assembled `
|
|
229
|
-
*
|
|
231
|
+
* Host gates over an assembled `NodeDurableAgentRuntime` stack. The runtime Layer owns
|
|
232
|
+
* executable registrations; omission registers no Agents, so resolved work fails closed.
|
|
230
233
|
*/
|
|
231
|
-
static readonly layer
|
|
232
|
-
bindings: ReadonlyArray<ResolvedBinding> = [],
|
|
233
|
-
): Layer.Layer<
|
|
234
|
+
static readonly layer: Layer.Layer<
|
|
234
235
|
NodeDurableHost,
|
|
235
236
|
DurableWorkerFailure,
|
|
236
|
-
DurableAgentRuntime |
|
|
237
|
-
>
|
|
237
|
+
DurableAgentRuntime | NodeDurableAgentRuntimeConfig
|
|
238
|
+
> = Layer.effect(NodeDurableHost)(makeHost);
|
|
238
239
|
|
|
239
|
-
/** The complete DN host: `
|
|
240
|
+
/** The complete DN host: `NodeDurableAgentRuntime.layer(options)` plus the host lifecycle gates. */
|
|
240
241
|
static layerStack<
|
|
241
242
|
ContextError = never,
|
|
242
243
|
ContextRequirements = never,
|
|
243
244
|
AuthorizationError = never,
|
|
244
245
|
AuthorizationRequirements = never,
|
|
245
246
|
>(
|
|
246
|
-
options:
|
|
247
|
+
options: NodeDurableAgentRuntimeOptions<
|
|
247
248
|
ContextError,
|
|
248
249
|
ContextRequirements,
|
|
249
250
|
AuthorizationError,
|
|
250
251
|
AuthorizationRequirements
|
|
251
252
|
> & { readonly bindings?: ReadonlyArray<ResolvedBinding> },
|
|
252
253
|
): Layer.Layer<
|
|
253
|
-
NodeDurableHost |
|
|
254
|
+
NodeDurableHost | NodeDurableAgentRuntimeServices,
|
|
254
255
|
| DurableWorkerFailure
|
|
255
|
-
|
|
|
256
|
+
| NodeDurableAgentRuntimeInitializationError
|
|
256
257
|
| ContextError
|
|
257
258
|
| AuthorizationError,
|
|
258
259
|
Exclude<ContextRequirements | AuthorizationRequirements, Crypto.Crypto>
|
|
259
260
|
> {
|
|
260
261
|
const { bindings = [], ...runtimeOptions } = options;
|
|
261
262
|
|
|
262
|
-
return NodeDurableHost.layer
|
|
263
|
-
Layer.provideMerge(
|
|
263
|
+
return NodeDurableHost.layer.pipe(
|
|
264
|
+
Layer.provideMerge(NodeDurableAgentRuntime.layerWithBindings(bindings, runtimeOptions)),
|
|
264
265
|
);
|
|
265
266
|
}
|
|
266
267
|
}
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type ScheduleProcessFailure,
|
|
3
2
|
type ScheduleAuthorizer,
|
|
4
3
|
type SchedulingLimits,
|
|
5
4
|
ScheduleStorageError,
|
|
6
5
|
ScheduleStore,
|
|
7
6
|
type ScheduleValidationError,
|
|
8
7
|
ScheduleWake,
|
|
8
|
+
defaultSchedulingLimits,
|
|
9
|
+
} from "@effect-agent/thread/Schedule";
|
|
10
|
+
import {
|
|
11
|
+
type ScheduleProcessFailure,
|
|
9
12
|
Scheduling,
|
|
10
13
|
ScheduleDriver,
|
|
11
|
-
|
|
12
|
-
} from "@effect-agent/thread";
|
|
14
|
+
} from "@effect-agent/thread/Scheduling";
|
|
13
15
|
import { NodeCrypto } from "@effect/platform-node";
|
|
14
16
|
import { Cause, Duration, Effect, Layer, Option, PubSub, Result } from "effect";
|
|
15
17
|
|
|
16
|
-
import type { NodeDurableHost } from "./
|
|
17
|
-
import { nodeScheduledInputAdmissionLayer } from "./
|
|
18
|
+
import type { NodeDurableHost } from "./NodeDurableHost.ts";
|
|
19
|
+
import { nodeScheduledInputAdmissionLayer } from "./NodeSubscriptions.ts";
|
|
18
20
|
|
|
19
21
|
/** One bounded hint slot for the single supported Node scheduler. Indexed polling repairs loss. */
|
|
20
22
|
export const nodeScheduleWakeLayer: Layer.Layer<ScheduleWake> = Layer.effect(
|