effect 4.0.0 → 4.0.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.
- package/dist/Cache.d.ts.map +1 -1
- package/dist/Cache.js +20 -16
- package/dist/Cache.js.map +1 -1
- package/dist/Cause.d.ts.map +1 -1
- package/dist/Cause.js +1 -1
- package/dist/Cause.js.map +1 -1
- package/dist/Effect.d.ts +150 -22
- package/dist/Effect.d.ts.map +1 -1
- package/dist/Effect.js +11 -5
- package/dist/Effect.js.map +1 -1
- package/dist/HashRing.d.ts.map +1 -1
- package/dist/HashRing.js +13 -5
- package/dist/HashRing.js.map +1 -1
- package/dist/Pool.d.ts +9 -5
- package/dist/Pool.d.ts.map +1 -1
- package/dist/Pool.js +34 -41
- package/dist/Pool.js.map +1 -1
- package/dist/RcMap.d.ts.map +1 -1
- package/dist/RcMap.js +16 -1
- package/dist/RcMap.js.map +1 -1
- package/dist/ScopedCache.d.ts.map +1 -1
- package/dist/ScopedCache.js +24 -16
- package/dist/ScopedCache.js.map +1 -1
- package/dist/Stream.d.ts +45 -6
- package/dist/Stream.d.ts.map +1 -1
- package/dist/Stream.js +55 -44
- package/dist/Stream.js.map +1 -1
- package/dist/ai/LanguageModel.d.ts +8 -0
- package/dist/ai/LanguageModel.d.ts.map +1 -1
- package/dist/ai/LanguageModel.js +13 -2
- package/dist/ai/LanguageModel.js.map +1 -1
- package/dist/ai/McpSchema.d.ts +508 -508
- package/dist/ai/McpSchema.d.ts.map +1 -1
- package/dist/ai/McpSchema.js +1 -1
- package/dist/ai/McpSchema.js.map +1 -1
- package/dist/ai/McpServer.d.ts.map +1 -1
- package/dist/ai/McpServer.js +11 -3
- package/dist/ai/McpServer.js.map +1 -1
- package/dist/ai/Response.d.ts.map +1 -1
- package/dist/ai/Response.js +22 -12
- package/dist/ai/Response.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2024_11_05.js +1 -0
- package/dist/ai/internal/mcpProtocol/v2024_11_05.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_03_26.js +1 -0
- package/dist/ai/internal/mcpProtocol/v2025_03_26.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_06_18.js +1 -0
- package/dist/ai/internal/mcpProtocol/v2025_06_18.js.map +1 -1
- package/dist/ai/internal/mcpProtocol/v2025_11_25.js +1 -0
- package/dist/ai/internal/mcpProtocol/v2025_11_25.js.map +1 -1
- package/dist/ai/internal/mcpSchema/v2024_11_05.js +3 -1
- package/dist/ai/internal/mcpSchema/v2024_11_05.js.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.d.ts.map +1 -1
- package/dist/cluster/ClusterWorkflowEngine.js +11 -2
- package/dist/cluster/ClusterWorkflowEngine.js.map +1 -1
- package/dist/cluster/Sharding.d.ts.map +1 -1
- package/dist/cluster/Sharding.js +14 -7
- package/dist/cluster/Sharding.js.map +1 -1
- package/dist/cluster/SqlMessageStorage.d.ts.map +1 -1
- package/dist/cluster/SqlMessageStorage.js +21 -12
- package/dist/cluster/SqlMessageStorage.js.map +1 -1
- package/dist/cluster/SqlRunnerStorage.d.ts.map +1 -1
- package/dist/cluster/SqlRunnerStorage.js +30 -44
- package/dist/cluster/SqlRunnerStorage.js.map +1 -1
- package/dist/cluster/internal/entityManager.js +63 -62
- package/dist/cluster/internal/entityManager.js.map +1 -1
- package/dist/cluster/internal/interruptors.js +8 -0
- package/dist/cluster/internal/interruptors.js.map +1 -1
- package/dist/cluster/internal/resourceMap.js +39 -14
- package/dist/cluster/internal/resourceMap.js.map +1 -1
- package/dist/cluster/internal/resourceRef.js +168 -87
- package/dist/cluster/internal/resourceRef.js.map +1 -1
- package/dist/http/HttpMiddleware.d.ts.map +1 -1
- package/dist/http/HttpMiddleware.js +3 -2
- package/dist/http/HttpMiddleware.js.map +1 -1
- package/dist/http/HttpStaticServer.d.ts.map +1 -1
- package/dist/http/HttpStaticServer.js +14 -0
- package/dist/http/HttpStaticServer.js.map +1 -1
- package/dist/http/HttpTraceContext.d.ts +1 -1
- package/dist/http/HttpTraceContext.d.ts.map +1 -1
- package/dist/http/HttpTraceContext.js +4 -4
- package/dist/http/HttpTraceContext.js.map +1 -1
- package/dist/http-api/HttpApiError.d.ts +1 -0
- package/dist/http-api/HttpApiError.d.ts.map +1 -1
- package/dist/http-api/HttpApiError.js +1 -0
- package/dist/http-api/HttpApiError.js.map +1 -1
- package/dist/internal/core.js +43 -2
- package/dist/internal/core.js.map +1 -1
- package/dist/internal/dateTime.js +1 -1
- package/dist/internal/dateTime.js.map +1 -1
- package/dist/internal/effect.js +63 -81
- package/dist/internal/effect.js.map +1 -1
- package/dist/internal/rcRef.js +59 -23
- package/dist/internal/rcRef.js.map +1 -1
- package/dist/internal/schema/fromJsonSchemaDocument.js +11 -8
- package/dist/internal/schema/fromJsonSchemaDocument.js.map +1 -1
- package/dist/rpc/RpcClient.d.ts.map +1 -1
- package/dist/rpc/RpcClient.js +20 -14
- package/dist/rpc/RpcClient.js.map +1 -1
- package/dist/rpc/RpcServer.d.ts.map +1 -1
- package/dist/rpc/RpcServer.js +2 -2
- package/dist/rpc/RpcServer.js.map +1 -1
- package/dist/rpc/Utils.d.ts +2 -3
- package/dist/rpc/Utils.d.ts.map +1 -1
- package/dist/rpc/Utils.js +3 -4
- package/dist/rpc/Utils.js.map +1 -1
- package/dist/workflow/WorkflowEngine.d.ts +2 -0
- package/dist/workflow/WorkflowEngine.d.ts.map +1 -1
- package/dist/workflow/WorkflowEngine.js +1 -0
- package/dist/workflow/WorkflowEngine.js.map +1 -1
- package/package.json +1 -1
- package/src/Cache.ts +22 -16
- package/src/Cause.ts +1 -1
- package/src/Effect.ts +153 -22
- package/src/HashRing.ts +14 -5
- package/src/Pool.ts +28 -36
- package/src/RcMap.ts +26 -2
- package/src/ScopedCache.ts +27 -16
- package/src/Stream.ts +158 -88
- package/src/ai/LanguageModel.ts +27 -2
- package/src/ai/McpSchema.ts +3 -3
- package/src/ai/McpServer.ts +12 -3
- package/src/ai/Response.ts +27 -12
- package/src/ai/internal/mcpProtocol/v2024_11_05.ts +1 -0
- package/src/ai/internal/mcpProtocol/v2025_03_26.ts +1 -0
- package/src/ai/internal/mcpProtocol/v2025_06_18.ts +1 -0
- package/src/ai/internal/mcpProtocol/v2025_11_25.ts +1 -0
- package/src/ai/internal/mcpSchema/v2024_11_05.ts +4 -2
- package/src/cluster/ClusterWorkflowEngine.ts +18 -4
- package/src/cluster/Sharding.ts +24 -24
- package/src/cluster/SqlMessageStorage.ts +26 -13
- package/src/cluster/SqlRunnerStorage.ts +85 -113
- package/src/cluster/internal/entityManager.ts +68 -80
- package/src/cluster/internal/interruptors.ts +13 -0
- package/src/cluster/internal/resourceMap.ts +55 -17
- package/src/cluster/internal/resourceRef.ts +189 -96
- package/src/http/HttpMiddleware.ts +8 -2
- package/src/http/HttpStaticServer.ts +16 -0
- package/src/http/HttpTraceContext.ts +8 -4
- package/src/http-api/HttpApiError.ts +1 -0
- package/src/internal/core.ts +56 -2
- package/src/internal/dateTime.ts +3 -1
- package/src/internal/effect.ts +109 -111
- package/src/internal/rcRef.ts +83 -33
- package/src/internal/schema/fromJsonSchemaDocument.ts +5 -3
- package/src/rpc/RpcClient.ts +26 -22
- package/src/rpc/RpcServer.ts +2 -1
- package/src/rpc/Utils.ts +4 -10
- package/src/workflow/WorkflowEngine.ts +4 -0
package/src/Stream.ts
CHANGED
|
@@ -13861,41 +13861,40 @@ export const scan: {
|
|
|
13861
13861
|
f: (s: S, a: A) => S
|
|
13862
13862
|
): Stream<S, E, R> =>
|
|
13863
13863
|
suspend(() => {
|
|
13864
|
-
|
|
13865
|
-
return
|
|
13866
|
-
|
|
13867
|
-
|
|
13868
|
-
|
|
13869
|
-
|
|
13870
|
-
|
|
13871
|
-
|
|
13872
|
-
|
|
13873
|
-
|
|
13874
|
-
|
|
13875
|
-
|
|
13876
|
-
|
|
13877
|
-
|
|
13878
|
-
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
|
|
13882
|
-
|
|
13883
|
-
|
|
13884
|
-
|
|
13885
|
-
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
|
|
13889
|
-
|
|
13890
|
-
|
|
13891
|
-
|
|
13892
|
-
|
|
13893
|
-
|
|
13894
|
-
|
|
13895
|
-
|
|
13896
|
-
}
|
|
13897
|
-
|
|
13898
|
-
}));
|
|
13864
|
+
const seed = initial()
|
|
13865
|
+
return concat(
|
|
13866
|
+
succeed(seed),
|
|
13867
|
+
fromChannel(Channel.mapAccum(self.channel, () => seed, (state, arr) => {
|
|
13868
|
+
const states = Arr.empty</**
|
|
13869
|
+
* Accumulates state across the stream, emitting the initial state and each updated state.
|
|
13870
|
+
*
|
|
13871
|
+
* **Example** (Scanning stream state)
|
|
13872
|
+
*
|
|
13873
|
+
* ```ts import.meta.vitest
|
|
13874
|
+
* import { Effect, Stream } from "effect"
|
|
13875
|
+
*
|
|
13876
|
+
* const program = Effect.gen(function*() {
|
|
13877
|
+
* const values = yield* Stream.make(1, 2, 3).pipe(
|
|
13878
|
+
* Stream.scan(() => 0, (acc, n) => acc + n),
|
|
13879
|
+
* Stream.runCollect
|
|
13880
|
+
* )
|
|
13881
|
+
* values // => [ 0, 1, 3, 6 ]
|
|
13882
|
+
* })
|
|
13883
|
+
*
|
|
13884
|
+
* await Effect.runPromise(program)
|
|
13885
|
+
* ```
|
|
13886
|
+
*
|
|
13887
|
+
* @category accumulation
|
|
13888
|
+
* @since 2.0.0
|
|
13889
|
+
*/
|
|
13890
|
+
S>() as Arr.NonEmptyArray<S>
|
|
13891
|
+
for (let index = 0; index < arr.length; index++) {
|
|
13892
|
+
state = f(state, arr[index])
|
|
13893
|
+
states.push(state)
|
|
13894
|
+
}
|
|
13895
|
+
return [state, Arr.of(states)]
|
|
13896
|
+
}))
|
|
13897
|
+
);
|
|
13899
13898
|
}))
|
|
13900
13899
|
|
|
13901
13900
|
/**
|
|
@@ -14329,37 +14328,36 @@ const throttleShapeEffect = <A, E, R, E2, R2>(
|
|
|
14329
14328
|
const durationMs = Duration.toMillis(Duration.fromInputUnsafe(duration))
|
|
14330
14329
|
const max = units + burst < 0 ? Number.POSITIVE_INFINITY : units + burst
|
|
14331
14330
|
let tokens = units
|
|
14332
|
-
let
|
|
14331
|
+
let timestampNanos = clock.monotonicTimeNanosUnsafe()
|
|
14333
14332
|
|
|
14334
14333
|
return Effect.succeed(Effect.flatMap(pull, (arr) =>
|
|
14335
14334
|
Effect.flatMap(cost(arr), (weight) => {
|
|
14336
|
-
const
|
|
14337
|
-
const elapsed =
|
|
14335
|
+
const currentNanos = clock.monotonicTimeNanosUnsafe()
|
|
14336
|
+
const elapsed = Number(currentNanos - timestampNanos) / 1_000_000
|
|
14338
14337
|
const cycles = elapsed / durationMs
|
|
14339
14338
|
const sum = tokens + (cycles * units)
|
|
14340
|
-
const available =
|
|
14339
|
+
const available = Math.min(sum, max)
|
|
14341
14340
|
const remaining = available - weight
|
|
14342
14341
|
|
|
14343
14342
|
if (remaining >= 0) {
|
|
14344
14343
|
tokens = remaining
|
|
14345
|
-
|
|
14344
|
+
timestampNanos = currentNanos
|
|
14346
14345
|
return Effect.succeed(arr)
|
|
14347
14346
|
}
|
|
14348
14347
|
|
|
14349
|
-
// Calculate delay needed
|
|
14350
14348
|
const waitCycles = -remaining / units
|
|
14351
14349
|
const delayMs = Math.max(0, waitCycles * durationMs)
|
|
14352
14350
|
|
|
14353
14351
|
if (delayMs > 0) {
|
|
14354
14352
|
return Effect.flatMap(Effect.sleep(delayMs), () => {
|
|
14355
14353
|
tokens = remaining
|
|
14356
|
-
|
|
14354
|
+
timestampNanos = currentNanos
|
|
14357
14355
|
return Effect.succeed(arr)
|
|
14358
14356
|
})
|
|
14359
14357
|
}
|
|
14360
14358
|
|
|
14361
14359
|
tokens = remaining
|
|
14362
|
-
|
|
14360
|
+
timestampNanos = currentNanos
|
|
14363
14361
|
return Effect.succeed(arr)
|
|
14364
14362
|
})))
|
|
14365
14363
|
}))
|
|
@@ -14629,8 +14627,9 @@ export const grouped: {
|
|
|
14629
14627
|
*
|
|
14630
14628
|
* **Details**
|
|
14631
14629
|
*
|
|
14632
|
-
*
|
|
14633
|
-
* are
|
|
14630
|
+
* The duration starts when the first element of a group arrives, so an idle
|
|
14631
|
+
* stream does not wake up. Finite fractional chunk sizes are rounded down.
|
|
14632
|
+
* `NaN` and non-positive sizes are treated as `1`.
|
|
14634
14633
|
*
|
|
14635
14634
|
* **Example** (Grouping elements by size or time)
|
|
14636
14635
|
*
|
|
@@ -14658,8 +14657,9 @@ export const groupedWithin: {
|
|
|
14658
14657
|
*
|
|
14659
14658
|
* **Details**
|
|
14660
14659
|
*
|
|
14661
|
-
*
|
|
14662
|
-
* are
|
|
14660
|
+
* The duration starts when the first element of a group arrives, so an idle
|
|
14661
|
+
* stream does not wake up. Finite fractional chunk sizes are rounded down.
|
|
14662
|
+
* `NaN` and non-positive sizes are treated as `1`.
|
|
14663
14663
|
*
|
|
14664
14664
|
* **Example** (Grouping elements by size or time)
|
|
14665
14665
|
*
|
|
@@ -14687,8 +14687,9 @@ export const groupedWithin: {
|
|
|
14687
14687
|
*
|
|
14688
14688
|
* **Details**
|
|
14689
14689
|
*
|
|
14690
|
-
*
|
|
14691
|
-
* are
|
|
14690
|
+
* The duration starts when the first element of a group arrives, so an idle
|
|
14691
|
+
* stream does not wake up. Finite fractional chunk sizes are rounded down.
|
|
14692
|
+
* `NaN` and non-positive sizes are treated as `1`.
|
|
14692
14693
|
*
|
|
14693
14694
|
* **Example** (Grouping elements by size or time)
|
|
14694
14695
|
*
|
|
@@ -15439,6 +15440,18 @@ export const aggregate: {
|
|
|
15439
15440
|
* **Details**
|
|
15440
15441
|
*
|
|
15441
15442
|
* The schedule can flush the current aggregation even if the sink has not finished.
|
|
15443
|
+
* It is stepped at most once per aggregation, when the aggregation receives its
|
|
15444
|
+
* first element, with the previous aggregation's output as input. An aggregation
|
|
15445
|
+
* the sink completes immediately, such as one built from leftovers, may finish
|
|
15446
|
+
* without stepping the schedule.
|
|
15447
|
+
*
|
|
15448
|
+
* Time between aggregations is hidden from the schedule, so an idle stream does
|
|
15449
|
+
* not run it. Time-based schedules such as `Schedule.fixed` and
|
|
15450
|
+
* `Schedule.upTo({ duration })` only count time spent aggregating; use
|
|
15451
|
+
* `Schedule.spaced` for a flush timer.
|
|
15452
|
+
*
|
|
15453
|
+
* When the schedule ends, the stream emits the current aggregation and any sink
|
|
15454
|
+
* leftovers, then ends without pulling more from upstream.
|
|
15442
15455
|
*
|
|
15443
15456
|
* **Example** (Aggregating with a sink and schedule)
|
|
15444
15457
|
*
|
|
@@ -15468,6 +15481,18 @@ export const aggregateWithin: {
|
|
|
15468
15481
|
* **Details**
|
|
15469
15482
|
*
|
|
15470
15483
|
* The schedule can flush the current aggregation even if the sink has not finished.
|
|
15484
|
+
* It is stepped at most once per aggregation, when the aggregation receives its
|
|
15485
|
+
* first element, with the previous aggregation's output as input. An aggregation
|
|
15486
|
+
* the sink completes immediately, such as one built from leftovers, may finish
|
|
15487
|
+
* without stepping the schedule.
|
|
15488
|
+
*
|
|
15489
|
+
* Time between aggregations is hidden from the schedule, so an idle stream does
|
|
15490
|
+
* not run it. Time-based schedules such as `Schedule.fixed` and
|
|
15491
|
+
* `Schedule.upTo({ duration })` only count time spent aggregating; use
|
|
15492
|
+
* `Schedule.spaced` for a flush timer.
|
|
15493
|
+
*
|
|
15494
|
+
* When the schedule ends, the stream emits the current aggregation and any sink
|
|
15495
|
+
* leftovers, then ends without pulling more from upstream.
|
|
15471
15496
|
*
|
|
15472
15497
|
* **Example** (Aggregating with a sink and schedule)
|
|
15473
15498
|
*
|
|
@@ -15500,6 +15525,18 @@ export const aggregateWithin: {
|
|
|
15500
15525
|
* **Details**
|
|
15501
15526
|
*
|
|
15502
15527
|
* The schedule can flush the current aggregation even if the sink has not finished.
|
|
15528
|
+
* It is stepped at most once per aggregation, when the aggregation receives its
|
|
15529
|
+
* first element, with the previous aggregation's output as input. An aggregation
|
|
15530
|
+
* the sink completes immediately, such as one built from leftovers, may finish
|
|
15531
|
+
* without stepping the schedule.
|
|
15532
|
+
*
|
|
15533
|
+
* Time between aggregations is hidden from the schedule, so an idle stream does
|
|
15534
|
+
* not run it. Time-based schedules such as `Schedule.fixed` and
|
|
15535
|
+
* `Schedule.upTo({ duration })` only count time spent aggregating; use
|
|
15536
|
+
* `Schedule.spaced` for a flush timer.
|
|
15537
|
+
*
|
|
15538
|
+
* When the schedule ends, the stream emits the current aggregation and any sink
|
|
15539
|
+
* leftovers, then ends without pulling more from upstream.
|
|
15503
15540
|
*
|
|
15504
15541
|
* **Example** (Aggregating with a sink and schedule)
|
|
15505
15542
|
*
|
|
@@ -15543,6 +15580,18 @@ export const aggregateWithin: {
|
|
|
15543
15580
|
* **Details**
|
|
15544
15581
|
*
|
|
15545
15582
|
* The schedule can flush the current aggregation even if the sink has not finished.
|
|
15583
|
+
* It is stepped at most once per aggregation, when the aggregation receives its
|
|
15584
|
+
* first element, with the previous aggregation's output as input. An aggregation
|
|
15585
|
+
* the sink completes immediately, such as one built from leftovers, may finish
|
|
15586
|
+
* without stepping the schedule.
|
|
15587
|
+
*
|
|
15588
|
+
* Time between aggregations is hidden from the schedule, so an idle stream does
|
|
15589
|
+
* not run it. Time-based schedules such as `Schedule.fixed` and
|
|
15590
|
+
* `Schedule.upTo({ duration })` only count time spent aggregating; use
|
|
15591
|
+
* `Schedule.spaced` for a flush timer.
|
|
15592
|
+
*
|
|
15593
|
+
* When the schedule ends, the stream emits the current aggregation and any sink
|
|
15594
|
+
* leftovers, then ends without pulling more from upstream.
|
|
15546
15595
|
*
|
|
15547
15596
|
* **Example** (Aggregating with a sink and schedule)
|
|
15548
15597
|
*
|
|
@@ -15571,6 +15620,18 @@ export const aggregateWithin: {
|
|
|
15571
15620
|
* **Details**
|
|
15572
15621
|
*
|
|
15573
15622
|
* The schedule can flush the current aggregation even if the sink has not finished.
|
|
15623
|
+
* It is stepped at most once per aggregation, when the aggregation receives its
|
|
15624
|
+
* first element, with the previous aggregation's output as input. An aggregation
|
|
15625
|
+
* the sink completes immediately, such as one built from leftovers, may finish
|
|
15626
|
+
* without stepping the schedule.
|
|
15627
|
+
*
|
|
15628
|
+
* Time between aggregations is hidden from the schedule, so an idle stream does
|
|
15629
|
+
* not run it. Time-based schedules such as `Schedule.fixed` and
|
|
15630
|
+
* `Schedule.upTo({ duration })` only count time spent aggregating; use
|
|
15631
|
+
* `Schedule.spaced` for a flush timer.
|
|
15632
|
+
*
|
|
15633
|
+
* When the schedule ends, the stream emits the current aggregation and any sink
|
|
15634
|
+
* leftovers, then ends without pulling more from upstream.
|
|
15574
15635
|
*
|
|
15575
15636
|
* **Example** (Aggregating with a sink and schedule)
|
|
15576
15637
|
*
|
|
@@ -15597,25 +15658,41 @@ export const aggregateWithin: {
|
|
|
15597
15658
|
capacity: 0
|
|
15598
15659
|
})
|
|
15599
15660
|
|
|
15600
|
-
// upstream -> buffer
|
|
15601
15661
|
yield* pull.pipe(
|
|
15602
15662
|
pullLatch.whenOpen,
|
|
15603
15663
|
Effect.flatMap((arr) => {
|
|
15604
15664
|
pullLatch.closeUnsafe()
|
|
15605
15665
|
return Queue.offer(buffer, arr)
|
|
15606
15666
|
}),
|
|
15607
|
-
Effect.forever, //
|
|
15667
|
+
Effect.forever, // Keep autoYield enabled so the schedule can run.
|
|
15608
15668
|
Effect.catchCause((cause) => Queue.failCause(buffer, cause)),
|
|
15609
15669
|
Effect.forkIn(scope)
|
|
15610
15670
|
)
|
|
15611
15671
|
|
|
15612
|
-
// schedule
|
|
15672
|
+
// The schedule clock excludes time between aggregations.
|
|
15673
|
+
const clock = yield* Clock
|
|
15674
|
+
const step = yield* Schedule.toStep(schedule)
|
|
15675
|
+
const hasInput = Latch.makeUnsafe(false)
|
|
15676
|
+
let scheduleTime = clock.currentTimeMillisUnsafe()
|
|
15677
|
+
let openedAt = 0
|
|
15613
15678
|
let lastOutput = Option.none</**
|
|
15614
15679
|
* Aggregates elements with a sink, emitting each result when the sink completes or the schedule triggers.
|
|
15615
15680
|
*
|
|
15616
15681
|
* **Details**
|
|
15617
15682
|
*
|
|
15618
15683
|
* The schedule can flush the current aggregation even if the sink has not finished.
|
|
15684
|
+
* It is stepped at most once per aggregation, when the aggregation receives its
|
|
15685
|
+
* first element, with the previous aggregation's output as input. An aggregation
|
|
15686
|
+
* the sink completes immediately, such as one built from leftovers, may finish
|
|
15687
|
+
* without stepping the schedule.
|
|
15688
|
+
*
|
|
15689
|
+
* Time between aggregations is hidden from the schedule, so an idle stream does
|
|
15690
|
+
* not run it. Time-based schedules such as `Schedule.fixed` and
|
|
15691
|
+
* `Schedule.upTo({ duration })` only count time spent aggregating; use
|
|
15692
|
+
* `Schedule.spaced` for a flush timer.
|
|
15693
|
+
*
|
|
15694
|
+
* When the schedule ends, the stream emits the current aggregation and any sink
|
|
15695
|
+
* leftovers, then ends without pulling more from upstream.
|
|
15619
15696
|
*
|
|
15620
15697
|
* **Example** (Aggregating with a sink and schedule)
|
|
15621
15698
|
*
|
|
@@ -15640,58 +15717,51 @@ export const aggregateWithin: {
|
|
|
15640
15717
|
*/
|
|
15641
15718
|
B>()
|
|
15642
15719
|
let leftover: Arr.NonEmptyReadonlyArray<A2> | undefined
|
|
15643
|
-
|
|
15644
|
-
|
|
15645
|
-
|
|
15646
|
-
|
|
15647
|
-
|
|
15648
|
-
|
|
15649
|
-
|
|
15650
|
-
|
|
15651
|
-
|
|
15652
|
-
|
|
15653
|
-
|
|
15654
|
-
|
|
15655
|
-
|
|
15656
|
-
E
|
|
15657
|
-
> = Queue.take(buffer).pipe(
|
|
15658
|
-
Effect.flatMap((arr) => {
|
|
15659
|
-
if (arr === scheduleStep) {
|
|
15660
|
-
return Cause.done()
|
|
15661
|
-
}
|
|
15662
|
-
sinkHasInput = true
|
|
15663
|
-
return Effect.succeed(arr)
|
|
15664
|
-
})
|
|
15720
|
+
const onInput = <X>(chunk: X): Effect.Effect<X> => {
|
|
15721
|
+
if (hasInput.openUnsafe()) {
|
|
15722
|
+
openedAt = clock.currentTimeMillisUnsafe()
|
|
15723
|
+
}
|
|
15724
|
+
return Effect.succeed(chunk)
|
|
15725
|
+
}
|
|
15726
|
+
const stepToBuffer: Pull.Pull<never, E3, void, R3> = hasInput.await.pipe(
|
|
15727
|
+
Effect.flatMap(() => step(scheduleTime, lastOutput)),
|
|
15728
|
+
Effect.flatMap(([, delay]) => Effect.sleep(delay)),
|
|
15729
|
+
Effect.flatMap(() => Queue.offer(buffer, scheduleStep)),
|
|
15730
|
+
// End input so the sink drains leftovers without further upstream pulls.
|
|
15731
|
+
Pull.catchDone(() => Queue.end(buffer)),
|
|
15732
|
+
Effect.flatMap(() => Effect.never)
|
|
15665
15733
|
)
|
|
15666
15734
|
|
|
15667
15735
|
const sinkUpstream = Effect.suspend((): Pull.Pull<Arr.NonEmptyReadonlyArray<A | A2>, E> => {
|
|
15668
15736
|
if (leftover !== undefined) {
|
|
15669
15737
|
const chunk = leftover
|
|
15670
15738
|
leftover = undefined
|
|
15671
|
-
|
|
15672
|
-
|
|
15739
|
+
return onInput(chunk)
|
|
15740
|
+
}
|
|
15741
|
+
if (buffer.state._tag === "Open") {
|
|
15742
|
+
pullLatch.openUnsafe()
|
|
15673
15743
|
}
|
|
15674
|
-
|
|
15675
|
-
return pullFromBuffer
|
|
15744
|
+
return Effect.flatMap(Queue.take(buffer), (arr) => arr === scheduleStep ? Cause.done() : onInput(arr))
|
|
15676
15745
|
})
|
|
15677
|
-
const
|
|
15678
|
-
|
|
15679
|
-
|
|
15746
|
+
const emit = Effect.flatMap(([value, leftover_]: Sink.End<B, A2>) => {
|
|
15747
|
+
if (hasInput.isOpen()) {
|
|
15748
|
+
scheduleTime += clock.currentTimeMillisUnsafe() - openedAt
|
|
15749
|
+
} else if (buffer.state._tag === "Done") {
|
|
15750
|
+
return Cause.done()
|
|
15751
|
+
}
|
|
15680
15752
|
lastOutput = Option.some(value)
|
|
15681
15753
|
leftover = leftover_
|
|
15682
15754
|
return Effect.succeed(Arr.of(value))
|
|
15683
15755
|
})
|
|
15684
15756
|
|
|
15685
|
-
return Effect.suspend(() => {
|
|
15686
|
-
// if the buffer has exited and there is no more data to process
|
|
15757
|
+
return Effect.suspend((): Pull.Pull<Arr.NonEmptyReadonlyArray<B>, E | E2 | E3, void, R2 | R3> => {
|
|
15687
15758
|
if (buffer.state._tag === "Done" && leftover === undefined) {
|
|
15688
15759
|
return buffer.state.exit as Exit.Exit<never, Cause.Done<void> | E>
|
|
15689
15760
|
}
|
|
15690
|
-
|
|
15691
|
-
|
|
15692
|
-
|
|
15693
|
-
|
|
15694
|
-
)
|
|
15761
|
+
hasInput.closeUnsafe()
|
|
15762
|
+
const pull = emit(Effect.suspend(() => sink.transform(sinkUpstream as any, scope)))
|
|
15763
|
+
return buffer.state._tag === "Open" ? Effect.raceFirst(pull, stepToBuffer) : pull
|
|
15764
|
+
})
|
|
15695
15765
|
}))))
|
|
15696
15766
|
|
|
15697
15767
|
/**
|
package/src/ai/LanguageModel.ts
CHANGED
|
@@ -107,6 +107,13 @@ export const TypeId: TypeId = "~effect/ai/LanguageModel"
|
|
|
107
107
|
export interface LanguageModel {
|
|
108
108
|
readonly [TypeId]: TypeId
|
|
109
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Whether the effective provider configuration supports system messages in
|
|
112
|
+
* history. Evaluate in the request's context to respect scoped overrides.
|
|
113
|
+
* Placement restrictions may apply; an absent capability means unknown support.
|
|
114
|
+
*/
|
|
115
|
+
readonly supportsSystemMessagesInHistory?: Effect.Effect<boolean> | undefined
|
|
116
|
+
|
|
110
117
|
/**
|
|
111
118
|
* Generate text using the language model.
|
|
112
119
|
*/
|
|
@@ -833,6 +840,9 @@ export const make: (params: {
|
|
|
833
840
|
* for structured output generation.
|
|
834
841
|
*/
|
|
835
842
|
readonly codecTransformer?: CodecTransformer | undefined
|
|
843
|
+
|
|
844
|
+
/** Whether the effective provider configuration supports system messages in history. */
|
|
845
|
+
readonly supportsSystemMessagesInHistory?: Effect.Effect<boolean> | undefined
|
|
836
846
|
}) => Effect.Effect<LanguageModel> = Effect.fnUntraced(function*(params) {
|
|
837
847
|
const codecTransformer = params.codecTransformer ?? defaultCodecTransformer
|
|
838
848
|
|
|
@@ -1749,6 +1759,7 @@ export const make: (params: {
|
|
|
1749
1759
|
|
|
1750
1760
|
return LanguageModel.of({
|
|
1751
1761
|
[TypeId]: TypeId,
|
|
1762
|
+
supportsSystemMessagesInHistory: params.supportsSystemMessagesInHistory,
|
|
1752
1763
|
generateText: generateText as LanguageModel["generateText"],
|
|
1753
1764
|
generateObject: generateObject as LanguageModel["generateObject"],
|
|
1754
1765
|
streamText: streamText as LanguageModel["streamText"]
|
|
@@ -2417,18 +2428,32 @@ const resolveToolCalls = <Tools extends Record<string, Tool.Any>>(
|
|
|
2417
2428
|
// Utilities
|
|
2418
2429
|
// =============================================================================
|
|
2419
2430
|
|
|
2431
|
+
// Stable parameter-mode copies let Response reuse each tool's part schemas.
|
|
2432
|
+
const parameterModeTools = new WeakMap<Tool.Any, { encoded?: Tool.Any; opaque?: Tool.Any }>()
|
|
2433
|
+
|
|
2434
|
+
const withParameterMode = (tool: Tool.Any, mode: "encoded" | "opaque"): Tool.Any => {
|
|
2435
|
+
let tools = parameterModeTools.get(tool)
|
|
2436
|
+
if (tools === undefined) {
|
|
2437
|
+
tools = {}
|
|
2438
|
+
parameterModeTools.set(tool, tools)
|
|
2439
|
+
}
|
|
2440
|
+
return tools[mode] ??= tool.setParameters(
|
|
2441
|
+
mode === "encoded" ? Schema.toEncoded(tool.parametersSchema) : Schema.Unknown
|
|
2442
|
+
)
|
|
2443
|
+
}
|
|
2444
|
+
|
|
2420
2445
|
const makeToolkitWithEncodedParameters = <Tools extends Record<string, Tool.Any>>(
|
|
2421
2446
|
toolkit: Toolkit.WithHandler<Tools>
|
|
2422
2447
|
): Toolkit.Any =>
|
|
2423
2448
|
Toolkit.make(
|
|
2424
|
-
...Object.values(toolkit.tools).map((tool) =>
|
|
2449
|
+
...Object.values(toolkit.tools).map((tool) => withParameterMode(tool, "encoded"))
|
|
2425
2450
|
)
|
|
2426
2451
|
|
|
2427
2452
|
const makeToolkitWithOpaqueParameters = <Tools extends Record<string, Tool.Any>>(
|
|
2428
2453
|
toolkit: Toolkit.WithHandler<Tools>
|
|
2429
2454
|
): Toolkit.Any =>
|
|
2430
2455
|
Toolkit.make(
|
|
2431
|
-
...Object.values(toolkit.tools).map((tool) => tool
|
|
2456
|
+
...Object.values(toolkit.tools).map((tool) => withParameterMode(tool, "opaque"))
|
|
2432
2457
|
)
|
|
2433
2458
|
|
|
2434
2459
|
// Provider-executed tools bypass Toolkit, so validate their parameters here.
|
package/src/ai/McpSchema.ts
CHANGED
|
@@ -86,10 +86,10 @@ export const optionalWithDefault = <S extends Schema.Constraint & Schema.Without
|
|
|
86
86
|
*/
|
|
87
87
|
export const optional = <S extends Schema.Constraint>(
|
|
88
88
|
schema: S
|
|
89
|
-
): Schema.decodeTo<Schema.optional<S
|
|
89
|
+
): Schema.decodeTo<Schema.toType<Schema.optional<S>>, Schema.optionalKey<S>> =>
|
|
90
90
|
Schema.optionalKey(schema).pipe(
|
|
91
|
-
Schema.decodeTo(Schema.optional(schema), {
|
|
92
|
-
decode: SchemaGetter.passthrough()
|
|
91
|
+
Schema.decodeTo(Schema.toType(Schema.optional(schema)), {
|
|
92
|
+
decode: SchemaGetter.passthrough(),
|
|
93
93
|
encode: SchemaGetter.transformOptional(Option.flatMap(Option.fromUndefinedOr))
|
|
94
94
|
})
|
|
95
95
|
)
|
package/src/ai/McpServer.ts
CHANGED
|
@@ -1620,7 +1620,7 @@ const layerMcpProtocolHttp = (options: {
|
|
|
1620
1620
|
const hasMultipleMessages = response.body._tag === "Uint8Array" &&
|
|
1621
1621
|
response.body.body.subarray(0, -1).includes(10)
|
|
1622
1622
|
return admission.isSubscription || response.body._tag === "Stream" || hasMultipleMessages
|
|
1623
|
-
? toServerSentEvents(response)
|
|
1623
|
+
? toServerSentEvents(response, admission.isSubscription)
|
|
1624
1624
|
: response
|
|
1625
1625
|
})
|
|
1626
1626
|
return yield* admission.acknowledge
|
|
@@ -1713,7 +1713,7 @@ function mcpJsonRpcSerialization(options?: {
|
|
|
1713
1713
|
})
|
|
1714
1714
|
}
|
|
1715
1715
|
|
|
1716
|
-
const toServerSentEvents = (response: HttpServerResponse.HttpServerResponse) => {
|
|
1716
|
+
const toServerSentEvents = (response: HttpServerResponse.HttpServerResponse, keepAlive: boolean) => {
|
|
1717
1717
|
const encoder = new TextEncoder()
|
|
1718
1718
|
const decoder = new TextDecoder()
|
|
1719
1719
|
const frame = (data: Uint8Array) =>
|
|
@@ -1726,7 +1726,16 @@ const toServerSentEvents = (response: HttpServerResponse.HttpServerResponse) =>
|
|
|
1726
1726
|
contentType: "text/event-stream"
|
|
1727
1727
|
}
|
|
1728
1728
|
if (response.body._tag === "Stream") {
|
|
1729
|
-
|
|
1729
|
+
const events = response.body.stream.pipe(Stream.map(frame))
|
|
1730
|
+
if (!keepAlive) {
|
|
1731
|
+
return HttpServerResponse.stream(events, options)
|
|
1732
|
+
}
|
|
1733
|
+
// Keep a native timer pending so workerd does not treat idle subscriptions as hung requests.
|
|
1734
|
+
const keepAliveComments = Stream.tick("15 seconds").pipe(
|
|
1735
|
+
Stream.drop(1),
|
|
1736
|
+
Stream.map(() => encoder.encode(": keepalive\n\n"))
|
|
1737
|
+
)
|
|
1738
|
+
return HttpServerResponse.stream(Stream.merge(events, keepAliveComments, { haltStrategy: "left" }), options)
|
|
1730
1739
|
}
|
|
1731
1740
|
if (response.body._tag === "Uint8Array") {
|
|
1732
1741
|
return HttpServerResponse.uint8Array(frame(response.body.body), options)
|
package/src/ai/Response.ts
CHANGED
|
@@ -152,6 +152,24 @@ export type AllPartsEncoded =
|
|
|
152
152
|
| FinishPartEncoded
|
|
153
153
|
| ErrorPartEncoded
|
|
154
154
|
|
|
155
|
+
// Tools are immutable, so response schemas can share their per-tool parts.
|
|
156
|
+
const toolPartSchemaCache = new WeakMap<Tool.Any, {
|
|
157
|
+
readonly toolCall: Schema.Top
|
|
158
|
+
readonly toolResult: Schema.Top
|
|
159
|
+
}>()
|
|
160
|
+
|
|
161
|
+
const toolPartSchemas = (tool: Tool.Any) => {
|
|
162
|
+
let parts = toolPartSchemaCache.get(tool)
|
|
163
|
+
if (parts === undefined) {
|
|
164
|
+
parts = {
|
|
165
|
+
toolCall: ToolCallPart(tool.name, tool.parametersSchema),
|
|
166
|
+
toolResult: ToolResultPart(tool.name, tool.successSchema, Tool.failureResultSchema(tool))
|
|
167
|
+
}
|
|
168
|
+
toolPartSchemaCache.set(tool, parts)
|
|
169
|
+
}
|
|
170
|
+
return parts
|
|
171
|
+
}
|
|
172
|
+
|
|
155
173
|
/**
|
|
156
174
|
* Creates a Schema for all response parts based on a toolkit.
|
|
157
175
|
*
|
|
@@ -192,10 +210,9 @@ export const AllParts = <T extends Toolkit.Any | Toolkit.WithHandler<any>>(
|
|
|
192
210
|
const toolCalls: Array<Schema.Top> = []
|
|
193
211
|
const toolResults: Array<Schema.Top> = []
|
|
194
212
|
for (const tool of Object.values(toolkit.tools as Record<string, Tool.Any>)) {
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
toolResults.push(toolResult)
|
|
213
|
+
const parts = toolPartSchemas(tool)
|
|
214
|
+
toolCalls.push(parts.toolCall)
|
|
215
|
+
toolResults.push(parts.toolResult)
|
|
199
216
|
}
|
|
200
217
|
return Schema.Union([
|
|
201
218
|
TextPart,
|
|
@@ -287,10 +304,9 @@ export const Part = <T extends Toolkit.Any | Toolkit.WithHandler<any>>(
|
|
|
287
304
|
const toolCalls: Array<Schema.Top> = []
|
|
288
305
|
const toolResults: Array<Schema.Top> = []
|
|
289
306
|
for (const tool of Object.values(toolkit.tools as Record<string, Tool.Any>)) {
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
toolResults.push(toolResult)
|
|
307
|
+
const parts = toolPartSchemas(tool)
|
|
308
|
+
toolCalls.push(parts.toolCall)
|
|
309
|
+
toolResults.push(parts.toolResult)
|
|
294
310
|
}
|
|
295
311
|
return Schema.Union([
|
|
296
312
|
TextPart,
|
|
@@ -385,10 +401,9 @@ export const StreamPart = <T extends Toolkit.Any | Toolkit.WithHandler<any>>(
|
|
|
385
401
|
const toolCalls: Array<Schema.Top> = []
|
|
386
402
|
const toolResults: Array<Schema.Top> = []
|
|
387
403
|
for (const tool of Object.values(toolkit.tools as Record<string, Tool.Any>)) {
|
|
388
|
-
const
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
toolResults.push(toolResult)
|
|
404
|
+
const parts = toolPartSchemas(tool)
|
|
405
|
+
toolCalls.push(parts.toolCall)
|
|
406
|
+
toolResults.push(parts.toolResult)
|
|
392
407
|
}
|
|
393
408
|
return Schema.Union([
|
|
394
409
|
TextStartPart,
|
|
@@ -53,6 +53,7 @@ const projectCapabilities = (
|
|
|
53
53
|
capabilities: McpCore.CanonicalServerCapabilities
|
|
54
54
|
): typeof McpSchema.ServerCapabilities.Type => ({
|
|
55
55
|
experimental: capabilities.experimental,
|
|
56
|
+
extensions: capabilities.extensions,
|
|
56
57
|
logging: capabilities.logging ? {} : undefined,
|
|
57
58
|
prompts: capabilities.prompts,
|
|
58
59
|
resources: capabilities.resources,
|
|
@@ -134,6 +134,7 @@ export const protocol = McpProtocol.make({
|
|
|
134
134
|
protocolVersion: McpSchema.protocolVersion,
|
|
135
135
|
capabilities: ({
|
|
136
136
|
experimental: result.capabilities.experimental,
|
|
137
|
+
extensions: result.capabilities.extensions,
|
|
137
138
|
logging: result.capabilities.logging ? {} : undefined,
|
|
138
139
|
completions: result.capabilities.completions ? {} : undefined,
|
|
139
140
|
prompts: result.capabilities.prompts,
|
|
@@ -150,6 +150,7 @@ export const protocol = McpProtocol.make({
|
|
|
150
150
|
protocolVersion: McpSchema.protocolVersion,
|
|
151
151
|
capabilities: ({
|
|
152
152
|
experimental: result.capabilities.experimental,
|
|
153
|
+
extensions: result.capabilities.extensions,
|
|
153
154
|
logging: result.capabilities.logging ? {} : undefined,
|
|
154
155
|
completions: result.capabilities.completions ? {} : undefined,
|
|
155
156
|
prompts: result.capabilities.prompts,
|
|
@@ -145,6 +145,7 @@ export const protocol = McpProtocol.make({
|
|
|
145
145
|
protocolVersion: McpSchema.protocolVersion,
|
|
146
146
|
capabilities: ({
|
|
147
147
|
experimental: result.capabilities.experimental,
|
|
148
|
+
extensions: result.capabilities.extensions,
|
|
148
149
|
logging: result.capabilities.logging ? {} : undefined,
|
|
149
150
|
completions: result.capabilities.completions ? {} : undefined,
|
|
150
151
|
prompts: result.capabilities.prompts,
|
|
@@ -22,9 +22,9 @@ export const protocolVersion = "2024-11-05"
|
|
|
22
22
|
*/
|
|
23
23
|
export const optional = <S extends Schema.Constraint>(
|
|
24
24
|
schema: S
|
|
25
|
-
): Schema.decodeTo<Schema.optional<S
|
|
25
|
+
): Schema.decodeTo<Schema.toType<Schema.optional<S>>, Schema.optionalKey<S>> =>
|
|
26
26
|
Schema.optionalKey(schema).pipe(
|
|
27
|
-
Schema.decodeTo(Schema.optional(schema), {
|
|
27
|
+
Schema.decodeTo(Schema.toType(Schema.optional(schema)), {
|
|
28
28
|
decode: SchemaGetter.passthrough(),
|
|
29
29
|
encode: SchemaGetter.transformOptional(Option.flatMap(Option.fromUndefinedOr))
|
|
30
30
|
})
|
|
@@ -111,6 +111,7 @@ export const Implementation = Schema.Struct({
|
|
|
111
111
|
* @internal
|
|
112
112
|
*/
|
|
113
113
|
export const ClientCapabilities = Schema.Struct({
|
|
114
|
+
extensions: optional(Schema.Record(Schema.TemplateLiteral([Schema.String, "/", Schema.String]), Schema.Json)),
|
|
114
115
|
experimental: optional(Schema.Record(Schema.String, JsonObject)),
|
|
115
116
|
roots: optional(Schema.Struct({
|
|
116
117
|
listChanged: optional(Schema.Boolean)
|
|
@@ -122,6 +123,7 @@ export const ClientCapabilities = Schema.Struct({
|
|
|
122
123
|
* @internal
|
|
123
124
|
*/
|
|
124
125
|
export const ServerCapabilities = Schema.Struct({
|
|
126
|
+
extensions: optional(Schema.Record(Schema.TemplateLiteral([Schema.String, "/", Schema.String]), Schema.Json)),
|
|
125
127
|
experimental: optional(Schema.Record(Schema.String, JsonObject)),
|
|
126
128
|
logging: optional(JsonObject),
|
|
127
129
|
prompts: optional(Schema.Struct({
|