stitchkit 0.68.9 → 0.68.10

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.
Files changed (52) hide show
  1. package/dist/agent-runtime/deferred-tool-search.d.ts +8 -0
  2. package/dist/agent-runtime/deferred-tool-search.d.ts.map +1 -0
  3. package/dist/agent-runtime/deferred-tool-selection.d.ts +15 -0
  4. package/dist/agent-runtime/deferred-tool-selection.d.ts.map +1 -0
  5. package/dist/agent-runtime/deferred-tool-types.d.ts +131 -0
  6. package/dist/agent-runtime/deferred-tool-types.d.ts.map +1 -0
  7. package/dist/agent-runtime/deferred-tools-internal.d.ts +10 -0
  8. package/dist/agent-runtime/deferred-tools-internal.d.ts.map +1 -0
  9. package/dist/agent-runtime/deferred-tools.d.ts +4 -0
  10. package/dist/agent-runtime/deferred-tools.d.ts.map +1 -0
  11. package/dist/agent-runtime/run-execution.d.ts.map +1 -1
  12. package/dist/agent-runtime-openrouter.js +1 -1
  13. package/dist/agent-runtime.d.ts +1 -0
  14. package/dist/agent-runtime.d.ts.map +1 -1
  15. package/dist/agent-runtime.js +471 -73
  16. package/dist/cli.js +7 -8
  17. package/dist/contract/index.js +2 -2
  18. package/dist/{index-vkk06pv1.js → index-22by16v6.js} +57 -9
  19. package/dist/{index-hmfpjnh7.js → index-22tjt2rk.js} +2 -2
  20. package/dist/{index-1bmpkhj2.js → index-2t6zt5cg.js} +9 -134
  21. package/dist/index-bt5179zb.js +99 -0
  22. package/dist/index-eqqyd9v8.js +130 -0
  23. package/dist/{index-51a19y3v.js → index-f24xg2cw.js} +2 -2
  24. package/dist/{index-j2nq04z6.js → index-f6n5n7nz.js} +1 -1
  25. package/dist/{index-9t2tdk1x.js → index-grgvpbch.js} +3 -5
  26. package/dist/{index-n34x0q5e.js → index-hb0mncmj.js} +3 -3
  27. package/dist/{index-6tqys26z.js → index-hcx9yypn.js} +4 -4
  28. package/dist/{index-z575awm9.js → index-hxh98zbm.js} +2 -2
  29. package/dist/{index-bmmtz6r9.js → index-pgsyp3xh.js} +1 -1
  30. package/dist/index-qyrqwr4c.js +41 -0
  31. package/dist/{index-r5s4wqb5.js → index-t23p2b68.js} +1 -1
  32. package/dist/{index-3ydx9j01.js → index-xyvxez9r.js} +3 -3
  33. package/dist/{index-04agqrs8.js → index-y2ctppmg.js} +72 -6
  34. package/dist/index.js +2 -2
  35. package/dist/internal/typed.d.ts +8 -0
  36. package/dist/internal/typed.d.ts.map +1 -1
  37. package/dist/node.js +5 -5
  38. package/dist/observability/index.js +4 -4
  39. package/dist/react.js +1 -1
  40. package/dist/remote.js +4 -4
  41. package/dist/server/index.js +7 -7
  42. package/dist/testing.js +5 -6
  43. package/dist/tool-invoker.js +6 -8
  44. package/dist/tools/internal/surface-projector.d.ts +7 -0
  45. package/dist/tools/internal/surface-projector.d.ts.map +1 -1
  46. package/dist/tools.js +34 -115
  47. package/llms-full.txt +80 -1
  48. package/package.json +1 -1
  49. package/dist/index-6djpbnda.js +0 -56
  50. package/dist/index-88yyydag.js +0 -75
  51. package/dist/index-smpbdg6k.js +0 -27
  52. /package/dist/{index-tss6bk5c.js → index-ksp6e2ye.js} +0 -0
