effect 4.0.3 → 4.0.4
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/AGENTS.md +24 -0
- package/CLAUDE.md +24 -0
- package/ai-docs/package.json +2 -2
- package/ai-docs/src/52_graphql/10_basics.ts +111 -0
- package/ai-docs/src/52_graphql/20_testing.ts +45 -0
- package/ai-docs/src/52_graphql/30_batching.ts +116 -0
- package/ai-docs/src/52_graphql/40_aliased-batching.ts +122 -0
- package/ai-docs/src/52_graphql/50_errors-and-retries.ts +74 -0
- package/ai-docs/src/52_graphql/index.md +6 -0
- package/dist/Context.d.ts.map +1 -1
- package/dist/Context.js +9 -0
- package/dist/Context.js.map +1 -1
- package/dist/RequestResolver.d.ts.map +1 -1
- package/dist/RequestResolver.js +4 -10
- package/dist/RequestResolver.js.map +1 -1
- package/dist/Scheduler.d.ts +9 -0
- package/dist/Scheduler.d.ts.map +1 -1
- package/dist/Scheduler.js +9 -0
- package/dist/Scheduler.js.map +1 -1
- package/dist/Schema.d.ts +8 -0
- package/dist/Schema.d.ts.map +1 -1
- package/dist/Schema.js +7 -0
- package/dist/Schema.js.map +1 -1
- package/dist/SchemaGetter.d.ts +4 -0
- package/dist/SchemaGetter.d.ts.map +1 -1
- package/dist/SchemaGetter.js +52 -33
- package/dist/SchemaGetter.js.map +1 -1
- package/dist/Sink.d.ts.map +1 -1
- package/dist/Sink.js +38 -17
- package/dist/Sink.js.map +1 -1
- package/dist/Stream.d.ts +11 -0
- package/dist/Stream.d.ts.map +1 -1
- package/dist/Stream.js +16 -1
- package/dist/Stream.js.map +1 -1
- package/dist/Utils.js +8 -3
- package/dist/Utils.js.map +1 -1
- package/dist/ai/AnthropicStructuredOutput.js +0 -2
- package/dist/ai/AnthropicStructuredOutput.js.map +1 -1
- package/dist/ai/Chat.d.ts +2 -2
- package/dist/ai/Chat.d.ts.map +1 -1
- package/dist/ai/LanguageModel.d.ts +38 -7
- package/dist/ai/LanguageModel.d.ts.map +1 -1
- package/dist/ai/LanguageModel.js +25 -7
- package/dist/ai/LanguageModel.js.map +1 -1
- package/dist/ai/McpServer.d.ts +55 -0
- package/dist/ai/McpServer.d.ts.map +1 -1
- package/dist/ai/McpServer.js +132 -22
- package/dist/ai/McpServer.js.map +1 -1
- package/dist/ai/Prompt.d.ts.map +1 -1
- package/dist/ai/Prompt.js +28 -5
- package/dist/ai/Prompt.js.map +1 -1
- package/dist/ai/Response.d.ts +4 -3
- package/dist/ai/Response.d.ts.map +1 -1
- package/dist/ai/Response.js.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.js +46 -8
- package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/cluster/Sharding.d.ts.map +1 -1
- package/dist/cluster/Sharding.js +6 -4
- package/dist/cluster/Sharding.js.map +1 -1
- package/dist/encoding/Sse.d.ts +6 -0
- package/dist/encoding/Sse.d.ts.map +1 -1
- package/dist/encoding/Sse.js +62 -70
- package/dist/encoding/Sse.js.map +1 -1
- package/dist/graphql/GraphQL.d.ts +349 -0
- package/dist/graphql/GraphQL.d.ts.map +1 -0
- package/dist/graphql/GraphQL.js +207 -0
- package/dist/graphql/GraphQL.js.map +1 -0
- package/dist/graphql/GraphQLClient.d.ts +562 -0
- package/dist/graphql/GraphQLClient.d.ts.map +1 -0
- package/dist/graphql/GraphQLClient.js +498 -0
- package/dist/graphql/GraphQLClient.js.map +1 -0
- package/dist/graphql/GraphQLClientError.d.ts +445 -0
- package/dist/graphql/GraphQLClientError.d.ts.map +1 -0
- package/dist/graphql/GraphQLClientError.js +479 -0
- package/dist/graphql/GraphQLClientError.js.map +1 -0
- package/dist/graphql/GraphQLGroup.d.ts +118 -0
- package/dist/graphql/GraphQLGroup.d.ts.map +1 -0
- package/dist/graphql/GraphQLGroup.js +109 -0
- package/dist/graphql/GraphQLGroup.js.map +1 -0
- package/dist/graphql/GraphQLMiddleware.d.ts +249 -0
- package/dist/graphql/GraphQLMiddleware.d.ts.map +1 -0
- package/dist/graphql/GraphQLMiddleware.js +130 -0
- package/dist/graphql/GraphQLMiddleware.js.map +1 -0
- package/dist/graphql/GraphQLProtocol.d.ts +731 -0
- package/dist/graphql/GraphQLProtocol.d.ts.map +1 -0
- package/dist/graphql/GraphQLProtocol.js +719 -0
- package/dist/graphql/GraphQLProtocol.js.map +1 -0
- package/dist/graphql/GraphQLResolver.d.ts +453 -0
- package/dist/graphql/GraphQLResolver.d.ts.map +1 -0
- package/dist/graphql/GraphQLResolver.js +552 -0
- package/dist/graphql/GraphQLResolver.js.map +1 -0
- package/dist/graphql/index.d.ts +40 -0
- package/dist/graphql/index.d.ts.map +1 -0
- package/dist/graphql/index.js +41 -0
- package/dist/graphql/index.js.map +1 -0
- package/dist/http/HttpClient.d.ts +15 -0
- package/dist/http/HttpClient.d.ts.map +1 -1
- package/dist/http/HttpClient.js +24 -10
- package/dist/http/HttpClient.js.map +1 -1
- package/dist/http/HttpEffect.d.ts.map +1 -1
- package/dist/http/HttpEffect.js +14 -7
- package/dist/http/HttpEffect.js.map +1 -1
- package/dist/http/HttpMiddleware.d.ts.map +1 -1
- package/dist/http/HttpMiddleware.js +31 -32
- package/dist/http/HttpMiddleware.js.map +1 -1
- package/dist/http/HttpRouter.d.ts +35 -0
- package/dist/http/HttpRouter.d.ts.map +1 -1
- package/dist/http/HttpRouter.js +35 -0
- package/dist/http/HttpRouter.js.map +1 -1
- package/dist/http/HttpServerResponse.d.ts +8 -6
- package/dist/http/HttpServerResponse.d.ts.map +1 -1
- package/dist/http/HttpServerResponse.js +27 -16
- package/dist/http/HttpServerResponse.js.map +1 -1
- package/dist/http/Multipart.d.ts.map +1 -1
- package/dist/http/Multipart.js +15 -1
- package/dist/http/Multipart.js.map +1 -1
- package/dist/http-api/HttpApiScalar.d.ts +5 -0
- package/dist/http-api/HttpApiScalar.d.ts.map +1 -1
- package/dist/http-api/HttpApiScalar.js.map +1 -1
- package/dist/internal/dateTime.js +40 -35
- package/dist/internal/dateTime.js.map +1 -1
- package/dist/internal/effect.js +8 -3
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/graphql.d.ts +2 -0
- package/dist/internal/graphql.d.ts.map +1 -0
- package/dist/internal/graphql.js +195 -0
- package/dist/internal/graphql.js.map +1 -0
- package/dist/internal/graphqlHeaders.d.ts +4 -0
- package/dist/internal/graphqlHeaders.d.ts.map +1 -0
- package/dist/internal/graphqlHeaders.js +11 -0
- package/dist/internal/graphqlHeaders.js.map +1 -0
- package/dist/internal/request.js +20 -1
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/schema/toCodeDocument.js +4 -1
- package/dist/internal/schema/toCodeDocument.js.map +1 -1
- package/dist/internal/schema/toJsonSchemaDocument.js +29 -5
- package/dist/internal/schema/toJsonSchemaDocument.js.map +1 -1
- package/dist/internal/version.js +1 -1
- package/dist/net/Host.d.ts +49 -0
- package/dist/net/Host.d.ts.map +1 -1
- package/dist/net/Host.js +55 -0
- package/dist/net/Host.js.map +1 -1
- package/dist/net/NetAddress.d.ts +8 -0
- package/dist/net/NetAddress.d.ts.map +1 -1
- package/dist/net/NetAddress.js +8 -0
- package/dist/net/NetAddress.js.map +1 -1
- package/dist/rpc/RpcServer.d.ts.map +1 -1
- package/dist/rpc/RpcServer.js +36 -9
- package/dist/rpc/RpcServer.js.map +1 -1
- package/dist/socket/Socket.d.ts +6 -0
- package/dist/socket/Socket.d.ts.map +1 -1
- package/dist/socket/Socket.js.map +1 -1
- package/dist/workflow/DurableDeferred.d.ts.map +1 -1
- package/dist/workflow/DurableDeferred.js +32 -3
- package/dist/workflow/DurableDeferred.js.map +1 -1
- package/dist/workflow/WorkflowEngine.d.ts +24 -2
- package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/workflow/WorkflowEngine.js +11 -2
- package/dist/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +6 -3
- package/src/Context.ts +9 -0
- package/src/RequestResolver.ts +4 -10
- package/src/Scheduler.ts +9 -0
- package/src/Schema.ts +8 -0
- package/src/SchemaGetter.ts +47 -35
- package/src/Sink.ts +45 -18
- package/src/Stream.ts +33 -4
- package/src/Utils.ts +8 -5
- package/src/ai/AnthropicStructuredOutput.ts +2 -2
- package/src/ai/Chat.ts +2 -2
- package/src/ai/LanguageModel.ts +96 -24
- package/src/ai/McpServer.ts +244 -90
- package/src/ai/Prompt.ts +24 -10
- package/src/ai/Response.ts +6 -3
- package/src/cluster/ClusterWorkflowEngine.ts +51 -12
- package/src/cluster/Sharding.ts +12 -9
- package/src/encoding/Sse.ts +69 -79
- package/src/graphql/GraphQL.ts +494 -0
- package/src/graphql/GraphQLClient.ts +912 -0
- package/src/graphql/GraphQLClientError.ts +542 -0
- package/src/graphql/GraphQLGroup.ts +167 -0
- package/src/graphql/GraphQLMiddleware.ts +253 -0
- package/src/graphql/GraphQLProtocol.ts +1286 -0
- package/src/graphql/GraphQLResolver.ts +1010 -0
- package/src/graphql/index.ts +48 -0
- package/src/http/HttpClient.ts +54 -10
- package/src/http/HttpEffect.ts +11 -5
- package/src/http/HttpMiddleware.ts +33 -34
- package/src/http/HttpRouter.ts +35 -0
- package/src/http/HttpServerResponse.ts +28 -16
- package/src/http/Multipart.ts +17 -1
- package/src/http-api/HttpApiScalar.ts +5 -0
- package/src/internal/dateTime.ts +13 -10
- package/src/internal/effect.ts +8 -3
- package/src/internal/graphql.ts +263 -0
- package/src/internal/graphqlHeaders.ts +11 -0
- package/src/internal/request.ts +31 -3
- package/src/internal/schema/toCodeDocument.ts +7 -1
- package/src/internal/schema/toJsonSchemaDocument.ts +34 -2
- package/src/internal/version.ts +1 -1
- package/src/net/Host.ts +72 -0
- package/src/net/NetAddress.ts +9 -0
- package/src/rpc/RpcServer.ts +55 -15
- package/src/socket/Socket.ts +6 -0
- package/src/workflow/DurableDeferred.ts +43 -5
- package/src/workflow/WorkflowEngine.ts +48 -4
|
@@ -134,6 +134,25 @@ const CurrentAttempt = Context.Reference<number>(
|
|
|
134
134
|
{ defaultValue: () => 1 }
|
|
135
135
|
)
|
|
136
136
|
|
|
137
|
+
/** Awaits registered under the instance copy of a `recordHeld` body. */
|
|
138
|
+
const awaitOwners = new WeakMap<WorkflowInstance["Service"], Array<string>>()
|
|
139
|
+
|
|
140
|
+
const registerAwait = (instance: WorkflowInstance["Service"], name: string) => {
|
|
141
|
+
instance.awaitedDeferreds.set(name, (instance.awaitedDeferreds.get(name) ?? 0) + 1)
|
|
142
|
+
awaitOwners.get(instance)?.push(name)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const releaseAwaits = (instance: WorkflowInstance["Service"], names: Array<string>) => {
|
|
146
|
+
for (const name of names) {
|
|
147
|
+
const count = instance.awaitedDeferreds.get(name)! - 1
|
|
148
|
+
if (count === 0) {
|
|
149
|
+
instance.awaitedDeferreds.delete(name)
|
|
150
|
+
} else {
|
|
151
|
+
instance.awaitedDeferreds.set(name, count)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
137
156
|
const await_: <Success extends Schema.Constraint, Error extends Schema.Constraint>(
|
|
138
157
|
self: DurableDeferred<Success, Error>
|
|
139
158
|
) => Effect.Effect<
|
|
@@ -150,7 +169,7 @@ const await_: <Success extends Schema.Constraint, Error extends Schema.Constrain
|
|
|
150
169
|
const engine = yield* EngineTag
|
|
151
170
|
const instance = yield* InstanceTag
|
|
152
171
|
// Register before the read so any later completion can preempt the run.
|
|
153
|
-
instance
|
|
172
|
+
registerAwait(instance, self.name)
|
|
154
173
|
const exit = yield* Workflow.wrapActivityResult(
|
|
155
174
|
engine.deferredResult(self),
|
|
156
175
|
Option.isNone
|
|
@@ -343,6 +362,10 @@ const recordHeld = Effect.fnUntraced(function*<A, E, R>(
|
|
|
343
362
|
suspended: false,
|
|
344
363
|
activityState: { count: 0, latch: Latch.makeUnsafe() }
|
|
345
364
|
}
|
|
365
|
+
// A losing branch parked on a durable wait has already exited when the
|
|
366
|
+
// race settles, so this body owns the waits registered beneath it.
|
|
367
|
+
const owned: Array<string> = []
|
|
368
|
+
awaitOwners.set(local, owned)
|
|
346
369
|
// A parked `effect` interrupts the fiber it runs on. The child fiber
|
|
347
370
|
// keeps that from skipping the suspension handling below.
|
|
348
371
|
const fiber = yield* effect.pipe(
|
|
@@ -350,10 +373,25 @@ const recordHeld = Effect.fnUntraced(function*<A, E, R>(
|
|
|
350
373
|
Effect.onExit((exit) => recordExit(engine, instance, self, exit)),
|
|
351
374
|
Effect.forkChild({ startImmediately: true })
|
|
352
375
|
)
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
376
|
+
return yield* Effect.onInterrupt(Fiber.await(fiber), () => Fiber.interrupt(fiber)).pipe(
|
|
377
|
+
Effect.map((exit) =>
|
|
378
|
+
local.suspended && Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause)
|
|
379
|
+
? Option.none()
|
|
380
|
+
: Option.some(exit)
|
|
381
|
+
),
|
|
382
|
+
// The waits are over once the body has a result. Otherwise every branch
|
|
383
|
+
// parked, or an enclosing race interrupted the body, and the waits move
|
|
384
|
+
// to the enclosing owner, if any, to be released when that race settles.
|
|
385
|
+
Effect.onExit((result) =>
|
|
386
|
+
Effect.sync(() => {
|
|
387
|
+
if (Exit.isSuccess(result) && Option.isSome(result.value)) {
|
|
388
|
+
releaseAwaits(instance, owned)
|
|
389
|
+
} else {
|
|
390
|
+
awaitOwners.get(instance)?.push(...owned)
|
|
391
|
+
}
|
|
392
|
+
})
|
|
393
|
+
)
|
|
394
|
+
)
|
|
357
395
|
}),
|
|
358
396
|
// Every branch of `effect` parked: release the hold and let the enclosing
|
|
359
397
|
// activities finish before suspending. External preemption does not wait.
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import * as Cause from "../Cause.ts"
|
|
14
14
|
import * as Context from "../Context.ts"
|
|
15
|
+
import * as Deferred from "../Deferred.ts"
|
|
15
16
|
import * as Effect from "../Effect.ts"
|
|
16
17
|
import * as Exit from "../Exit.ts"
|
|
17
18
|
import * as Fiber from "../Fiber.ts"
|
|
@@ -75,6 +76,14 @@ export class WorkflowEngine extends Context.Service<
|
|
|
75
76
|
|
|
76
77
|
/**
|
|
77
78
|
* Execute a registered workflow.
|
|
79
|
+
*
|
|
80
|
+
* **Details**
|
|
81
|
+
*
|
|
82
|
+
* Unless `discard` is set, a caller outside any workflow waits for the
|
|
83
|
+
* result. While the execution is suspended, the caller retries on
|
|
84
|
+
* `suspendedRetrySchedule`; engines that observe the final result wake it
|
|
85
|
+
* sooner. `ClusterWorkflowEngine` does so only for callers on the runner
|
|
86
|
+
* that owns the execution.
|
|
78
87
|
*/
|
|
79
88
|
readonly execute: <
|
|
80
89
|
Name extends string,
|
|
@@ -271,8 +280,11 @@ export class WorkflowInstance extends Context.Service<
|
|
|
271
280
|
*/
|
|
272
281
|
cause: Cause.Cause<never> | undefined
|
|
273
282
|
|
|
274
|
-
/**
|
|
275
|
-
|
|
283
|
+
/**
|
|
284
|
+
* Deferred names this run waits on, counted per live wait; their
|
|
285
|
+
* completions preempt the run.
|
|
286
|
+
*/
|
|
287
|
+
readonly awaitedDeferreds: Map<string, number>
|
|
276
288
|
|
|
277
289
|
/** Deferred names this run completed itself; their completions need not wake it. */
|
|
278
290
|
readonly completedDeferreds: Set<string>
|
|
@@ -296,7 +308,7 @@ export class WorkflowInstance extends Context.Service<
|
|
|
296
308
|
interrupted: false,
|
|
297
309
|
abandoned: false,
|
|
298
310
|
cause: undefined,
|
|
299
|
-
awaitedDeferreds: new
|
|
311
|
+
awaitedDeferreds: new Map(),
|
|
300
312
|
completedDeferreds: new Set(),
|
|
301
313
|
activityState: {
|
|
302
314
|
count: 0,
|
|
@@ -414,6 +426,22 @@ export interface Encoded {
|
|
|
414
426
|
workflow: Workflow.Any,
|
|
415
427
|
executionId: string
|
|
416
428
|
) => Effect.Effect<void>
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Waits until a suspended execution has a result other than `Suspended`.
|
|
432
|
+
*
|
|
433
|
+
* **Gotchas**
|
|
434
|
+
*
|
|
435
|
+
* External callers race this with their `suspendedRetrySchedule`, so it may
|
|
436
|
+
* never complete when the engine cannot observe the result. Completing while
|
|
437
|
+
* the execution is still suspended skips the sleep and spends a step of that
|
|
438
|
+
* schedule. A hook that keeps completing early makes the caller spin.
|
|
439
|
+
*/
|
|
440
|
+
readonly awaitComplete?: (
|
|
441
|
+
workflow: Workflow.Any,
|
|
442
|
+
executionId: string
|
|
443
|
+
) => Effect.Effect<void>
|
|
444
|
+
|
|
417
445
|
readonly activityExecute: (
|
|
418
446
|
activity: Activity.Any,
|
|
419
447
|
attempt: number
|
|
@@ -548,7 +576,10 @@ export const makeUnsafe = (options: Encoded): WorkflowEngine["Service"] =>
|
|
|
548
576
|
)
|
|
549
577
|
)
|
|
550
578
|
)
|
|
551
|
-
|
|
579
|
+
// Completion wakes the caller early; the schedule is the fallback.
|
|
580
|
+
yield* options.awaitComplete
|
|
581
|
+
? Effect.raceFirst(sleep, options.awaitComplete(self, executionId))
|
|
582
|
+
: sleep
|
|
552
583
|
}
|
|
553
584
|
}),
|
|
554
585
|
poll: options.poll,
|
|
@@ -685,6 +716,8 @@ export const layerMemory: Layer.Layer<WorkflowEngine> = Layer.effect(WorkflowEng
|
|
|
685
716
|
interrupted: boolean
|
|
686
717
|
resumeRequested: boolean
|
|
687
718
|
fiber: Fiber.Fiber<Workflow.Result<unknown, unknown>> | undefined
|
|
719
|
+
// Completed once a run succeeds with `Complete`, after which it cannot resume.
|
|
720
|
+
readonly done: Deferred.Deferred<void>
|
|
688
721
|
}
|
|
689
722
|
const executions = new Map<string, ExecutionState>()
|
|
690
723
|
|
|
@@ -742,6 +775,11 @@ export const layerMemory: Layer.Layer<WorkflowEngine> = Layer.effect(WorkflowEng
|
|
|
742
775
|
}
|
|
743
776
|
return Effect.forkIn(resume(state.parent), scope)
|
|
744
777
|
}),
|
|
778
|
+
Effect.onExit((exit) => {
|
|
779
|
+
return Exit.isSuccess(exit) && exit.value._tag === "Complete"
|
|
780
|
+
? Deferred.succeed(state.done, void 0)
|
|
781
|
+
: Effect.void
|
|
782
|
+
}),
|
|
745
783
|
Effect.forkIn(entry.scope)
|
|
746
784
|
)
|
|
747
785
|
})
|
|
@@ -773,6 +811,7 @@ export const layerMemory: Layer.Layer<WorkflowEngine> = Layer.effect(WorkflowEng
|
|
|
773
811
|
interrupted: false,
|
|
774
812
|
resumeRequested: false,
|
|
775
813
|
fiber: undefined,
|
|
814
|
+
done: Deferred.makeUnsafe(),
|
|
776
815
|
parent: options.parent?.executionId
|
|
777
816
|
}
|
|
778
817
|
executions.set(options.executionId, state)
|
|
@@ -788,6 +827,11 @@ export const layerMemory: Layer.Layer<WorkflowEngine> = Layer.effect(WorkflowEng
|
|
|
788
827
|
}
|
|
789
828
|
return (yield* exit) as any
|
|
790
829
|
}),
|
|
830
|
+
awaitComplete: (_workflow, executionId) =>
|
|
831
|
+
Effect.suspend(() => {
|
|
832
|
+
const state = executions.get(executionId)
|
|
833
|
+
return state ? Deferred.await(state.done) : Effect.never
|
|
834
|
+
}),
|
|
791
835
|
interrupt: Effect.fnUntraced(function*(_workflow, executionId) {
|
|
792
836
|
const state = executions.get(executionId)
|
|
793
837
|
if (!state) return
|