@fitzzero/quickdraw-core 5.0.1 → 5.1.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/README.md +303 -32
- package/dist/{admin-CBlTY0do.d.ts → admin-DKwkIh5i.d.ts} +2 -2
- package/dist/{adminSchemas-zji11V74.d.ts → adminSchemas-2DUA_hZ8.d.ts} +1 -1
- package/dist/{auth-CMyRkfjZ.d.ts → auth-BhWqdyb-.d.ts} +2 -2
- package/dist/{caller-BqCYnpmC.d.ts → caller-CXTFswBO.d.ts} +27 -5
- package/dist/{chunk-2XJFNVHW.js → chunk-2PWMUVC7.js} +1 -1
- package/dist/{chunk-2XJFNVHW.js.map → chunk-2PWMUVC7.js.map} +1 -1
- package/dist/{chunk-3JNMVB2V.js → chunk-2UELNHDD.js} +2 -2
- package/dist/{chunk-HQ6WIRE2.js → chunk-3674EIRT.js} +4 -4
- package/dist/{chunk-NS5PUHIZ.js → chunk-A6DJBGOG.js} +130 -23
- package/dist/chunk-A6DJBGOG.js.map +1 -0
- package/dist/{chunk-ZACRRYWL.js → chunk-JZBCLNDU.js} +4 -4
- package/dist/{chunk-O2PWC2YW.js → chunk-KNDDCVQJ.js} +3 -3
- package/dist/{chunk-5YRQ26LF.js → chunk-RT6OILOI.js} +1 -1
- package/dist/chunk-RT6OILOI.js.map +1 -0
- package/dist/{chunk-WVIRXYI4.js → chunk-VJTFXHOK.js} +2 -2
- package/dist/{chunk-WVIRXYI4.js.map → chunk-VJTFXHOK.js.map} +1 -1
- package/dist/chunk-XNLWBZIG.js +9 -0
- package/dist/chunk-XNLWBZIG.js.map +1 -0
- package/dist/cli/quickdraw-docs.js +241 -27
- package/dist/cli/quickdraw-docs.js.map +1 -1
- package/dist/client/index.d.ts +7 -7
- package/dist/client/index.js +4 -4
- package/dist/{clientTypes-DuZW_8mb.d.ts → clientTypes-Bc-G8n-U.d.ts} +3 -3
- package/dist/{connection-DuN8GvcD.d.ts → connection-Cr1BU07W.d.ts} +2 -2
- package/dist/{createServer-CGsJlxM8.d.ts → createServer-CP9eDHZZ.d.ts} +30 -9
- package/dist/{createTestApp-Cg2CZa1g.d.ts → createTestApp-UKVGEmOf.d.ts} +6 -6
- package/dist/{envelope-nf5eGB-a.d.ts → envelope-Cp3YcVxC.d.ts} +1 -1
- package/dist/{http-D3fSFQ57.d.ts → http-Djj2Inuu.d.ts} +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +26 -6
- package/dist/index.js.map +1 -1
- package/dist/{infer-Dw21kmLw.d.ts → infer-Teo1xpsd.d.ts} +17 -0
- package/dist/{metrics-C0WvB7-I.d.ts → metrics-BdBu5o8G.d.ts} +2 -2
- package/dist/prisma/index.d.ts +4 -4
- package/dist/server/auth/index.d.ts +3 -3
- package/dist/server/index.d.ts +47 -26
- package/dist/server/index.js +62 -36
- package/dist/server/index.js.map +1 -1
- package/dist/server/mcp/index.d.ts +51 -11
- package/dist/server/mcp/index.js +129 -8
- package/dist/server/mcp/index.js.map +1 -1
- package/dist/server/otel.d.ts +3 -3
- package/dist/{sharing-CoreezAq.d.ts → sharing-DVa8W-yR.d.ts} +3 -3
- package/dist/testing/client.d.ts +13 -13
- package/dist/testing/client.js +5 -5
- package/dist/testing/index.d.ts +156 -12
- package/dist/testing/index.js +1036 -21
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/mock.d.ts +5 -5
- package/dist/testing/mock.js +4 -4
- package/dist/{types-Bwg3kIEc.d.ts → types-Cu0vmx7c.d.ts} +8 -2
- package/dist/utils/index.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-5YRQ26LF.js.map +0 -1
- package/dist/chunk-NS5PUHIZ.js.map +0 -1
- /package/dist/{chunk-3JNMVB2V.js.map → chunk-2UELNHDD.js.map} +0 -0
- /package/dist/{chunk-HQ6WIRE2.js.map → chunk-3674EIRT.js.map} +0 -0
- /package/dist/{chunk-ZACRRYWL.js.map → chunk-JZBCLNDU.js.map} +0 -0
- /package/dist/{chunk-O2PWC2YW.js.map → chunk-KNDDCVQJ.js.map} +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { A as AnyService,
|
|
1
|
+
import { A as AnyService, d as Caller } from '../../caller-CXTFswBO.js';
|
|
2
2
|
import { IncomingHttpHeaders, IncomingMessage } from 'node:http';
|
|
3
|
-
import { ap as MethodName, d as StandardSchemaV1, c as InferOutput } from '../../infer-
|
|
3
|
+
import { ap as MethodName, d as StandardSchemaV1, c as InferOutput } from '../../infer-Teo1xpsd.js';
|
|
4
4
|
import { Q as QuickdrawError, a as ErrorCode } from '../../errors-S-bxEIBC.js';
|
|
5
|
-
import { P as PrincipalOfServices, C as ContractOfServices, D as Dispatcher, H as HttpRouter } from '../../http-
|
|
6
|
-
import { a as McpContext, b as McpContextOf, M as MaybePromise } from '../../types-
|
|
5
|
+
import { P as PrincipalOfServices, C as ContractOfServices, D as Dispatcher, H as HttpRouter } from '../../http-Djj2Inuu.js';
|
|
6
|
+
import { a as McpContext, b as McpContextOf, M as MaybePromise } from '../../types-Cu0vmx7c.js';
|
|
7
7
|
import { L as Logger } from '../../logger-BY28acW-.js';
|
|
8
|
-
import { A as AuthenticateResult } from '../../auth-
|
|
8
|
+
import { A as AuthenticateResult } from '../../auth-BhWqdyb-.js';
|
|
9
9
|
import { Readable, Writable } from 'node:stream';
|
|
10
|
-
import '../../envelope-
|
|
11
|
-
import '../../metrics-
|
|
10
|
+
import '../../envelope-Cp3YcVxC.js';
|
|
11
|
+
import '../../metrics-BdBu5o8G.js';
|
|
12
12
|
import 'socket.io';
|
|
13
13
|
|
|
14
14
|
/** The JSON Schema of a tool's arguments. MCP requires an object schema. */
|
|
@@ -134,6 +134,28 @@ interface McpToolCall<S extends readonly AnyService[] = readonly AnyService[], A
|
|
|
134
134
|
readonly signal: AbortSignal;
|
|
135
135
|
readonly request: McpRequest;
|
|
136
136
|
}
|
|
137
|
+
/** What a function of the registry's `bind` receives: one call of a tool whose method's input has its argument. */
|
|
138
|
+
interface McpBindCall<S extends readonly AnyService[] = readonly AnyService[]> {
|
|
139
|
+
/**
|
|
140
|
+
* Who the call acts for, from the registry's `principal`. Never `null`: an
|
|
141
|
+
* anonymous caller of a tool with a bound argument is refused with
|
|
142
|
+
* `UNAUTHENTICATED` before any binder runs.
|
|
143
|
+
*/
|
|
144
|
+
readonly principal: PrincipalOfServices<S>;
|
|
145
|
+
/** The fields the registry's `context` produced for the call, if any. */
|
|
146
|
+
readonly mcp: McpContextOfServices<S> | undefined;
|
|
147
|
+
readonly request: McpRequest;
|
|
148
|
+
/** The service and method the tool calls, for example `"messageService"` and `"post"`. */
|
|
149
|
+
readonly service: string;
|
|
150
|
+
readonly method: string;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Fills one argument of the registry's `bind` from who is calling, for
|
|
154
|
+
* example a claim of the principal's token. Returning `undefined` or `null`
|
|
155
|
+
* refuses the call with `FORBIDDEN`; throwing fails it with `INTERNAL`, or
|
|
156
|
+
* with the code of a `QuickdrawError`.
|
|
157
|
+
*/
|
|
158
|
+
type McpBinder<S extends readonly AnyService[] = readonly AnyService[]> = (call: McpBindCall<S>) => MaybePromise<unknown>;
|
|
137
159
|
/**
|
|
138
160
|
* Who may call a custom tool: `"authenticated"` callers only, or `"public"`,
|
|
139
161
|
* anonymous callers too. These are the two method access forms that need no
|
|
@@ -206,6 +228,21 @@ interface McpRegistryOptions<S extends readonly AnyService[], Tools extends read
|
|
|
206
228
|
* for example. Runs per call, after `principal`.
|
|
207
229
|
*/
|
|
208
230
|
readonly context?: (request: McpRequest, principal: PrincipalOfServices<S> | null) => MaybePromise<McpContextOfServices<S>>;
|
|
231
|
+
/**
|
|
232
|
+
* Arguments filled from who is calling instead of by the agent, by name:
|
|
233
|
+
* `{ taskId: ({ principal }) => principal.claims?.taskId }`. Each one is
|
|
234
|
+
* left out of the `inputSchema` of every method's tool whose object input
|
|
235
|
+
* has it, and each call of such a tool, by `call` or `callMethod`, gets the
|
|
236
|
+
* binder's value before its input is validated. The call is refused
|
|
237
|
+
* before the method runs when the caller is anonymous (`UNAUTHENTICATED`),
|
|
238
|
+
* or when the binder returns `undefined` or `null` or the caller sent the
|
|
239
|
+
* argument with another value (`FORBIDDEN`); a binder that throws fails it
|
|
240
|
+
* with `INTERNAL`, or with the code of a `QuickdrawError`. Custom tools are
|
|
241
|
+
* never bound. Binding is not access control: the same principal reaches
|
|
242
|
+
* the method over a socket or HTTP with nothing bound, so the method's
|
|
243
|
+
* access must still confine it.
|
|
244
|
+
*/
|
|
245
|
+
readonly bind?: Readonly<Record<string, McpBinder<S>>>;
|
|
209
246
|
/** The app's own tools, listed after the generated ones. */
|
|
210
247
|
readonly customTools?: {
|
|
211
248
|
readonly [K in keyof Tools]: McpCustomTool<S, Tools[K]>;
|
|
@@ -235,7 +272,8 @@ interface McpRegistry {
|
|
|
235
272
|
/**
|
|
236
273
|
* Calls a method's tool by its service and method name with the method's
|
|
237
274
|
* `input` as it is, without the tool's argument mapping: the shape 4.1's
|
|
238
|
-
* HTTP route took.
|
|
275
|
+
* HTTP route took. Bound arguments are filled as for `call`. A method that
|
|
276
|
+
* is not a tool is `NOT_FOUND`.
|
|
239
277
|
*/
|
|
240
278
|
callMethod(service: string, method: string, input: unknown, options: McpCallOptions): Promise<McpCallResult>;
|
|
241
279
|
}
|
|
@@ -243,8 +281,10 @@ interface McpRegistry {
|
|
|
243
281
|
* Builds the MCP tools of `services` (see `describeTools`) and the app's
|
|
244
282
|
* `customTools`, served by `dispatcher`. Throws at once when a method's
|
|
245
283
|
* input schema cannot describe itself as JSON Schema (use Zod 4.2 or later
|
|
246
|
-
* for it, or `exclude` the method), when two tools share a name,
|
|
247
|
-
* dispatcher does not serve one of the services
|
|
284
|
+
* for it, or `exclude` the method), when two tools share a name, when the
|
|
285
|
+
* dispatcher does not serve one of the services, or when an argument of
|
|
286
|
+
* `bind` is in no tool's object input or is in an input that is not an
|
|
287
|
+
* object.
|
|
248
288
|
*
|
|
249
289
|
* @example
|
|
250
290
|
* const registry = createMcpRegistry({
|
|
@@ -366,4 +406,4 @@ type McpHttpReply = {
|
|
|
366
406
|
*/
|
|
367
407
|
declare function createMcpHttpRouter(options: McpHttpRouterOptions): HttpRouter;
|
|
368
408
|
|
|
369
|
-
export { type DescribeToolsOptions, MCP_PROTOCOL_VERSION, type McpCallOptions, type McpCallResult, type McpContextOfServices, type McpCustomTool, type McpHttpReply, type McpHttpRequest, type McpHttpRouterOptions, type McpInputSchema, type McpMethodRef, type McpRegistry, type McpRegistryOptions, type McpRequest, type McpStdioRequest, type McpStdioServer, type McpStdioServerOptions, type McpTextContent, type McpTool, type McpToolAccess, type McpToolAnnotations, type McpToolArguments, type McpToolCall, type McpToolInputSchema, type McpToolResult, bootstrapMcpServer, createMcpHttpRouter, createMcpRegistry, createMcpStdioServer, describeTools, toToolResult };
|
|
409
|
+
export { type DescribeToolsOptions, MCP_PROTOCOL_VERSION, type McpBindCall, type McpBinder, type McpCallOptions, type McpCallResult, type McpContextOfServices, type McpCustomTool, type McpHttpReply, type McpHttpRequest, type McpHttpRouterOptions, type McpInputSchema, type McpMethodRef, type McpRegistry, type McpRegistryOptions, type McpRequest, type McpStdioRequest, type McpStdioServer, type McpStdioServerOptions, type McpTextContent, type McpTool, type McpToolAccess, type McpToolAnnotations, type McpToolArguments, type McpToolCall, type McpToolInputSchema, type McpToolResult, bootstrapMcpServer, createMcpHttpRouter, createMcpRegistry, createMcpStdioServer, describeTools, toToolResult };
|
package/dist/server/mcp/index.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defaultToolName
|
|
3
|
+
} from "../../chunk-XNLWBZIG.js";
|
|
1
4
|
import {
|
|
2
5
|
NEVER_ABORTED,
|
|
3
6
|
lazyMembers,
|
|
4
7
|
parseInput,
|
|
5
8
|
toQuickdrawError
|
|
6
|
-
} from "../../chunk-
|
|
9
|
+
} from "../../chunk-2PWMUVC7.js";
|
|
7
10
|
import {
|
|
8
11
|
describeError
|
|
9
12
|
} from "../../chunk-DD4SKCNO.js";
|
|
@@ -122,7 +125,7 @@ function toolNamer(options, fail) {
|
|
|
122
125
|
fail("name must be a function of (service, method)");
|
|
123
126
|
}
|
|
124
127
|
return (service, method) => {
|
|
125
|
-
const named = name === void 0 ?
|
|
128
|
+
const named = name === void 0 ? defaultToolName(service, method) : name(service, method);
|
|
126
129
|
if (typeof named !== "string" || named === "") {
|
|
127
130
|
const shown = typeof named === "string" ? `""` : String(named);
|
|
128
131
|
fail(`name returned ${shown} for ${service}.${method}; a tool name is a non-empty string`);
|
|
@@ -133,7 +136,50 @@ function toolNamer(options, fail) {
|
|
|
133
136
|
function describeMethod(service, method, kind, text) {
|
|
134
137
|
return typeof text === "string" && text !== "" ? text : `${service}.${method} (${kind})`;
|
|
135
138
|
}
|
|
136
|
-
function
|
|
139
|
+
function propertiesOf(schema) {
|
|
140
|
+
return isRecord(schema) && isRecord(schema.properties) ? Object.keys(schema.properties) : [];
|
|
141
|
+
}
|
|
142
|
+
function branchProperties(schema, found = /* @__PURE__ */ new Set()) {
|
|
143
|
+
if (!isRecord(schema)) {
|
|
144
|
+
return found;
|
|
145
|
+
}
|
|
146
|
+
for (const keyword of ["anyOf", "oneOf", "allOf"]) {
|
|
147
|
+
const branches = schema[keyword];
|
|
148
|
+
for (const branch of Array.isArray(branches) ? branches : []) {
|
|
149
|
+
for (const key of propertiesOf(branch)) {
|
|
150
|
+
found.add(key);
|
|
151
|
+
}
|
|
152
|
+
branchProperties(branch, found);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return found;
|
|
156
|
+
}
|
|
157
|
+
function boundArguments(label, input, bind, fail) {
|
|
158
|
+
if (input.mode === "object") {
|
|
159
|
+
const properties = propertiesOf(input.schema);
|
|
160
|
+
return bind.filter((key) => properties.includes(key));
|
|
161
|
+
}
|
|
162
|
+
const wrapped = input.schema.properties?.input;
|
|
163
|
+
const unbindable = branchProperties(wrapped, new Set(propertiesOf(wrapped)));
|
|
164
|
+
const misplaced = bind.find((key) => unbindable.has(key));
|
|
165
|
+
if (misplaced !== void 0) {
|
|
166
|
+
fail(
|
|
167
|
+
`bind.${misplaced} names a property of the input of ${label}, which is not an object: bind fills properties of object inputs only; leave ${label} out with exclude, or make its input an object`
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
return [];
|
|
171
|
+
}
|
|
172
|
+
function withoutArguments(schema, bound) {
|
|
173
|
+
const kept = (key) => !bound.includes(key);
|
|
174
|
+
const { properties = {}, required, ...rest } = schema;
|
|
175
|
+
const stillRequired = required?.filter(kept) ?? [];
|
|
176
|
+
return {
|
|
177
|
+
...rest,
|
|
178
|
+
properties: Object.fromEntries(Object.entries(properties).filter(([key]) => kept(key))),
|
|
179
|
+
...stillRequired.length === 0 ? {} : { required: stillRequired }
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function planMethodTools(services, options, fail, bind = []) {
|
|
137
183
|
const given = services;
|
|
138
184
|
if (!Array.isArray(given)) {
|
|
139
185
|
fail("services must be an array of services from qd.defineService");
|
|
@@ -148,13 +194,14 @@ function planMethodTools(services, options, fail) {
|
|
|
148
194
|
}
|
|
149
195
|
const label = `${service.name}.${method}`;
|
|
150
196
|
const input = toolInputOf(label, def.input, fail);
|
|
197
|
+
const bound = boundArguments(label, input, bind, fail);
|
|
151
198
|
const tool = {
|
|
152
199
|
name: toolName(service.name, method),
|
|
153
200
|
description: describeMethod(service.name, method, def.kind, def.describe),
|
|
154
|
-
inputSchema: input.schema,
|
|
201
|
+
inputSchema: bound.length === 0 ? input.schema : withoutArguments(input.schema, bound),
|
|
155
202
|
...def.kind === "query" ? { annotations: { readOnlyHint: true } } : {}
|
|
156
203
|
};
|
|
157
|
-
planned.push({ ...input, tool: Object.freeze(tool), service: service.name, method });
|
|
204
|
+
planned.push({ ...input, tool: Object.freeze(tool), service: service.name, method, bound });
|
|
158
205
|
}
|
|
159
206
|
}
|
|
160
207
|
return planned;
|
|
@@ -390,6 +437,31 @@ function checkDispatcher(dispatcher, services, fail) {
|
|
|
390
437
|
}
|
|
391
438
|
}
|
|
392
439
|
}
|
|
440
|
+
function checkBinders(bind, fail) {
|
|
441
|
+
if (bind === void 0) {
|
|
442
|
+
return /* @__PURE__ */ new Map();
|
|
443
|
+
}
|
|
444
|
+
if (!isRecord3(bind) || Array.isArray(bind)) {
|
|
445
|
+
fail("bind must be an object of functions, one per argument it fills");
|
|
446
|
+
}
|
|
447
|
+
const binders = /* @__PURE__ */ new Map();
|
|
448
|
+
for (const [key, binder] of Object.entries(bind)) {
|
|
449
|
+
if (typeof binder !== "function") {
|
|
450
|
+
fail(`bind.${key} must be a function of the call, returning the argument's value`);
|
|
451
|
+
}
|
|
452
|
+
binders.set(key, binder);
|
|
453
|
+
}
|
|
454
|
+
return binders;
|
|
455
|
+
}
|
|
456
|
+
function checkBound(binders, methodTools, fail) {
|
|
457
|
+
for (const key of binders.keys()) {
|
|
458
|
+
if (!methodTools.some((tool) => tool.bound.includes(key))) {
|
|
459
|
+
fail(
|
|
460
|
+
`bind.${key} fills nothing: no method served as a tool has "${key}" in its object input`
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
393
465
|
function resolveRegistry(options) {
|
|
394
466
|
const fail = (message) => {
|
|
395
467
|
throw new TypeError(`createMcpRegistry: ${message}`);
|
|
@@ -400,7 +472,9 @@ function resolveRegistry(options) {
|
|
|
400
472
|
checkDispatcher(options.dispatcher, options.services, fail);
|
|
401
473
|
checkHook("principal", options.principal, fail);
|
|
402
474
|
checkHook("context", options.context, fail);
|
|
403
|
-
const
|
|
475
|
+
const binders = checkBinders(options.bind, fail);
|
|
476
|
+
const methodTools = planMethodTools(options.services, options, fail, [...binders.keys()]);
|
|
477
|
+
checkBound(binders, methodTools, fail);
|
|
404
478
|
const customTools = checkCustomTools(options.customTools, fail);
|
|
405
479
|
const entries = [
|
|
406
480
|
...methodTools.map((tool) => ({ kind: "method", ...tool })),
|
|
@@ -419,7 +493,8 @@ function resolveRegistry(options) {
|
|
|
419
493
|
context: options.context,
|
|
420
494
|
logger: options.logger ?? consoleLogger,
|
|
421
495
|
entries: new Map(entries.map((entry2) => [entry2.tool.name, entry2])),
|
|
422
|
-
methods: new Map(methodTools.map((tool) => [methodKey(tool.service, tool.method), tool]))
|
|
496
|
+
methods: new Map(methodTools.map((tool) => [methodKey(tool.service, tool.method), tool])),
|
|
497
|
+
binders
|
|
423
498
|
};
|
|
424
499
|
}
|
|
425
500
|
async function inSession(settings, name, options, run) {
|
|
@@ -431,12 +506,58 @@ async function inSession(settings, name, options, run) {
|
|
|
431
506
|
}
|
|
432
507
|
return run(session);
|
|
433
508
|
}
|
|
509
|
+
async function bindInput(settings, tool, input, session, request) {
|
|
510
|
+
const { principal } = session;
|
|
511
|
+
if (principal === null) {
|
|
512
|
+
throw new QuickdrawError("UNAUTHENTICATED", "Authentication required");
|
|
513
|
+
}
|
|
514
|
+
const given = input ?? {};
|
|
515
|
+
if (!isRecord3(given) || Array.isArray(given)) {
|
|
516
|
+
throw new QuickdrawError("VALIDATION", `Invalid input for ${tool.service}.${tool.method}`, {
|
|
517
|
+
issues: [{ path: [], message: "Expected an object" }]
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
const call = {
|
|
521
|
+
principal,
|
|
522
|
+
mcp: session.mcp,
|
|
523
|
+
request,
|
|
524
|
+
service: tool.service,
|
|
525
|
+
method: tool.method
|
|
526
|
+
};
|
|
527
|
+
const filled = [];
|
|
528
|
+
for (const [key, binder] of settings.binders) {
|
|
529
|
+
if (!tool.bound.includes(key)) {
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
532
|
+
const value = await binder(call);
|
|
533
|
+
if (value === void 0 || value === null) {
|
|
534
|
+
throw new QuickdrawError("FORBIDDEN", `"${key}" is bound to the caller, who has none`);
|
|
535
|
+
}
|
|
536
|
+
const sent = Object.hasOwn(given, key) ? given[key] : void 0;
|
|
537
|
+
if (sent !== void 0 && JSON.stringify(sent) !== JSON.stringify(value)) {
|
|
538
|
+
throw new QuickdrawError(
|
|
539
|
+
"FORBIDDEN",
|
|
540
|
+
`"${key}" is bound to the caller and cannot be set to another value`
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
filled.push([key, value]);
|
|
544
|
+
}
|
|
545
|
+
return { ...given, ...Object.fromEntries(filled) };
|
|
546
|
+
}
|
|
434
547
|
async function dispatchMethod(settings, tool, input, session, options) {
|
|
548
|
+
let bound = input;
|
|
549
|
+
if (tool.bound.length > 0) {
|
|
550
|
+
try {
|
|
551
|
+
bound = await bindInput(settings, tool, input, session, options.request);
|
|
552
|
+
} catch (error) {
|
|
553
|
+
return settle(settings, options, failure(settings, error, tool.tool.name));
|
|
554
|
+
}
|
|
555
|
+
}
|
|
435
556
|
const { respond } = options;
|
|
436
557
|
const request = sessionRequest(session, {
|
|
437
558
|
service: tool.service,
|
|
438
559
|
method: tool.method,
|
|
439
|
-
input,
|
|
560
|
+
input: bound,
|
|
440
561
|
signal: options.signal,
|
|
441
562
|
respond: respond === void 0 ? void 0 : (result) => respond(fromDispatch(result))
|
|
442
563
|
});
|