@effect-uai/core 0.18.0 → 0.19.0-dev-20261109183959
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/Content-D_Qfn8Ja.d.mts +48 -0
- package/dist/Content-D_Qfn8Ja.d.mts.map +1 -0
- package/dist/File-B923KvZ9.d.mts +46 -0
- package/dist/File-B923KvZ9.d.mts.map +1 -0
- package/dist/{Image-Cv6iBLTy.d.mts → Image-Bzc1H_UK.d.mts} +19 -8
- package/dist/Image-Bzc1H_UK.d.mts.map +1 -0
- package/dist/{Items-C7MyrYPX.d.mts → Items-Bvx8s9QH.d.mts} +109 -16
- package/dist/Items-Bvx8s9QH.d.mts.map +1 -0
- package/dist/{Loop-ChpaO-ya.d.mts → Loop-CeA0AelN.d.mts} +7 -6
- package/dist/Loop-CeA0AelN.d.mts.map +1 -0
- package/dist/Tool-Bkryw6-h.d.mts +206 -0
- package/dist/Tool-Bkryw6-h.d.mts.map +1 -0
- package/dist/ToolEvent-9inLx5cI.d.mts +22 -0
- package/dist/ToolEvent-9inLx5cI.d.mts.map +1 -0
- package/dist/ToolOutput-BNTIQgGB.d.mts +151 -0
- package/dist/ToolOutput-BNTIQgGB.d.mts.map +1 -0
- package/dist/Toolkit-D2VGeD5R.d.mts +212 -0
- package/dist/Toolkit-D2VGeD5R.d.mts.map +1 -0
- package/dist/browser/BrowserTool.d.mts +84 -22
- package/dist/browser/BrowserTool.d.mts.map +1 -1
- package/dist/browser/BrowserTool.mjs +5 -0
- package/dist/browser/BrowserTool.mjs.map +1 -1
- package/dist/capabilities/Capabilities.d.mts +1 -1
- package/dist/decision-model/Decision.test.mjs +1 -1
- package/dist/{dist-C8RmtoR8.mjs → dist-B5K-y4Be.mjs} +51 -32
- package/dist/dist-B5K-y4Be.mjs.map +1 -0
- package/dist/domain/File.d.mts +2 -0
- package/dist/domain/File.mjs +51 -0
- package/dist/domain/File.mjs.map +1 -0
- package/dist/domain/Image.d.mts +2 -2
- package/dist/domain/Image.mjs +12 -2
- package/dist/domain/Image.mjs.map +1 -1
- package/dist/domain/Items.d.mts +2 -2
- package/dist/domain/Items.mjs +65 -4
- package/dist/domain/Items.mjs.map +1 -1
- package/dist/domain/Realtime.d.mts +72 -490
- package/dist/domain/Realtime.d.mts.map +1 -1
- package/dist/domain/Research.d.mts +1 -1
- package/dist/domain/Transcript.test.mjs +1 -1
- package/dist/domain/Turn.d.mts +57 -262
- package/dist/domain/Turn.d.mts.map +1 -1
- package/dist/domain/Turn.mjs +1 -1
- package/dist/embedding-model/Embedding.d.mts +1 -1
- package/dist/image-generator/ImageGenerator.d.mts +10 -66
- package/dist/image-generator/ImageGenerator.d.mts.map +1 -1
- package/dist/index.d.mts +10 -9
- package/dist/index.mjs +7 -6
- package/dist/language-model/LanguageModel.d.mts +2 -2
- package/dist/loop/Loop.d.mts +1 -1
- package/dist/loop/Loop.mjs.map +1 -1
- package/dist/messenger/Messenger.d.mts +43 -289
- package/dist/messenger/Messenger.d.mts.map +1 -1
- package/dist/messenger/MessengerAdapter.test.mjs +1 -1
- package/dist/observability/Metrics.d.mts +1 -1
- package/dist/observability/Metrics.test.mjs +1 -1
- package/dist/observability/Telemetry.test.mjs +1 -1
- package/dist/realtime/RealtimeSession.d.mts +1 -1
- package/dist/realtime/RealtimeSession.test.mjs +1 -1
- package/dist/sandbox/Sandbox.d.mts +32 -237
- package/dist/sandbox/Sandbox.d.mts.map +1 -1
- package/dist/streaming/Multipart.mjs +2 -1
- package/dist/streaming/Multipart.mjs.map +1 -1
- package/dist/streaming/Multipart.test.mjs +28 -0
- package/dist/streaming/Multipart.test.mjs.map +1 -0
- package/dist/streaming/Settle.test.mjs +1 -1
- package/dist/streaming/WebSocketSession.test.mjs +1 -1
- package/dist/testing/MockMessenger.d.mts +19 -134
- package/dist/testing/MockMessenger.d.mts.map +1 -1
- package/dist/testing/MockProvider.d.mts +1 -1
- package/dist/testing/MockSandbox.d.mts +65 -446
- package/dist/testing/MockSandbox.d.mts.map +1 -1
- package/dist/tool/Content.d.mts +2 -0
- package/dist/tool/Content.mjs +46 -0
- package/dist/tool/Content.mjs.map +1 -0
- package/dist/tool/Content.test.d.mts +1 -0
- package/dist/tool/Content.test.mjs +48 -0
- package/dist/tool/Content.test.mjs.map +1 -0
- package/dist/tool/HistoryCheck.d.mts +6 -15
- package/dist/tool/HistoryCheck.d.mts.map +1 -1
- package/dist/tool/HistoryCheck.mjs +10 -24
- package/dist/tool/HistoryCheck.mjs.map +1 -1
- package/dist/tool/Tool.d.mts +2 -2
- package/dist/tool/Tool.mjs +55 -130
- package/dist/tool/Tool.mjs.map +1 -1
- package/dist/tool/Tool.test.mjs +220 -176
- package/dist/tool/Tool.test.mjs.map +1 -1
- package/dist/tool/ToolDecision.d.mts +164 -0
- package/dist/tool/ToolDecision.d.mts.map +1 -0
- package/dist/tool/ToolDecision.mjs +146 -0
- package/dist/tool/ToolDecision.mjs.map +1 -0
- package/dist/tool/ToolDecision.test.d.mts +1 -0
- package/dist/tool/ToolDecision.test.mjs +330 -0
- package/dist/tool/ToolDecision.test.mjs.map +1 -0
- package/dist/tool/ToolEvent.d.mts +2 -2
- package/dist/tool/ToolEvent.mjs +2 -34
- package/dist/tool/ToolEvent.mjs.map +1 -1
- package/dist/tool/ToolOutput.d.mts +2 -0
- package/dist/tool/ToolOutput.mjs +128 -0
- package/dist/tool/ToolOutput.mjs.map +1 -0
- package/dist/tool/ToolOutput.test.d.mts +1 -0
- package/dist/tool/ToolOutput.test.mjs +153 -0
- package/dist/tool/ToolOutput.test.mjs.map +1 -0
- package/dist/tool/Toolkit.d.mts +2 -2
- package/dist/tool/Toolkit.mjs +230 -165
- package/dist/tool/Toolkit.mjs.map +1 -1
- package/dist/tool/Toolkit.test.mjs +431 -389
- package/dist/tool/Toolkit.test.mjs.map +1 -1
- package/dist/web-read/WebReadTool.d.mts +2 -2
- package/dist/web-read/WebReadTool.mjs +1 -0
- package/dist/web-read/WebReadTool.mjs.map +1 -1
- package/dist/web-search/WebSearchTool.d.mts +2 -2
- package/dist/web-search/WebSearchTool.mjs +1 -0
- package/dist/web-search/WebSearchTool.mjs.map +1 -1
- package/package.json +17 -9
- package/src/browser/BrowserTool.ts +5 -0
- package/src/domain/File.ts +79 -0
- package/src/domain/Image.ts +14 -4
- package/src/domain/Items.ts +39 -3
- package/src/index.ts +3 -2
- package/src/loop/Loop.ts +24 -13
- package/src/streaming/Multipart.test.ts +26 -0
- package/src/streaming/Multipart.ts +5 -4
- package/src/tool/Content.test.ts +40 -0
- package/src/tool/Content.ts +38 -0
- package/src/tool/HistoryCheck.ts +21 -26
- package/src/tool/Tool.test.ts +240 -241
- package/src/tool/Tool.ts +203 -308
- package/src/tool/ToolDecision.test.ts +301 -0
- package/src/tool/ToolDecision.ts +360 -0
- package/src/tool/ToolEvent.ts +21 -41
- package/src/tool/ToolOutput.test.ts +132 -0
- package/src/tool/ToolOutput.ts +198 -0
- package/src/tool/Toolkit.test.ts +594 -454
- package/src/tool/Toolkit.ts +631 -356
- package/src/web-read/WebReadTool.ts +2 -1
- package/src/web-search/WebSearchTool.ts +2 -1
- package/dist/Image-Cv6iBLTy.d.mts.map +0 -1
- package/dist/Items-C7MyrYPX.d.mts.map +0 -1
- package/dist/Loop-ChpaO-ya.d.mts.map +0 -1
- package/dist/Tool-BF78QWtn.d.mts +0 -314
- package/dist/Tool-BF78QWtn.d.mts.map +0 -1
- package/dist/ToolEvent-Di4a723B.d.mts +0 -144
- package/dist/ToolEvent-Di4a723B.d.mts.map +0 -1
- package/dist/ToolResult-BsYQRjmW.d.mts +0 -152
- package/dist/ToolResult-BsYQRjmW.d.mts.map +0 -1
- package/dist/Toolkit-tlL0F2YR.d.mts +0 -193
- package/dist/Toolkit-tlL0F2YR.d.mts.map +0 -1
- package/dist/dist-C8RmtoR8.mjs.map +0 -1
- package/dist/tool/Approval.d.mts +0 -113
- package/dist/tool/Approval.d.mts.map +0 -1
- package/dist/tool/Approval.mjs +0 -80
- package/dist/tool/Approval.mjs.map +0 -1
- package/dist/tool/Approval.test.mjs +0 -371
- package/dist/tool/Approval.test.mjs.map +0 -1
- package/dist/tool/ToolResult.d.mts +0 -2
- package/dist/tool/ToolResult.mjs +0 -85
- package/dist/tool/ToolResult.mjs.map +0 -1
- package/src/tool/Approval.test.ts +0 -400
- package/src/tool/Approval.ts +0 -181
- package/src/tool/ToolResult.ts +0 -114
- /package/dist/{tool/Approval.test.d.mts → streaming/Multipart.test.d.mts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolkit.mjs","names":["Arr","Loop.value","Loop.next"],"sources":["../../src/tool/Toolkit.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\"\nimport {\n Array as Arr,\n Cause,\n Data,\n Effect,\n Fiber,\n Function,\n Match,\n Option,\n Queue,\n Record,\n Ref,\n Stream,\n} from \"effect\"\nimport * as Loop from \"../loop/Loop.js\"\nimport type { HistoryItem, ToolCall } from \"../domain/Items.js\"\nimport { appendToHistory, type Turn } from \"../domain/Turn.js\"\nimport {\n type AnyLocalTool,\n type AnyTool,\n type DecodeResult,\n decodeCallInput,\n type Emit,\n type InteractionTool,\n type ProviderTool,\n type SignalTool,\n type Tool,\n type ToolDescriptor,\n type ToolE,\n ToolFailed,\n type ToolR,\n toDescriptors,\n} from \"./Tool.js\"\nimport {\n ToolResult,\n failed,\n nonLocalTool,\n toToolCallOutput,\n validationError,\n} from \"./ToolResult.js\"\nimport { ToolEvent } from \"./ToolEvent.js\"\nimport { isOutput } from \"./ToolEvent.js\"\n\n// ---------------------------------------------------------------------------\n// Toolkit: a name-indexed record of tools — \"what the model sees\". The record\n// gives O(1) dispatch and within-toolkit name-uniqueness for free; descriptors\n// are derived, not stored. Build a static one with `make` (compile-time\n// duplicate-name check), a dynamic one with `fromArray` (trusted single source,\n// last-wins), and combine independent ones with `compose` (the application\n// boundary where cross-source names can clash).\n// ---------------------------------------------------------------------------\n\nexport type ToolMap = Record<string, AnyTool>\n\nexport type Toolkit<Tools extends ToolMap = ToolMap> = Tools\n\nconst indexByName = (tools: ReadonlyArray<AnyTool>): ToolMap =>\n Object.fromEntries(tools.map((tool) => [tool.name, tool]))\n\n/**\n * Index literal tools by their `name`. Duplicate names are a compile error\n * (`UniqueTools`). Names are not otherwise checked: a malformed name is a\n * developer typo in a literal that the provider rejects clearly on first use,\n * and there is no single cross-provider name rule to enforce here anyway.\n */\nconst buildStatic = <Tools extends ReadonlyArray<AnyTool>>(\n tools: Tools,\n): Toolkit<{ [T in Tools[number] as T[\"name\"]]: T }> =>\n indexByName(tools) as Toolkit<{ [T in Tools[number] as T[\"name\"]]: T }>\n\nexport const make = <const Tools extends ReadonlyArray<AnyTool>>(\n ...tools: UniqueTools<Tools>\n): Toolkit<{ [T in Tools[number] as T[\"name\"]]: T }> => buildStatic(tools as unknown as Tools)\n\n/**\n * Build a toolkit from a dynamically-sourced array (MCP server, plugin). Names\n * are not validated (MCP legitimately uses dots / >64 chars — sanitize at the\n * provider adapter); same-named tools resolve last-wins. Cross-source clashes\n * are caught by `compose`.\n */\nexport const fromArray = (tools: ReadonlyArray<AnyTool>): Toolkit => indexByName(tools)\n\n/** Render the provider-facing descriptors for a toolkit on demand. */\nexport const descriptors = (toolkit: Toolkit): ReadonlyArray<ToolDescriptor> =>\n toDescriptors(Object.values(toolkit))\n\n/**\n * Union of every tool's `R` requirements in a toolkit. Surfaced by `run` so the\n * loop's stream type carries the services tools need through to `Effect.provide`.\n *\n * The `ToolMap extends T` guard yields `never` for the wide `Toolkit` type (a\n * toolkit passed through an untyped boundary, where the requirements aren't\n * statically known) instead of `any`, which would otherwise poison the\n * resulting stream's `R`. Concrete toolkits from `make` keep their precise R.\n */\nexport type ToolkitR<T extends Toolkit> = ToolMap extends T ? never : ToolR<T[keyof T]>\n\n/**\n * Union of every tool's `E` error type in a toolkit. `Toolkit.run` reports\n * `Exclude<ToolkitE<T>, string | ToolFailed>` on its stream: the sentinel\n * failures are absorbed into results, everything else propagates typed. The\n * same `ToolMap extends T` guard as `ToolkitR` keeps a wide toolkit at\n * `never` rather than `any`.\n */\nexport type ToolkitE<T extends Toolkit> = ToolMap extends T ? never : ToolE<T[keyof T]>\n\n// ---------------------------------------------------------------------------\n// Uniqueness & composition. `make` rejects duplicate literal names at compile\n// time; `compose` rejects cross-source collisions — at compile time when the\n// names are statically known, and at runtime (`DuplicateToolName`) for dynamic\n// sources whose keys are only `string`. No silent last-wins overwrite, no late\n// provider 400.\n// ---------------------------------------------------------------------------\n\n// --- compile-time duplicate detection --------------------------------------\n\ntype DuplicateName<\n Tools extends ReadonlyArray<AnyTool>,\n Seen extends string = never,\n> = Tools extends readonly [\n infer Head extends AnyTool,\n ...infer Tail extends ReadonlyArray<AnyTool>,\n]\n ? Head[\"name\"] extends Seen\n ? Head[\"name\"]\n : DuplicateName<Tail, Seen | Head[\"name\"]>\n : never\n\ntype DuplicateNameError<Name extends string> = {\n readonly __error: `Duplicate tool name: ${Name}`\n}\n\nexport type NoDuplicateNames<Tools extends ReadonlyArray<AnyTool>> = [\n DuplicateName<Tools>,\n] extends [never]\n ? unknown\n : DuplicateNameError<DuplicateName<Tools>>\n\n/** `Tools` constrained so a repeated literal name is a compile error in `make`. */\nexport type UniqueTools<Tools extends ReadonlyArray<AnyTool>> = Tools & NoDuplicateNames<Tools>\n\n// Cross-toolkit literal-key collision, skipping wide (`string`-keyed, dynamic)\n// toolkits so the compile-time check never false-positives on `fromArray`.\ntype ComposeDuplicateKey<\n Kits extends ReadonlyArray<Toolkit>,\n Seen extends string = never,\n> = Kits extends readonly [infer Head extends Toolkit, ...infer Tail extends ReadonlyArray<Toolkit>]\n ? string extends keyof Head\n ? ComposeDuplicateKey<Tail, Seen>\n : Extract<keyof Head & string, Seen> extends never\n ? ComposeDuplicateKey<Tail, Seen | (keyof Head & string)>\n : Extract<keyof Head & string, Seen>\n : never\n\ntype NoDuplicateComposedKeys<Kits extends ReadonlyArray<Toolkit>> = [\n ComposeDuplicateKey<Kits>,\n] extends [never]\n ? unknown\n : DuplicateNameError<ComposeDuplicateKey<Kits>>\n\ntype UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) extends (\n x: infer I,\n) => void\n ? I\n : never\n\ntype Composed<Kits extends ReadonlyArray<Toolkit>> =\n UnionToIntersection<Kits[number]> extends infer M ? (M extends ToolMap ? M : ToolMap) : ToolMap\n\n// --- uniqueness error ------------------------------------------------------\n\n/**\n * Two composed toolkits resolved to the same final name. Carries the colliding\n * `sources` (the positions of the clashing toolkits) so the error says *which*\n * inputs collided. Raised at runtime by `compose` for dynamic sources; static\n * collisions are caught earlier at compile time.\n */\nexport class DuplicateToolName extends Data.TaggedError(\"DuplicateToolName\")<{\n readonly name: string\n readonly sources: ReadonlyArray<string>\n}> {}\n\n// --- namespacing -----------------------------------------------------------\n\ntype PrefixName<Prefix extends string, Name extends string> = `${Prefix}__${Name}`\n\ntype PrefixTool<Prefix extends string, T extends AnyTool> =\n T extends Tool<infer N, infer I, infer Ev, infer O, infer E, infer R>\n ? Tool<PrefixName<Prefix, N>, I, Ev, O, E, R>\n : T extends ProviderTool<infer N, infer I, infer P, infer C>\n ? ProviderTool<PrefixName<Prefix, N>, I, P, C>\n : T extends SignalTool<infer N, infer I>\n ? SignalTool<PrefixName<Prefix, N>, I>\n : T extends InteractionTool<infer N, infer I>\n ? InteractionTool<PrefixName<Prefix, N>, I>\n : T\n\ntype Namespaced<Prefix extends string, T extends ToolMap> = {\n readonly [K in keyof T & string as PrefixName<Prefix, K>]: T[K] extends AnyTool\n ? PrefixTool<Prefix, T[K]>\n : never\n}\n\n/**\n * Prefix every tool name with `<namespace>__`, returning a new toolkit. Use it\n * to keep generic names (`search`) from two sources distinct before `compose`.\n * If two namespaces collide at the `__` separator, the duplicate final name\n * surfaces from `compose` as a `DuplicateToolName`.\n */\nexport const namespace = <const Prefix extends string, const T extends ToolMap>(\n prefix: Prefix,\n toolkit: Toolkit<T>,\n): Toolkit<Namespaced<Prefix, T>> => {\n const renamed = Arr.map(Record.values(toolkit), (tool) => ({\n ...tool,\n name: `${prefix}__${tool.name}`,\n }))\n return indexByName(renamed) as Toolkit<Namespaced<Prefix, T>>\n}\n\n/** `namespace(prefix, make(...tools))` in one step, for static namespaced tools. */\nexport const makeNamespaced = <\n const Prefix extends string,\n const Tools extends ReadonlyArray<AnyTool>,\n>(\n prefix: Prefix,\n ...tools: UniqueTools<Tools>\n): Toolkit<Namespaced<Prefix, { [T in Tools[number] as T[\"name\"]]: T }>> =>\n namespace(prefix, buildStatic(tools as unknown as Tools))\n\n// --- composition (the application boundary) --------------------------------\n\n/**\n * Combine independently-built toolkits into one. This is where names from\n * separate sources can collide, so it is the one effectful constructor: a\n * duplicate final name fails with `DuplicateToolName` (naming the colliding\n * input positions) instead of silently overwriting or 400-ing later at the\n * provider. Statically-known collisions are additionally a compile error.\n */\nexport const compose = <const Kits extends ReadonlyArray<Toolkit>>(\n ...toolkits: Kits & NoDuplicateComposedKeys<Kits>\n): Effect.Effect<Toolkit<Composed<Kits>>, DuplicateToolName> =>\n Effect.gen(function* () {\n const kits = toolkits as unknown as ReadonlyArray<Toolkit>\n const labelled = Arr.flatMap(kits, (kit, i) =>\n Arr.map(Record.keys(kit), (name) => ({ name, source: `toolkit-${i}` })),\n )\n const collision = Arr.findFirst(\n Record.toEntries(Arr.groupBy(labelled, (entry) => entry.name)),\n ([, group]) => group.length > 1,\n )\n if (Option.isSome(collision)) {\n const [name, group] = collision.value\n return yield* new DuplicateToolName({ name, sources: Arr.map(group, (e) => e.source) })\n }\n return Arr.reduce(kits, {} as ToolMap, (acc, kit) => ({ ...acc, ...kit })) as Toolkit<\n Composed<Kits>\n >\n })\n\n// ---------------------------------------------------------------------------\n// Middleware: a `Toolkit -> Toolkit` transform applied up front, then the\n// wrapped toolkit is run. A middleware transforms one local tool's `run` given\n// its name (logging, retry, auth, metrics); `wrap` lifts it over the whole\n// toolkit, leaving provider/signal/interaction kinds untouched. The one reason\n// this is a combinator rather than native `Record.map`: it tracks the\n// middleware's added requirement `R2`, unioning it into `ToolkitR` instead of\n// widening every tool's type.\n// ---------------------------------------------------------------------------\n\ntype Handler<Input, Event, Output, E, R> = (\n input: Input,\n emit: Emit<Event>,\n) => Effect.Effect<Output, E, R>\n\n/**\n * A `run` transform, tracking an added requirement `R2` and optional added\n * error `E2`. The tool's own `E` is preserved; `describeFailures` is the\n * combinator that *replaces* it (mapping every error to `string`).\n */\nexport type Middleware<R2 = never, E2 = never> = <Input, Event, Output, E, R>(\n run: Handler<Input, Event, Output, E, R>,\n name: string,\n) => Handler<Input, Event, Output, E | E2, R | R2>\n\ntype WrapTool<T extends AnyTool, R2, E2> =\n T extends Tool<infer N, infer I, infer Ev, infer O, infer E, infer R>\n ? Tool<N, I, Ev, O, E | E2, R | R2>\n : T\n\ntype WrapToolkit<T extends ToolMap, R2, E2> = {\n readonly [K in keyof T]: T[K] extends AnyTool ? WrapTool<T[K], R2, E2> : T[K]\n}\n\n/**\n * Wrap every local tool's `run` with a middleware, preserving each tool's\n * `Input`/`Output` and unioning the middleware's requirement `R2` into the\n * toolkit's `ToolkitR`. Non-local kinds pass through unchanged. Stack with\n * `pipe` - inner-first, so the last `wrap` applied is the outermost and runs\n * first:\n *\n * const observed = pipe(toolkit, Toolkit.wrap(logging), Toolkit.wrap(authz))\n * Toolkit.run(observed, calls) // authz runs, then logging, then the tool\n *\n * A middleware that fails with `string` / `ToolFailed` is absorbed by the\n * executor into a `ToolResult.Failure`; any other error propagates typed. Use\n * `describeFailures` for the total \"everything to the model\" case, or the\n * `Approval` flow for a distinct \"denied\" verdict.\n */\nexport const wrap: {\n <R2, E2>(\n middleware: Middleware<R2, E2>,\n ): <T extends Toolkit>(toolkit: T) => WrapToolkit<T, R2, E2>\n <T extends Toolkit, R2, E2>(toolkit: T, middleware: Middleware<R2, E2>): WrapToolkit<T, R2, E2>\n} = Function.dual(\n 2,\n <T extends Toolkit, R2, E2>(toolkit: T, middleware: Middleware<R2, E2>): WrapToolkit<T, R2, E2> =>\n Record.map(toolkit, (tool) =>\n tool._tag === \"LocalTool\" ? { ...tool, run: middleware(tool.run, tool.name) } : tool,\n ) as WrapToolkit<T, R2, E2>,\n)\n\n// ---------------------------------------------------------------------------\n// describeFailures: map every local tool's error to a model-visible string,\n// opting its failures into recovery. Group tools by recovery policy, wrap\n// each group, then compose.\n// ---------------------------------------------------------------------------\n\ntype DescribeTool<T extends AnyTool> =\n T extends Tool<infer N, infer I, infer Ev, infer O, any, infer R>\n ? Tool<N, I, Ev, O, string, R>\n : T\n\ntype DescribeToolkit<T extends ToolMap> = {\n readonly [K in keyof T]: T[K] extends AnyTool ? DescribeTool<T[K]> : T[K]\n}\n\n/**\n * Map every local tool's error to a `string`, so `Toolkit.run` absorbs those\n * failures into `ToolResult.Failure` the model reads and adapts to. Pairs\n * with the domain `describe` helpers (`AiError.describe`,\n * `BrowserError.describe`). Non-local kinds pass through.\n *\n * const kit = yield* Toolkit.compose(\n * Toolkit.describeFailures(searchKit, AiError.describe),\n * browserToolkit(session), // failures stay typed\n * )\n */\nexport const describeFailures: {\n <E>(describe: (e: E) => string): <T extends Toolkit>(toolkit: T) => DescribeToolkit<T>\n <T extends Toolkit>(toolkit: T, describe: (e: ToolkitE<T>) => string): DescribeToolkit<T>\n} = Function.dual(\n 2,\n <T extends Toolkit>(toolkit: T, describe: (e: any) => string): DescribeToolkit<T> =>\n Record.map(toolkit, (tool) =>\n tool._tag === \"LocalTool\"\n ? {\n ...tool,\n run: (input: unknown, emit: Emit<unknown>) =>\n (tool as AnyLocalTool).run(input, emit).pipe(Effect.mapError(describe)),\n }\n : tool,\n ) as DescribeToolkit<T>,\n)\n\n// ---------------------------------------------------------------------------\n// Tool executor. Streams `ToolEvent`s in real time. Policy stays outside this\n// module: callers pass only the calls they have already decided should run.\n// ---------------------------------------------------------------------------\n\nexport type ExecuteOptions = {\n readonly concurrency?: number | \"unbounded\"\n}\n\n/**\n * Execute every provided call. Approval/rejection policy belongs upstream.\n *\n * String and `ToolFailed` failures are absorbed into `ToolResult.Failure`\n * (the model reads and adapts to them); every other tool error propagates\n * typed on the stream, so `Exclude<ToolkitE<T>, string | ToolFailed>` is\n * what a caller catches or lets end the run. If one call in a concurrent\n * batch fails the stream, siblings may go unanswered: a loop that catches\n * and continues must reconcile history first (`HistoryCheck.cancelAllPending`).\n */\nexport const run = <T extends Toolkit>(\n toolkit: T,\n calls: ReadonlyArray<ToolCall>,\n options?: ExecuteOptions,\n): Stream.Stream<ToolEvent, Exclude<ToolkitE<T>, string | ToolFailed>, ToolkitR<T>> =>\n Stream.fromIterable(calls).pipe(\n Stream.flatMap((call) => runOne(toolkit, call), {\n concurrency: options?.concurrency ?? \"unbounded\",\n }),\n ) as Stream.Stream<ToolEvent, Exclude<ToolkitE<T>, string | ToolFailed>, ToolkitR<T>>\n\nconst okResult = (call: ToolCall, tool: string, value: unknown): ToolResult =>\n ToolResult.Ok({ call_id: call.call_id, tool, value })\n\nconst outputEvent = (result: ToolResult): Stream.Stream<ToolEvent, never, any> =>\n Stream.succeed(ToolEvent.Output({ result }))\n\nconst runOne = (toolkit: ToolMap, call: ToolCall): Stream.Stream<ToolEvent, unknown, any> => {\n // Own-property lookup: a hallucinated call named `constructor` / `toString`\n // must not resolve to a prototype method.\n const tool = Object.hasOwn(toolkit, call.name) ? toolkit[call.name] : undefined\n return Match.value(tool).pipe(\n // No such tool. Graceful: emit a synthetic Failure so OTHER calls in this\n // turn still execute. LLMs hallucinate tool names; MCP tools come and go.\n Match.when(Match.undefined, () =>\n outputEvent(failed(call, \"unknown_tool\", `No tool registered with name \"${call.name}\"`)),\n ),\n Match.tag(\"LocalTool\", (local) => runTool(local, call)),\n // Provider/signal/interaction tools are model-visible but not locally\n // executable. The loop is expected to intercept these (decode + act) before\n // execution; reaching here means it didn't, so report it rather than crash.\n Match.orElse(() => outputEvent(nonLocalTool(call))),\n )\n}\n\nconst describeIssues = (issues: ReadonlyArray<StandardSchemaV1.Issue>): string =>\n issues\n .map((issue) => {\n const path = (issue.path ?? [])\n .map((seg) => (typeof seg === \"object\" && seg !== null ? String(seg.key) : String(seg)))\n .join(\".\")\n return path === \"\" ? issue.message : `${path}: ${issue.message}`\n })\n .join(\"; \")\n .slice(0, 500)\n\n// A decode failure is the model's contract violation: report it as a result\n// (never a stream failure) so the model can correct its next call.\nconst runTool = (tool: AnyLocalTool, call: ToolCall): Stream.Stream<ToolEvent, unknown, any> =>\n Stream.unwrap(\n decodeCallInput(tool, call).pipe(\n Effect.map(\n Match.type<DecodeResult<unknown>>().pipe(\n Match.tag(\"parseError\", () =>\n outputEvent(validationError(call, \"arguments are not valid JSON\")),\n ),\n Match.tag(\"invalid\", ({ issues }) =>\n outputEvent(validationError(call, describeIssues(issues))),\n ),\n Match.tag(\"ok\", ({ input }) => runValidated(tool, call, input)),\n Match.exhaustive,\n ),\n ),\n ),\n )\n\nconst runValidated = (\n tool: AnyLocalTool,\n call: ToolCall,\n input: unknown,\n): Stream.Stream<ToolEvent, unknown, any> =>\n Stream.unwrap(\n Effect.gen(function* () {\n // Per-call queue: `emit` offers events as `run` produces them; the\n // progress stream drains them in real time; `Queue.end` (in the\n // `ensuring`) flushes pending events then signals a clean end, which\n // `Stream.fromQueue` treats as completion. `Queue.shutdown` would clear\n // queued items and interrupt pending takes — wrong for graceful teardown.\n const queue = yield* Queue.make<unknown, Cause.Done>({ capacity: tool.emitBufferSize })\n const emit = (event: unknown) => Effect.asVoid(Queue.offer(queue, event))\n const fiber = yield* tool\n .run(input, emit)\n .pipe(Effect.ensuring(Queue.end(queue)), Effect.forkScoped)\n\n const progress = Stream.fromQueue(queue).pipe(\n Stream.map((data) => ToolEvent.Progress({ call_id: call.call_id, tool: tool.name, data })),\n )\n const output = Stream.fromEffect(\n Fiber.join(fiber).pipe(\n Effect.matchCauseEffect({\n onSuccess: (value: unknown) =>\n Effect.succeed(ToolEvent.Output({ result: okResult(call, tool.name, value) })),\n onFailure: (cause: Cause.Cause<unknown>) => routeCause(call, cause),\n }),\n ),\n )\n return progress.pipe(Stream.concat(output))\n }),\n )\n\n// A clean single string / ToolFailed failure is absorbed as a model-visible\n// result; interruption, defects, and typed non-sentinel errors propagate.\nconst routeCause = (\n call: ToolCall,\n cause: Cause.Cause<unknown>,\n): Effect.Effect<ToolEvent, unknown> => {\n const only = cause.reasons.length === 1 ? cause.reasons[0] : undefined\n if (only !== undefined && Cause.isFailReason(only)) {\n const error = only.error\n if (typeof error === \"string\") {\n return Effect.succeed(ToolEvent.Output({ result: failed(call, \"tool_failed\", error) }))\n }\n if (error instanceof ToolFailed) {\n return Effect.succeed(\n ToolEvent.Output({ result: failed(call, error.kind ?? \"tool_failed\", error.message) }),\n )\n }\n }\n return Effect.failCause(cause)\n}\n\n// ---------------------------------------------------------------------------\n// `continueWithResults` - bridge from a `Stream<ToolEvent>` to the loop's\n// emit shape. Drains the stream to the consumer in real-time, taps every\n// `Output` into an internal Ref, and at end-of-stream emits\n// `Loop.next(build(results))`. Recipe never sees the Ref.\n//\n// Dual: data-first `continueWithResults(stream, build)` and data-last\n// `stream.pipe(continueWithResults(build))` both work.\n// ---------------------------------------------------------------------------\n\n/**\n * Append a completed turn plus tool results to a state's history, converting\n * the results to wire-format `ToolCallOutput`s. Curried so it slots directly\n * into `continueWithResults`:\n *\n * Toolkit.run(toolkit, calls).pipe(\n * Toolkit.continueWithResults(Toolkit.appendToolResults(state, turn)),\n * )\n *\n * Equivalent to `appendToHistory(state, turn, results.map(toToolCallOutput))`\n * — the helper just hides the wire-conversion step.\n */\nexport const appendToolResults =\n <S extends { readonly history: ReadonlyArray<HistoryItem> }>(state: S, turn: Turn) =>\n (results: ReadonlyArray<ToolResult>): S =>\n appendToHistory(state, turn, results.map(toToolCallOutput))\n\n/**\n * Drain a `Stream<ToolEvent>` and return the accumulated `ToolResult`s\n * from every `Output` event. One-shot — the type is `Effect<results>`,\n * not a one-element stream — so it composes naturally with `Effect.map`\n * to build state.\n *\n * Counterpart to `continueWithResults`: `continueWithResults` bundles\n * drain + emit Next into one bridge; this one is the right arm of a\n * broadcast/fork-and-merge for callers that want to vary the left arm\n * (e.g., filter/tap ToolEvents before forwarding).\n */\nexport const collectResults = <E, R>(\n stream: Stream.Stream<ToolEvent, E, R>,\n): Effect.Effect<ReadonlyArray<ToolResult>, E, R> =>\n stream.pipe(\n Stream.filter(isOutput),\n Stream.map((e) => e.result),\n Stream.runCollect,\n )\n\n/**\n * Bridge from a `Stream<ToolEvent>` to the loop's emit shape. Forwards\n * every ToolEvent downstream as a `Loop.value` and at end-of-stream emits\n * one `Loop.next(build(results))` carrying the accumulated `ToolResult`s\n * from terminal `Output` events.\n *\n * Conceptually a broadcast fork (one arm passes events through, the other\n * drains them into a state). Implemented as a single-pass Ref tap + concat\n * for zero buffering — the broadcast version is observationally equivalent\n * but holds events in a PubSub until both arms drain. The public primitives\n * (`Loop.value`, `collectResults`, `Loop.next`) compose the same pattern\n * when you need to vary an arm.\n *\n * Dual: data-first `continueWithResults(stream, build)` and data-last\n * `stream.pipe(continueWithResults(build))` both work.\n */\nexport const continueWithResults: {\n <S>(\n build: (results: ReadonlyArray<ToolResult>) => S,\n ): <E, R>(stream: Stream.Stream<ToolEvent, E, R>) => Stream.Stream<Loop.Step<ToolEvent, S>, E, R>\n <S, E, R>(\n stream: Stream.Stream<ToolEvent, E, R>,\n build: (results: ReadonlyArray<ToolResult>) => S,\n ): Stream.Stream<Loop.Step<ToolEvent, S>, E, R>\n} = Function.dual(\n 2,\n <S, E, R>(\n stream: Stream.Stream<ToolEvent, E, R>,\n build: (results: ReadonlyArray<ToolResult>) => S,\n ): Stream.Stream<Loop.Step<ToolEvent, S>, E, R> =>\n Stream.unwrap(\n Effect.gen(function* () {\n const ref = yield* Ref.make<ReadonlyArray<ToolResult>>([])\n const tapped = stream.pipe(\n Stream.tap((e) =>\n isOutput(e) ? Ref.update(ref, (acc) => Arr.append(acc, e.result)) : Effect.void,\n ),\n Stream.map(Loop.value),\n )\n const continuation = Stream.unwrap(\n Ref.get(ref).pipe(Effect.map((acc) => Loop.next(build(acc)))),\n )\n return tapped.pipe(Stream.concat(continuation))\n }),\n ),\n)\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Toolkit.mjs","names":["Arr","withToolFailures","Content.Value","ToolOutput.success","ToolOutput.failure","ToolOutput.encoded","ToolOutput.value","Loop.value","Loop.next"],"sources":["../../src/tool/Toolkit.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\"\nimport {\n Array as Arr,\n Cause,\n Data,\n Effect,\n Function,\n Match,\n Option,\n Predicate,\n Record,\n Ref,\n Result,\n Schema,\n Stream,\n} from \"effect\"\nimport type { HistoryItem, ToolCall, ToolCallOutput } from \"../domain/Items.js\"\nimport { appendToHistory, getToolCalls, type Turn } from \"../domain/Turn.js\"\nimport * as Loop from \"../loop/Loop.js\"\nimport * as Content from \"./Content.js\"\nimport {\n type AnyDescribed,\n type AnyLocalTool,\n type AnyTool,\n type DecodeResult,\n decodeCallInput,\n type ProviderTool,\n type Tool,\n type ToolDescriptor,\n ToolFailed,\n type ToolFailure,\n type ToolOutput as OutputOf,\n type ToolR,\n type ToolUnhandled,\n isStreamed,\n toDescriptors,\n toStream,\n withFailures as withToolFailures,\n} from \"./Tool.js\"\nimport type * as ToolEvent from \"./ToolEvent.js\"\nimport * as ToolOutput from \"./ToolOutput.js\"\nimport { CoreError, InputInvalid, OutputInvalid, type RunError, UnknownTool } from \"./ToolOutput.js\"\n\n// ---------------------------------------------------------------------------\n// Toolkit: a name-indexed record of tools, what the model sees. `make` checks\n// duplicate names at compile time, `fromArray` takes a dynamic source\n// (last wins), `compose` joins independent toolkits and fails on clashes.\n// ---------------------------------------------------------------------------\n\nexport type ToolMap = Record<string, AnyTool>\n\nexport type Toolkit<Tools extends ToolMap = ToolMap> = Tools\n\ntype Indexed<Tools extends ReadonlyArray<AnyTool>> = { [T in Tools[number] as T[\"name\"]]: T }\n\nconst indexByName = (tools: ReadonlyArray<AnyTool>): ToolMap =>\n Object.fromEntries(tools.map((tool) => [tool.name, tool]))\n\nconst buildStatic = <Tools extends ReadonlyArray<AnyTool>>(tools: Tools): Toolkit<Indexed<Tools>> =>\n indexByName(tools) as Toolkit<Indexed<Tools>>\n\n/** Index tools by `name`. A repeated literal name is a compile error. */\nexport const make = <const Tools extends ReadonlyArray<AnyTool>>(\n ...tools: UniqueTools<Tools>\n): Toolkit<Indexed<Tools>> => buildStatic<Tools>(tools)\n\n/** A toolkit from a dynamic source (MCP server, plugin). Same-named tools: last wins. */\nexport const fromArray = (tools: ReadonlyArray<AnyTool>): Toolkit => indexByName(tools)\n\nexport const descriptors = (toolkit: Toolkit): ReadonlyArray<ToolDescriptor> =>\n toDescriptors(Object.values(toolkit))\n\n// A wide `Toolkit` (types unknown statically) yields `never`, not `any`.\ntype Locals<T extends Toolkit> = Extract<T[keyof T], { readonly _tag: \"LocalTool\" }>\n\n/** Every tool's requirements. */\nexport type ToolkitR<T extends Toolkit> = ToolMap extends T ? never : ToolR<T[keyof T]>\n\n/** Every error a tool did not declare in `failureSchema`: these fail `run`'s stream. */\nexport type ToolkitE<T extends Toolkit> = ToolMap extends T ? never : ToolUnhandled<T[keyof T]>\n\n/** What `run` emits: one member per local tool, plus calls it could not run at all. */\nexport type Event<T extends Toolkit> =\n | (Locals<T> extends infer X\n ? X extends Tool<infer N, any, infer O, infer F, any, any>\n ? ToolEvent.ToolEvent<N, O, F | RunError>\n : never\n : never)\n | ToolEvent.Output<string, never, RunError>\n\n// ---------------------------------------------------------------------------\n// Uniqueness and composition\n// ---------------------------------------------------------------------------\n\ntype DuplicateName<\n Tools extends ReadonlyArray<AnyTool>,\n Seen extends string = never,\n> = Tools extends readonly [\n infer Head extends AnyTool,\n ...infer Tail extends ReadonlyArray<AnyTool>,\n]\n ? Head[\"name\"] extends Seen\n ? Head[\"name\"]\n : DuplicateName<Tail, Seen | Head[\"name\"]>\n : never\n\ntype DuplicateNameError<Name extends string> = {\n readonly __error: `Duplicate tool name: ${Name}`\n}\n\nexport type NoDuplicateNames<Tools extends ReadonlyArray<AnyTool>> = [\n DuplicateName<Tools>,\n] extends [never]\n ? unknown\n : DuplicateNameError<DuplicateName<Tools>>\n\nexport type UniqueTools<Tools extends ReadonlyArray<AnyTool>> = Tools & NoDuplicateNames<Tools>\n\n// Skips wide (`string`-keyed) toolkits so `fromArray` never false-positives.\ntype ComposeDuplicateKey<\n Kits extends ReadonlyArray<Toolkit>,\n Seen extends string = never,\n> = Kits extends readonly [infer Head extends Toolkit, ...infer Tail extends ReadonlyArray<Toolkit>]\n ? string extends keyof Head\n ? ComposeDuplicateKey<Tail, Seen>\n : Extract<keyof Head & string, Seen> extends never\n ? ComposeDuplicateKey<Tail, Seen | (keyof Head & string)>\n : Extract<keyof Head & string, Seen>\n : never\n\ntype NoDuplicateComposedKeys<Kits extends ReadonlyArray<Toolkit>> = [\n ComposeDuplicateKey<Kits>,\n] extends [never]\n ? unknown\n : DuplicateNameError<ComposeDuplicateKey<Kits>>\n\ntype UnionToIntersection<U> = (U extends unknown ? (x: U) => void : never) extends (\n x: infer I,\n) => void\n ? I\n : never\n\ntype Composed<Kits extends ReadonlyArray<Toolkit>> =\n UnionToIntersection<Kits[number]> extends infer M ? (M extends ToolMap ? M : ToolMap) : ToolMap\n\n/** Two composed toolkits share a final name; `sources` are their positions. */\nexport class DuplicateToolName extends Data.TaggedError(\"DuplicateToolName\")<{\n readonly name: string\n readonly sources: ReadonlyArray<string>\n}> {}\n\ntype PrefixName<Prefix extends string, Name extends string> = `${Prefix}__${Name}`\n\ntype PrefixTool<Prefix extends string, T extends AnyTool> =\n T extends Tool<infer N, infer I, infer O, infer F, infer E, infer R>\n ? Tool<PrefixName<Prefix, N>, I, O, F, E, R>\n : T extends ProviderTool<infer N, infer I, infer P, infer C>\n ? ProviderTool<PrefixName<Prefix, N>, I, P, C>\n : T\n\ntype Namespaced<Prefix extends string, T extends ToolMap> = {\n readonly [K in keyof T & string as PrefixName<Prefix, K>]: T[K] extends AnyTool\n ? PrefixTool<Prefix, T[K]>\n : never\n}\n\n/** Prefix every tool name with `<namespace>__`, e.g. to keep two `search` tools apart. */\nexport const namespace = <const Prefix extends string, const T extends ToolMap>(\n prefix: Prefix,\n toolkit: Toolkit<T>,\n): Toolkit<Namespaced<Prefix, T>> =>\n indexByName(\n Arr.map(Record.values(toolkit), (tool) => ({ ...tool, name: `${prefix}__${tool.name}` })),\n ) as Toolkit<Namespaced<Prefix, T>>\n\n/** `namespace(prefix, make(...tools))` in one step. */\nexport const makeNamespaced = <\n const Prefix extends string,\n const Tools extends ReadonlyArray<AnyTool>,\n>(\n prefix: Prefix,\n ...tools: UniqueTools<Tools>\n): Toolkit<Namespaced<Prefix, Indexed<Tools>>> => namespace(prefix, buildStatic<Tools>(tools))\n\n/**\n * Join independently built toolkits. A duplicate final name fails with\n * `DuplicateToolName`; statically known duplicates are a compile error too.\n */\nexport const compose = <const Kits extends ReadonlyArray<Toolkit>>(\n ...toolkits: Kits & NoDuplicateComposedKeys<Kits>\n): Effect.Effect<Toolkit<Composed<Kits>>, DuplicateToolName> => {\n const kits: ReadonlyArray<Toolkit> = toolkits\n const labelled = Arr.flatMap(kits, (kit, i) =>\n Arr.map(Record.keys(kit), (name) => ({ name, source: `toolkit-${i}` })),\n )\n return Arr.findFirst(\n Record.toEntries(Arr.groupBy(labelled, (entry) => entry.name)),\n ([, group]) => group.length > 1,\n ).pipe(\n Option.match({\n onNone: () =>\n Effect.succeed(\n Arr.reduce(kits, {}, (acc: ToolMap, kit) => ({ ...acc, ...kit })) as Toolkit<\n Composed<Kits>\n >,\n ),\n onSome: ([name, group]) =>\n Effect.fail(new DuplicateToolName({ name, sources: Arr.map(group, (e) => e.source) })),\n }),\n )\n}\n\n// ---------------------------------------------------------------------------\n// Middleware: transforms each local tool's `run`, seen as a stream (an `Effect`\n// run is a one-element stream), and tracks the added `R2` / `E2`.\n// ---------------------------------------------------------------------------\n\nexport type Handler<Input, Output, E, R> = (input: Input) => Stream.Stream<Output, E, R>\n\nexport type Middleware<R2 = never, E2 = never> = <Input, Output, E, R>(\n run: Handler<Input, Output, E, R>,\n name: string,\n) => Handler<Input, Output, E | E2, R | R2>\n\ntype WrapTool<T extends AnyTool, R2, E2> =\n T extends Tool<infer N, infer I, infer O, infer F, infer E, infer R>\n ? Tool<N, I, O, F, E | E2, R | R2>\n : T\n\ntype WrapToolkit<T extends ToolMap, R2, E2> = {\n readonly [K in keyof T]: T[K] extends AnyTool ? WrapTool<T[K], R2, E2> : T[K]\n}\n\nconst mapLocal = <T extends Toolkit, Out>(\n toolkit: T,\n f: (tool: AnyLocalTool) => AnyLocalTool,\n): Out => Record.map(toolkit, (tool) => (tool._tag === \"LocalTool\" ? f(tool) : tool)) as Out\n\n/**\n * Wrap every local tool's `run`. Stacks with `pipe`, inner first: the last\n * `wrap` runs first. The middleware sees a stream; an `Effect` tool stays one,\n * with the stream's last value.\n *\n * const observed = pipe(toolkit, Toolkit.wrap(logging), Toolkit.wrap(authz))\n */\nexport const wrap: {\n <R2, E2>(\n middleware: Middleware<R2, E2>,\n ): <T extends Toolkit>(toolkit: T) => WrapToolkit<T, R2, E2>\n <T extends Toolkit, R2, E2>(toolkit: T, middleware: Middleware<R2, E2>): WrapToolkit<T, R2, E2>\n} = Function.dual(\n 2,\n <T extends Toolkit, R2, E2>(toolkit: T, middleware: Middleware<R2, E2>): WrapToolkit<T, R2, E2> =>\n mapLocal(toolkit, (tool) => {\n const wrapped = middleware((input: unknown) => toStream(tool.run(input)), tool.name)\n // Keeps the shape: an `Effect` tool stays single-valued, so it emits no partials.\n return {\n ...tool,\n run: (input: unknown) =>\n isStreamed(tool.run(input)) ? wrapped(input) : lastOf(tool.name, wrapped(input)),\n }\n }),\n)\n\nconst lastOf = <A, E, R>(name: string, values: Stream.Stream<A, E, R>): Effect.Effect<A, E, R> =>\n Effect.flatMap(\n Stream.runLast(values),\n Option.match({\n onSome: Effect.succeed,\n onNone: () => Effect.die(`A middleware left the Effect tool \"${name}\" without a value`),\n }),\n )\n\ntype AddFailures<T extends AnyTool, F2> =\n T extends Tool<infer N, infer I, infer O, infer F, infer E, infer R>\n ? Tool<N, I, O, F | F2, E, R>\n : T\n\ntype AddFailuresToolkit<T extends ToolMap, F2> = {\n readonly [K in keyof T]: T[K] extends AnyTool ? AddFailures<T[K], F2> : T[K]\n}\n\n/**\n * `Tool.withFailures` for every local tool, e.g. a whole MCP toolkit that needs\n * approval. Prefer it per tool when only some tools are gated.\n */\nexport const withFailures: {\n <F2, F2Encoded extends Schema.Json>(\n failures: Schema.Codec<F2, F2Encoded>,\n ): <T extends Toolkit>(toolkit: T) => AddFailuresToolkit<T, F2>\n <T extends Toolkit, F2, F2Encoded extends Schema.Json>(\n toolkit: T,\n failures: Schema.Codec<F2, F2Encoded>,\n ): AddFailuresToolkit<T, F2>\n} = Function.dual(\n 2,\n <T extends Toolkit, F2>(\n toolkit: T,\n failures: Schema.Codec<F2, Schema.Json>,\n ): AddFailuresToolkit<T, F2> => mapLocal(toolkit, (tool) => withToolFailures(tool, failures)),\n)\n\n// `D` is what `describe` returns: with `undefined` possible, some errors stay on the stream.\ntype DescribeTool<T extends AnyTool, D> =\n T extends Tool<infer N, infer I, infer O, infer F, infer E, infer R>\n ? Tool<N, I, O, F | ToolFailed, F | ToolFailed | (undefined extends D ? E : never), R>\n : T\n\ntype DescribeToolkit<T extends ToolMap, D> = {\n readonly [K in keyof T]: T[K] extends AnyTool ? DescribeTool<T[K], D> : T[K]\n}\n\n/**\n * Undeclared errors become a `ToolFailed` the model reads, e.g. with\n * `AiError.describe`. Declared failures pass through unchanged. Return\n * `undefined` for an error that should still fail the run (a dead session).\n */\nexport const describeFailures: {\n <E, D extends string | undefined>(\n describe: (e: E) => D,\n ): <T extends Toolkit>(toolkit: T) => DescribeToolkit<T, D>\n <T extends Toolkit, D extends string | undefined>(\n toolkit: T,\n describe: (e: ToolkitE<T>) => D,\n ): DescribeToolkit<T, D>\n} = Function.dual(\n 2,\n <T extends Toolkit>(\n toolkit: T,\n describe: (e: unknown) => string | undefined,\n ): DescribeToolkit<T, string | undefined> =>\n mapLocal(toolkit, (tool) => {\n const isDeclared = isDeclaredBy(tool)\n const toFailed = (e: unknown) =>\n isDeclared(e)\n ? e\n : Option.match(Option.fromNullishOr(describe(e)), {\n onNone: () => e,\n onSome: (message) => new ToolFailed({ message }),\n })\n return {\n ...tool,\n failureSchema:\n tool.failureSchema === undefined\n ? ToolFailed\n : Schema.Union([tool.failureSchema, ToolFailed]),\n // Keeps the shape: an `Effect` tool must not start emitting partials.\n run: (input: unknown) => {\n const out = tool.run(input)\n return isStreamed(out) ? Stream.mapError(out, toFailed) : Effect.mapError(out, toFailed)\n },\n }\n }),\n)\n\n// ---------------------------------------------------------------------------\n// Executor\n// ---------------------------------------------------------------------------\n\nexport type ExecuteOptions = {\n readonly concurrency?: number | \"unbounded\"\n}\n\n/**\n * Run the calls, emitting each one's partials and its `Output`, typed per tool\n * and decoded. An error matching the tool's `failureSchema` becomes a `Failure`;\n * any other error fails the stream (siblings of a failed batch may then stay\n * unanswered: see `HistoryCheck.cancelAllPending`). Which calls run is the caller's call.\n */\nexport const run = <T extends Toolkit>(\n toolkit: T,\n calls: ReadonlyArray<ToolCall>,\n options?: ExecuteOptions,\n): Stream.Stream<Event<T>, ToolkitE<T>, ToolkitR<T>> =>\n Stream.fromIterable(calls).pipe(\n Stream.flatMap((call) => runOne(toolkit, call), {\n concurrency: options?.concurrency ?? \"unbounded\",\n }),\n ) as Stream.Stream<Event<T>, ToolkitE<T>, ToolkitR<T>>\n\ntype AnyEvent = ToolEvent.ToolEvent<string, unknown, unknown>\n\n// Own-property lookup: a call named `constructor` must not hit the prototype.\nconst lookup = (toolkit: Toolkit, name: string): AnyTool | undefined =>\n Object.hasOwn(toolkit, name) ? toolkit[name] : undefined\n\n// A tool whose schemas apply to the call's outcome: `Tool` or `Declared`.\nconst local = (toolkit: Toolkit, name: string): AnyDescribed | undefined => {\n const tool = lookup(toolkit, name)\n return tool === undefined || tool._tag === \"ProviderTool\" ? undefined : tool\n}\n\nconst done = (call: ToolCall, result: Result.Result<unknown, unknown>): AnyEvent => ({\n _tag: \"Output\",\n call_id: call.call_id,\n tool: call.name,\n result,\n})\n\nconst failWith = (call: ToolCall, error: RunError): Stream.Stream<AnyEvent> =>\n Stream.succeed(done(call, Result.fail(error)))\n\nconst runOne = (toolkit: Toolkit, call: ToolCall): Stream.Stream<AnyEvent, unknown, any> =>\n Match.value(lookup(toolkit, call.name)).pipe(\n Match.when(Match.undefined, () =>\n failWith(call, new UnknownTool({ message: `No tool named \"${call.name}\"` })),\n ),\n Match.discriminatorsExhaustive(\"_tag\")({\n LocalTool: (tool) => runTool(tool, call),\n DeclaredTool: () =>\n failWith(\n call,\n new UnknownTool({ message: `\"${call.name}\" has no run; the app handles its calls` }),\n ),\n ProviderTool: () =>\n failWith(call, new UnknownTool({ message: `\"${call.name}\" is run by the provider` })),\n }),\n )\n\nconst describeIssues = (issues: ReadonlyArray<StandardSchemaV1.Issue>): string =>\n issues\n .map((issue) => {\n const path = (issue.path ?? [])\n .map((seg) => (typeof seg === \"object\" && seg !== null ? String(seg.key) : String(seg)))\n .join(\".\")\n return path === \"\" ? issue.message : `${path}: ${issue.message}`\n })\n .join(\"; \")\n .slice(0, 500)\n\n// A call's input, or the `InputInvalid` the model gets for it.\nconst decodeInput = (\n tool: AnyDescribed,\n call: ToolCall,\n): Effect.Effect<Result.Result<unknown, InputInvalid>> =>\n Effect.map(\n decodeCallInput(tool, call),\n Match.type<DecodeResult<unknown>>().pipe(\n Match.tag(\"parseError\", () =>\n Result.fail(new InputInvalid({ message: \"arguments are not valid JSON\" })),\n ),\n Match.tag(\"invalid\", ({ issues }) =>\n Result.fail(new InputInvalid({ message: describeIssues(issues) })),\n ),\n Match.tag(\"ok\", ({ input }) => Result.succeed(input)),\n Match.exhaustive,\n ),\n )\n\nconst runTool = (tool: AnyLocalTool, call: ToolCall): Stream.Stream<AnyEvent, unknown, any> =>\n Stream.unwrap(\n Effect.map(\n decodeInput(tool, call),\n Result.match({\n onFailure: (error) => failWith(call, error),\n onSuccess: (input) => execute(tool, call, input),\n }),\n ),\n )\n\n// An `Effect` tool emits its `Output`. A `Stream` tool emits each value as a\n// `Partial` as it arrives, then the last one again as the `Output`. Each value\n// is checked against `outputSchema` and handed on decoded.\nconst execute = (\n tool: AnyLocalTool,\n call: ToolCall,\n input: unknown,\n): Stream.Stream<AnyEvent, unknown, any> => {\n const out = tool.run(input)\n const events = isStreamed(out)\n ? streamed(tool, call, out)\n : Stream.fromEffect(\n Effect.map(\n Effect.tap(out, (value) => check(tool, value)),\n (value) => done(call, Result.succeed(value)),\n ),\n )\n return Stream.catchCause(events, (cause) =>\n Stream.fromEffect(Effect.map(declared(tool, cause), (error) => done(call, Result.fail(error)))),\n )\n}\n\nconst streamed = (\n tool: AnyLocalTool,\n call: ToolCall,\n values: Stream.Stream<unknown, unknown, unknown>,\n): Stream.Stream<AnyEvent, unknown, unknown> =>\n values.pipe(\n Stream.mapEffect((value) => Effect.as(check(tool, value), Option.some(value))),\n // `None` marks a clean end: `concat` never runs after a failure, so a\n // failing tool can't have its last partial promoted to a `Success`.\n Stream.concat(Stream.succeed(Option.none<unknown>())),\n Stream.mapAccum(\n () => Option.none<unknown>(),\n (last, next): readonly [Option.Option<unknown>, ReadonlyArray<AnyEvent>] =>\n Option.match(next, {\n onSome: (value) => [\n Option.some(value),\n [{ _tag: \"Partial\", call_id: call.call_id, tool: tool.name, value }],\n ],\n onNone: () => [\n last,\n [\n done(\n call,\n Option.match(last, {\n onNone: () =>\n Result.fail(new OutputInvalid({ message: \"The tool produced no value\" })),\n onSome: Result.succeed,\n }),\n ),\n ],\n ],\n }),\n ),\n )\n\n// Marks a value `outputSchema` rejected, apart from the tool's own errors\n// (matched by class, so a tool error with the same tag can't pose as one).\nclass EncodeFailed extends Data.TaggedError(\"EncodeFailed\")<{ readonly message: string }> {}\n\nconst check = (tool: AnyDescribed, value: unknown): Effect.Effect<unknown, EncodeFailed> =>\n tool.outputSchema === undefined\n ? Effect.void\n : Schema.encodeUnknownEffect(tool.outputSchema)(value).pipe(\n Effect.mapError((e) => new EncodeFailed({ message: e.message.slice(0, 500) })),\n )\n\nconst isDeclaredBy = (tool: AnyLocalTool): ((e: unknown) => boolean) =>\n tool.failureSchema === undefined ? () => false : Schema.is(tool.failureSchema)\n\n// The error of a cause holding exactly one failure; `None` for anything mixed.\nconst soleError = (cause: Cause.Cause<unknown>): Option.Option<unknown> =>\n Option.fromNullishOr(cause.reasons.length === 1 ? cause.reasons[0] : undefined).pipe(\n Option.filter(Cause.isFailReason),\n Option.map((reason) => reason.error),\n )\n\n// One failure the tool declared (or a rejected value) becomes a `Failure`.\n// Anything else (undeclared errors, defects, interruption) propagates.\nconst declared = (\n tool: AnyLocalTool,\n cause: Cause.Cause<unknown>,\n): Effect.Effect<unknown, unknown> =>\n soleError(cause).pipe(\n Option.flatMap((error) =>\n Match.value(error).pipe(\n Match.when(Match.instanceOf(EncodeFailed), (e) =>\n Option.some<unknown>(new OutputInvalid({ message: e.message })),\n ),\n Match.when(isDeclaredBy(tool), Option.some),\n Match.orElse(() => Option.none()),\n ),\n ),\n Option.match({ onNone: () => Effect.failCause(cause), onSome: Effect.succeed }),\n )\n\n// ---------------------------------------------------------------------------\n// To history and back\n// ---------------------------------------------------------------------------\n\nconst outputs = (tool: AnyDescribed | undefined): Schema.Codec<unknown, Schema.Json> =>\n tool?.outputSchema ?? Content.Value\n\nconst failures = (tool: AnyDescribed | undefined): Schema.Codec<unknown, Schema.Json> =>\n tool?.failureSchema === undefined ? CoreError : Schema.Union([tool.failureSchema, CoreError])\n\n/** Any call's outcome, as `run` emits it. */\nexport type Outcome = ToolEvent.Output<string, unknown, unknown>\n\n/** Every error the toolkit's tools declare (core's errors are always possible too). */\nexport type ToolkitFailure<T extends Toolkit> = ToolMap extends T\n ? unknown\n : ToolFailure<T[keyof T]>\n\n/** `Toolkit.close` got an error the call's tool doesn't declare: a bug in the app. */\nexport class UndeclaredFailure extends Data.TaggedError(\"UndeclaredFailure\")<{\n readonly tool: string\n readonly message: string\n}> {}\n\nconst describeError = (error: unknown): string =>\n Predicate.hasProperty(error, \"_tag\") && Predicate.isString(error._tag)\n ? error._tag\n : String(error)\n\n/**\n * A call the app closes itself (denied, superseded), as the outcome `run`\n * would emit. `error` must be core's or declared by the call's tool\n * (`failureSchema`, `Tool.withFailures`), else this fails with `UndeclaredFailure`.\n * Pass the tool's name to check `error` against that tool at compile time:\n *\n * Toolkit.close(toolkit, \"issue_refund\", call, new Escalated({ team: \"finance\" }))\n */\nexport function close<T extends Toolkit, N extends keyof T & string>(\n toolkit: T,\n name: N,\n call: ToolCall,\n error: ToolFailure<T[N]> | CoreError,\n): Effect.Effect<ToolEvent.Output<N, never, ToolFailure<T[N]> | CoreError>, UndeclaredFailure>\nexport function close<T extends Toolkit>(\n toolkit: T,\n call: ToolCall,\n error: ToolkitFailure<T> | CoreError,\n): Effect.Effect<ToolEvent.Output<string, never, ToolkitFailure<T> | CoreError>, UndeclaredFailure>\nexport function close(\n toolkit: Toolkit,\n ...args: [name: string, call: ToolCall, error: unknown] | [call: ToolCall, error: unknown]\n): Effect.Effect<ToolEvent.Output<string, never, unknown>, UndeclaredFailure> {\n const [name, call, error] = args.length === 3 ? args : [args[0].name, ...args]\n return Match.value({ name, call, error }).pipe(\n Match.when(\n ({ call }) => call.name !== name,\n () =>\n Effect.fail(\n new UndeclaredFailure({\n tool: name,\n message: `the call is for \"${call.name}\", not \"${name}\"`,\n }),\n ),\n ),\n Match.when(\n ({ error }) => !Schema.is(failures(local(toolkit, name)))(error),\n () =>\n Effect.fail(\n new UndeclaredFailure({\n tool: name,\n message: `\"${name}\" does not declare ${describeError(error)} in its failureSchema`,\n }),\n ),\n ),\n Match.orElse(() =>\n Effect.succeed<ToolEvent.Output<string, never, unknown>>({\n _tag: \"Output\",\n call_id: call.call_id,\n tool: name,\n result: Result.fail(error),\n }),\n ),\n )\n}\n\n/**\n * A call the app answers itself (`ask_user`, a signal's acknowledgement), as\n * the outcome `run` would emit: `close`'s success side. `value` is typed by the\n * tool's `outputSchema`; a value it rejects ends the call with `OutputInvalid`,\n * as from `run`. Fails with `UndeclaredFailure` if `call` is for another tool.\n */\nexport const complete = <T extends Toolkit, N extends keyof T & string>(\n toolkit: T,\n name: N,\n call: ToolCall,\n value: OutputOf<T[N]>,\n): Effect.Effect<ToolEvent.Output<N, OutputOf<T[N]>, OutputInvalid>, UndeclaredFailure> =>\n Option.match(Option.fromNullishOr(call.name === name ? local(toolkit, name) : undefined), {\n onNone: () =>\n Effect.fail(\n new UndeclaredFailure({\n tool: name,\n message:\n call.name === name\n ? `\"${name}\" is not a tool of this toolkit`\n : `the call is for \"${call.name}\", not \"${name}\"`,\n }),\n ),\n onSome: (tool) =>\n check(tool, value).pipe(\n Effect.match({\n onFailure: (e) => Result.fail(new OutputInvalid({ message: e.message })),\n onSuccess: () => Result.succeed(value),\n }),\n Effect.map((result) => ({ _tag: \"Output\", call_id: call.call_id, tool: name, result })),\n ),\n })\n\n// ---------------------------------------------------------------------------\n// Calls to declared tools\n// ---------------------------------------------------------------------------\n\ntype InputOf<T> = T extends { readonly inputSchema: StandardSchemaV1<any, infer I> } ? I : never\n\n// Distributes over the tool type, so a loose toolkit yields `{ tool: string, input: any }`.\ntype DeclaredCallOf<K extends string, X> = X extends { readonly _tag: \"DeclaredTool\" }\n ? { readonly tool: K; readonly call: ToolCall; readonly input: InputOf<X> }\n : never\n\n/** A call to one of the toolkit's declared tools, its input decoded. `tool` is the discriminant. */\nexport type DeclaredCall<T extends Toolkit> = {\n [K in keyof T & string]: DeclaredCallOf<K, T[K]>\n}[keyof T & string]\n\n/** A turn's calls, sorted for the loop. */\nexport type Split<T extends Toolkit> = {\n /** For `Toolkit.run`: calls to tools with `run`, and to unknown names (closed there). */\n readonly run: ReadonlyArray<ToolCall>\n /** Calls to declared tools, decoded: handle them with `Match.discriminatorsExhaustive(\"tool\")`. */\n readonly declared: ReadonlyArray<DeclaredCall<T>>\n /** Calls to declared tools with bad arguments, closed with `InputInvalid` for the model. */\n readonly invalid: ReadonlyArray<ToolEvent.Output<string, never, InputInvalid>>\n}\n\ntype Sorted =\n | { readonly _tag: \"run\"; readonly call: ToolCall }\n | { readonly _tag: \"declared\"; readonly declared: DeclaredCall<ToolMap> }\n | { readonly _tag: \"invalid\"; readonly output: ToolEvent.Output<string, never, InputInvalid> }\n\nconst sortCall = (toolkit: Toolkit, call: ToolCall): Effect.Effect<Sorted> => {\n const tool = lookup(toolkit, call.name)\n return tool?._tag === \"DeclaredTool\"\n ? Effect.map(\n decodeInput(tool, call),\n Result.match({\n onFailure: (error): Sorted => ({\n _tag: \"invalid\",\n output: {\n _tag: \"Output\",\n call_id: call.call_id,\n tool: call.name,\n result: Result.fail(error),\n },\n }),\n onSuccess: (input): Sorted => ({\n _tag: \"declared\",\n declared: { tool: call.name, call, input },\n }),\n }),\n )\n : Effect.succeed({ _tag: \"run\", call })\n}\n\n/**\n * The turn's tool calls, sorted: `run` for `Toolkit.run`, and the calls to\n * declared tools decoded and typed per tool. Handling `declared` with\n * `Match.discriminatorsExhaustive(\"tool\")` makes a new declared tool a compile\n * error until the loop handles it:\n *\n * const { run, declared, invalid } = yield* Toolkit.split(toolkit, turn)\n * declared.map(Match.discriminatorsExhaustive(\"tool\")({ ask_user: ..., escalate: ... }))\n */\nexport const split = <T extends Toolkit>(toolkit: T, turn: Turn): Effect.Effect<Split<T>> =>\n Effect.map(\n Effect.forEach(getToolCalls(turn), (call) => sortCall(toolkit, call)),\n (sorted) => ({\n run: sorted.flatMap((s) => (s._tag === \"run\" ? [s.call] : [])),\n declared: sorted.flatMap((s) =>\n s._tag === \"declared\" ? [s.declared as DeclaredCall<T>] : [],\n ),\n invalid: sorted.flatMap((s) => (s._tag === \"invalid\" ? [s.output] : [])),\n }),\n )\n\n/** Narrows to the `Output` members (also in a loop's mixed stream), keeping the per-tool types. */\nexport const isOutcome = <A extends { readonly _tag: string }>(\n e: A,\n): e is Extract<A, { readonly _tag: \"Output\" }> => e._tag === \"Output\"\n\nconst toOutput = (\n toolkit: Toolkit,\n event: Outcome,\n): Effect.Effect<ToolCallOutput, Schema.SchemaError> => {\n const tool = local(toolkit, event.tool)\n return Result.match(event.result, {\n onSuccess: (value) => ToolOutput.success(event, outputs(tool), value),\n onFailure: (error) => ToolOutput.failure(event, failures(tool), error),\n })\n}\n\n/**\n * An outcome as history, encoded with the tool's schemas (never stringified:\n * that is the provider codec's job). `output(toolkit)` is the pipeable form.\n */\nexport function output(\n toolkit: Toolkit,\n): (event: Outcome) => Effect.Effect<ToolCallOutput, Schema.SchemaError>\nexport function output(\n toolkit: Toolkit,\n event: Outcome,\n): Effect.Effect<ToolCallOutput, Schema.SchemaError>\nexport function output(toolkit: Toolkit, event?: Outcome) {\n return event === undefined ? (e: Outcome) => toOutput(toolkit, e) : toOutput(toolkit, event)\n}\n\n/** History back to a typed `Result` for tool `name`, decoded with its schemas. */\nexport function decode<T extends Toolkit, N extends keyof T & string>(\n toolkit: T,\n name: N,\n item: ToolCallOutput,\n): Effect.Effect<\n Result.Result<OutputOf<T[N]>, ToolFailure<T[N]> | ToolOutput.CoreError>,\n Schema.SchemaError\n>\nexport function decode(\n toolkit: Toolkit,\n name: string,\n item: ToolCallOutput,\n): Effect.Effect<Result.Result<unknown, unknown>, Schema.SchemaError> {\n const tool = local(toolkit, name)\n const decodeWith = (schema: Schema.Codec<unknown, unknown>) =>\n Effect.flatMap(ToolOutput.encoded(item.output), Schema.decodeUnknownEffect(schema))\n return Match.value(item).pipe(\n Match.when({ isError: true }, () => Effect.map(decodeWith(failures(tool)), Result.fail)),\n Match.orElse(() =>\n Option.match(Option.fromNullishOr(tool?.outputSchema), {\n // Without `outputSchema` the parts' own types say what the value is.\n onNone: () => Effect.succeed(Result.succeed(ToolOutput.value(item.output))),\n onSome: (schema) => Effect.map(decodeWith(schema), Result.succeed),\n }),\n ),\n )\n}\n\n// ---------------------------------------------------------------------------\n// Into the loop\n// ---------------------------------------------------------------------------\n\ntype Tagged = { readonly _tag: string }\n\n// An app's own events may travel alongside; `Output` is reserved for outcomes.\nconst isOutcomeOf = <A extends Tagged>(e: A): e is A & Outcome => e._tag === \"Output\"\n\n/**\n * Forward every event as a `Loop.value`, then continue the loop with\n * `build(outcomes)`. `build` is an Effect, so it can encode. The stream may\n * carry the app's own tagged events too (any tag but `Output`).\n */\nexport const continueWith: {\n <S, E2, R2>(\n build: (outcomes: ReadonlyArray<Outcome>) => Effect.Effect<S, E2, R2>,\n ): <A extends Tagged, E, R>(\n stream: Stream.Stream<A, E, R>,\n ) => Stream.Stream<Loop.Step<A, S>, E | E2, R | R2>\n <A extends Tagged, E, R, S, E2, R2>(\n stream: Stream.Stream<A, E, R>,\n build: (outcomes: ReadonlyArray<Outcome>) => Effect.Effect<S, E2, R2>,\n ): Stream.Stream<Loop.Step<A, S>, E | E2, R | R2>\n} = Function.dual(\n 2,\n <A extends Tagged, E, R, S, E2, R2>(\n stream: Stream.Stream<A, E, R>,\n build: (outcomes: ReadonlyArray<Outcome>) => Effect.Effect<S, E2, R2>,\n ): Stream.Stream<Loop.Step<A, S>, E | E2, R | R2> =>\n Stream.unwrap(\n Effect.map(Ref.make<ReadonlyArray<Outcome>>([]), (outcomes) =>\n Stream.concat(\n stream.pipe(\n Stream.tap((e) =>\n isOutcomeOf(e) ? Ref.update(outcomes, Arr.append<Outcome>(e)) : Effect.void,\n ),\n Stream.map(Loop.value),\n ),\n Stream.unwrap(Ref.get(outcomes).pipe(Effect.flatMap(build), Effect.map(Loop.next))),\n ),\n ),\n ),\n)\n\n/** Encode each outcome with `output` and append the turn plus the outputs to history. */\nexport const appendResults =\n <S extends { readonly history: ReadonlyArray<HistoryItem> }>(\n toolkit: Toolkit,\n state: S,\n turn: Turn,\n ) =>\n (outcomes: ReadonlyArray<Outcome>): Effect.Effect<S, Schema.SchemaError> =>\n Effect.map(Effect.forEach(outcomes, output(toolkit)), (items) =>\n appendToHistory(state, turn, items),\n )\n\n/** `continueWith(appendResults(toolkit, state, turn))`. */\nexport const next = <S extends { readonly history: ReadonlyArray<HistoryItem> }>(\n toolkit: Toolkit,\n state: S,\n turn: Turn,\n) => continueWith(appendResults(toolkit, state, turn))\n"],"mappings":"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"}
|