package/dist/tools.js CHANGED
@@ -1,10 +1,14 @@
1
1
  import {
2
2
  redact
3
- } from "./index-hmfpjnh7.js";
3
+ } from "./index-22tjt2rk.js";
4
+ import {
5
+ buildToolManifest,
6
+ mountAgent
7
+ } from "./index-bt5179zb.js";
4
8
  import {
5
9
  signJwt,
6
10
  verifyPkce
7
- } from "./index-3ydx9j01.js";
11
+ } from "./index-xyvxez9r.js";
8
12
  import {
9
13
  DEFAULT_CORS_ALLOW_HEADERS,
10
14
  DEFAULT_PROCESS_SIGNALS,
@@ -12,39 +16,39 @@ import {
12
16
  defaultSignalSource,
13
17
  guardSignalCallback,
14
18
  reportSignalError
15
- } from "./index-z575awm9.js";
19
+ } from "./index-hxh98zbm.js";
16
20
  import {
17
21
  createToolInvoker
18
- } from "./index-9t2tdk1x.js";
22
+ } from "./index-grgvpbch.js";
19
23
  import {
20
24
  WaitTimeoutError,
21
- collectToolSurface,
22
25
  createCli,
23
- createRuntimeToolFactory,
24
26
  defineCliCommand,
25
- defineRuntimeTool,
26
27
  fetchGuarded,
27
28
  fetchPinnedDocument,
28
29
  readCapped,
29
30
  runWaitOperation
30
- } from "./index-1bmpkhj2.js";
31
+ } from "./index-2t6zt5cg.js";
31
32
  import {
32
- collectTools,
33
- createToolRunner,
34
- formatToolError
35
- } from "./index-88yyydag.js";
33
+ collectToolSurface,
34
+ createRuntimeToolFactory,
35
+ defineRuntimeTool
36
+ } from "./index-eqqyd9v8.js";
36
37
  import {
37
38
  ToolExecutionControlError,
38
39
  coerceJsonArgs,
40
+ collectTools,
41
+ createToolRunner,
39
42
  executeToolMethod,
43
+ formatToolError,
40
44
  isToolExecutionControlError,
41
45
  toolResultFromError
42
- } from "./index-04agqrs8.js";
46
+ } from "./index-y2ctppmg.js";
43
47
  import {
44
48
  getRequestContext,
45
49
  getTraceId,
46
50
  runWithRequestContext
47
- } from "./index-51a19y3v.js";
51
+ } from "./index-f24xg2cw.js";
48
52
  import {
49
53
  ManagedFileError
50
54
  } from "./index-bfcpjw20.js";
@@ -59,17 +63,16 @@ import {
59
63
  prepareProjectedMcpTools,
60
64
  presentationMetadata,
61
65
  validateMcpRoundPolicy
62
- } from "./index-vkk06pv1.js";
63
- import"./index-6djpbnda.js";
66
+ } from "./index-22by16v6.js";
64
67
  import"./index-cby4ar3v.js";
