@effect-uai/core 0.8.0 → 0.9.0
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/{AiError-CAX_48RU.d.mts → AiError-CrdR1EQi.d.mts} +2 -2
- package/dist/{AiError-CAX_48RU.d.mts.map → AiError-CrdR1EQi.d.mts.map} +1 -1
- package/dist/{Audio-DPlTsNdz.d.mts → Audio-DDSKCkSe.d.mts} +2 -2
- package/dist/{Audio-DPlTsNdz.d.mts.map → Audio-DDSKCkSe.d.mts.map} +1 -1
- package/dist/{Image-HNmMpMTh.d.mts → Image-C_Zjpwhc.d.mts} +2 -2
- package/dist/{Image-HNmMpMTh.d.mts.map → Image-C_Zjpwhc.d.mts.map} +1 -1
- package/dist/{Items-7ljaVxH_.d.mts → Items-CgKD6Npw.d.mts} +13 -13
- package/dist/{Items-7ljaVxH_.d.mts.map → Items-CgKD6Npw.d.mts.map} +1 -1
- package/dist/Loop-B5_cqumi.d.mts +173 -0
- package/dist/Loop-B5_cqumi.d.mts.map +1 -0
- package/dist/{Media-D_CpcM1Z.d.mts → Media-DOLyaygI.d.mts} +1 -1
- package/dist/{Media-D_CpcM1Z.d.mts.map → Media-DOLyaygI.d.mts.map} +1 -1
- package/dist/{SandboxError-BvKypkJm.d.mts → SandboxError-CIrVDOMV.d.mts} +2 -2
- package/dist/{SandboxError-BvKypkJm.d.mts.map → SandboxError-CIrVDOMV.d.mts.map} +1 -1
- package/dist/{StructuredFormat-BbN4dosH.d.mts → StructuredFormat-CMJFD3sn.d.mts} +2 -2
- package/dist/{StructuredFormat-BbN4dosH.d.mts.map → StructuredFormat-CMJFD3sn.d.mts.map} +1 -1
- package/dist/Tool-0XUIT2A2.d.mts +232 -0
- package/dist/Tool-0XUIT2A2.d.mts.map +1 -0
- package/dist/ToolEvent-DYrAUJGs.d.mts +151 -0
- package/dist/ToolEvent-DYrAUJGs.d.mts.map +1 -0
- package/dist/ToolResult-BZd-cEWW.d.mts +151 -0
- package/dist/ToolResult-BZd-cEWW.d.mts.map +1 -0
- package/dist/Toolkit-BKC8b8Xo.d.mts +155 -0
- package/dist/Toolkit-BKC8b8Xo.d.mts.map +1 -0
- package/dist/{dist-DV5ISja1.mjs → dist-B04dlFHg.mjs} +3 -3
- package/dist/{dist-DV5ISja1.mjs.map → dist-B04dlFHg.mjs.map} +1 -1
- package/dist/dist-DWgRbDN3.mjs +140 -0
- package/dist/dist-DWgRbDN3.mjs.map +1 -0
- package/dist/domain/AiError.d.mts +1 -1
- package/dist/domain/Audio.d.mts +1 -1
- package/dist/domain/Image.d.mts +1 -1
- package/dist/domain/Items.d.mts +1 -1
- package/dist/domain/Media.d.mts +1 -1
- package/dist/domain/Music.d.mts +1 -1
- package/dist/domain/Turn.d.mts +4 -4
- package/dist/domain/Turn.test.mjs +1 -1
- package/dist/embedding-model/Embedding.d.mts +1 -1
- package/dist/embedding-model/EmbeddingModel.d.mts +1 -1
- package/dist/embedding-model/EmbeddingModel.test.mjs +1 -1
- package/dist/embedding-model/EmbeddingModel.test.mjs.map +1 -1
- package/dist/index.d.mts +14 -13
- package/dist/index.mjs +2 -1
- package/dist/language-model/LanguageModel.d.mts +10 -5
- package/dist/language-model/LanguageModel.d.mts.map +1 -1
- package/dist/language-model/LanguageModel.mjs.map +1 -1
- package/dist/language-model/LanguageModel.test.mjs +1 -1
- package/dist/loop/Loop.d.mts +2 -141
- package/dist/loop/Loop.mjs +16 -20
- package/dist/loop/Loop.mjs.map +1 -1
- package/dist/loop/Loop.test.mjs +18 -1
- package/dist/loop/Loop.test.mjs.map +1 -1
- package/dist/{magic-string.es-BgIV5Mu3.mjs → magic-string.es-Dk-MMA0F.mjs} +1 -1
- package/dist/{magic-string.es-BgIV5Mu3.mjs.map → magic-string.es-Dk-MMA0F.mjs.map} +1 -1
- package/dist/music-generator/MusicGenerator.d.mts +2 -2
- package/dist/music-generator/MusicGenerator.test.mjs +1 -1
- package/dist/observability/Metrics.d.mts +116 -28
- package/dist/observability/Metrics.d.mts.map +1 -1
- package/dist/observability/Metrics.mjs +250 -38
- package/dist/observability/Metrics.mjs.map +1 -1
- package/dist/observability/Metrics.test.d.mts +1 -0
- package/dist/observability/Metrics.test.mjs +187 -0
- package/dist/observability/Metrics.test.mjs.map +1 -0
- package/dist/observability/Telemetry.d.mts +37 -0
- package/dist/observability/Telemetry.d.mts.map +1 -0
- package/dist/observability/Telemetry.mjs +57 -0
- package/dist/observability/Telemetry.mjs.map +1 -0
- package/dist/observability/Telemetry.test.d.mts +1 -0
- package/dist/observability/Telemetry.test.mjs +92 -0
- package/dist/observability/Telemetry.test.mjs.map +1 -0
- package/dist/retry/Retry.d.mts +2 -2
- package/dist/retry/Retry.test.mjs +1 -1
- package/dist/sandbox/Sandbox.d.mts +1 -1
- package/dist/sandbox/SandboxError.d.mts +1 -1
- package/dist/speech-synthesizer/SpeechSynthesizer.d.mts +2 -2
- package/dist/speech-synthesizer/SpeechSynthesizer.test.mjs +1 -1
- package/dist/streaming/JSONL.d.mts +1 -1
- package/dist/streaming/JSONL.test.mjs +1 -1
- package/dist/streaming/SSE.test.mjs +1 -1
- package/dist/structured-format/StructuredFormat.d.mts +1 -1
- package/dist/structured-format/StructuredFormat.mjs.map +1 -1
- package/dist/structured-format/StructuredFormat.test.mjs +1 -1
- package/dist/testing/MockMusicGenerator.d.mts +1 -1
- package/dist/testing/MockProvider.d.mts +1 -1
- package/dist/testing/MockSpeechSynthesizer.d.mts +1 -1
- package/dist/tool/Approval.d.mts +3 -3
- package/dist/tool/Approval.test.mjs +35 -34
- package/dist/tool/Approval.test.mjs.map +1 -1
- package/dist/tool/HistoryCheck.d.mts +2 -2
- package/dist/tool/Tool.d.mts +2 -2
- package/dist/tool/Tool.mjs +112 -22
- package/dist/tool/Tool.mjs.map +1 -1
- package/dist/tool/Tool.test.mjs +41 -3
- package/dist/tool/Tool.test.mjs.map +1 -1
- package/dist/tool/ToolEvent.d.mts +2 -151
- package/dist/tool/ToolResult.d.mts +2 -138
- package/dist/tool/ToolResult.mjs +18 -3
- package/dist/tool/ToolResult.mjs.map +1 -1
- package/dist/tool/Toolkit.d.mts +2 -73
- package/dist/tool/Toolkit.mjs +106 -28
- package/dist/tool/Toolkit.mjs.map +1 -1
- package/dist/tool/Toolkit.test.mjs +113 -7
- package/dist/tool/Toolkit.test.mjs.map +1 -1
- package/dist/transcriber/Transcriber.d.mts +2 -2
- package/dist/transcriber/Transcriber.test.mjs +1 -1
- package/dist/web-search/WebSearch.d.mts +1 -1
- package/dist/web-search/WebSearchTool.d.mts +2 -2
- package/dist/web-search/WebSearchTool.d.mts.map +1 -1
- package/dist/web-search/WebSearchTool.mjs.map +1 -1
- package/package.json +1 -1
- package/src/embedding-model/EmbeddingModel.test.ts +4 -0
- package/src/index.ts +1 -0
- package/src/language-model/LanguageModel.ts +7 -2
- package/src/loop/Loop.test.ts +22 -0
- package/src/loop/Loop.ts +27 -4
- package/src/observability/Metrics.test.ts +266 -0
- package/src/observability/Metrics.ts +505 -65
- package/src/observability/Telemetry.test.ts +123 -0
- package/src/observability/Telemetry.ts +96 -0
- package/src/structured-format/StructuredFormat.ts +4 -0
- package/src/tool/Approval.test.ts +22 -21
- package/src/tool/Tool.test.ts +55 -2
- package/src/tool/Tool.ts +221 -55
- package/src/tool/ToolResult.ts +22 -1
- package/src/tool/Toolkit.test.ts +168 -7
- package/src/tool/Toolkit.ts +336 -99
- package/src/web-search/WebSearchTool.ts +1 -1
- package/dist/Tool-BKiieFXk.d.mts +0 -102
- package/dist/Tool-BKiieFXk.d.mts.map +0 -1
- package/dist/loop/Loop.d.mts.map +0 -1
- package/dist/tool/ToolEvent.d.mts.map +0 -1
- package/dist/tool/ToolResult.d.mts.map +0 -1
- package/dist/tool/Toolkit.d.mts.map +0 -1
package/dist/tool/Tool.mjs
CHANGED
|
@@ -4,13 +4,19 @@ import { Effect, Schema } from "effect";
|
|
|
4
4
|
//#region src/tool/Tool.ts
|
|
5
5
|
var Tool_exports = /* @__PURE__ */ __exportAll({
|
|
6
6
|
ToolError: () => ToolError,
|
|
7
|
+
ToolValidationError: () => ToolValidationError,
|
|
8
|
+
decodeArgs: () => decodeArgs,
|
|
9
|
+
descriptorsOf: () => descriptorsOf,
|
|
7
10
|
execute: () => execute,
|
|
8
11
|
fromEffectSchema: () => fromEffectSchema,
|
|
9
12
|
fromStandardSchema: () => fromStandardSchema,
|
|
10
|
-
|
|
13
|
+
interaction: () => interaction,
|
|
11
14
|
make: () => make,
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
provider: () => provider,
|
|
16
|
+
signal: () => signal,
|
|
17
|
+
toDescriptors: () => toDescriptors,
|
|
18
|
+
withName: () => withName,
|
|
19
|
+
withRun: () => withRun
|
|
14
20
|
});
|
|
15
21
|
var ToolError = class extends Schema.TaggedErrorClass("@betalyra/effect-uai/ToolError")("ToolError", {
|
|
16
22
|
call_id: Schema.String,
|
|
@@ -19,6 +25,26 @@ var ToolError = class extends Schema.TaggedErrorClass("@betalyra/effect-uai/Tool
|
|
|
19
25
|
cause: Schema.optional(Schema.Unknown)
|
|
20
26
|
}) {};
|
|
21
27
|
/**
|
|
28
|
+
* One Standard Schema validation issue, carried on `ToolValidationError`.
|
|
29
|
+
* Mirrors `StandardSchemaV1.Issue`; `path` is left as `unknown` elements
|
|
30
|
+
* because Standard Schema path segments may be symbols or `{ key }` objects.
|
|
31
|
+
*/
|
|
32
|
+
const ToolValidationIssue = Schema.Struct({
|
|
33
|
+
message: Schema.String,
|
|
34
|
+
path: Schema.optional(Schema.Array(Schema.Unknown))
|
|
35
|
+
});
|
|
36
|
+
/**
|
|
37
|
+
* The model's `arguments` for a call failed the tool's `inputSchema`. Distinct
|
|
38
|
+
* from `ToolError` (malformed JSON, runtime crash) so callers can tell a
|
|
39
|
+
* contract violation apart from a parse or execution failure, and so the
|
|
40
|
+
* structured `issues` survive instead of being flattened into a message string.
|
|
41
|
+
*/
|
|
42
|
+
var ToolValidationError = class extends Schema.TaggedErrorClass("@betalyra/effect-uai/ToolValidationError")("ToolValidationError", {
|
|
43
|
+
call_id: Schema.String,
|
|
44
|
+
tool: Schema.String,
|
|
45
|
+
issues: Schema.Array(ToolValidationIssue)
|
|
46
|
+
}) {};
|
|
47
|
+
/**
|
|
22
48
|
* Convenience wrapper for Effect Schema users - adds both the
|
|
23
49
|
* `validate` and `jsonSchema` extensions to a plain Effect Schema so it
|
|
24
50
|
* can be used as a `Tool.inputSchema`.
|
|
@@ -40,30 +66,85 @@ const fromEffectSchema = (schema) => Schema.toStandardJSONSchemaV1(Schema.toStan
|
|
|
40
66
|
* helper makes the input type inference explicit at the call site.
|
|
41
67
|
*/
|
|
42
68
|
const fromStandardSchema = (schema) => schema;
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
69
|
+
/** A model-visible tool with a local `Effect` executor. */
|
|
70
|
+
const make = (spec) => ({
|
|
71
|
+
_tag: "LocalTool",
|
|
72
|
+
...spec
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* A provider-hosted tool (native web search, code execution, RAG grounding).
|
|
76
|
+
* No local executor — `provider`/`config` drive the provider adapter's
|
|
77
|
+
* rendering. The model sees it; `Toolkit.run` reports it as `non_local_tool`.
|
|
78
|
+
*/
|
|
79
|
+
const provider = (spec) => ({
|
|
80
|
+
_tag: "ProviderTool",
|
|
81
|
+
...spec
|
|
82
|
+
});
|
|
83
|
+
/**
|
|
84
|
+
* A typed control-flow signal to the agent loop (escalate, pause, schedule,
|
|
85
|
+
* hand off). Decode-only: the loop interprets the call rather than executing a
|
|
86
|
+
* handler, so there is no `run`.
|
|
87
|
+
*/
|
|
88
|
+
const signal = (spec) => ({
|
|
89
|
+
_tag: "SignalTool",
|
|
90
|
+
...spec
|
|
91
|
+
});
|
|
92
|
+
/**
|
|
93
|
+
* A typed request for an external actor to respond before the loop resumes
|
|
94
|
+
* (frontend, Telegram, CLI prompt). Decode-only; the loop stops/pauses and
|
|
95
|
+
* resumes by appending the actor's `function_call_output`.
|
|
96
|
+
*/
|
|
97
|
+
const interaction = (spec) => ({
|
|
98
|
+
_tag: "InteractionTool",
|
|
46
99
|
...spec
|
|
47
100
|
});
|
|
48
|
-
const isStreamingTool = (t) => "_kind" in t && t._kind === "streaming";
|
|
49
101
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
102
|
+
* Return a copy of a tool under a new `name`. Useful for resolving a name
|
|
103
|
+
* clash before combining tools into one `Toolkit`. Literal-preserving, so the
|
|
104
|
+
* renamed tool keys the toolkit record under the new name statically.
|
|
53
105
|
*/
|
|
106
|
+
const withName = (tool, name) => ({
|
|
107
|
+
...tool,
|
|
108
|
+
name
|
|
109
|
+
});
|
|
110
|
+
/**
|
|
111
|
+
* Replace a local tool's `run`, keeping its model-facing definition (name,
|
|
112
|
+
* description, schema, `_tag`) identical. The new `run`'s `input` is typed from
|
|
113
|
+
* the original tool, so override/mock need no annotation:
|
|
114
|
+
*
|
|
115
|
+
* const safe = { ...toolkit, send_email: Tool.withRun(toolkit.send_email,
|
|
116
|
+
* ({ to }) => Effect.succeed({ status: "dry-run", to })) }
|
|
117
|
+
*
|
|
118
|
+
* Descriptors stay identical to production, so a mocked toolkit can't drift
|
|
119
|
+
* from the contract the model sees.
|
|
120
|
+
*/
|
|
121
|
+
const withRun = (tool, run) => ({
|
|
122
|
+
...tool,
|
|
123
|
+
run
|
|
124
|
+
});
|
|
125
|
+
/** Render tools to provider-agnostic descriptors. Every kind is model-visible. */
|
|
54
126
|
const toDescriptors = (tools) => tools.map((tool) => {
|
|
55
127
|
const inputSchema = tool.inputSchema["~standard"].jsonSchema.input({ target: "draft-2020-12" });
|
|
56
|
-
|
|
128
|
+
const strict = "strict" in tool ? tool.strict : void 0;
|
|
129
|
+
return strict !== void 0 ? {
|
|
57
130
|
name: tool.name,
|
|
58
131
|
description: tool.description,
|
|
59
132
|
inputSchema,
|
|
60
|
-
strict
|
|
133
|
+
strict
|
|
61
134
|
} : {
|
|
62
135
|
name: tool.name,
|
|
63
136
|
description: tool.description,
|
|
64
137
|
inputSchema
|
|
65
138
|
};
|
|
66
139
|
});
|
|
140
|
+
/**
|
|
141
|
+
* Render a `Toolkit` (a name-indexed record of tools) to descriptors, treating
|
|
142
|
+
* an absent toolkit as no tools. The normalization point the `LanguageModel`
|
|
143
|
+
* boundary uses so a request can carry the toolkit itself instead of a
|
|
144
|
+
* pre-rendered descriptor array. Lives here (not on `Toolkit`) to keep providers
|
|
145
|
+
* free of a dependency on the toolkit module — it only needs the tool values.
|
|
146
|
+
*/
|
|
147
|
+
const descriptorsOf = (toolkit) => toolkit === void 0 ? [] : toDescriptors(Object.values(toolkit));
|
|
67
148
|
const toToolError = (call, toolName, message) => (cause) => new ToolError({
|
|
68
149
|
call_id: call.call_id,
|
|
69
150
|
tool: toolName,
|
|
@@ -71,26 +152,35 @@ const toToolError = (call, toolName, message) => (cause) => new ToolError({
|
|
|
71
152
|
cause
|
|
72
153
|
});
|
|
73
154
|
/**
|
|
74
|
-
* Decode and validate
|
|
75
|
-
*
|
|
76
|
-
*
|
|
155
|
+
* Decode and validate a function_call's JSON `arguments` against the tool's
|
|
156
|
+
* own `inputSchema`, yielding the typed input. The decode-only half of
|
|
157
|
+
* `execute` - reach for it when you intercept a call to translate it into a
|
|
158
|
+
* control-flow decision rather than running the tool's `run`.
|
|
159
|
+
*
|
|
160
|
+
* Malformed JSON fails with `ToolError`; a parsed body that violates
|
|
161
|
+
* `inputSchema` fails with `ToolValidationError` carrying the issues.
|
|
77
162
|
*/
|
|
78
|
-
const
|
|
163
|
+
const decodeArgs = (tool, call) => Effect.gen(function* () {
|
|
79
164
|
const parsed = yield* Effect.try({
|
|
80
165
|
try: () => JSON.parse(call.arguments),
|
|
81
166
|
catch: toToolError(call, tool.name, "Failed to parse JSON arguments")
|
|
82
167
|
});
|
|
83
168
|
const result = yield* Effect.promise(() => Promise.resolve(tool.inputSchema["~standard"].validate(parsed)));
|
|
84
|
-
if (result.issues !== void 0) return yield* new
|
|
169
|
+
if (result.issues !== void 0) return yield* new ToolValidationError({
|
|
85
170
|
call_id: call.call_id,
|
|
86
171
|
tool: tool.name,
|
|
87
|
-
|
|
88
|
-
cause: result.issues
|
|
172
|
+
issues: result.issues
|
|
89
173
|
});
|
|
90
|
-
|
|
91
|
-
return toolCallOutput(call.call_id, JSON.stringify(output));
|
|
174
|
+
return result.value;
|
|
92
175
|
});
|
|
176
|
+
/**
|
|
177
|
+
* Decode and validate the JSON arguments of a function_call against the
|
|
178
|
+
* tool's input schema, run the tool, and serialize the output into a
|
|
179
|
+
* function_call_output item. Single-shot: intermediate events emitted by
|
|
180
|
+
* `run` are discarded (use `Toolkit.run` to stream them).
|
|
181
|
+
*/
|
|
182
|
+
const execute = (tool, call) => decodeArgs(tool, call).pipe(Effect.flatMap((input) => tool.run(input, () => Effect.void).pipe(Effect.mapError(toToolError(call, tool.name, "Tool execution failed")))), Effect.map((output) => toolCallOutput(call.call_id, JSON.stringify(output))));
|
|
93
183
|
//#endregion
|
|
94
|
-
export { ToolError, execute, fromEffectSchema, fromStandardSchema,
|
|
184
|
+
export { ToolError, ToolValidationError, decodeArgs, descriptorsOf, execute, fromEffectSchema, fromStandardSchema, interaction, make, provider, signal, Tool_exports as t, toDescriptors, withName, withRun };
|
|
95
185
|
|
|
96
186
|
//# sourceMappingURL=Tool.mjs.map
|
package/dist/tool/Tool.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tool.mjs","names":[],"sources":["../../src/tool/Tool.ts"],"sourcesContent":["import type { StandardJSONSchemaV1, StandardSchemaV1 } from \"@standard-schema/spec\"\nimport { Effect, Schema, Stream } from \"effect\"\nimport type { ToolCall, ToolCallOutput } from \"../domain/Items.js\"\nimport { toolCallOutput } from \"../domain/Items.js\"\n\nexport class ToolError extends Schema.TaggedErrorClass<ToolError>(\"@betalyra/effect-uai/ToolError\")(\n \"ToolError\",\n {\n call_id: Schema.String,\n tool: Schema.String,\n message: Schema.String,\n cause: Schema.optional(Schema.Unknown),\n },\n) {}\n\n/**\n * Schemas accepted on `Tool.inputSchema`. Must implement both Standard\n * Schema validation and JSON Schema conversion (for rendering tool\n * descriptors to provider request bodies).\n *\n * Any Standard-Schema-compliant library that exposes both interfaces\n * works directly: Zod 4+, Valibot, ArkType, Effect Schema (after\n * `fromEffectSchema`), etc.\n */\nexport type ToolInputSchema<Input = unknown> = StandardSchemaV1<unknown, Input> &\n StandardJSONSchemaV1<unknown, Input>\n\n/**\n * Convenience wrapper for Effect Schema users - adds both the\n * `validate` and `jsonSchema` extensions to a plain Effect Schema so it\n * can be used as a `Tool.inputSchema`.\n */\nexport const fromEffectSchema = <S extends Schema.Codec<any, any, never, any>>(\n schema: S,\n): S & ToolInputSchema<S[\"Type\"]> =>\n Schema.toStandardJSONSchemaV1(Schema.toStandardSchemaV1(schema)) as unknown as S &\n ToolInputSchema<S[\"Type\"]>\n\n/**\n * Use any schema library that implements both Standard Schema (validation)\n * and Standard JSON Schema (JSON Schema generation) as a `Tool.inputSchema`.\n * Covers Zod 4.2+, Valibot 1.2+, and ArkType 2.1.28+ in one helper.\n *\n * Effect Schema doesn't implement Standard JSON Schema natively — use\n * `fromEffectSchema` for those.\n *\n * The intersection constraint catches missing interfaces at compile time:\n * a Zod v3 schema (no Standard JSON Schema) produces a precise type error\n * pointing at the missing interface rather than a runtime surprise. The\n * helper itself is a thin type-narrowing identity — schemas that satisfy\n * both standards already structurally satisfy `ToolInputSchema`; the\n * helper makes the input type inference explicit at the call site.\n */\nexport const fromStandardSchema = <S extends StandardSchemaV1 & StandardJSONSchemaV1>(\n schema: S,\n): S & ToolInputSchema<StandardSchemaV1.InferOutput<S>> =>\n schema as S & ToolInputSchema<StandardSchemaV1.InferOutput<S>>\n\nexport type Tool<Name extends string, Input, Output, R = never> = {\n readonly name: Name\n readonly description: string\n readonly inputSchema: ToolInputSchema<Input>\n readonly run: (input: Input) => Effect.Effect<Output, unknown, R>\n /**\n * Whether the provider should render this tool with its strict-mode\n * flag (OpenAI's `strict: true`, etc). Default: true. The framework\n * never rewrites the schema; if the rendered JSON Schema isn't\n * compatible, the provider returns an error.\n */\n readonly strict?: boolean\n}\n\n/**\n * Provider-agnostic tool descriptor. Each provider maps `inputSchema`\n * to its own wire field (OpenAI → `parameters`, Anthropic →\n * `input_schema`). Built from a `Tool` by `Tool.toDescriptors`.\n */\nexport type ToolDescriptor = {\n readonly name: string\n readonly description: string\n readonly inputSchema: Record<string, unknown>\n readonly strict?: boolean\n}\n\nexport const make = <Name extends string, Input, Output, R = never>(\n spec: Tool<Name, Input, Output, R>,\n): Tool<Name, Input, Output, R> => spec\n\n// ---------------------------------------------------------------------------\n// Streaming tools\n//\n// `run` returns a `Stream<Event>` instead of an `Effect<Output>`. Events\n// flow through to the consumer as `ToolEvent.Progress`s in real time;\n// at end-of-stream `finalize(events)` reduces them to the model-facing\n// `Output`. Sub-agents, slow downloads with progress, recipe streamers.\n// ---------------------------------------------------------------------------\n\nexport type StreamingTool<Name extends string, Input, Event, Output, R = never> = {\n readonly _kind: \"streaming\"\n readonly name: Name\n readonly description: string\n readonly inputSchema: ToolInputSchema<Input>\n readonly run: (input: Input) => Stream.Stream<Event, unknown, R>\n readonly finalize: (events: ReadonlyArray<Event>) => Output\n readonly strict?: boolean\n}\n\nexport const streaming = <Name extends string, Input, Event, Output, R = never>(\n spec: Omit<StreamingTool<Name, Input, Event, Output, R>, \"_kind\">,\n): StreamingTool<Name, Input, Event, Output, R> => ({ _kind: \"streaming\", ...spec })\n\nexport type AnyStreamingTool<R = any> = StreamingTool<string, any, any, any, R>\nexport type AnyPlainTool<R = any> = Tool<string, any, any, R>\nexport type AnyTool<R = any> = AnyStreamingTool<R> | AnyPlainTool<R>\n\nexport const isStreamingTool = <R>(t: AnyTool<R>): t is AnyStreamingTool<R> =>\n \"_kind\" in t && t._kind === \"streaming\"\n\n/**\n * Render any-kind tools (mixed plain and streaming) to provider-agnostic\n * descriptors. Accepts the union type so a single list can carry both\n * plain and streaming tools.\n */\nexport const toDescriptors = <R>(tools: ReadonlyArray<AnyTool<R>>): ReadonlyArray<ToolDescriptor> =>\n tools.map((tool) => {\n const inputSchema = tool.inputSchema[\"~standard\"].jsonSchema.input({\n target: \"draft-2020-12\",\n })\n return tool.strict !== undefined\n ? { name: tool.name, description: tool.description, inputSchema, strict: tool.strict }\n : { name: tool.name, description: tool.description, inputSchema }\n })\n\nconst toToolError = (call: ToolCall, toolName: string, message: string) => (cause: unknown) =>\n new ToolError({ call_id: call.call_id, tool: toolName, message, cause })\n\n/**\n * Decode and validate the JSON arguments of a function_call against the\n * tool's input schema, run the tool, and serialize the output into a\n * function_call_output item.\n */\nexport const execute = <Name extends string, Input, Output, R>(\n tool: Tool<Name, Input, Output, R>,\n call: ToolCall,\n): Effect.Effect<ToolCallOutput, ToolError, R> =>\n Effect.gen(function* () {\n const parsed = yield* Effect.try({\n try: () => JSON.parse(call.arguments) as unknown,\n catch: toToolError(call, tool.name, \"Failed to parse JSON arguments\"),\n })\n\n const result = yield* Effect.promise(() =>\n Promise.resolve(tool.inputSchema[\"~standard\"].validate(parsed)),\n )\n if (result.issues !== undefined) {\n return yield* new ToolError({\n call_id: call.call_id,\n tool: tool.name,\n message: \"Tool input failed schema validation\",\n cause: result.issues,\n })\n }\n\n const output = yield* tool\n .run(result.value)\n .pipe(Effect.mapError(toToolError(call, tool.name, \"Tool execution failed\")))\n return toolCallOutput(call.call_id, JSON.stringify(output))\n })\n"],"mappings":";;;;;;;;;;;;;;AAKA,IAAa,YAAb,cAA+B,OAAO,iBAA4B,iCAAiC,CACjG,aACA;CACE,SAAS,OAAO;CAChB,MAAM,OAAO;CACb,SAAS,OAAO;CAChB,OAAO,OAAO,SAAS,OAAO,QAAQ;CACvC,CACF,CAAC;;;;;;AAmBF,MAAa,oBACX,WAEA,OAAO,uBAAuB,OAAO,mBAAmB,OAAO,CAAC;;;;;;;;;;;;;;;;AAkBlE,MAAa,sBACX,WAEA;AA4BF,MAAa,QACX,SACiC;AAqBnC,MAAa,aACX,UACkD;CAAE,OAAO;CAAa,GAAG;CAAM;AAMnF,MAAa,mBAAsB,MACjC,WAAW,KAAK,EAAE,UAAU;;;;;;AAO9B,MAAa,iBAAoB,UAC/B,MAAM,KAAK,SAAS;CAClB,MAAM,cAAc,KAAK,YAAY,aAAa,WAAW,MAAM,EACjE,QAAQ,iBACT,CAAC;AACF,QAAO,KAAK,WAAW,KAAA,IACnB;EAAE,MAAM,KAAK;EAAM,aAAa,KAAK;EAAa;EAAa,QAAQ,KAAK;EAAQ,GACpF;EAAE,MAAM,KAAK;EAAM,aAAa,KAAK;EAAa;EAAa;EACnE;AAEJ,MAAM,eAAe,MAAgB,UAAkB,aAAqB,UAC1E,IAAI,UAAU;CAAE,SAAS,KAAK;CAAS,MAAM;CAAU;CAAS;CAAO,CAAC;;;;;;AAO1E,MAAa,WACX,MACA,SAEA,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,OAAO,OAAO,IAAI;EAC/B,WAAW,KAAK,MAAM,KAAK,UAAU;EACrC,OAAO,YAAY,MAAM,KAAK,MAAM,iCAAiC;EACtE,CAAC;CAEF,MAAM,SAAS,OAAO,OAAO,cAC3B,QAAQ,QAAQ,KAAK,YAAY,aAAa,SAAS,OAAO,CAAC,CAChE;AACD,KAAI,OAAO,WAAW,KAAA,EACpB,QAAO,OAAO,IAAI,UAAU;EAC1B,SAAS,KAAK;EACd,MAAM,KAAK;EACX,SAAS;EACT,OAAO,OAAO;EACf,CAAC;CAGJ,MAAM,SAAS,OAAO,KACnB,IAAI,OAAO,MAAM,CACjB,KAAK,OAAO,SAAS,YAAY,MAAM,KAAK,MAAM,wBAAwB,CAAC,CAAC;AAC/E,QAAO,eAAe,KAAK,SAAS,KAAK,UAAU,OAAO,CAAC;EAC3D"}
|
|
1
|
+
{"version":3,"file":"Tool.mjs","names":[],"sources":["../../src/tool/Tool.ts"],"sourcesContent":["import type { StandardJSONSchemaV1, StandardSchemaV1 } from \"@standard-schema/spec\"\nimport { Effect, Schema } from \"effect\"\nimport type { ToolCall, ToolCallOutput } from \"../domain/Items.js\"\nimport { toolCallOutput } from \"../domain/Items.js\"\n\nexport class ToolError extends Schema.TaggedErrorClass<ToolError>(\"@betalyra/effect-uai/ToolError\")(\n \"ToolError\",\n {\n call_id: Schema.String,\n tool: Schema.String,\n message: Schema.String,\n cause: Schema.optional(Schema.Unknown),\n },\n) {}\n\n/**\n * One Standard Schema validation issue, carried on `ToolValidationError`.\n * Mirrors `StandardSchemaV1.Issue`; `path` is left as `unknown` elements\n * because Standard Schema path segments may be symbols or `{ key }` objects.\n */\nconst ToolValidationIssue = Schema.Struct({\n message: Schema.String,\n path: Schema.optional(Schema.Array(Schema.Unknown)),\n})\n\n/**\n * The model's `arguments` for a call failed the tool's `inputSchema`. Distinct\n * from `ToolError` (malformed JSON, runtime crash) so callers can tell a\n * contract violation apart from a parse or execution failure, and so the\n * structured `issues` survive instead of being flattened into a message string.\n */\nexport class ToolValidationError extends Schema.TaggedErrorClass<ToolValidationError>(\n \"@betalyra/effect-uai/ToolValidationError\",\n)(\"ToolValidationError\", {\n call_id: Schema.String,\n tool: Schema.String,\n issues: Schema.Array(ToolValidationIssue),\n}) {}\n\n/**\n * Schemas accepted on `Tool.inputSchema`. Must implement both Standard\n * Schema validation and JSON Schema conversion (for rendering tool\n * descriptors to provider request bodies).\n *\n * Any Standard-Schema-compliant library that exposes both interfaces\n * works directly: Zod 4+, Valibot, ArkType, Effect Schema (after\n * `fromEffectSchema`), etc.\n */\nexport type ToolInputSchema<Input = unknown> = StandardSchemaV1<unknown, Input> &\n StandardJSONSchemaV1<unknown, Input>\n\n/**\n * Convenience wrapper for Effect Schema users - adds both the\n * `validate` and `jsonSchema` extensions to a plain Effect Schema so it\n * can be used as a `Tool.inputSchema`.\n */\nexport const fromEffectSchema = <S extends Schema.Codec<any, any, never, any>>(\n schema: S,\n): S & ToolInputSchema<S[\"Type\"]> =>\n Schema.toStandardJSONSchemaV1(Schema.toStandardSchemaV1(schema))\n\n/**\n * Use any schema library that implements both Standard Schema (validation)\n * and Standard JSON Schema (JSON Schema generation) as a `Tool.inputSchema`.\n * Covers Zod 4.2+, Valibot 1.2+, and ArkType 2.1.28+ in one helper.\n *\n * Effect Schema doesn't implement Standard JSON Schema natively — use\n * `fromEffectSchema` for those.\n *\n * The intersection constraint catches missing interfaces at compile time:\n * a Zod v3 schema (no Standard JSON Schema) produces a precise type error\n * pointing at the missing interface rather than a runtime surprise. The\n * helper itself is a thin type-narrowing identity — schemas that satisfy\n * both standards already structurally satisfy `ToolInputSchema`; the\n * helper makes the input type inference explicit at the call site.\n */\nexport const fromStandardSchema = <S extends StandardSchemaV1 & StandardJSONSchemaV1>(\n schema: S,\n): S & ToolInputSchema<StandardSchemaV1.InferOutput<S>> =>\n schema as S & ToolInputSchema<StandardSchemaV1.InferOutput<S>>\n\n/**\n * Emit one intermediate `Event` from inside a tool's `run`. Backed by the\n * executor's per-call queue, so it returns an `Effect` (backpressure) and\n * composes with `Stream.runForEach(emit)`.\n */\nexport type Emit<Event> = (event: Event) => Effect.Effect<void>\n\n/**\n * A model-visible tool with a local `Effect` executor. `run` computes the\n * model-facing `Output`; emitting progress is a side channel via `emit`. A\n * plain tool never calls `emit` (its `Event` is irrelevant); a streaming tool\n * emits intermediate `Event`s that flow to the consumer as\n * `ToolEvent.Progress` in real time.\n *\n * This is one of four tool *kinds*, discriminated by `_tag`. The other three\n * (`ProviderTool`, `SignalTool`, `InteractionTool`) are model-visible but have\n * no local executor — see their constructors below. `Tool` keeps its name (and\n * the `Tool.make` constructor) because the local kind is by far the common one.\n */\nexport type Tool<Name extends string, Input, Event, Output, R = never> = {\n readonly _tag: \"LocalTool\"\n readonly name: Name\n readonly description: string\n readonly inputSchema: ToolInputSchema<Input>\n readonly run: (input: Input, emit: Emit<Event>) => Effect.Effect<Output, unknown, R>\n /**\n * Bound on this tool's emit queue. Unbounded when omitted. Per-tool because\n * backpressure depends on how a given tool emits, unlike `concurrency`\n * (cross-tool, on `Toolkit.run`'s options).\n */\n readonly emitBufferSize?: number\n /**\n * Whether the provider should render this tool with its strict-mode\n * flag (OpenAI's `strict: true`, etc). Default: true. The framework\n * never rewrites the schema; if the rendered JSON Schema isn't\n * compatible, the provider returns an error.\n */\n readonly strict?: boolean\n}\n\n/**\n * A provider-hosted tool: visible to the model and executed by the *provider*\n * (native web search, code execution, RAG grounding), never by this process.\n * It has no local `run`; `provider`/`config` tell the provider adapter how to\n * render it. Passing it to `Toolkit.run` yields a `non_local_tool` result.\n */\nexport type ProviderTool<Name extends string, Input, Provider extends string, Config> = {\n readonly _tag: \"ProviderTool\"\n readonly name: Name\n readonly description: string\n readonly inputSchema: ToolInputSchema<Input>\n readonly provider: Provider\n readonly config: Config\n readonly strict?: boolean\n}\n\n/**\n * A typed request for the agent loop to change control flow (escalate, pause,\n * schedule, hand off). Model-visible and decodable (`decodeArgs`) but never\n * locally executed — the loop intercepts the call in `onTurnComplete` and acts\n * on it, so there is no fake `run`. `Toolkit.run` reports it as `non_local_tool`.\n */\nexport type SignalTool<Name extends string, Input> = {\n readonly _tag: \"SignalTool\"\n readonly name: Name\n readonly description: string\n readonly inputSchema: ToolInputSchema<Input>\n}\n\n/**\n * A typed request for an external actor (user, channel, frontend) to respond\n * before the loop resumes. Like `SignalTool` it is decode-only, but its\n * lifecycle differs: the loop usually stops/pauses and resumes later by\n * appending a `function_call_output` once the actor replies.\n */\nexport type InteractionTool<Name extends string, Input> = {\n readonly _tag: \"InteractionTool\"\n readonly name: Name\n readonly description: string\n readonly inputSchema: ToolInputSchema<Input>\n}\n\n/** A local (executable) tool of any shape. Readability alias. */\nexport type AnyLocalTool<R = any> = Tool<string, any, any, any, R>\n\n/** Any of the four model-visible tool kinds. */\nexport type AnyTool<R = any> =\n | Tool<string, any, any, any, R>\n | ProviderTool<string, any, string, any>\n | SignalTool<string, any>\n | InteractionTool<string, any>\n\n/** A model-visible tool that carries a decodable input schema (every kind). */\nexport type DecodableTool<Input> = {\n readonly name: string\n readonly inputSchema: ToolInputSchema<Input>\n}\n\n/** Extract the `R` of a local tool; non-local kinds contribute `never`. */\nexport type ToolR<T> = T extends Tool<string, any, any, any, infer R> ? R : never\n\n/**\n * Provider-agnostic tool descriptor. Each provider maps `inputSchema`\n * to its own wire field (OpenAI → `parameters`, Anthropic →\n * `input_schema`). Built from a `Tool` by `Tool.toDescriptors`.\n */\nexport type ToolDescriptor = {\n readonly name: string\n readonly description: string\n readonly inputSchema: Record<string, unknown>\n readonly strict?: boolean\n}\n\n/** A model-visible tool with a local `Effect` executor. */\nexport const make = <Name extends string, Input, Event, Output, R = never>(\n spec: Omit<Tool<Name, Input, Event, Output, R>, \"_tag\">,\n): Tool<Name, Input, Event, Output, R> => ({ _tag: \"LocalTool\", ...spec })\n\n/**\n * A provider-hosted tool (native web search, code execution, RAG grounding).\n * No local executor — `provider`/`config` drive the provider adapter's\n * rendering. The model sees it; `Toolkit.run` reports it as `non_local_tool`.\n */\nexport const provider = <Name extends string, Input, Provider extends string, Config>(\n spec: Omit<ProviderTool<Name, Input, Provider, Config>, \"_tag\">,\n): ProviderTool<Name, Input, Provider, Config> => ({ _tag: \"ProviderTool\", ...spec })\n\n/**\n * A typed control-flow signal to the agent loop (escalate, pause, schedule,\n * hand off). Decode-only: the loop interprets the call rather than executing a\n * handler, so there is no `run`.\n */\nexport const signal = <Name extends string, Input>(\n spec: Omit<SignalTool<Name, Input>, \"_tag\">,\n): SignalTool<Name, Input> => ({ _tag: \"SignalTool\", ...spec })\n\n/**\n * A typed request for an external actor to respond before the loop resumes\n * (frontend, Telegram, CLI prompt). Decode-only; the loop stops/pauses and\n * resumes by appending the actor's `function_call_output`.\n */\nexport const interaction = <Name extends string, Input>(\n spec: Omit<InteractionTool<Name, Input>, \"_tag\">,\n): InteractionTool<Name, Input> => ({ _tag: \"InteractionTool\", ...spec })\n\n/**\n * Return a copy of a tool under a new `name`. Useful for resolving a name\n * clash before combining tools into one `Toolkit`. Literal-preserving, so the\n * renamed tool keys the toolkit record under the new name statically.\n */\nexport const withName = <N extends string, T extends AnyTool>(\n tool: T,\n name: N,\n): Omit<T, \"name\"> & { readonly name: N } => ({ ...tool, name })\n\n/**\n * Replace a local tool's `run`, keeping its model-facing definition (name,\n * description, schema, `_tag`) identical. The new `run`'s `input` is typed from\n * the original tool, so override/mock need no annotation:\n *\n * const safe = { ...toolkit, send_email: Tool.withRun(toolkit.send_email,\n * ({ to }) => Effect.succeed({ status: \"dry-run\", to })) }\n *\n * Descriptors stay identical to production, so a mocked toolkit can't drift\n * from the contract the model sees.\n */\nexport const withRun = <Name extends string, Input, Event, Output, R, Output2, R2 = never>(\n tool: Tool<Name, Input, Event, Output, R>,\n run: (input: Input, emit: Emit<Event>) => Effect.Effect<Output2, unknown, R2>,\n): Tool<Name, Input, Event, Output2, R2> => ({ ...tool, run })\n\n/** Render tools to provider-agnostic descriptors. Every kind is model-visible. */\nexport const toDescriptors = (tools: ReadonlyArray<AnyTool>): ReadonlyArray<ToolDescriptor> =>\n tools.map((tool) => {\n const inputSchema = tool.inputSchema[\"~standard\"].jsonSchema.input({\n target: \"draft-2020-12\",\n })\n // `strict` only exists on local/provider kinds; signals/interactions omit it.\n const strict = \"strict\" in tool ? tool.strict : undefined\n return strict !== undefined\n ? { name: tool.name, description: tool.description, inputSchema, strict }\n : { name: tool.name, description: tool.description, inputSchema }\n })\n\n/**\n * Render a `Toolkit` (a name-indexed record of tools) to descriptors, treating\n * an absent toolkit as no tools. The normalization point the `LanguageModel`\n * boundary uses so a request can carry the toolkit itself instead of a\n * pre-rendered descriptor array. Lives here (not on `Toolkit`) to keep providers\n * free of a dependency on the toolkit module — it only needs the tool values.\n */\nexport const descriptorsOf = (\n toolkit?: Readonly<Record<string, AnyTool>>,\n): ReadonlyArray<ToolDescriptor> =>\n toolkit === undefined ? [] : toDescriptors(Object.values(toolkit))\n\nconst toToolError = (call: ToolCall, toolName: string, message: string) => (cause: unknown) =>\n new ToolError({ call_id: call.call_id, tool: toolName, message, cause })\n\n/**\n * Decode and validate a function_call's JSON `arguments` against the tool's\n * own `inputSchema`, yielding the typed input. The decode-only half of\n * `execute` - reach for it when you intercept a call to translate it into a\n * control-flow decision rather than running the tool's `run`.\n *\n * Malformed JSON fails with `ToolError`; a parsed body that violates\n * `inputSchema` fails with `ToolValidationError` carrying the issues.\n */\nexport const decodeArgs = <Input>(\n tool: DecodableTool<Input>,\n call: ToolCall,\n): Effect.Effect<Input, ToolError | ToolValidationError> =>\n Effect.gen(function* () {\n const parsed = yield* Effect.try({\n // inputSchema validates through Standard Schema, not Effect Schema, so its\n // JSON codecs don't apply; the parse is separate to keep ToolError (bad\n // JSON) distinct from ToolValidationError (bad shape).\n // @effect-diagnostics-next-line effect/preferSchemaOverJson:off\n try: () => JSON.parse(call.arguments) as unknown,\n catch: toToolError(call, tool.name, \"Failed to parse JSON arguments\"),\n })\n\n const result = yield* Effect.promise(() =>\n Promise.resolve(tool.inputSchema[\"~standard\"].validate(parsed)),\n )\n if (result.issues !== undefined) {\n return yield* new ToolValidationError({\n call_id: call.call_id,\n tool: tool.name,\n issues: result.issues,\n })\n }\n return result.value\n })\n\n/**\n * Decode and validate the JSON arguments of a function_call against the\n * tool's input schema, run the tool, and serialize the output into a\n * function_call_output item. Single-shot: intermediate events emitted by\n * `run` are discarded (use `Toolkit.run` to stream them).\n */\nexport const execute = <Name extends string, Input, Event, Output, R>(\n tool: Tool<Name, Input, Event, Output, R>,\n call: ToolCall,\n): Effect.Effect<ToolCallOutput, ToolError | ToolValidationError, R> =>\n decodeArgs(tool, call).pipe(\n Effect.flatMap((input) =>\n tool\n .run(input, () => Effect.void)\n .pipe(Effect.mapError(toToolError(call, tool.name, \"Tool execution failed\"))),\n ),\n Effect.map((output) => toolCallOutput(call.call_id, JSON.stringify(output))),\n )\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAKA,IAAa,YAAb,cAA+B,OAAO,iBAA4B,iCAAiC,CACjG,aACA;CACE,SAAS,OAAO;CAChB,MAAM,OAAO;CACb,SAAS,OAAO;CAChB,OAAO,OAAO,SAAS,OAAO,QAAQ;CACvC,CACF,CAAC;;;;;;AAOF,MAAM,sBAAsB,OAAO,OAAO;CACxC,SAAS,OAAO;CAChB,MAAM,OAAO,SAAS,OAAO,MAAM,OAAO,QAAQ,CAAC;CACpD,CAAC;;;;;;;AAQF,IAAa,sBAAb,cAAyC,OAAO,iBAC9C,2CACD,CAAC,uBAAuB;CACvB,SAAS,OAAO;CAChB,MAAM,OAAO;CACb,QAAQ,OAAO,MAAM,oBAAoB;CAC1C,CAAC,CAAC;;;;;;AAmBH,MAAa,oBACX,WAEA,OAAO,uBAAuB,OAAO,mBAAmB,OAAO,CAAC;;;;;;;;;;;;;;;;AAiBlE,MAAa,sBACX,WAEA;;AAoHF,MAAa,QACX,UACyC;CAAE,MAAM;CAAa,GAAG;CAAM;;;;;;AAOzE,MAAa,YACX,UACiD;CAAE,MAAM;CAAgB,GAAG;CAAM;;;;;;AAOpF,MAAa,UACX,UAC6B;CAAE,MAAM;CAAc,GAAG;CAAM;;;;;;AAO9D,MAAa,eACX,UACkC;CAAE,MAAM;CAAmB,GAAG;CAAM;;;;;;AAOxE,MAAa,YACX,MACA,UAC4C;CAAE,GAAG;CAAM;CAAM;;;;;;;;;;;;AAa/D,MAAa,WACX,MACA,SAC2C;CAAE,GAAG;CAAM;CAAK;;AAG7D,MAAa,iBAAiB,UAC5B,MAAM,KAAK,SAAS;CAClB,MAAM,cAAc,KAAK,YAAY,aAAa,WAAW,MAAM,EACjE,QAAQ,iBACT,CAAC;CAEF,MAAM,SAAS,YAAY,OAAO,KAAK,SAAS,KAAA;AAChD,QAAO,WAAW,KAAA,IACd;EAAE,MAAM,KAAK;EAAM,aAAa,KAAK;EAAa;EAAa;EAAQ,GACvE;EAAE,MAAM,KAAK;EAAM,aAAa,KAAK;EAAa;EAAa;EACnE;;;;;;;;AASJ,MAAa,iBACX,YAEA,YAAY,KAAA,IAAY,EAAE,GAAG,cAAc,OAAO,OAAO,QAAQ,CAAC;AAEpE,MAAM,eAAe,MAAgB,UAAkB,aAAqB,UAC1E,IAAI,UAAU;CAAE,SAAS,KAAK;CAAS,MAAM;CAAU;CAAS;CAAO,CAAC;;;;;;;;;;AAW1E,MAAa,cACX,MACA,SAEA,OAAO,IAAI,aAAa;CACtB,MAAM,SAAS,OAAO,OAAO,IAAI;EAK/B,WAAW,KAAK,MAAM,KAAK,UAAU;EACrC,OAAO,YAAY,MAAM,KAAK,MAAM,iCAAiC;EACtE,CAAC;CAEF,MAAM,SAAS,OAAO,OAAO,cAC3B,QAAQ,QAAQ,KAAK,YAAY,aAAa,SAAS,OAAO,CAAC,CAChE;AACD,KAAI,OAAO,WAAW,KAAA,EACpB,QAAO,OAAO,IAAI,oBAAoB;EACpC,SAAS,KAAK;EACd,MAAM,KAAK;EACX,QAAQ,OAAO;EAChB,CAAC;AAEJ,QAAO,OAAO;EACd;;;;;;;AAQJ,MAAa,WACX,MACA,SAEA,WAAW,MAAM,KAAK,CAAC,KACrB,OAAO,SAAS,UACd,KACG,IAAI,aAAa,OAAO,KAAK,CAC7B,KAAK,OAAO,SAAS,YAAY,MAAM,KAAK,MAAM,wBAAwB,CAAC,CAAC,CAChF,EACD,OAAO,KAAK,WAAW,eAAe,KAAK,SAAS,KAAK,UAAU,OAAO,CAAC,CAAC,CAC7E"}
|
package/dist/tool/Tool.test.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { fromStandardSchema, make } from "./Tool.mjs";
|
|
2
|
-
import {
|
|
1
|
+
import { decodeArgs, fromStandardSchema, make, toDescriptors, withRun } from "./Tool.mjs";
|
|
2
|
+
import { a as describe, n as globalExpect, o as it, t as import_dist } from "../dist-B04dlFHg.mjs";
|
|
3
3
|
import { Effect } from "effect";
|
|
4
4
|
//#region src/tool/Tool.test.ts
|
|
5
5
|
const emailRecipientSchema = { "~standard": {
|
|
@@ -45,7 +45,7 @@ describe("Tool.fromStandardSchema", () => {
|
|
|
45
45
|
inputSchema: fromStandardSchema(emailRecipientSchema),
|
|
46
46
|
run: ({ to }) => Effect.succeed(`queued: ${to}`)
|
|
47
47
|
});
|
|
48
|
-
globalExpect(await Effect.runPromise(sendEmail.run({ to: "x@y.z" }))).toBe("queued: x@y.z");
|
|
48
|
+
globalExpect(await Effect.runPromise(sendEmail.run({ to: "x@y.z" }, () => Effect.void))).toBe("queued: x@y.z");
|
|
49
49
|
});
|
|
50
50
|
it("type: rejects schemas missing the Standard JSON Schema half at compile time", () => {
|
|
51
51
|
fromStandardSchema(standardOnly);
|
|
@@ -60,6 +60,44 @@ describe("Tool.fromStandardSchema", () => {
|
|
|
60
60
|
(0, import_dist.expectTypeOf)().toEqualTypeOf();
|
|
61
61
|
});
|
|
62
62
|
});
|
|
63
|
+
describe("Tool.withRun", () => {
|
|
64
|
+
const sendEmail = make({
|
|
65
|
+
name: "send_email",
|
|
66
|
+
description: "Send an email to a single recipient.",
|
|
67
|
+
inputSchema: fromStandardSchema(emailRecipientSchema),
|
|
68
|
+
run: ({ to }) => Effect.succeed(`sent: ${to}`)
|
|
69
|
+
});
|
|
70
|
+
it("swaps run while keeping the model-facing descriptor identical", async () => {
|
|
71
|
+
const dryRun = withRun(sendEmail, ({ to }) => Effect.succeed(`dry-run: ${to}`));
|
|
72
|
+
globalExpect(toDescriptors([dryRun])).toEqual(toDescriptors([sendEmail]));
|
|
73
|
+
globalExpect(await Effect.runPromise(dryRun.run({ to: "x@y.z" }, () => Effect.void))).toBe("dry-run: x@y.z");
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe("Tool.decodeArgs", () => {
|
|
77
|
+
const sendEmail = make({
|
|
78
|
+
name: "send_email",
|
|
79
|
+
description: "Send an email to a single recipient.",
|
|
80
|
+
inputSchema: fromStandardSchema(emailRecipientSchema),
|
|
81
|
+
run: ({ to }) => Effect.succeed(`queued: ${to}`)
|
|
82
|
+
});
|
|
83
|
+
const callWith = (args) => ({
|
|
84
|
+
type: "function_call",
|
|
85
|
+
call_id: "call_1",
|
|
86
|
+
name: "send_email",
|
|
87
|
+
arguments: args
|
|
88
|
+
});
|
|
89
|
+
it("decodes valid JSON arguments to the typed input", async () => {
|
|
90
|
+
const input = await Effect.runPromise(decodeArgs(sendEmail, callWith("{\"to\":\"x@y.z\"}")));
|
|
91
|
+
globalExpect(input).toEqual({ to: "x@y.z" });
|
|
92
|
+
(0, import_dist.expectTypeOf)(input).toEqualTypeOf();
|
|
93
|
+
});
|
|
94
|
+
it("fails with ToolError when the arguments aren't valid JSON", async () => {
|
|
95
|
+
globalExpect((await Effect.runPromiseExit(decodeArgs(sendEmail, callWith("not json"))))._tag).toBe("Failure");
|
|
96
|
+
});
|
|
97
|
+
it("fails with ToolError when the arguments don't satisfy the schema", async () => {
|
|
98
|
+
globalExpect((await Effect.runPromiseExit(decodeArgs(sendEmail, callWith("{\"to\":42}"))))._tag).toBe("Failure");
|
|
99
|
+
});
|
|
100
|
+
});
|
|
63
101
|
//#endregion
|
|
64
102
|
export {};
|
|
65
103
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tool.test.mjs","names":["Tool.fromStandardSchema","Tool.make"],"sources":["../../src/tool/Tool.test.ts"],"sourcesContent":["import type { StandardJSONSchemaV1, StandardSchemaV1 } from \"@standard-schema/spec\"\nimport { Effect } from \"effect\"\nimport { describe, expect, expectTypeOf, it } from \"vitest\"\nimport * as Tool from \"./Tool.js\"\n\n// ---------------------------------------------------------------------------\n// Minimal dual-standard schema for testing — no need to pull Zod / Valibot /\n// ArkType as devDeps. This is the smallest possible object satisfying both\n// `StandardSchemaV1` and `StandardJSONSchemaV1` per their published specs.\n// ---------------------------------------------------------------------------\n\ntype EmailRecipient = { readonly to: string }\n\nconst emailRecipientSchema: StandardSchemaV1<unknown, EmailRecipient> &\n StandardJSONSchemaV1<unknown, EmailRecipient> = {\n \"~standard\": {\n version: 1,\n vendor: \"test-fixture\",\n validate: (value) => {\n if (\n typeof value === \"object\" &&\n value !== null &&\n \"to\" in value &&\n typeof (value as { to: unknown }).to === \"string\"\n ) {\n return { value: value as EmailRecipient }\n }\n return { issues: [{ message: \"expected { to: string }\" }] }\n },\n jsonSchema: {\n input: () => ({\n type: \"object\",\n properties: { to: { type: \"string\" } },\n required: [\"to\"],\n }),\n output: () => ({\n type: \"object\",\n properties: { to: { type: \"string\" } },\n required: [\"to\"],\n }),\n },\n },\n}\n\n// A schema that satisfies StandardSchemaV1 only (no JSON Schema). Used to\n// verify the helper's compile-time guard.\nconst standardOnly: StandardSchemaV1<unknown, EmailRecipient> = {\n \"~standard\": {\n version: 1,\n vendor: \"test-fixture\",\n validate: () => ({ value: { to: \"\" } }),\n },\n}\n\ndescribe(\"Tool.fromStandardSchema\", () => {\n it(\"returns the schema (structurally) typed as ToolInputSchema<Output>\", () => {\n const adapted = Tool.fromStandardSchema(emailRecipientSchema)\n\n // Same object — helper is a type-narrowing identity at runtime.\n expect(adapted).toBe(emailRecipientSchema)\n\n // Both interfaces accessible through the same `~standard` key.\n const valid = adapted[\"~standard\"].validate({ to: \"hi@example.com\" })\n expect(valid).toEqual({ value: { to: \"hi@example.com\" } })\n\n const json = adapted[\"~standard\"].jsonSchema.input({ target: \"draft-2020-12\" })\n expect(json).toEqual({\n type: \"object\",\n properties: { to: { type: \"string\" } },\n required: [\"to\"],\n })\n })\n\n it(\"composes with Tool.make so Input is inferred from the schema's Output\", async () => {\n const sendEmail = Tool.make({\n name: \"send_email\",\n description: \"Send an email to a single recipient.\",\n inputSchema: Tool.fromStandardSchema(emailRecipientSchema),\n run: ({ to }) => Effect.succeed(`queued: ${to}`),\n })\n\n // `run`'s parameter is typed as { to: string } via the schema's Output —\n // this property access compiles without annotation.\n const result = await Effect.runPromise(sendEmail.run({ to: \"x@y.z\" }))\n expect(result).toBe(\"queued: x@y.z\")\n })\n\n it(\"type: rejects schemas missing the Standard JSON Schema half at compile time\", () => {\n // @ts-expect-error — `standardOnly` lacks `jsonSchema`; helper's\n // intersection constraint refuses it.\n Tool.fromStandardSchema(standardOnly)\n })\n\n it(\"type: Output type flows through fromStandardSchema into Tool.make\", () => {\n const tool = Tool.make({\n name: \"send_email\",\n description: \"send\",\n inputSchema: Tool.fromStandardSchema(emailRecipientSchema),\n run: (input) => Effect.succeed(input),\n })\n\n type InputOf<T> = T extends Tool.Tool<string, infer I,
|
|
1
|
+
{"version":3,"file":"Tool.test.mjs","names":["Tool.fromStandardSchema","Tool.make","Tool.withRun","Tool.toDescriptors","Tool.decodeArgs"],"sources":["../../src/tool/Tool.test.ts"],"sourcesContent":["import type { StandardJSONSchemaV1, StandardSchemaV1 } from \"@standard-schema/spec\"\nimport { Effect } from \"effect\"\nimport { describe, expect, expectTypeOf, it } from \"vitest\"\nimport type * as Items from \"../domain/Items.js\"\nimport * as Tool from \"./Tool.js\"\n\n// ---------------------------------------------------------------------------\n// Minimal dual-standard schema for testing — no need to pull Zod / Valibot /\n// ArkType as devDeps. This is the smallest possible object satisfying both\n// `StandardSchemaV1` and `StandardJSONSchemaV1` per their published specs.\n// ---------------------------------------------------------------------------\n\ntype EmailRecipient = { readonly to: string }\n\nconst emailRecipientSchema: StandardSchemaV1<unknown, EmailRecipient> &\n StandardJSONSchemaV1<unknown, EmailRecipient> = {\n \"~standard\": {\n version: 1,\n vendor: \"test-fixture\",\n validate: (value) => {\n if (\n typeof value === \"object\" &&\n value !== null &&\n \"to\" in value &&\n typeof (value as { to: unknown }).to === \"string\"\n ) {\n return { value: value as EmailRecipient }\n }\n return { issues: [{ message: \"expected { to: string }\" }] }\n },\n jsonSchema: {\n input: () => ({\n type: \"object\",\n properties: { to: { type: \"string\" } },\n required: [\"to\"],\n }),\n output: () => ({\n type: \"object\",\n properties: { to: { type: \"string\" } },\n required: [\"to\"],\n }),\n },\n },\n}\n\n// A schema that satisfies StandardSchemaV1 only (no JSON Schema). Used to\n// verify the helper's compile-time guard.\nconst standardOnly: StandardSchemaV1<unknown, EmailRecipient> = {\n \"~standard\": {\n version: 1,\n vendor: \"test-fixture\",\n validate: () => ({ value: { to: \"\" } }),\n },\n}\n\ndescribe(\"Tool.fromStandardSchema\", () => {\n it(\"returns the schema (structurally) typed as ToolInputSchema<Output>\", () => {\n const adapted = Tool.fromStandardSchema(emailRecipientSchema)\n\n // Same object — helper is a type-narrowing identity at runtime.\n expect(adapted).toBe(emailRecipientSchema)\n\n // Both interfaces accessible through the same `~standard` key.\n const valid = adapted[\"~standard\"].validate({ to: \"hi@example.com\" })\n expect(valid).toEqual({ value: { to: \"hi@example.com\" } })\n\n const json = adapted[\"~standard\"].jsonSchema.input({ target: \"draft-2020-12\" })\n expect(json).toEqual({\n type: \"object\",\n properties: { to: { type: \"string\" } },\n required: [\"to\"],\n })\n })\n\n it(\"composes with Tool.make so Input is inferred from the schema's Output\", async () => {\n const sendEmail = Tool.make({\n name: \"send_email\",\n description: \"Send an email to a single recipient.\",\n inputSchema: Tool.fromStandardSchema(emailRecipientSchema),\n run: ({ to }) => Effect.succeed(`queued: ${to}`),\n })\n\n // `run`'s parameter is typed as { to: string } via the schema's Output —\n // this property access compiles without annotation.\n const result = await Effect.runPromise(sendEmail.run({ to: \"x@y.z\" }, () => Effect.void))\n expect(result).toBe(\"queued: x@y.z\")\n })\n\n it(\"type: rejects schemas missing the Standard JSON Schema half at compile time\", () => {\n // @ts-expect-error — `standardOnly` lacks `jsonSchema`; helper's\n // intersection constraint refuses it.\n Tool.fromStandardSchema(standardOnly)\n })\n\n it(\"type: Output type flows through fromStandardSchema into Tool.make\", () => {\n const tool = Tool.make({\n name: \"send_email\",\n description: \"send\",\n inputSchema: Tool.fromStandardSchema(emailRecipientSchema),\n run: (input) => Effect.succeed(input),\n })\n\n type InputOf<T> = T extends Tool.Tool<string, infer I, any, any, any> ? I : never\n expectTypeOf<InputOf<typeof tool>>().toEqualTypeOf<EmailRecipient>()\n })\n})\n\ndescribe(\"Tool.withRun\", () => {\n const sendEmail = Tool.make({\n name: \"send_email\",\n description: \"Send an email to a single recipient.\",\n inputSchema: Tool.fromStandardSchema(emailRecipientSchema),\n run: ({ to }) => Effect.succeed(`sent: ${to}`),\n })\n\n it(\"swaps run while keeping the model-facing descriptor identical\", async () => {\n const dryRun = Tool.withRun(sendEmail, ({ to }) => Effect.succeed(`dry-run: ${to}`))\n\n // Definition (name/description/schema) is byte-identical -> same descriptor.\n expect(Tool.toDescriptors([dryRun])).toEqual(Tool.toDescriptors([sendEmail]))\n // input is typed from the original tool, no annotation needed.\n const out = await Effect.runPromise(dryRun.run({ to: \"x@y.z\" }, () => Effect.void))\n expect(out).toBe(\"dry-run: x@y.z\")\n })\n})\n\ndescribe(\"Tool.decodeArgs\", () => {\n const sendEmail = Tool.make({\n name: \"send_email\",\n description: \"Send an email to a single recipient.\",\n inputSchema: Tool.fromStandardSchema(emailRecipientSchema),\n run: ({ to }) => Effect.succeed(`queued: ${to}`),\n })\n\n const callWith = (args: string): Items.ToolCall => ({\n type: \"function_call\",\n call_id: \"call_1\",\n name: \"send_email\",\n arguments: args,\n })\n\n it(\"decodes valid JSON arguments to the typed input\", async () => {\n const input = await Effect.runPromise(Tool.decodeArgs(sendEmail, callWith('{\"to\":\"x@y.z\"}')))\n expect(input).toEqual({ to: \"x@y.z\" })\n // The return type is the tool's Input, no annotation needed.\n expectTypeOf(input).toEqualTypeOf<EmailRecipient>()\n })\n\n it(\"fails with ToolError when the arguments aren't valid JSON\", async () => {\n const exit = await Effect.runPromiseExit(Tool.decodeArgs(sendEmail, callWith(\"not json\")))\n expect(exit._tag).toBe(\"Failure\")\n })\n\n it(\"fails with ToolError when the arguments don't satisfy the schema\", async () => {\n const exit = await Effect.runPromiseExit(Tool.decodeArgs(sendEmail, callWith('{\"to\":42}')))\n expect(exit._tag).toBe(\"Failure\")\n })\n})\n"],"mappings":";;;;AAcA,MAAM,uBAC4C,EAChD,aAAa;CACX,SAAS;CACT,QAAQ;CACR,WAAW,UAAU;AACnB,MACE,OAAO,UAAU,YACjB,UAAU,QACV,QAAQ,SACR,OAAQ,MAA0B,OAAO,SAEzC,QAAO,EAAS,OAAyB;AAE3C,SAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,2BAA2B,CAAC,EAAE;;CAE7D,YAAY;EACV,cAAc;GACZ,MAAM;GACN,YAAY,EAAE,IAAI,EAAE,MAAM,UAAU,EAAE;GACtC,UAAU,CAAC,KAAK;GACjB;EACD,eAAe;GACb,MAAM;GACN,YAAY,EAAE,IAAI,EAAE,MAAM,UAAU,EAAE;GACtC,UAAU,CAAC,KAAK;GACjB;EACF;CACF,EACF;AAID,MAAM,eAA0D,EAC9D,aAAa;CACX,SAAS;CACT,QAAQ;CACR,iBAAiB,EAAE,OAAO,EAAE,IAAI,IAAI,EAAE;CACvC,EACF;AAED,SAAS,iCAAiC;AACxC,IAAG,4EAA4E;EAC7E,MAAM,UAAUA,mBAAwB,qBAAqB;AAG7D,eAAO,QAAQ,CAAC,KAAK,qBAAqB;AAI1C,eADc,QAAQ,aAAa,SAAS,EAAE,IAAI,kBAAkB,CACxD,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,kBAAkB,EAAE,CAAC;AAG1D,eADa,QAAQ,aAAa,WAAW,MAAM,EAAE,QAAQ,iBAAiB,CACnE,CAAC,CAAC,QAAQ;GACnB,MAAM;GACN,YAAY,EAAE,IAAI,EAAE,MAAM,UAAU,EAAE;GACtC,UAAU,CAAC,KAAK;GACjB,CAAC;GACF;AAEF,IAAG,yEAAyE,YAAY;EACtF,MAAM,YAAYC,KAAU;GAC1B,MAAM;GACN,aAAa;GACb,aAAaD,mBAAwB,qBAAqB;GAC1D,MAAM,EAAE,SAAS,OAAO,QAAQ,WAAW,KAAK;GACjD,CAAC;AAKF,eAAO,MADc,OAAO,WAAW,UAAU,IAAI,EAAE,IAAI,SAAS,QAAQ,OAAO,KAAK,CAAC,CAC3E,CAAC,KAAK,gBAAgB;GACpC;AAEF,IAAG,qFAAqF;AAGtF,qBAAwB,aAAa;GACrC;AAEF,IAAG,2EAA2E;AAC/D,OAAU;GACrB,MAAM;GACN,aAAa;GACb,aAAaA,mBAAwB,qBAAqB;GAC1D,MAAM,UAAU,OAAO,QAAQ,MAAM;GACtC,CAAC;AAGF,GAAA,GAAA,YAAA,eAAoC,CAAC,eAA+B;GACpE;EACF;AAEF,SAAS,sBAAsB;CAC7B,MAAM,YAAYC,KAAU;EAC1B,MAAM;EACN,aAAa;EACb,aAAaD,mBAAwB,qBAAqB;EAC1D,MAAM,EAAE,SAAS,OAAO,QAAQ,SAAS,KAAK;EAC/C,CAAC;AAEF,IAAG,iEAAiE,YAAY;EAC9E,MAAM,SAASE,QAAa,YAAY,EAAE,SAAS,OAAO,QAAQ,YAAY,KAAK,CAAC;AAGpF,eAAOC,cAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQA,cAAmB,CAAC,UAAU,CAAC,CAAC;AAG7E,eAAO,MADW,OAAO,WAAW,OAAO,IAAI,EAAE,IAAI,SAAS,QAAQ,OAAO,KAAK,CAAC,CACxE,CAAC,KAAK,iBAAiB;GAClC;EACF;AAEF,SAAS,yBAAyB;CAChC,MAAM,YAAYF,KAAU;EAC1B,MAAM;EACN,aAAa;EACb,aAAaD,mBAAwB,qBAAqB;EAC1D,MAAM,EAAE,SAAS,OAAO,QAAQ,WAAW,KAAK;EACjD,CAAC;CAEF,MAAM,YAAY,UAAkC;EAClD,MAAM;EACN,SAAS;EACT,MAAM;EACN,WAAW;EACZ;AAED,IAAG,mDAAmD,YAAY;EAChE,MAAM,QAAQ,MAAM,OAAO,WAAWI,WAAgB,WAAW,SAAS,qBAAiB,CAAC,CAAC;AAC7F,eAAO,MAAM,CAAC,QAAQ,EAAE,IAAI,SAAS,CAAC;AAEtC,GAAA,GAAA,YAAA,cAAa,MAAM,CAAC,eAA+B;GACnD;AAEF,IAAG,6DAA6D,YAAY;AAE1E,gBAAO,MADY,OAAO,eAAeA,WAAgB,WAAW,SAAS,WAAW,CAAC,CAAC,EAC9E,KAAK,CAAC,KAAK,UAAU;GACjC;AAEF,IAAG,oEAAoE,YAAY;AAEjF,gBAAO,MADY,OAAO,eAAeA,WAAgB,WAAW,SAAS,cAAY,CAAC,CAAC,EAC/E,KAAK,CAAC,KAAK,UAAU;GACjC;EACF"}
|
|
@@ -1,151 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import * as _$effect_Unify0 from "effect/Unify";
|
|
4
|
-
|
|
5
|
-
//#region src/tool/ToolEvent.d.ts
|
|
6
|
-
declare namespace ToolEvent_d_exports {
|
|
7
|
-
export { ToolEvent, isApprovalRequested, isOutput, isProgress };
|
|
8
|
-
}
|
|
9
|
-
type ToolEvent = Data.TaggedEnum<{
|
|
10
|
-
ApprovalRequested: {
|
|
11
|
-
readonly call_id: string;
|
|
12
|
-
readonly tool: string;
|
|
13
|
-
readonly arguments: string;
|
|
14
|
-
};
|
|
15
|
-
Progress: {
|
|
16
|
-
readonly call_id: string;
|
|
17
|
-
readonly tool: string;
|
|
18
|
-
readonly data: unknown;
|
|
19
|
-
};
|
|
20
|
-
Output: {
|
|
21
|
-
readonly result: ToolResult;
|
|
22
|
-
};
|
|
23
|
-
}>;
|
|
24
|
-
/**
|
|
25
|
-
* Namespace of constructors, type guards, and matchers for `ToolEvent`,
|
|
26
|
-
* provided by `Data.taggedEnum`. Use `ToolEvent.Output({ result })` to build
|
|
27
|
-
* an event, `ToolEvent.$is("Output")` for type narrowing,
|
|
28
|
-
* `ToolEvent.$match({ ApprovalRequested, Progress, Output })` for
|
|
29
|
-
* exhaustive pattern matching.
|
|
30
|
-
*/
|
|
31
|
-
declare const ToolEvent: {
|
|
32
|
-
readonly ApprovalRequested: Data.TaggedEnum.ConstructorFrom<{
|
|
33
|
-
readonly _tag: "ApprovalRequested";
|
|
34
|
-
readonly call_id: string;
|
|
35
|
-
readonly tool: string;
|
|
36
|
-
readonly arguments: string;
|
|
37
|
-
}, "_tag">;
|
|
38
|
-
readonly Progress: Data.TaggedEnum.ConstructorFrom<{
|
|
39
|
-
readonly _tag: "Progress";
|
|
40
|
-
readonly call_id: string;
|
|
41
|
-
readonly tool: string;
|
|
42
|
-
readonly data: unknown;
|
|
43
|
-
}, "_tag">;
|
|
44
|
-
readonly Output: Data.TaggedEnum.ConstructorFrom<{
|
|
45
|
-
readonly _tag: "Output";
|
|
46
|
-
readonly result: ToolResult;
|
|
47
|
-
}, "_tag">;
|
|
48
|
-
readonly $is: <Tag extends "ApprovalRequested" | "Progress" | "Output">(tag: Tag) => (u: unknown) => u is Extract<{
|
|
49
|
-
readonly _tag: "ApprovalRequested";
|
|
50
|
-
readonly call_id: string;
|
|
51
|
-
readonly tool: string;
|
|
52
|
-
readonly arguments: string;
|
|
53
|
-
}, {
|
|
54
|
-
readonly _tag: Tag;
|
|
55
|
-
}> | Extract<{
|
|
56
|
-
readonly _tag: "Progress";
|
|
57
|
-
readonly call_id: string;
|
|
58
|
-
readonly tool: string;
|
|
59
|
-
readonly data: unknown;
|
|
60
|
-
}, {
|
|
61
|
-
readonly _tag: Tag;
|
|
62
|
-
}> | Extract<{
|
|
63
|
-
readonly _tag: "Output";
|
|
64
|
-
readonly result: ToolResult;
|
|
65
|
-
}, {
|
|
66
|
-
readonly _tag: Tag;
|
|
67
|
-
}>;
|
|
68
|
-
readonly $match: {
|
|
69
|
-
<Cases extends {
|
|
70
|
-
readonly ApprovalRequested: (args: {
|
|
71
|
-
readonly _tag: "ApprovalRequested";
|
|
72
|
-
readonly call_id: string;
|
|
73
|
-
readonly tool: string;
|
|
74
|
-
readonly arguments: string;
|
|
75
|
-
}) => any;
|
|
76
|
-
readonly Progress: (args: {
|
|
77
|
-
readonly _tag: "Progress";
|
|
78
|
-
readonly call_id: string;
|
|
79
|
-
readonly tool: string;
|
|
80
|
-
readonly data: unknown;
|
|
81
|
-
}) => any;
|
|
82
|
-
readonly Output: (args: {
|
|
83
|
-
readonly _tag: "Output";
|
|
84
|
-
readonly result: ToolResult;
|
|
85
|
-
}) => any;
|
|
86
|
-
}>(cases: Cases): (value: {
|
|
87
|
-
readonly _tag: "ApprovalRequested";
|
|
88
|
-
readonly call_id: string;
|
|
89
|
-
readonly tool: string;
|
|
90
|
-
readonly arguments: string;
|
|
91
|
-
} | {
|
|
92
|
-
readonly _tag: "Progress";
|
|
93
|
-
readonly call_id: string;
|
|
94
|
-
readonly tool: string;
|
|
95
|
-
readonly data: unknown;
|
|
96
|
-
} | {
|
|
97
|
-
readonly _tag: "Output";
|
|
98
|
-
readonly result: ToolResult;
|
|
99
|
-
}) => _$effect_Unify0.Unify<ReturnType<Cases["ApprovalRequested" | "Progress" | "Output"]>>;
|
|
100
|
-
<Cases extends {
|
|
101
|
-
readonly ApprovalRequested: (args: {
|
|
102
|
-
readonly _tag: "ApprovalRequested";
|
|
103
|
-
readonly call_id: string;
|
|
104
|
-
readonly tool: string;
|
|
105
|
-
readonly arguments: string;
|
|
106
|
-
}) => any;
|
|
107
|
-
readonly Progress: (args: {
|
|
108
|
-
readonly _tag: "Progress";
|
|
109
|
-
readonly call_id: string;
|
|
110
|
-
readonly tool: string;
|
|
111
|
-
readonly data: unknown;
|
|
112
|
-
}) => any;
|
|
113
|
-
readonly Output: (args: {
|
|
114
|
-
readonly _tag: "Output";
|
|
115
|
-
readonly result: ToolResult;
|
|
116
|
-
}) => any;
|
|
117
|
-
}>(value: {
|
|
118
|
-
readonly _tag: "ApprovalRequested";
|
|
119
|
-
readonly call_id: string;
|
|
120
|
-
readonly tool: string;
|
|
121
|
-
readonly arguments: string;
|
|
122
|
-
} | {
|
|
123
|
-
readonly _tag: "Progress";
|
|
124
|
-
readonly call_id: string;
|
|
125
|
-
readonly tool: string;
|
|
126
|
-
readonly data: unknown;
|
|
127
|
-
} | {
|
|
128
|
-
readonly _tag: "Output";
|
|
129
|
-
readonly result: ToolResult;
|
|
130
|
-
}, cases: Cases): _$effect_Unify0.Unify<ReturnType<Cases["ApprovalRequested" | "Progress" | "Output"]>>;
|
|
131
|
-
};
|
|
132
|
-
};
|
|
133
|
-
declare const isApprovalRequested: (u: unknown) => u is {
|
|
134
|
-
readonly _tag: "ApprovalRequested";
|
|
135
|
-
readonly call_id: string;
|
|
136
|
-
readonly tool: string;
|
|
137
|
-
readonly arguments: string;
|
|
138
|
-
};
|
|
139
|
-
declare const isProgress: (u: unknown) => u is {
|
|
140
|
-
readonly _tag: "Progress";
|
|
141
|
-
readonly call_id: string;
|
|
142
|
-
readonly tool: string;
|
|
143
|
-
readonly data: unknown;
|
|
144
|
-
};
|
|
145
|
-
declare const isOutput: (u: unknown) => u is {
|
|
146
|
-
readonly _tag: "Output";
|
|
147
|
-
readonly result: ToolResult;
|
|
148
|
-
};
|
|
149
|
-
//#endregion
|
|
150
|
-
export { ToolEvent, isApprovalRequested, isOutput, isProgress, ToolEvent_d_exports as t };
|
|
151
|
-
//# sourceMappingURL=ToolEvent.d.mts.map
|
|
1
|
+
import { a as isProgress, i as isOutput, r as isApprovalRequested, t as ToolEvent } from "../ToolEvent-DYrAUJGs.mjs";
|
|
2
|
+
export { ToolEvent, isApprovalRequested, isOutput, isProgress };
|
|
@@ -1,138 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import * as _$effect_Unify0 from "effect/Unify";
|
|
4
|
-
|
|
5
|
-
//#region src/tool/ToolResult.d.ts
|
|
6
|
-
declare namespace ToolResult_d_exports {
|
|
7
|
-
export { ToolResult, cancelled, denied, executionError, failed, isFailure, isOk, toToolCallOutput };
|
|
8
|
-
}
|
|
9
|
-
type ToolResult = Data.TaggedEnum<{
|
|
10
|
-
Ok: {
|
|
11
|
-
readonly call_id: string;
|
|
12
|
-
readonly tool: string;
|
|
13
|
-
readonly value: unknown;
|
|
14
|
-
};
|
|
15
|
-
Failure: {
|
|
16
|
-
readonly call_id: string;
|
|
17
|
-
readonly tool: string;
|
|
18
|
-
readonly kind: string;
|
|
19
|
-
readonly reason?: string;
|
|
20
|
-
};
|
|
21
|
-
}>;
|
|
22
|
-
/**
|
|
23
|
-
* Namespace of constructors, type guards, and matchers for `ToolResult`,
|
|
24
|
-
* provided by `Data.taggedEnum`. Use `ToolResult.$is("Ok")` for type
|
|
25
|
-
* narrowing and `ToolResult.$match({ Ok, Failure })` for exhaustive
|
|
26
|
-
* pattern matching. Synthetic-result helpers (`denied`, `cancelled`,
|
|
27
|
-
* `executionError`, `failed`) below are kinder constructors than the
|
|
28
|
-
* raw `ToolResult.Failure(...)`.
|
|
29
|
-
*/
|
|
30
|
-
declare const ToolResult: {
|
|
31
|
-
readonly Ok: Data.TaggedEnum.ConstructorFrom<{
|
|
32
|
-
readonly _tag: "Ok";
|
|
33
|
-
readonly call_id: string;
|
|
34
|
-
readonly tool: string;
|
|
35
|
-
readonly value: unknown;
|
|
36
|
-
}, "_tag">;
|
|
37
|
-
readonly Failure: Data.TaggedEnum.ConstructorFrom<{
|
|
38
|
-
readonly _tag: "Failure";
|
|
39
|
-
readonly call_id: string;
|
|
40
|
-
readonly tool: string;
|
|
41
|
-
readonly kind: string;
|
|
42
|
-
readonly reason?: string;
|
|
43
|
-
}, "_tag">;
|
|
44
|
-
readonly $is: <Tag extends "Ok" | "Failure">(tag: Tag) => (u: unknown) => u is Extract<{
|
|
45
|
-
readonly _tag: "Ok";
|
|
46
|
-
readonly call_id: string;
|
|
47
|
-
readonly tool: string;
|
|
48
|
-
readonly value: unknown;
|
|
49
|
-
}, {
|
|
50
|
-
readonly _tag: Tag;
|
|
51
|
-
}> | Extract<{
|
|
52
|
-
readonly _tag: "Failure";
|
|
53
|
-
readonly call_id: string;
|
|
54
|
-
readonly tool: string;
|
|
55
|
-
readonly kind: string;
|
|
56
|
-
readonly reason?: string;
|
|
57
|
-
}, {
|
|
58
|
-
readonly _tag: Tag;
|
|
59
|
-
}>;
|
|
60
|
-
readonly $match: {
|
|
61
|
-
<Cases extends {
|
|
62
|
-
readonly Ok: (args: {
|
|
63
|
-
readonly _tag: "Ok";
|
|
64
|
-
readonly call_id: string;
|
|
65
|
-
readonly tool: string;
|
|
66
|
-
readonly value: unknown;
|
|
67
|
-
}) => any;
|
|
68
|
-
readonly Failure: (args: {
|
|
69
|
-
readonly _tag: "Failure";
|
|
70
|
-
readonly call_id: string;
|
|
71
|
-
readonly tool: string;
|
|
72
|
-
readonly kind: string;
|
|
73
|
-
readonly reason?: string;
|
|
74
|
-
}) => any;
|
|
75
|
-
}>(cases: Cases): (value: {
|
|
76
|
-
readonly _tag: "Ok";
|
|
77
|
-
readonly call_id: string;
|
|
78
|
-
readonly tool: string;
|
|
79
|
-
readonly value: unknown;
|
|
80
|
-
} | {
|
|
81
|
-
readonly _tag: "Failure";
|
|
82
|
-
readonly call_id: string;
|
|
83
|
-
readonly tool: string;
|
|
84
|
-
readonly kind: string;
|
|
85
|
-
readonly reason?: string;
|
|
86
|
-
}) => _$effect_Unify0.Unify<ReturnType<Cases["Ok" | "Failure"]>>;
|
|
87
|
-
<Cases extends {
|
|
88
|
-
readonly Ok: (args: {
|
|
89
|
-
readonly _tag: "Ok";
|
|
90
|
-
readonly call_id: string;
|
|
91
|
-
readonly tool: string;
|
|
92
|
-
readonly value: unknown;
|
|
93
|
-
}) => any;
|
|
94
|
-
readonly Failure: (args: {
|
|
95
|
-
readonly _tag: "Failure";
|
|
96
|
-
readonly call_id: string;
|
|
97
|
-
readonly tool: string;
|
|
98
|
-
readonly kind: string;
|
|
99
|
-
readonly reason?: string;
|
|
100
|
-
}) => any;
|
|
101
|
-
}>(value: {
|
|
102
|
-
readonly _tag: "Ok";
|
|
103
|
-
readonly call_id: string;
|
|
104
|
-
readonly tool: string;
|
|
105
|
-
readonly value: unknown;
|
|
106
|
-
} | {
|
|
107
|
-
readonly _tag: "Failure";
|
|
108
|
-
readonly call_id: string;
|
|
109
|
-
readonly tool: string;
|
|
110
|
-
readonly kind: string;
|
|
111
|
-
readonly reason?: string;
|
|
112
|
-
}, cases: Cases): _$effect_Unify0.Unify<ReturnType<Cases["Ok" | "Failure"]>>;
|
|
113
|
-
};
|
|
114
|
-
};
|
|
115
|
-
declare const isOk: (u: unknown) => u is {
|
|
116
|
-
readonly _tag: "Ok";
|
|
117
|
-
readonly call_id: string;
|
|
118
|
-
readonly tool: string;
|
|
119
|
-
readonly value: unknown;
|
|
120
|
-
};
|
|
121
|
-
declare const isFailure: (u: unknown) => u is {
|
|
122
|
-
readonly _tag: "Failure";
|
|
123
|
-
readonly call_id: string;
|
|
124
|
-
readonly tool: string;
|
|
125
|
-
readonly kind: string;
|
|
126
|
-
readonly reason?: string;
|
|
127
|
-
};
|
|
128
|
-
declare const failed: (call: ToolCall, kind: string, reason?: string) => ToolResult;
|
|
129
|
-
/** Explicit user/policy rejection. */
|
|
130
|
-
declare const denied: (call: ToolCall, reason?: string) => ToolResult;
|
|
131
|
-
/** Implicit non-answer (follow-up, inactivity, abort). */
|
|
132
|
-
declare const cancelled: (call: ToolCall, reason?: string) => ToolResult;
|
|
133
|
-
/** Tool's own execution failed (parse error, schema, runtime crash). */
|
|
134
|
-
declare const executionError: (call: ToolCall, reason: string) => ToolResult;
|
|
135
|
-
declare const toToolCallOutput: (r: ToolResult) => ToolCallOutput;
|
|
136
|
-
//#endregion
|
|
137
|
-
export { ToolResult, cancelled, denied, executionError, failed, isFailure, isOk, ToolResult_d_exports as t, toToolCallOutput };
|
|
138
|
-
//# sourceMappingURL=ToolResult.d.mts.map
|
|
1
|
+
import { a as executionError, c as isOk, d as validationError, i as denied, l as nonLocalTool, o as failed, r as cancelled, s as isFailure, t as ToolResult, u as toToolCallOutput } from "../ToolResult-BZd-cEWW.mjs";
|
|
2
|
+
export { ToolResult, cancelled, denied, executionError, failed, isFailure, isOk, nonLocalTool, toToolCallOutput, validationError };
|