@jini-ai/mcp 0.4.2 → 0.4.4
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/CHANGELOG.md +4 -0
- package/README.md +1 -0
- package/dist/agent-install/chrome-devtools.d.ts +4 -0
- package/dist/agent-install/chrome-devtools.js +7 -0
- package/dist/agent-install/index.d.ts +1 -0
- package/dist/agent-install/index.js +1 -0
- package/dist/agent-install/install.js +102 -194
- package/dist/bin/serve.d.ts +4 -1
- package/dist/bin/serve.js +120 -45
- package/dist/client/client.js +71 -58
- package/dist/core/config.js +113 -149
- package/dist/core/tokens.js +29 -53
- package/dist/federation/adapter.http.js +3 -2
- package/dist/federation/approvals/call-confirmation.js +5 -70
- package/dist/federation/approvals/remembered-approval.d.ts +39 -0
- package/dist/federation/approvals/remembered-approval.js +98 -0
- package/dist/federation/approvals/revocation-reason.d.ts +9 -0
- package/dist/federation/approvals/revocation-reason.js +11 -0
- package/dist/federation/approvals/revocation.js +19 -13
- package/dist/federation/approvals/scope-option.d.ts +6 -0
- package/dist/federation/approvals/scope-option.js +6 -0
- package/dist/federation/bootstrap.d.ts +18 -0
- package/dist/federation/bootstrap.js +4 -4
- package/dist/federation/presets.d.ts +16 -17
- package/dist/federation/presets.js +35 -28
- package/dist/federation/stdio/adapter.stdio.js +14 -6
- package/dist/federation/stdio/default-connect.js +24 -27
- package/dist/federation/stdio/stdio-launch-resolver.d.ts +1 -1
- package/dist/federation/stdio/stdio-launch-resolver.js +13 -9
- package/dist/federation/tool-approvals.js +3 -1
- package/dist/federation/trust.d.ts +23 -2
- package/dist/federation/trust.js +69 -35
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/server/daemon-client.d.ts +2 -0
- package/dist/server/daemon-client.js +86 -69
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/resources/site-guide-resource.d.ts +15 -0
- package/dist/server/resources/site-guide-resource.js +25 -0
- package/dist/server/tool-arguments.d.ts +46 -0
- package/dist/server/tool-arguments.js +111 -0
- package/dist/server/tool-protocol.d.ts +62 -7
- package/dist/server/tool-protocol.js +30 -40
- package/dist/server/tool-server.d.ts +19 -0
- package/dist/server/tool-server.js +91 -19
- package/dist/server/tools/delegated-tool.d.ts +47 -0
- package/dist/server/tools/delegated-tool.js +35 -2
- package/dist/server/tools/tool-catalog-tools.js +30 -8
- package/dist/tools/ask-choice/index.d.ts +213 -14
- package/dist/tools/ask-choice/index.js +90 -46
- package/dist/tools/ask-choice/question.d.ts +5 -1
- package/dist/tools/ask-choice/question.js +36 -2
- package/dist/tools/ask-choice/schema.d.ts +196 -10
- package/dist/tools/ask-choice/schema.js +33 -12
- package/dist/tools/ask-choice/types.d.ts +8 -0
- package/package.json +6 -5
- package/dist/core/oauth.d.ts +0 -274
- package/dist/core/oauth.js +0 -667
- package/dist/core/secure-write.d.ts +0 -17
- package/dist/core/secure-write.js +0 -72
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @jini-ai/mcp/server/tools/delegated-tool
|
|
3
|
+
*
|
|
4
|
+
* `execute_delegated_tool` and its read-only companion `execute_readonly_delegated_tool` — the
|
|
5
|
+
* MCP-callback half of gap 3's continuation transport (see
|
|
6
|
+
* `packages/daemon/archived provenance ledger`'s "run/chat orchestration gap 3, part 1" addition and this
|
|
7
|
+
* package's own dated section in `archived provenance ledger` for the rest of the spike). The swarm-consensus
|
|
8
|
+
* Final Recommendation asked for exactly this: "inject the already-shipped MCP host into one
|
|
9
|
+
* MCP-capable CLI's launch config, prove a tool round-trip through the existing
|
|
10
|
+
* `delegated-tool-bridge.ts`." Where `../tools/run-tools.js`'s tools proxy generic
|
|
11
|
+
* run-lifecycle HTTP endpoints, this tool proxies the new `POST /api/delegated-tool-calls`
|
|
12
|
+
* daemon route (`packages/http/src/delegated-tools.ts`), which is the one and only thing that
|
|
13
|
+
* calls into `createDelegatedToolBridge` (`packages/daemon/src/delegated-tool-bridge.ts`) — the
|
|
14
|
+
* same `ToolExecutor` deny-by-default gate every other tool-execution path in this codebase
|
|
15
|
+
* already uses. No parallel authorization mechanism is introduced anywhere on this path.
|
|
16
|
+
*
|
|
17
|
+
* Unlike every other tool this package ships (`run-tools.ts`'s five tools, plain static
|
|
18
|
+
* objects), this one is a **factory**. The MCP server subprocess a `claude` run spawns via
|
|
19
|
+
* `.mcp.json` (see `../../bin/serve.js`) is scoped to exactly one `runId` for its entire
|
|
20
|
+
* lifetime — the daemon injected that run id into the subprocess's own environment at spawn
|
|
21
|
+
* time, before the model ever said a word. `runId` is therefore closed over at construction
|
|
22
|
+
* time, not accepted as a per-call tool argument: a model has no legitimate way to pick, or
|
|
23
|
+
* need to know, which run it is currently inside, and letting it supply one would open a
|
|
24
|
+
* confused-deputy path (one run's MCP subprocess executing a tool call "as" a different run).
|
|
25
|
+
* `toolUseId` is likewise generated per call (`randomUUID` by default), not model-supplied — a
|
|
26
|
+
* model has no legitimate reason to choose its own correlation id either.
|
|
27
|
+
*
|
|
28
|
+
* TWO defs, ONE code path. `createDelegatedGateway` builds both; the factories differ only in the
|
|
29
|
+
* name/title/description they present and in whether the request carries `requireReadOnly: true`.
|
|
30
|
+
* The read-only companion exists because MCP annotations are static per tool declaration — a
|
|
31
|
+
* surface that promises "this only reads" can only be a second declaration, never a per-call mode —
|
|
32
|
+
* and it ENFORCES that promise daemon-side rather than asserting it, because a `readOnlyHint: true`
|
|
33
|
+
* tool that could still reach writes would launder a write past its caller's own safety gate. See
|
|
34
|
+
* {@link createExecuteReadonlyDelegatedToolTool} for the failure that motivated it.
|
|
35
|
+
*/
|
|
36
|
+
import { type ExposedToolDescriptor } from '@jini-ai/core';
|
|
1
37
|
import { type McpToolDef } from '../tool-protocol.js';
|
|
2
38
|
/**
|
|
3
39
|
* Request deadline for one delegated tool call, overriding `daemon-client.ts`'s 15 s default.
|
|
@@ -87,4 +123,15 @@ export declare function createExecuteDelegatedToolTool(requiredArgs: CreateExecu
|
|
|
87
123
|
* every caller, including the ones the annotation exists to protect.
|
|
88
124
|
*/
|
|
89
125
|
export declare function createExecuteReadonlyDelegatedToolTool(requiredArgs: CreateExecuteDelegatedToolToolRequiredArgs, options?: CreateExecuteDelegatedToolToolOptions): McpToolDef;
|
|
126
|
+
/**
|
|
127
|
+
* Project a pinned registry descriptor as one concrete MCP tool, reusing the existing gateway.
|
|
128
|
+
* @param requiredArgs - Trusted run scope and F0's collision-checked, exposed descriptor.
|
|
129
|
+
* @param options - The same correlation source and deadline used by the legacy wrappers.
|
|
130
|
+
* @returns A schema-preserving definition; model arguments become only the delegated input.
|
|
131
|
+
* @throws Error when the descriptor has no MCP object input schema.
|
|
132
|
+
* @complexity O(s) schema parsing time/space for s schema fields; execution is one daemon call.
|
|
133
|
+
*/
|
|
134
|
+
export declare function createTypedDelegatedToolTool({ runId, tool }: CreateExecuteDelegatedToolToolRequiredArgs & {
|
|
135
|
+
tool: ExposedToolDescriptor;
|
|
136
|
+
}, options?: CreateExecuteDelegatedToolToolOptions): McpToolDef;
|
|
90
137
|
//# sourceMappingURL=delegated-tool.d.ts.map
|
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
* tool that could still reach writes would launder a write past its caller's own safety gate. See
|
|
34
34
|
* {@link createExecuteReadonlyDelegatedToolTool} for the failure that motivated it.
|
|
35
35
|
*/
|
|
36
|
+
import { batchOutcomeFor, isReadOnlyTool } from '@jini-ai/core';
|
|
37
|
+
import { ToolSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
36
38
|
import { randomUUID } from 'node:crypto';
|
|
37
39
|
import { postDaemonJson } from '../daemon-client.js';
|
|
38
40
|
import { daemonCallOptions, requireString } from '../tool-protocol.js';
|
|
@@ -42,6 +44,7 @@ function isRecord(value) {
|
|
|
42
44
|
/**
|
|
43
45
|
* Unwraps a completed delegated call's `{executionId, status, output, ...}` envelope down to just
|
|
44
46
|
* `output` when — and only when — `output` is itself an MCP content envelope (`{content: [...]}`).
|
|
47
|
+
* Batches expose partial_failure/error and isError while retaining every item.
|
|
45
48
|
* Every other shape (a non-completed status, a plain JSON `output` like a string or a list, no
|
|
46
49
|
* `output` at all) is returned byte-identical to `result` — this is an additive unwrap, not a new
|
|
47
50
|
* general response shape, so the existing "surfaces the result envelope unchanged" contract for an
|
|
@@ -57,9 +60,14 @@ function isRecord(value) {
|
|
|
57
60
|
* block the bridge already preserved.
|
|
58
61
|
*/
|
|
59
62
|
function unwrapMcpContentEnvelope(result) {
|
|
60
|
-
if (!isRecord(result)
|
|
63
|
+
if (!isRecord(result))
|
|
61
64
|
return result;
|
|
62
65
|
const output = result['output'];
|
|
66
|
+
const outcome = batchOutcomeFor({ output });
|
|
67
|
+
if (outcome === 'partial_failure' || outcome === 'error')
|
|
68
|
+
return { ...result, status: outcome, outcome, isError: true };
|
|
69
|
+
if (result['status'] !== 'completed')
|
|
70
|
+
return result;
|
|
63
71
|
if (!isRecord(output) || !Array.isArray(output['content']))
|
|
64
72
|
return result;
|
|
65
73
|
return output;
|
|
@@ -109,7 +117,8 @@ function createDelegatedGateway(variant, { runId }, options) {
|
|
|
109
117
|
: DEFAULT_DELEGATED_TOOL_TIMEOUT_MS;
|
|
110
118
|
return {
|
|
111
119
|
name: variant.name,
|
|
112
|
-
description: variant.description
|
|
120
|
+
description: `${variant.description} Put the tool's own arguments inside input; non-conflicting top-level tool arguments are moved there automatically.`,
|
|
121
|
+
argumentNormalization: { foldIntoInput: true },
|
|
113
122
|
inputSchema: {
|
|
114
123
|
type: 'object',
|
|
115
124
|
properties: {
|
|
@@ -223,4 +232,28 @@ export function createExecuteReadonlyDelegatedToolTool(requiredArgs, options = {
|
|
|
223
232
|
requireReadOnly: true,
|
|
224
233
|
}, requiredArgs, options);
|
|
225
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Project a pinned registry descriptor as one concrete MCP tool, reusing the existing gateway.
|
|
237
|
+
* @param requiredArgs - Trusted run scope and F0's collision-checked, exposed descriptor.
|
|
238
|
+
* @param options - The same correlation source and deadline used by the legacy wrappers.
|
|
239
|
+
* @returns A schema-preserving definition; model arguments become only the delegated input.
|
|
240
|
+
* @throws Error when the descriptor has no MCP object input schema.
|
|
241
|
+
* @complexity O(s) schema parsing time/space for s schema fields; execution is one daemon call.
|
|
242
|
+
*/
|
|
243
|
+
export function createTypedDelegatedToolTool({ runId, tool }, options = {}) {
|
|
244
|
+
const { descriptor, wireName } = tool;
|
|
245
|
+
const inputSchema = ToolSchema.shape.inputSchema.parse(descriptor.inputSchema);
|
|
246
|
+
const readOnly = isReadOnlyTool({ descriptor });
|
|
247
|
+
const gateway = readOnly
|
|
248
|
+
? createExecuteReadonlyDelegatedToolTool({ runId }, options)
|
|
249
|
+
: createExecuteDelegatedToolTool({ runId }, options);
|
|
250
|
+
return {
|
|
251
|
+
name: wireName,
|
|
252
|
+
description: descriptor.description ?? descriptor.id,
|
|
253
|
+
// Parse to check the MCP boundary, but publish the original schema, including extensions.
|
|
254
|
+
inputSchema: descriptor.inputSchema,
|
|
255
|
+
annotations: { ...gateway.annotations, title: descriptor.id },
|
|
256
|
+
handler: ({ args, ctx }) => gateway.handler({ args: { toolId: descriptor.id, input: args }, ctx }),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
226
259
|
//# sourceMappingURL=delegated-tool.js.map
|
|
@@ -4,24 +4,40 @@
|
|
|
4
4
|
* `search_tools` / `describe_tool` — the discovery half of `ai-control-plane.md` §29 /
|
|
5
5
|
* `PROP-tool-catalog-discovery-2026-07-26.md` §6.1, proxying `@jini-ai/http-kit`'s
|
|
6
6
|
* `GET /api/tools/search` / `GET /api/tools/:id` exactly as `run-tools.ts`'s tools proxy
|
|
7
|
-
* `runs.ts` — no separate authorization mechanism
|
|
7
|
+
* `runs.ts` — no separate authorization mechanism or catalog cache.
|
|
8
8
|
*
|
|
9
9
|
* v0 scope: no principal scoping, no versioning, no schema narrowing. Execution is unchanged —
|
|
10
|
-
* a caller
|
|
11
|
-
*
|
|
10
|
+
* a caller runs a discovered id through the delegated gateway (`../tools/delegated-tool.js`),
|
|
11
|
+
* either with its legacy wrapper or a concrete definition published after a successful describe.
|
|
12
|
+
* Both reach the same `ToolExecutor`.
|
|
12
13
|
* Finding a tool id here grants nothing (`PROP` §6.3).
|
|
13
14
|
*/
|
|
14
15
|
import { getDaemonJson } from '../daemon-client.js';
|
|
16
|
+
import { isRecord } from '../tool-arguments.js';
|
|
15
17
|
import { daemonCallOptions, requireString } from '../tool-protocol.js';
|
|
16
18
|
const READ_ANNOTATIONS = {
|
|
17
19
|
readOnlyHint: true,
|
|
18
20
|
idempotentHint: true,
|
|
19
21
|
openWorldHint: false,
|
|
20
22
|
};
|
|
23
|
+
/** Validate the daemon's identity before publishing; discovery cannot substitute another tool.
|
|
24
|
+
* Unknown risk remains unclassified and therefore cannot claim a read-only annotation.
|
|
25
|
+
* @complexity O(1); no effects. The schema is checked by the publication boundary.
|
|
26
|
+
*/
|
|
27
|
+
function describedDescriptor({ id, data }) {
|
|
28
|
+
if (!isRecord(data) || data.id !== id)
|
|
29
|
+
throw new Error('daemon returned a mismatched tool descriptor');
|
|
30
|
+
return {
|
|
31
|
+
id,
|
|
32
|
+
...(typeof data.description === 'string' ? { description: data.description } : {}),
|
|
33
|
+
...(typeof data.readOnly === 'boolean' ? { readOnly: data.readOnly } : {}),
|
|
34
|
+
...(data.inputSchema === undefined ? {} : { inputSchema: data.inputSchema }),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
21
37
|
/** `search_tools` -> `GET /api/tools/search` (`packages/http/src/tool-catalog.ts`'s `toolCatalogSearchRoute`). */
|
|
22
38
|
export const searchToolsTool = {
|
|
23
39
|
name: 'search_tools',
|
|
24
|
-
description: 'Search the durable tool catalog. Returns ranked {id, description, source, score} candidates only — no input schemas, so this stays cheap to call broadly. Call describe_tool on the 1-3 candidates that look right before calling execute_delegated_tool. If nothing in the results fits, re-search with a higher limit or different phrasing rather than assuming the tool does not exist.',
|
|
40
|
+
description: 'Search the durable tool catalog. Returns ranked {id, description, source, score, readOnly, sideEffects} candidates only — no input schemas, so this stays cheap to call broadly. Call describe_tool on the 1-3 candidates that look right before calling execute_delegated_tool. If nothing in the results fits, re-search with a higher limit or different phrasing rather than assuming the tool does not exist.',
|
|
25
41
|
inputSchema: {
|
|
26
42
|
type: 'object',
|
|
27
43
|
properties: {
|
|
@@ -80,19 +96,25 @@ export const searchToolsTool = {
|
|
|
80
96
|
/** `describe_tool` -> `GET /api/tools/:id` (`packages/http/src/tool-catalog.ts`'s `toolCatalogDescribeRoute`). */
|
|
81
97
|
export const describeToolTool = {
|
|
82
98
|
name: 'describe_tool',
|
|
83
|
-
description: 'Get the full descriptor for one tool id found via search_tools — description
|
|
99
|
+
description: 'Get the full descriptor for one tool id found via search_tools — description, input schema, readOnly and sideEffects. When dynamic publication is enabled, this also exposes that operation as a concrete tool in tools/list; call it with its own arguments. Legacy fallback: use execute_readonly_delegated_tool only when readOnly is true. Supply id (aliases: toolId or name). Paid for only on the candidates that survive search, per the tool catalog\'s staged-discovery design.',
|
|
84
100
|
inputSchema: {
|
|
85
101
|
type: 'object',
|
|
86
102
|
properties: {
|
|
87
|
-
id: { type: 'string', description: 'Tool id returned by search_tools.
|
|
103
|
+
id: { type: 'string', description: 'Tool id returned by search_tools. Supply id, toolId, or name.' },
|
|
104
|
+
toolId: { type: 'string', description: 'Alias of id, matching the delegated-execute wrappers.' },
|
|
105
|
+
name: { type: 'string', description: 'Alias of id.' },
|
|
88
106
|
},
|
|
89
|
-
required: ['id'],
|
|
107
|
+
anyOf: [{ required: ['id'] }, { required: ['toolId'] }, { required: ['name'] }],
|
|
90
108
|
additionalProperties: false,
|
|
91
109
|
},
|
|
110
|
+
argumentNormalization: { aliases: { toolId: 'id', name: 'id' } },
|
|
92
111
|
annotations: { ...READ_ANNOTATIONS, title: 'Describe a tool' },
|
|
93
112
|
handler: async ({ args, ctx }) => {
|
|
94
113
|
const id = requireString({ value: args.id, name: 'id' });
|
|
95
|
-
|
|
114
|
+
const data = await getDaemonJson({ baseUrl: ctx.baseUrl, route: `/api/tools/${encodeURIComponent(id)}` }, daemonCallOptions({ ctx }));
|
|
115
|
+
if (ctx.publishTool)
|
|
116
|
+
await ctx.publishTool({ descriptor: describedDescriptor({ id, data }) });
|
|
117
|
+
return data;
|
|
96
118
|
},
|
|
97
119
|
};
|
|
98
120
|
/** Both tool-catalog discovery tools, ready to pass as `createMcpToolServer`'s `tools` option. */
|
|
@@ -1,9 +1,23 @@
|
|
|
1
|
-
import type { AskChoiceCall, AskChoiceExchangeStore, AskChoiceMessages, AskChoicePendingStore, AskChoicePolicy, AskChoicePresentation } from './types.js';
|
|
1
|
+
import type { AskChoiceCall, AskChoiceExchange, AskChoiceExchangeStore, AskChoiceMessages, AskChoicePendingStore, AskChoicePolicy, AskChoicePresentation, AskChoiceQuestion } from './types.js';
|
|
2
2
|
export type * from './types.js';
|
|
3
3
|
export { ASK_CHOICE_INPUT_SCHEMA } from './schema.js';
|
|
4
4
|
export { createAskChoiceAnswerTicketStore } from './pending.js';
|
|
5
5
|
/** Existing callback wire keys; the tool's identity is supplied by the host. */
|
|
6
6
|
export declare const ASK_CHOICE_ANSWER_TICKET_PARAM = "__askChoiceAnswerTicket";
|
|
7
|
+
/** Run a trusted host question through the same abort, delivery, validation and cleanup lifecycle
|
|
8
|
+
* as the model-facing tool. The host owns presentation and action policy, never exchange mechanics.
|
|
9
|
+
* @returns Classified human answer, including an offered action when configured.
|
|
10
|
+
* @complexity O(n) offered options and selections.
|
|
11
|
+
*/
|
|
12
|
+
export declare function askChoice({ exchange, question, toolId, principalId, presentation, signal, messages }: {
|
|
13
|
+
exchange: AskChoiceExchange;
|
|
14
|
+
question: AskChoiceQuestion;
|
|
15
|
+
toolId: string;
|
|
16
|
+
principalId: string;
|
|
17
|
+
presentation: Pick<AskChoicePresentation, 'render'>;
|
|
18
|
+
signal: AbortSignal;
|
|
19
|
+
messages: AskChoiceMessages;
|
|
20
|
+
}, _options?: {}): Promise<Record<string, unknown>>;
|
|
7
21
|
/** Creates a choice tool without a CMS, renderer, permission system, clock, or global store.
|
|
8
22
|
* The host composes this descriptor/handler into its registry and mounts callbacks against the
|
|
9
23
|
* same exchange and pending stores. Policy and presentation are required, with no product defaults.
|
|
@@ -29,15 +43,50 @@ export declare function createAskChoiceTool({ toolId, description, permission, p
|
|
|
29
43
|
inputSchema: {
|
|
30
44
|
readonly type: "object";
|
|
31
45
|
readonly additionalProperties: false;
|
|
32
|
-
readonly required: readonly ["title"];
|
|
33
46
|
readonly anyOf: readonly [{
|
|
34
|
-
readonly required: readonly ["
|
|
47
|
+
readonly required: readonly ["question", "options"];
|
|
35
48
|
}, {
|
|
36
|
-
readonly required: readonly ["
|
|
49
|
+
readonly required: readonly ["title", "singleSelect"];
|
|
50
|
+
}, {
|
|
51
|
+
readonly required: readonly ["title", "multiSelect"];
|
|
37
52
|
}];
|
|
38
53
|
readonly properties: {
|
|
54
|
+
readonly question: {
|
|
55
|
+
readonly type: "string";
|
|
56
|
+
readonly minLength: 1;
|
|
57
|
+
readonly description: "The question to ask the human.";
|
|
58
|
+
};
|
|
59
|
+
readonly options: {
|
|
60
|
+
readonly type: "array";
|
|
61
|
+
readonly minItems: 1;
|
|
62
|
+
readonly items: {
|
|
63
|
+
readonly type: "object";
|
|
64
|
+
readonly additionalProperties: false;
|
|
65
|
+
readonly required: readonly ["label"];
|
|
66
|
+
readonly properties: {
|
|
67
|
+
readonly label: {
|
|
68
|
+
readonly type: "string";
|
|
69
|
+
readonly minLength: 1;
|
|
70
|
+
};
|
|
71
|
+
readonly value: {
|
|
72
|
+
readonly type: "string";
|
|
73
|
+
readonly minLength: 1;
|
|
74
|
+
readonly description: "Defaults to label when omitted.";
|
|
75
|
+
};
|
|
76
|
+
readonly description: {
|
|
77
|
+
readonly type: "string";
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
readonly multiple: {
|
|
83
|
+
readonly type: "boolean";
|
|
84
|
+
readonly description: "Allow several selections. Defaults to false.";
|
|
85
|
+
};
|
|
39
86
|
readonly title: {
|
|
40
87
|
readonly type: "string";
|
|
88
|
+
readonly minLength: 1;
|
|
89
|
+
readonly description: "Legacy alias: title with singleSelect or multiSelect.";
|
|
41
90
|
};
|
|
42
91
|
readonly description: {
|
|
43
92
|
readonly type: "string";
|
|
@@ -46,25 +95,33 @@ export declare function createAskChoiceTool({ toolId, description, permission, p
|
|
|
46
95
|
readonly type: "string";
|
|
47
96
|
};
|
|
48
97
|
readonly singleSelect: {
|
|
98
|
+
readonly description: "Legacy nested single-choice alias.";
|
|
49
99
|
readonly type: "object";
|
|
50
100
|
readonly additionalProperties: false;
|
|
51
101
|
readonly required: readonly ["label", "options"];
|
|
52
102
|
readonly properties: {
|
|
53
103
|
readonly label: {
|
|
54
104
|
readonly type: "string";
|
|
105
|
+
readonly minLength: 1;
|
|
55
106
|
};
|
|
56
107
|
readonly options: {
|
|
57
108
|
readonly type: "array";
|
|
58
109
|
readonly minItems: 1;
|
|
59
110
|
readonly items: {
|
|
111
|
+
readonly required: readonly ["value", "label"];
|
|
60
112
|
readonly type: "object";
|
|
61
113
|
readonly additionalProperties: false;
|
|
62
|
-
readonly required: readonly ["value", "label"];
|
|
63
114
|
readonly properties: {
|
|
115
|
+
readonly label: {
|
|
116
|
+
readonly type: "string";
|
|
117
|
+
readonly minLength: 1;
|
|
118
|
+
};
|
|
64
119
|
readonly value: {
|
|
65
120
|
readonly type: "string";
|
|
121
|
+
readonly minLength: 1;
|
|
122
|
+
readonly description: "Defaults to label when omitted.";
|
|
66
123
|
};
|
|
67
|
-
readonly
|
|
124
|
+
readonly description: {
|
|
68
125
|
readonly type: "string";
|
|
69
126
|
};
|
|
70
127
|
};
|
|
@@ -73,25 +130,33 @@ export declare function createAskChoiceTool({ toolId, description, permission, p
|
|
|
73
130
|
};
|
|
74
131
|
};
|
|
75
132
|
readonly multiSelect: {
|
|
133
|
+
readonly description: "Legacy nested multiple-choice alias.";
|
|
76
134
|
readonly properties: {
|
|
77
135
|
readonly hint: {
|
|
78
136
|
readonly type: "string";
|
|
79
137
|
};
|
|
80
138
|
readonly label: {
|
|
81
139
|
readonly type: "string";
|
|
140
|
+
readonly minLength: 1;
|
|
82
141
|
};
|
|
83
142
|
readonly options: {
|
|
84
143
|
readonly type: "array";
|
|
85
144
|
readonly minItems: 1;
|
|
86
145
|
readonly items: {
|
|
146
|
+
readonly required: readonly ["value", "label"];
|
|
87
147
|
readonly type: "object";
|
|
88
148
|
readonly additionalProperties: false;
|
|
89
|
-
readonly required: readonly ["value", "label"];
|
|
90
149
|
readonly properties: {
|
|
150
|
+
readonly label: {
|
|
151
|
+
readonly type: "string";
|
|
152
|
+
readonly minLength: 1;
|
|
153
|
+
};
|
|
91
154
|
readonly value: {
|
|
92
155
|
readonly type: "string";
|
|
156
|
+
readonly minLength: 1;
|
|
157
|
+
readonly description: "Defaults to label when omitted.";
|
|
93
158
|
};
|
|
94
|
-
readonly
|
|
159
|
+
readonly description: {
|
|
95
160
|
readonly type: "string";
|
|
96
161
|
};
|
|
97
162
|
};
|
|
@@ -102,19 +167,153 @@ export declare function createAskChoiceTool({ toolId, description, permission, p
|
|
|
102
167
|
readonly additionalProperties: false;
|
|
103
168
|
readonly required: readonly ["label", "options"];
|
|
104
169
|
};
|
|
105
|
-
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
invocationSchema: {
|
|
174
|
+
readonly anyOf: readonly [{
|
|
175
|
+
readonly required: readonly ["question", "options"];
|
|
176
|
+
}, {
|
|
177
|
+
readonly required: readonly ["title", "singleSelect"];
|
|
178
|
+
}, {
|
|
179
|
+
readonly required: readonly ["title", "multiSelect"];
|
|
180
|
+
}, {
|
|
181
|
+
readonly required: readonly ["choice", "__askChoiceAnswerTicket"];
|
|
182
|
+
}, {
|
|
183
|
+
readonly required: readonly ["selections", "__askChoiceAnswerTicket"];
|
|
184
|
+
}];
|
|
185
|
+
readonly properties: {
|
|
186
|
+
readonly choice: {
|
|
187
|
+
readonly type: "string";
|
|
188
|
+
};
|
|
189
|
+
readonly selections: {
|
|
190
|
+
readonly type: "array";
|
|
191
|
+
readonly items: {
|
|
106
192
|
readonly type: "string";
|
|
107
|
-
readonly description: "Set by the rendered form; never by the model.";
|
|
108
193
|
};
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
194
|
+
};
|
|
195
|
+
readonly __askChoiceAnswerTicket: {
|
|
196
|
+
readonly type: "string";
|
|
197
|
+
};
|
|
198
|
+
readonly question: {
|
|
199
|
+
readonly type: "string";
|
|
200
|
+
readonly minLength: 1;
|
|
201
|
+
readonly description: "The question to ask the human.";
|
|
202
|
+
};
|
|
203
|
+
readonly options: {
|
|
204
|
+
readonly type: "array";
|
|
205
|
+
readonly minItems: 1;
|
|
206
|
+
readonly items: {
|
|
207
|
+
readonly type: "object";
|
|
208
|
+
readonly additionalProperties: false;
|
|
209
|
+
readonly required: readonly ["label"];
|
|
210
|
+
readonly properties: {
|
|
211
|
+
readonly label: {
|
|
212
|
+
readonly type: "string";
|
|
213
|
+
readonly minLength: 1;
|
|
214
|
+
};
|
|
215
|
+
readonly value: {
|
|
216
|
+
readonly type: "string";
|
|
217
|
+
readonly minLength: 1;
|
|
218
|
+
readonly description: "Defaults to label when omitted.";
|
|
219
|
+
};
|
|
220
|
+
readonly description: {
|
|
221
|
+
readonly type: "string";
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
};
|
|
225
|
+
};
|
|
226
|
+
readonly multiple: {
|
|
227
|
+
readonly type: "boolean";
|
|
228
|
+
readonly description: "Allow several selections. Defaults to false.";
|
|
229
|
+
};
|
|
230
|
+
readonly title: {
|
|
231
|
+
readonly type: "string";
|
|
232
|
+
readonly minLength: 1;
|
|
233
|
+
readonly description: "Legacy alias: title with singleSelect or multiSelect.";
|
|
234
|
+
};
|
|
235
|
+
readonly description: {
|
|
236
|
+
readonly type: "string";
|
|
237
|
+
};
|
|
238
|
+
readonly submitLabel: {
|
|
239
|
+
readonly type: "string";
|
|
240
|
+
};
|
|
241
|
+
readonly singleSelect: {
|
|
242
|
+
readonly description: "Legacy nested single-choice alias.";
|
|
243
|
+
readonly type: "object";
|
|
244
|
+
readonly additionalProperties: false;
|
|
245
|
+
readonly required: readonly ["label", "options"];
|
|
246
|
+
readonly properties: {
|
|
247
|
+
readonly label: {
|
|
112
248
|
readonly type: "string";
|
|
249
|
+
readonly minLength: 1;
|
|
250
|
+
};
|
|
251
|
+
readonly options: {
|
|
252
|
+
readonly type: "array";
|
|
253
|
+
readonly minItems: 1;
|
|
254
|
+
readonly items: {
|
|
255
|
+
readonly required: readonly ["value", "label"];
|
|
256
|
+
readonly type: "object";
|
|
257
|
+
readonly additionalProperties: false;
|
|
258
|
+
readonly properties: {
|
|
259
|
+
readonly label: {
|
|
260
|
+
readonly type: "string";
|
|
261
|
+
readonly minLength: 1;
|
|
262
|
+
};
|
|
263
|
+
readonly value: {
|
|
264
|
+
readonly type: "string";
|
|
265
|
+
readonly minLength: 1;
|
|
266
|
+
readonly description: "Defaults to label when omitted.";
|
|
267
|
+
};
|
|
268
|
+
readonly description: {
|
|
269
|
+
readonly type: "string";
|
|
270
|
+
};
|
|
271
|
+
};
|
|
272
|
+
};
|
|
273
|
+
};
|
|
274
|
+
};
|
|
275
|
+
};
|
|
276
|
+
readonly multiSelect: {
|
|
277
|
+
readonly description: "Legacy nested multiple-choice alias.";
|
|
278
|
+
readonly properties: {
|
|
279
|
+
readonly hint: {
|
|
280
|
+
readonly type: "string";
|
|
281
|
+
};
|
|
282
|
+
readonly label: {
|
|
283
|
+
readonly type: "string";
|
|
284
|
+
readonly minLength: 1;
|
|
285
|
+
};
|
|
286
|
+
readonly options: {
|
|
287
|
+
readonly type: "array";
|
|
288
|
+
readonly minItems: 1;
|
|
289
|
+
readonly items: {
|
|
290
|
+
readonly required: readonly ["value", "label"];
|
|
291
|
+
readonly type: "object";
|
|
292
|
+
readonly additionalProperties: false;
|
|
293
|
+
readonly properties: {
|
|
294
|
+
readonly label: {
|
|
295
|
+
readonly type: "string";
|
|
296
|
+
readonly minLength: 1;
|
|
297
|
+
};
|
|
298
|
+
readonly value: {
|
|
299
|
+
readonly type: "string";
|
|
300
|
+
readonly minLength: 1;
|
|
301
|
+
readonly description: "Defaults to label when omitted.";
|
|
302
|
+
};
|
|
303
|
+
readonly description: {
|
|
304
|
+
readonly type: "string";
|
|
305
|
+
};
|
|
306
|
+
};
|
|
307
|
+
};
|
|
113
308
|
};
|
|
114
|
-
readonly description: "Set by the rendered form; never by the model.";
|
|
115
309
|
};
|
|
310
|
+
readonly type: "object";
|
|
311
|
+
readonly additionalProperties: false;
|
|
312
|
+
readonly required: readonly ["label", "options"];
|
|
116
313
|
};
|
|
117
314
|
};
|
|
315
|
+
readonly type: "object";
|
|
316
|
+
readonly additionalProperties: false;
|
|
118
317
|
};
|
|
119
318
|
handler({ ctx }: {
|
|
120
319
|
ctx: AskChoiceCall;
|