65
68
  import {
66
69
  defineContract,
67
70
  normalizeError,
68
71
  resolvePropagationContext
69
- } from "./index-bmmtz6r9.js";
72
+ } from "./index-pgsyp3xh.js";
70
73
  import {
71
74
  isRecord
72
- } from "./index-smpbdg6k.js";
75
+ } from "./index-qyrqwr4c.js";
73
76
  import {
74
77
  AppError,
75
78
  STITCH_ERROR_STATUS
@@ -78,77 +81,6 @@ import {
78
81
  ManagedFilePathSchema,
79
82
  ManagedFileRefSchema
80
83
  } from "./index-6k1937bx.js";
81
-
82
- // src/tools/agent.ts
83
- import { jsonSchema, tool } from "ai";
84
- function mountAgent(services, config = {}) {
85
- const serviceList = Array.isArray(services) ? services : [services];
86
- const tools = {};
87
- const runTool = createToolRunner({
88
- source: "agent",
89
- extend: config.extend,
90
- context: config.context,
91
- hooks: config.hooks,
92
- lifecycle: config.lifecycle,
93
- errorHint: config.errorHint,
94
- coerceJsonArgs: config.coerceJsonArgs,
95
- onOutputStrip: config.onOutputStrip
96
- });
97
- for (const entry of collectToolSurface({
98
- surface: { services: serviceList, runtimeTools: config.runtimeTools },
99
- transport: "AGENT",
100
- extend: config.extend,
101
- flattenUnionInput: config.flattenUnionInput
102
- })) {
103
- const { mountable } = entry;
104
- const inputSchema = jsonSchema(mountable.presentationSchema, {
105
- validate: async (value) => isRecord(value) ? { success: true, value } : { success: false, error: new Error("Tool arguments must be an object") }
106
- });
107
- const execute = async (rawArgs, options) => {
108
- const args = isRecord(rawArgs) ? rawArgs : {};
109
- try {
110
- const result = await runTool(mountable, args, { signal: options.abortSignal });
111
- if (result.ok)
112
- return result.data;
113
- return formatToolError(result, mountable.name, config.errorHint);
114
- } catch (err) {
115
- if (isToolExecutionControlError(err))
116
- throw err;
117
- return formatToolError(toolResultFromError(err), mountable.name, config.errorHint);
118
- }
119
- };
120
- const presenter = entry.kind === "runtime" ? entry.definition.present?.agent : undefined;
121
- if (entry.kind === "runtime" && presenter) {
122
- const { definition } = entry;
123
- const output = definition.output;
124
- if (!output) {
125
- throw new Error(`Runtime tool "${definition.name}" presenter requires an output schema`);
126
- }
127
- tools[definition.name] = tool({
128
- description: definition.description,
129
- inputSchema,
130
- outputSchema: output,
131
- execute,
132
- toModelOutput: async ({ output: rawOutput }) => {
133
- const parsed = output.safeParse(rawOutput);
134
- if (!parsed.success) {
135
- return { type: "text", value: JSON.stringify(rawOutput) };
136
- }
137
- return presenter(parsed.data);
138
- }
139
- });
140
- } else {
141
- const output = entry.kind === "runtime" ? entry.definition.output : undefined;
142
- tools[mountable.name] = tool({
143
- description: mountable.method.desc,
144
- inputSchema,
145
- ...output && { outputSchema: output },
146
- execute
147
- });
148
- }
149
- }
150
- return tools;
151
- }
152
84
  // src/tools/async-operation.ts
153
85
  import { z } from "zod";
154
86
 
@@ -1003,19 +935,6 @@ function listToolNames(surface) {
1003
935
  function listContractToolNames(contracts) {
1004
936
  return listToolNames({ services: contracts.map(contractOnlyService) });
1005
937
  }
1006
- // src/tools/manifest.ts
1007
- function buildToolManifest(config) {
1008
- return collectToolSurface({
1009
- surface: config,
1010
- transport: config.transport,
1011
- extend: config.extend,
1012
- flattenUnionInput: config.flattenUnionInput
1013
- }).map(({ mountable }) => ({
1014
- name: mountable.name,
1015
- description: mountable.method.desc,
1016
- inputSchema: mountable.presentationSchema
1017
- }));
1018
- }
1019
938
  // src/tools/mcp.ts
1020
939
  import {
1021
940
  createRequestStateCodec,
@@ -1178,23 +1097,23 @@ async function argumentsDigest(args) {
1178
1097
  binary += String.fromCodePoint(byte);
1179
1098
  return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
1180
1099
  }
1181
- function operationIdentity(tool2) {
1100
+ function operationIdentity(tool) {
1182
1101
  return {
1183
- toolName: tool2.name,
1184
- serviceName: tool2.method.serviceName,
1185
- action: tool2.method.key,
1186
- method: tool2.method.method,
1187
- ...tool2.method.scope !== undefined && { scope: tool2.method.scope }
1102
+ toolName: tool.name,
1103
+ serviceName: tool.method.serviceName,
1104
+ action: tool.method.key,
1105
+ method: tool.method.method,
1106
+ ...tool.method.scope !== undefined && { scope: tool.method.scope }
1188
1107
  };
1189
1108
  }
1190
1109
  function sameIdentity(left, right) {
1191
1110
  return left.toolName === right.toolName && left.serviceName === right.serviceName && left.action === right.action && left.method === right.method && left.scope === right.scope;
1192
1111
  }
1193
- async function runRoundSuccess(tool2, rawArgs, runTool, context) {
1112
+ async function runRoundSuccess(tool, rawArgs, runTool, context) {
1194
1113
  return runTool({
1195
- ...tool2,
1114
+ ...tool,
1196
1115
  method: {
1197
- ...tool2.method,
1116
+ ...tool.method,
1198
1117
  outputSchema: undefined,
1199
1118
  handler: () => {
1200
1119
  return;
@@ -1202,11 +1121,11 @@ async function runRoundSuccess(tool2, rawArgs, runTool, context) {
1202
1121
  }
1203
1122
  }, rawArgs, context);
1204
1123
  }
1205
- async function runRoundFailure(tool2, rawArgs, runTool, context, code, message) {
1124
+ async function runRoundFailure(tool, rawArgs, runTool, context, code, message) {
1206
1125
  return runTool({
1207
- ...tool2,
1126
+ ...tool,
1208
1127
  method: {
1209
- ...tool2.method,
1128
+ ...tool.method,
1210
1129
  outputSchema: undefined,
1211
1130
  handler: () => {
1212
1131
  throw new AppError(code, message, 400);
@@ -1402,7 +1321,7 @@ function mountPreparedRuntimeMcp(server, tools, config) {
1402
1321
  }
1403
1322
  server.registerTool(definition.name, toolConfig, async (rawArgs, mcpContext) => runInMcpRequestContext(mcpContext, definition.name, async () => {
1404
1323
  const args = isRecord(rawArgs) ? rawArgs : {};
1405
- const runTool = (tool2, toolArgs, roundContext) => executeToolMethod(tool2.method, definition.name, toolArgs, { ...config.context, ...roundContext, source: "mcp" }, config.hooks, config.lifecycle, config.coerceJsonArgs ?? true, config.onOutputStrip ? (paths) => config.onOutputStrip?.(definition.name, paths) : undefined);
1324
+ const runTool = (tool, toolArgs, roundContext) => executeToolMethod(tool.method, definition.name, toolArgs, { ...config.context, ...roundContext, source: "mcp" }, config.hooks, config.lifecycle, config.coerceJsonArgs ?? true, config.onOutputStrip ? (paths) => config.onOutputStrip?.(definition.name, paths) : undefined);
1406
1325
  const round = await resolveMcpRound({
1407
1326
  tool: mountable,
1408
1327
  rawArgs: args,
package/llms-full.txt CHANGED
@@ -3712,6 +3712,16 @@ fails first on duplicate contract/runtime names. There is no runtime-only
3712
3712
  manifest helper or public mount adapter: the framework owns merging and schema
3713
3713
  projection.
3714
3714
 
3715
+ Applications using Stitchkit's durable runtime can compose this manifest with
3716
+ bounded per-run activation through `createDeferredAgentToolSurface` from
3717
+ `stitchkit/agent-runtime`. It keeps selected calls as direct `mountAgent` tools
3718
+ rather than routing them through a generic executor. Search receipts live in
3719
+ ordinary durable tool-result history, so recovery restores activation and a
3720
+ queued successor cannot inherit it. See
3721
+ [Bounded deferred tool catalogs](./agent-runtime.md#bounded-deferred-tool-catalogs)
3722
+ and ADR 0129. Raw `mountAgent`, `mountMcp` and `buildToolManifest` behavior is
3723
+ unchanged.
3724
+
3715
3725
  `listToolNames` remains diagnostic and reports `kind: 'contract' | 'runtime'`
3716
3726
  for every identity. `summarizeTransports` returns `contractServices`,
3717
3727
  `runtimeTools`, aggregate `totals`, and a `sources` breakdown. Runtime tools
@@ -3763,7 +3773,7 @@ description: Configure Stitchkit's optional durable history, stream loop, run co
3763
3773
  type: architecture
3764
3774
  status: active
3765
3775
  created: 2026-08-22
3766
- updated: 2026-08-28
3776
+ updated: 2026-08-29
3767
3777
  ---
3768
3778
 
3769
3779
  # Agent application runtime
@@ -3918,6 +3928,69 @@ await ticket.accepted
3918
3928
  const terminal = await ticket.result
3919
3929
  ```
3920
3930
 
3931
+ ## Bounded deferred tool catalogs
3932
+
3933
+ Use `createDeferredAgentToolSurface` when a measured large catalog makes
3934
+ sending every schema on every provider step expensive. The controller mounts
3935
+ the complete executable surface in process, but initially advertises only its
3936
+ search tool, explicit `alwaysOn` tools and bounded policy pins:
3937
+
3938
+ ```ts
3939
+ import { createDeferredAgentToolSurface } from 'stitchkit/agent-runtime'
3940
+ import { composeToolLifecycle } from 'stitchkit/tools'
3941
+
3942
+ const deferred = createDeferredAgentToolSurface({
3943
+ surfaces: {
3944
+ member: { services: memberServices, runtimeTools, alwaysOn: ['ask_user'] },
3945
+ broadcast: { services: broadcastServices, runtimeTools },
3946
+ },
3947
+ selectSurface: ({ context }) => context.mode,
3948
+ pins: ({ context }) => context.skillTools,
3949
+ search: {
3950
+ name: 'tool_search',
3951
+ maxQueryBytes: 1_024,
3952
+ maxResults: 8,
3953
+ maxResultBytes: 8_192,
3954
+ select: ({ query, manifest }) => rankCatalog(query, manifest),
3955
+ },
3956
+ activation: {
3957
+ maxSelectedTools: 8,
3958
+ maxActiveTools: 16,
3959
+ maxSchemaBytes: 32_768,
3960
+ },
3961
+ observe: event => recordDeferredToolEvidence(event),
3962
+ })
3963
+
3964
+ const runtime = createAgentRuntime({
3965
+ // protocol, store, models and prompt...
3966
+ tools: runContext => deferred.mount(runContext, {
3967
+ context: runContext.context,
3968
+ lifecycle: composeToolLifecycle(authLifecycle, runContext.toolFenceLifecycle),
3969
+ }),
3970
+ loop: { prepareStep: deferred.prepareStep(applicationPrepareStep) },
3971
+ })
3972
+ ```
3973
+
3974
+ The built-in selector deterministically ranks exact name, prefix/token and
3975
+ description matches. A custom async selector returns names only; unknown and
3976
+ duplicate output is removed against the local canonical manifest. Search never
3977
+ executes the selected operation and never returns its schema. A later provider
3978
+ step receives the real selected tools by name, so their direct lifecycle,
3979
+ fencing, hooks, errors and `present.agent` output remain unchanged.
3980
+
3981
+ Selection is a versioned receipt in the ordinary durable tool-result history.
3982
+ The latest valid same-run search replaces the earlier selection; parallel
3983
+ searches in one step merge in call order. Recovery reconstructs it, while a
3984
+ different run or finite surface cannot inherit it. Known inactive calls take a
3985
+ recoverable `SEARCH_REQUIRED` search round; unknown names still fail.
3986
+
3987
+ Every ceiling is required. `maxSchemaBytes` measures UTF-8 bytes over canonical
3988
+ name, description and presentation schema. It is useful for before/after
3989
+ comparison, but provider serialization and tokenization differ: use existing
3990
+ provider-reported input usage and cost to decide whether the extra search round
3991
+ is beneficial. Controller evidence intentionally omits query text, prompts,
3992
+ arguments and application context. → ADR 0129.
3993
+
3921
3994
  ### Executable headless harness and capability map
3922
3995
 
3923
3996
  [`packages/core/examples/headless-agent-harness.ts`](../../packages/core/examples/headless-agent-harness.ts)
@@ -11683,6 +11756,12 @@ Server-only optional application runtime. See the
11683
11756
  | Export | Kind | Summary |
11684
11757
  |--------|------|---------|
11685
11758
  | `createAgentRuntime` | function | compose durable acceptance, stream loop, checkpoints, coordination, managed tools and winner-only terminal publication; reconciles same-owner terminal/interrupt/head CAS races before releasing the lane |
11759
+ | `createDeferredAgentToolSurface` | function | bounded canonical catalog search plus durable same-run activation of direct `mountAgent` tools; supports one immutable surface or a finite identity-specific registry |
11760
+ | `DeferredAgentToolSearchInputSchema` / `DeferredAgentToolMatchSchema` / `DeferredAgentToolReceiptSchema` | schema | bounded search input, public match and versioned durable selection receipt |
11761
+ | `DeferredAgentToolSurfaceConfig` / `DeferredAgentToolCommonConfig` / `DeferredAgentToolSurfaceDefinition` / `DeferredAgentToolController` | _type_ | finite catalogs, selector, pin, budget and `mount`/`prepareStep` composition contracts |
11762
+ | `DeferredAgentRuntimeToolDefinition` / `DeferredAgentToolMountConfig` | _type_ | peer-free Agent-only runtime definition and canonical mount configuration accepted by the controller |
11763
+ | `DeferredAgentToolManifestEntry` / `DeferredAgentToolSearchContext` / `DeferredAgentToolReceipt` | _type_ | canonical selector input and inferred durable receipt records |
11764
+ | `DeferredAgentToolEvent` | _type_ | PII-free search/step evidence with surface, provenance, counts, canonical schema bytes and ceilings |
11686
11765
  | `defineAgentProtocol` | function | declare context, input metadata, canonical parts and optional pre-CAS terminal acceptance (`allow-empty`, `require-output` or callback) |
11687
11766
  | `hasAgentTerminalOutput` | function | generic `require-output` predicate for non-blank text, generated files, structured provider parts and explicit tool-only policy stops |
11688
11767
  | `AgentMessageSchema` / `AgentRunSchema` / `AgentSnapshotSchema` | schema | versioned canonical engine records |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stitchkit",
3
- "version": "0.68.9",
3
+ "version": "0.68.10",
4
4
  "description": "Contract-first backend framework — one defineContract() into an HTTP API, MCP tools, AI-agent tools and a typed client. Bun and Node.",
5
5
  "keywords": [
6
6
  "bun",
@@ -1,56 +0,0 @@
1
- import {
2
- toJsonSchema
3
- } from "./index-cby4ar3v.js";
4
-
5
- // src/tools/schema.ts
6
- import { z } from "zod";
7
- function objectShapeKeys(schema) {
8
- return schema instanceof z.ZodObject ? Object.keys(schema.shape) : [];
9
- }
10
- function keyPolicyOf(schema) {
11
- return schema.def.catchall;
12
- }
13
- function rebuildObject(source, shape) {
14
- return withKeyPolicy(z.object(shape), keyPolicyOf(source));
15
- }
16
- function withKeyPolicy(object, policy) {
17
- if (policy === undefined)
18
- return object;
19
- return object.catchall(representable(policy));
20
- }
21
- function representable(policy) {
22
- if (policy instanceof z.ZodNever || policy instanceof z.ZodUnknown)
23
- return policy;
24
- if (!(policy instanceof z.ZodType))
25
- return z.unknown();
26
- try {
27
- toJsonSchema(policy, "input");
28
- return policy;
29
- } catch {
30
- return z.unknown();
31
- }
32
- }
33
- function mergeSchemas(paramsSchema, inputSchema) {
34
- if (paramsSchema && !(paramsSchema instanceof z.ZodObject)) {
35
- throw new Error("Tool params schema must be a z.object()");
36
- }
37
- const paramsObject = paramsSchema instanceof z.ZodObject ? paramsSchema : undefined;
38
- if (!inputSchema) {
39
- return paramsObject ?? z.object({});
40
- }
41
- if (inputSchema instanceof z.ZodObject) {
42
- if (paramsObject) {
43
- const conflicts = Object.keys(paramsObject.shape).filter((key) => (key in inputSchema.shape));
44
- if (conflicts.length > 0) {
45
- throw new Error(`Schema merge conflict: ${conflicts.join(", ")} appear in both params and input`);
46
- }
47
- }
48
- return rebuildObject(inputSchema, {
49
- ...paramsObject?.shape ?? {},
50
- ...inputSchema.shape
51
- });
52
- }
53
- return paramsObject ? z.intersection(paramsObject, inputSchema) : inputSchema;
54
- }
55
-
56
- export { objectShapeKeys, rebuildObject, mergeSchemas };
@@ -1,75 +0,0 @@
1
- import {
2
- executeToolMethod
3
- } from "./index-04agqrs8.js";
4
- import {
5
- assertToolExtensionCompatible,
6
- projectToolSurface
7
- } from "./index-vkk06pv1.js";
8
- import {
9
- mergeSchemas,
10
- rebuildObject
11
- } from "./index-6djpbnda.js";
12
-
13
- // src/tools/mount.ts
14
- import { z } from "zod";
15
- function applyExtend(base, extra) {
16
- if (base instanceof z.ZodObject) {
17
- assertToolExtensionCompatible(base, extra);
18
- return rebuildObject(base, { ...extra, ...base.shape });
19
- }
20
- return z.intersection(z.object(extra), base);
21
- }
22
- function contractToolMountable(projected, extend) {
23
- const method = projected.source;
24
- const baseArgumentSchema = mergeSchemas(method.paramsSchema, method.inputSchema);
25
- const argumentSchema = projected.shouldExtend && extend ? applyExtend(baseArgumentSchema, extend.schema) : baseArgumentSchema;
26
- return {
27
- method,
28
- name: projected.name,
29
- argumentSchema,
30
- presentationSchema: projected.presentationSchema,
31
- shouldExtend: projected.shouldExtend
32
- };
33
- }
34
- function collectTools(service, transport, config = {}) {
35
- const { extend, flattenUnionInput = false, assertNames = true } = config;
36
- const tools = [];
37
- for (const projected of projectToolSurface({ services: [service] }, transport === "HTTP" ? "AGENT" : transport, {
38
- extend,
39
- flattenUnionInput,
40
- assertNames,
41
- assertUniqueNames: false
42
- })) {
43
- if (projected.kind !== "contract")
44
- continue;
45
- tools.push(contractToolMountable(projected, extend));
46
- }
47
- return tools;
48
- }
49
- function createToolRunner(config) {
50
- const extension = config.extend ? {
51
- schema: z.object(config.extend.schema),
52
- resolve: config.extend.resolve
53
- } : undefined;
54
- return async function runOneToolCall(tool, rawArgs, context) {
55
- return executeToolMethod(tool.method, tool.name, rawArgs, { ...config.context, ...context, source: config.source }, config.hooks, config.lifecycle, config.coerceJsonArgs ?? true, config.onOutputStrip ? (paths) => config.onOutputStrip?.(tool.name, paths) : undefined, tool.shouldExtend ? extension : undefined);
56
- };
57
- }
58
- function formatToolError(result, toolName, errorHint) {
59
- const err = { error: result.code };
60
- if (result.details)
61
- err.details = result.details;
62
- const hints = [];
63
- if (result.hint)
64
- hints.push(result.hint);
65
- if (errorHint && toolName) {
66
- const global = errorHint(toolName, result.code);
67
- if (global)
68
- hints.push(global);
69
- }
70
- if (hints.length > 0)
71
- err._hint = hints.join(" ");
72
- return err;
73
- }
74
-
75
- export { contractToolMountable, collectTools, createToolRunner, formatToolError };
@@ -1,27 +0,0 @@
1
- // src/internal/typed.ts
2
- function typedEntries(value) {
3
- return Object.entries(value);
4
- }
5
- function isRecord(value) {
6
- return typeof value === "object" && value !== null && !Array.isArray(value);
7
- }
8
- function callRuntimeHandler(handler, context) {
9
- if (typeof handler !== "function") {
10
- throw new TypeError("Runtime handler must be a function");
11
- }
12
- return Reflect.apply(handler, undefined, [context]);
13
- }
14
- function transportResult(value) {
15
- return value;
16
- }
17
- function mapObject(source, mapper) {
18
- const result = {};
19
- for (const [key, value] of typedEntries(source)) {
20
- const mapped = mapper(key, value);
21
- if (mapped !== undefined)
22
- result[key] = mapped;
23
- }
24
- return result;
25
- }
26
-
27
- export { typedEntries, isRecord, callRuntimeHandler, transportResult, mapObject };
File without changes