@bevel-software/platform-mcp-core 0.22.0 → 0.24.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/chain-example.d.ts +58 -0
- package/dist/chain-example.d.ts.map +1 -0
- package/dist/chain-example.js +259 -0
- package/dist/chain-example.js.map +1 -0
- package/dist/chain-runtime.d.ts +122 -0
- package/dist/chain-runtime.d.ts.map +1 -0
- package/dist/chain-runtime.js +352 -0
- package/dist/chain-runtime.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/meta-tools.d.ts +100 -1
- package/dist/meta-tools.d.ts.map +1 -1
- package/dist/meta-tools.js +181 -53
- package/dist/meta-tools.js.map +1 -1
- package/dist/results.d.ts +20 -0
- package/dist/results.d.ts.map +1 -1
- package/dist/results.js +111 -1
- package/dist/results.js.map +1 -1
- package/dist/retired-tools.d.ts +0 -12
- package/dist/retired-tools.d.ts.map +1 -1
- package/dist/retired-tools.js +0 -22
- package/dist/retired-tools.js.map +1 -1
- package/package.json +1 -1
- package/src/chain-example.ts +315 -0
- package/src/chain-runtime.ts +382 -0
- package/src/index.ts +29 -2
- package/src/meta-tools.ts +212 -58
- package/src/results.ts +106 -1
- package/src/retired-tools.ts +0 -22
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { utcpNameToTsInterfaceName } from './code-mode-names.js';
|
|
2
|
+
import { describeToolFailure } from './results.js';
|
|
3
|
+
/**
|
|
4
|
+
* What runs a `call_tool_chain` chain, for every surface that offers one: the
|
|
5
|
+
* hosted MCP proxy, the local `hexis-mcp` server and the in-process agent's
|
|
6
|
+
* Mastra tool.
|
|
7
|
+
*
|
|
8
|
+
* Three things live here because all three surfaces need them to be the same:
|
|
9
|
+
*
|
|
10
|
+
* - the BROWSER GLOBALS a chain is promised (`atob`, `btoa`, `TextEncoder`,
|
|
11
|
+
* `TextDecoder`). `@utcp/code-mode` runs the chain in a bare `isolated-vm`
|
|
12
|
+
* isolate — plain V8, so no Node globals (`Buffer`) and no web platform
|
|
13
|
+
* (`atob`), and a chain could not decode base64 or bytes at all. They are
|
|
14
|
+
* added as a PRELUDE to the chain's own source rather than injected into
|
|
15
|
+
* the isolate's context, because the isolate is created inside
|
|
16
|
+
* `callToolChain` and is reachable from nowhere else (see
|
|
17
|
+
* {@link CHAIN_RUNTIME_PRELUDE});
|
|
18
|
+
* - the ANSWER for a chain that failed. `callToolChain` does not throw when
|
|
19
|
+
* the chain dies: it resolves `{ result: null, logs: ['[ERROR] Code
|
|
20
|
+
* execution failed: …'] }`, so a surface that read only `result` reported
|
|
21
|
+
* `success: true` with a null result and the agent was told nothing. Every
|
|
22
|
+
* failure — a timeout, an undefined namespace, a tool that threw — becomes
|
|
23
|
+
* an error that says what happened;
|
|
24
|
+
* - the promise that a chain ALWAYS answers. A request that never settles is
|
|
25
|
+
* what reaches an agent as a dropped connection rather than as something it
|
|
26
|
+
* can act on, so the runner is raced against a watchdog (see
|
|
27
|
+
* {@link WATCHDOG_GRACE_MS}).
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* The largest `timeout` a chain may ask for, in milliseconds. One constant: it
|
|
31
|
+
* is the schema's bound on every surface AND the figure the timeout error tells
|
|
32
|
+
* the agent it may raise `timeout` to, and those two drifting apart would send
|
|
33
|
+
* an agent to retry with a value the schema then clamps straight back down.
|
|
34
|
+
*/
|
|
35
|
+
export const CHAIN_TIMEOUT_MAX_MS = 120_000;
|
|
36
|
+
/** The smallest `timeout` a chain may ask for, in milliseconds. */
|
|
37
|
+
export const CHAIN_TIMEOUT_MIN_MS = 1_000;
|
|
38
|
+
/** The `timeout` a chain that does not ask for one gets, in milliseconds. */
|
|
39
|
+
export const CHAIN_TIMEOUT_DEFAULT_MS = 30_000;
|
|
40
|
+
/**
|
|
41
|
+
* How long past its own `timeout` the runner is given to answer before the
|
|
42
|
+
* watchdog answers for it. `callToolChain` enforces the timeout itself and so
|
|
43
|
+
* normally settles well inside this; the watchdog covers the case where it does
|
|
44
|
+
* not, where the alternative is a request that hangs until the client gives up
|
|
45
|
+
* — the dropped connection an agent cannot tell from a crash.
|
|
46
|
+
*/
|
|
47
|
+
const WATCHDOG_GRACE_MS = 5_000;
|
|
48
|
+
/** The log line `@utcp/code-mode` records when a chain's code fails. */
|
|
49
|
+
const CHAIN_FAILURE_LOG = '[ERROR] Code execution failed: ';
|
|
50
|
+
/** The runner's own wording for a chain it stopped at the timeout. */
|
|
51
|
+
const RUNNER_TIMEOUT = /Script execution timeout after (\d+)\s*ms/;
|
|
52
|
+
/** `isolated-vm`'s wording when V8 itself terminated the script at the deadline. */
|
|
53
|
+
const ISOLATE_TERMINATED = /Script execution timed out|execution was terminated|script execution interrupted/i;
|
|
54
|
+
/** `isolated-vm`'s wording when the chain exhausted the isolate's heap. */
|
|
55
|
+
const ISOLATE_OUT_OF_MEMORY = /memory limit|out of memory|allocation failed/i;
|
|
56
|
+
/** The identifier a chain named that the isolate has no binding for. */
|
|
57
|
+
const UNDEFINED_IDENTIFIER = /ReferenceError: ([A-Za-z_$][\w$]*) is not defined/;
|
|
58
|
+
/**
|
|
59
|
+
* The browser globals, as ONE physical line of plain ES5 JavaScript.
|
|
60
|
+
*
|
|
61
|
+
* One line on purpose. The prelude is prepended to the agent's own chain
|
|
62
|
+
* source, and a failed chain is reported with its stack in it; a multi-line
|
|
63
|
+
* prelude would shift every line number in that stack and point the agent at
|
|
64
|
+
* the wrong line of its own code. Prepended WITHOUT a trailing newline for the
|
|
65
|
+
* same reason, so the chain's first line stays line one. (The one casualty is
|
|
66
|
+
* a `'use strict'` directive written as a chain's first statement, which is no
|
|
67
|
+
* longer in first position and so no longer applies. A chain is a handful of
|
|
68
|
+
* statements against a tool catalog, and strict mode is not something the
|
|
69
|
+
* chain protocol ever offered.)
|
|
70
|
+
*
|
|
71
|
+
* `atob`/`btoa` follow WHATWG forgiving-base64: ASCII whitespace is stripped,
|
|
72
|
+
* the padding is optional, and anything else throws rather than decoding to
|
|
73
|
+
* silent garbage. `TextEncoder`/`TextDecoder` are UTF-8 only — that is the
|
|
74
|
+
* encoding the Specification asks for, and a decoder that took a `label` it
|
|
75
|
+
* then ignored would quietly answer mojibake. `TextDecoder` drops a leading
|
|
76
|
+
* byte-order mark the way a browser's default does, and keeps it under
|
|
77
|
+
* `{ ignoreBOM: true }`: a chain decoding a UTF-8 file written on Windows would
|
|
78
|
+
* otherwise find a stray `\uFEFF` at the front of it, which breaks a
|
|
79
|
+
* `JSON.parse` and every exact-match comparison. It honours `{ stream: true }`:
|
|
80
|
+
* a chain that decodes bytes in pieces gets a character whose bytes straddle
|
|
81
|
+
* two pieces whole, where a decoder that started afresh on every call returned
|
|
82
|
+
* two replacement characters for it — and a call without the option ends the
|
|
83
|
+
* stream, answering a sequence left unfinished as one. Each is defined only when the
|
|
84
|
+
* runtime does not already have it, so a future `@utcp/code-mode` that ships
|
|
85
|
+
* them natively wins.
|
|
86
|
+
*/
|
|
87
|
+
export const CHAIN_RUNTIME_PRELUDE = [
|
|
88
|
+
'(function(g){',
|
|
89
|
+
"var A='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';",
|
|
90
|
+
'if(typeof g.btoa!=="function"){g.btoa=function(input){',
|
|
91
|
+
'var s=String(input),i,o="";',
|
|
92
|
+
'for(i=0;i<s.length;i++){if(s.charCodeAt(i)>255)throw new Error("InvalidCharacterError: btoa() takes a string whose every character is in the Latin-1 range (0-255). To base64 text, encode it to UTF-8 bytes with TextEncoder first.");}',
|
|
93
|
+
'for(i=0;i<s.length;i+=3){',
|
|
94
|
+
'var b0=s.charCodeAt(i),b1=s.charCodeAt(i+1),b2=s.charCodeAt(i+2),h1=!isNaN(b1),h2=!isNaN(b2);',
|
|
95
|
+
'o+=A.charAt(b0>>2)+A.charAt(((b0&3)<<4)|(h1?b1>>4:0));',
|
|
96
|
+
'o+=(h1?A.charAt(((b1&15)<<2)|(h2?b2>>6:0)):"=")+(h2?A.charAt(b2&63):"=");',
|
|
97
|
+
'}return o;};}',
|
|
98
|
+
'if(typeof g.atob!=="function"){g.atob=function(input){',
|
|
99
|
+
'var s=String(input).replace(/[\\t\\n\\f\\r ]/g,"");',
|
|
100
|
+
'if(s.length%4===0)s=s.replace(/==?$/,"");',
|
|
101
|
+
'if(s.length%4===1||/[^+\\/0-9A-Za-z]/.test(s))throw new Error("InvalidCharacterError: atob() was given a string that is not valid base64.");',
|
|
102
|
+
'var o="",buf=0,bits=0,i;',
|
|
103
|
+
'for(i=0;i<s.length;i++){buf=(buf<<6)|A.indexOf(s.charAt(i));bits+=6;',
|
|
104
|
+
'if(bits>=8){bits-=8;o+=String.fromCharCode((buf>>bits)&255);}}',
|
|
105
|
+
'return o;};}',
|
|
106
|
+
'if(typeof g.TextEncoder!=="function"){',
|
|
107
|
+
'var TE=function TextEncoder(){};',
|
|
108
|
+
'TE.prototype.encoding="utf-8";',
|
|
109
|
+
'TE.prototype.encode=function(input){',
|
|
110
|
+
'var s=String(input===undefined?"":input),out=[],i=0;',
|
|
111
|
+
'while(i<s.length){var c=s.codePointAt(i);i+=c>65535?2:1;',
|
|
112
|
+
'if(c<128)out.push(c);',
|
|
113
|
+
'else if(c<2048)out.push(192|(c>>6),128|(c&63));',
|
|
114
|
+
'else if(c>=55296&&c<=57343)out.push(239,191,189);',
|
|
115
|
+
'else if(c<65536)out.push(224|(c>>12),128|((c>>6)&63),128|(c&63));',
|
|
116
|
+
'else out.push(240|(c>>18),128|((c>>12)&63),128|((c>>6)&63),128|(c&63));}',
|
|
117
|
+
'return new Uint8Array(out);};',
|
|
118
|
+
'g.TextEncoder=TE;}',
|
|
119
|
+
'if(typeof g.TextDecoder!=="function"){',
|
|
120
|
+
'var TD=function TextDecoder(label,options){',
|
|
121
|
+
'var e=String(label===undefined?"utf-8":label).toLowerCase();',
|
|
122
|
+
'if(e!=="utf-8"&&e!=="utf8"&&e!=="unicode-1-1-utf-8")throw new RangeError("TextDecoder(): the tool-chain runtime decodes UTF-8 only, not \\""+label+"\\".");',
|
|
123
|
+
'this.ignoreBOM=!!(options&&options.ignoreBOM);};',
|
|
124
|
+
'TD.prototype.encoding="utf-8";',
|
|
125
|
+
'TD.prototype.ignoreBOM=false;',
|
|
126
|
+
// `p` is what one call leaves for the next under `{ stream: true }`: the
|
|
127
|
+
// sequence in progress (need, seen, c and the bounds on its next byte) and
|
|
128
|
+
// whether the stream has produced its first character yet, which is the
|
|
129
|
+
// only place a byte-order mark is one.
|
|
130
|
+
'TD.prototype.decode=function(input,options){',
|
|
131
|
+
'var st=!!(options&&options.stream),ig=this.ignoreBOM,p=this._p||[0,0,0,128,191,0];',
|
|
132
|
+
'var b=(input===undefined||input===null)?new Uint8Array(0):(input instanceof Uint8Array?input:(input instanceof ArrayBuffer?new Uint8Array(input):(input&&input.buffer instanceof ArrayBuffer?new Uint8Array(input.buffer,input.byteOffset,input.byteLength):new Uint8Array(input))));',
|
|
133
|
+
'var o="",n=b.length,need=p[0],seen=p[1],c=p[2],lo=p[3],hi=p[4],bom=p[5],i=0,x,t;',
|
|
134
|
+
'while(i<n){x=b[i];',
|
|
135
|
+
'if(need===0){i++;',
|
|
136
|
+
'if(x<128){bom=1;o+=String.fromCharCode(x);}',
|
|
137
|
+
'else if(x>=194&&x<=223){need=1;c=x&31;}',
|
|
138
|
+
'else if(x>=224&&x<=239){if(x===224)lo=160;if(x===237)hi=159;need=2;c=x&15;}',
|
|
139
|
+
'else if(x>=240&&x<=244){if(x===240)lo=144;if(x===244)hi=143;need=3;c=x&7;}',
|
|
140
|
+
'else{bom=1;o+="\\uFFFD";}',
|
|
141
|
+
'continue;}',
|
|
142
|
+
'if(x<lo||x>hi){need=0;seen=0;c=0;lo=128;hi=191;bom=1;o+="\\uFFFD";continue;}',
|
|
143
|
+
'lo=128;hi=191;i++;c=(c<<6)|(x&63);seen++;',
|
|
144
|
+
'if(seen===need){',
|
|
145
|
+
'if(c===65279&&!bom&&!ig){}',
|
|
146
|
+
'else if(c<=65535)o+=String.fromCharCode(c);',
|
|
147
|
+
'else{t=c-65536;o+=String.fromCharCode(55296+(t>>10),56320+(t&1023));}',
|
|
148
|
+
'bom=1;need=0;seen=0;c=0;}}',
|
|
149
|
+
'if(st){this._p=[need,seen,c,lo,hi,bom];return o;}',
|
|
150
|
+
'if(need!==0)o+="\\uFFFD";',
|
|
151
|
+
'this._p=null;',
|
|
152
|
+
'return o;};',
|
|
153
|
+
'g.TextDecoder=TD;}',
|
|
154
|
+
'})(globalThis);',
|
|
155
|
+
].join('');
|
|
156
|
+
/**
|
|
157
|
+
* The agent's chain source with the runtime prelude in front of it, on the same
|
|
158
|
+
* physical line, so a stack from the chain still names the chain's own line
|
|
159
|
+
* numbers (see {@link CHAIN_RUNTIME_PRELUDE}).
|
|
160
|
+
*/
|
|
161
|
+
export function withChainRuntime(code) {
|
|
162
|
+
return `${CHAIN_RUNTIME_PRELUDE}${code}`;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* What a chain can actually call. `@utcp/code-mode` gives every tool whose UTCP
|
|
166
|
+
* name is `MANUAL.tool` a `global.MANUAL` object, so the namespaces are the
|
|
167
|
+
* sanitized manual names — and a tool registered under a bare name becomes a
|
|
168
|
+
* global function rather than a namespace, which is why those are listed apart.
|
|
169
|
+
*/
|
|
170
|
+
export async function chainNamespaces(client) {
|
|
171
|
+
const namespaces = new Set();
|
|
172
|
+
const bare = new Set();
|
|
173
|
+
for (const tool of await client.config.tool_repository.getTools()) {
|
|
174
|
+
const tsName = utcpNameToTsInterfaceName(tool.name);
|
|
175
|
+
const dot = tsName.indexOf('.');
|
|
176
|
+
if (dot > 0)
|
|
177
|
+
namespaces.add(tsName.slice(0, dot));
|
|
178
|
+
else
|
|
179
|
+
bare.add(tsName);
|
|
180
|
+
}
|
|
181
|
+
return { namespaces: [...namespaces].sort(), bare: [...bare].sort() };
|
|
182
|
+
}
|
|
183
|
+
/** What a chain is told when it timed out: the limit it hit, and how to raise it. */
|
|
184
|
+
export function chainTimeoutMessage(timeoutMs) {
|
|
185
|
+
return (`The tool chain timed out after ${timeoutMs} ms and was stopped, so it has no result. ` +
|
|
186
|
+
`Raise \`timeout\` (milliseconds, up to a maximum of ${CHAIN_TIMEOUT_MAX_MS}) and run it again, ` +
|
|
187
|
+
'or split the work across several shorter chains. The connection is unaffected — your next tool call works as usual.');
|
|
188
|
+
}
|
|
189
|
+
/** What a chain is told when it exhausted the isolate's heap. */
|
|
190
|
+
export function chainOutOfMemoryMessage(reason) {
|
|
191
|
+
return (`The tool chain ran out of memory and was stopped, so it has no result (${reason}). ` +
|
|
192
|
+
'Return less from the chain — filter, map or count inside it instead of accumulating every record — ' +
|
|
193
|
+
'or split the work across several chains. The connection is unaffected — your next tool call works as usual.');
|
|
194
|
+
}
|
|
195
|
+
/** What a chain is told when it named something the runtime has no binding for. */
|
|
196
|
+
export function unknownNamespaceMessage(identifier, found) {
|
|
197
|
+
const { namespaces, bare } = found;
|
|
198
|
+
const existing = namespaces.length
|
|
199
|
+
? `The tool namespaces this connection exposes are: ${namespaces.join(', ')}.`
|
|
200
|
+
: 'This connection exposes no tool namespaces at all.';
|
|
201
|
+
const example = namespaces[0] ? ` Call a tool as \`${namespaces[0]}.<tool>({ body: { … } })\`.` : '';
|
|
202
|
+
const bareNote = bare.length ? ` Callable without a namespace: ${bare.join(', ')}.` : '';
|
|
203
|
+
return (`ReferenceError: ${identifier} is not defined — "${identifier}" is not one of them. ` +
|
|
204
|
+
`${existing}${example}${bareNote} Use \`list_tools\` for the exact callable names.`);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Why a RESOLVED `callToolChain` is a failure, or undefined when it is not one.
|
|
208
|
+
*
|
|
209
|
+
* `callToolChain` resolves rather than throws on a dead chain, reporting it as
|
|
210
|
+
* a `[ERROR] Code execution failed: …` log line with a null result. Both halves
|
|
211
|
+
* are required: a chain that returned a value succeeded however it logged.
|
|
212
|
+
*
|
|
213
|
+
* The LAST such line, not the last line: the runner appends its own entry in a
|
|
214
|
+
* `catch` and then, in the `finally`, a `[WARN] Tool call "…" abandoned` line
|
|
215
|
+
* per tool call still in flight — so a chain that timed out mid-call has the
|
|
216
|
+
* reason second-from-last or further back. A chain that prints that exact
|
|
217
|
+
* prefix itself through `console.error` AND returns null is read as a failure;
|
|
218
|
+
* that trade is deliberate, since the alternative — a dead chain reported as a
|
|
219
|
+
* success with a null result — is the bug this replaces.
|
|
220
|
+
*/
|
|
221
|
+
function failureReason(outcome) {
|
|
222
|
+
if (outcome.result !== null && outcome.result !== undefined)
|
|
223
|
+
return undefined;
|
|
224
|
+
for (let i = outcome.logs.length - 1; i >= 0; i -= 1) {
|
|
225
|
+
const line = outcome.logs[i];
|
|
226
|
+
if (typeof line === 'string' && line.startsWith(CHAIN_FAILURE_LOG)) {
|
|
227
|
+
return line.slice(CHAIN_FAILURE_LOG.length);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Turn the runner's reason into the sentence the agent reads. A timeout, an
|
|
234
|
+
* exhausted heap and an undefined namespace each get their own; anything else
|
|
235
|
+
* passes through exactly as the runner reported it, so a real cause is never
|
|
236
|
+
* replaced by a guess.
|
|
237
|
+
*/
|
|
238
|
+
export async function describeChainFailure(client, reason, timeoutMs) {
|
|
239
|
+
// Memory before termination: an isolate killed for its heap reports being
|
|
240
|
+
// disposed too, and calling that a timeout would send the agent to raise a
|
|
241
|
+
// limit that was never the problem.
|
|
242
|
+
if (ISOLATE_OUT_OF_MEMORY.test(reason))
|
|
243
|
+
return chainOutOfMemoryMessage(reason);
|
|
244
|
+
const runnerTimeout = RUNNER_TIMEOUT.exec(reason);
|
|
245
|
+
if (runnerTimeout)
|
|
246
|
+
return chainTimeoutMessage(Number(runnerTimeout[1]));
|
|
247
|
+
if (ISOLATE_TERMINATED.test(reason))
|
|
248
|
+
return chainTimeoutMessage(timeoutMs);
|
|
249
|
+
const undefinedIdentifier = UNDEFINED_IDENTIFIER.exec(reason);
|
|
250
|
+
if (undefinedIdentifier) {
|
|
251
|
+
// The namespace list costs one catalog read, so it is fetched only on the
|
|
252
|
+
// failure that needs it. A catalog that cannot be read must not replace the
|
|
253
|
+
// chain's own reason with an unrelated one: the agent keeps the
|
|
254
|
+
// ReferenceError, just without the list.
|
|
255
|
+
try {
|
|
256
|
+
return unknownNamespaceMessage(undefinedIdentifier[1], await chainNamespaces(client));
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
return reason;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return reason;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Run a chain and ALWAYS answer: with its value, or with the reason it has
|
|
266
|
+
* none. Never throws, and never leaves a caller waiting past the chain's own
|
|
267
|
+
* timeout plus {@link WATCHDOG_GRACE_MS}.
|
|
268
|
+
*
|
|
269
|
+
* What the caller does with an error is still the caller's (the hosted proxy
|
|
270
|
+
* maps a retired tool's name onto its own message first, for instance); this
|
|
271
|
+
* decides only whether there IS one and what it says about the runtime.
|
|
272
|
+
*/
|
|
273
|
+
export async function runToolChain(client, code, timeoutMs) {
|
|
274
|
+
let watchdog;
|
|
275
|
+
try {
|
|
276
|
+
const watchdogFired = new Promise((resolve) => {
|
|
277
|
+
watchdog = setTimeout(() => resolve('watchdog'), timeoutMs + WATCHDOG_GRACE_MS);
|
|
278
|
+
// A watchdog nobody is waiting on must not hold a CLI's exit open.
|
|
279
|
+
watchdog.unref?.();
|
|
280
|
+
});
|
|
281
|
+
const settled = await Promise.race([
|
|
282
|
+
client.callToolChain(withChainRuntime(code), timeoutMs).then((outcome) => ({ outcome })),
|
|
283
|
+
watchdogFired,
|
|
284
|
+
]);
|
|
285
|
+
if (settled === 'watchdog')
|
|
286
|
+
return { ok: false, error: chainTimeoutMessage(timeoutMs), logs: [] };
|
|
287
|
+
const logs = Array.isArray(settled.outcome.logs) ? settled.outcome.logs : [];
|
|
288
|
+
const reason = failureReason({ result: settled.outcome.result, logs });
|
|
289
|
+
if (reason !== undefined) {
|
|
290
|
+
return { ok: false, error: await describeChainFailure(client, reason, timeoutMs), logs };
|
|
291
|
+
}
|
|
292
|
+
return { ok: true, result: settled.outcome.result, logs };
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
// Everything the runner throws BEFORE the chain starts (a catalog read, a
|
|
296
|
+
// registry outage) and anything a tool bridge rethrows. The http transport
|
|
297
|
+
// carries a status and a body on a tool failure, and both are worth more to
|
|
298
|
+
// the agent than the message on its own.
|
|
299
|
+
//
|
|
300
|
+
// `describeToolFailure` is what reads the PROVIDER's own reason out of such
|
|
301
|
+
// a failure — `response.data.error`, with the machine-readable `kind` kept
|
|
302
|
+
// beside it on a typed refusal. The MCP dispatcher used to call it on the
|
|
303
|
+
// thrown error itself; now that the catch lives here, taking `err.message`
|
|
304
|
+
// instead would hand the agent a generic transport line and drop the half
|
|
305
|
+
// it can act on.
|
|
306
|
+
//
|
|
307
|
+
// Under a guard even so. `describeToolFailure` is total — it reads `err`
|
|
308
|
+
// through try/catch — but THIS function's contract is that it never throws,
|
|
309
|
+
// and that contract is what the "no chain failure reaches the agent as a
|
|
310
|
+
// dropped connection" criterion rests on. A guard here keeps it local
|
|
311
|
+
// rather than resting on another module staying total.
|
|
312
|
+
let error;
|
|
313
|
+
try {
|
|
314
|
+
error = describeToolFailure(err);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
// Describing it is the first thing that can fail, so the fallback is
|
|
318
|
+
// itself layered: the thrown value's own message if it can be read, and
|
|
319
|
+
// a fixed sentence if even that throws. An opaque answer is still an
|
|
320
|
+
// ANSWER — what must never happen is a rejection out of this catch.
|
|
321
|
+
try {
|
|
322
|
+
error = err instanceof Error ? err.message : String(err);
|
|
323
|
+
}
|
|
324
|
+
catch {
|
|
325
|
+
error = '(indescribable tool failure)';
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
let status;
|
|
329
|
+
let data;
|
|
330
|
+
try {
|
|
331
|
+
const e = err;
|
|
332
|
+
status = e?.status ?? e?.response?.status;
|
|
333
|
+
data = e?.data ?? e?.response?.data;
|
|
334
|
+
}
|
|
335
|
+
catch {
|
|
336
|
+
// A throwing getter or Proxy says nothing about the failure; the message
|
|
337
|
+
// above already stands on its own.
|
|
338
|
+
}
|
|
339
|
+
return {
|
|
340
|
+
ok: false,
|
|
341
|
+
error,
|
|
342
|
+
logs: [],
|
|
343
|
+
...(typeof status === 'number' ? { status } : {}),
|
|
344
|
+
...(data !== undefined ? { data } : {}),
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
finally {
|
|
348
|
+
if (watchdog)
|
|
349
|
+
clearTimeout(watchdog);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
//# sourceMappingURL=chain-runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-runtime.js","sourceRoot":"","sources":["../src/chain-runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -26,10 +26,12 @@
|
|
|
26
26
|
* thing as session recovery, and stays each surface's own.
|
|
27
27
|
*/
|
|
28
28
|
export { type ProxiedTool, toListedTool, sanitizeInputSchema, flattenManualTool, flattenDiscoveredTool, } from './proxied-tool.js';
|
|
29
|
-
export { describeToolFailure, toCallToolResult, renderProgress, toolError, needsAuthorizationResult, MCP_IMAGE_RESULT_KIND, type McpImageResult, mcpImageResult, isMcpImageResult, omitImagePayloads, } from './results.js';
|
|
30
|
-
export {
|
|
29
|
+
export { describeToolFailure, withTransportDetail, toCallToolResult, renderProgress, toolError, needsAuthorizationResult, MCP_IMAGE_RESULT_KIND, type McpImageResult, mcpImageResult, isMcpImageResult, omitImagePayloads, } from './results.js';
|
|
30
|
+
export { codeModeMetaTools, chainNamespaceExample, META_TOOL_NAMES, CALL_TOOL_CHAIN_MAX_OUTPUT, CALL_TOOL_CHAIN_NAME, CHAIN_FAILURES_RULE, CHAIN_LARGE_RESULTS_RULE, type CodeModeMetaToolsOptions, type SpillPort, dispatchMetaTool, } from './meta-tools.js';
|
|
31
|
+
export { CHAIN_RUNTIME_PRELUDE, CHAIN_TIMEOUT_DEFAULT_MS, CHAIN_TIMEOUT_MAX_MS, CHAIN_TIMEOUT_MIN_MS, type ChainNamespaces, type ToolChainOutcome, chainNamespaces, chainOutOfMemoryMessage, chainTimeoutMessage, describeChainFailure, runToolChain, unknownNamespaceMessage, withChainRuntime, } from './chain-runtime.js';
|
|
32
|
+
export { type ChainExample, type ChainExampleTool, chainExample, } from './chain-example.js';
|
|
31
33
|
export { registerManual, dispatchToolCall } from './dispatch.js';
|
|
32
|
-
export { RETIRED_TOOL_MESSAGES, RETIRED_TOOL_NAMES, retiredToolMessage, retiredToolInFailure,
|
|
34
|
+
export { RETIRED_TOOL_MESSAGES, RETIRED_TOOL_NAMES, retiredToolMessage, retiredToolInFailure, } from './retired-tools.js';
|
|
33
35
|
export { isSessionLoss, installSessionRecovery, noteManualReregistered, type SessionRecoveryOptions, } from './session-recovery.js';
|
|
34
36
|
export { type SkillSummary, type LoadedSkill, skillPromptText, } from './skills.js';
|
|
35
37
|
export { utcpNamespacePrefix, utcpNamespacedKey, seedBevelHostedManualVars, } from './utcp-namespace.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EACL,KAAK,WAAW,EAChB,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,wBAAwB,EACxB,qBAAqB,EACrB,KAAK,cAAc,EACnB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EACL,KAAK,WAAW,EAChB,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,wBAAwB,EACxB,qBAAqB,EACrB,KAAK,cAAc,EACnB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,SAAS,EACd,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,eAAe,EACf,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,sBAAsB,EACtB,KAAK,sBAAsB,GAC5B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,cAAc,EACd,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -26,10 +26,12 @@
|
|
|
26
26
|
* thing as session recovery, and stays each surface's own.
|
|
27
27
|
*/
|
|
28
28
|
export { toListedTool, sanitizeInputSchema, flattenManualTool, flattenDiscoveredTool, } from './proxied-tool.js';
|
|
29
|
-
export { describeToolFailure, toCallToolResult, renderProgress, toolError, needsAuthorizationResult, MCP_IMAGE_RESULT_KIND, mcpImageResult, isMcpImageResult, omitImagePayloads, } from './results.js';
|
|
30
|
-
export {
|
|
29
|
+
export { describeToolFailure, withTransportDetail, toCallToolResult, renderProgress, toolError, needsAuthorizationResult, MCP_IMAGE_RESULT_KIND, mcpImageResult, isMcpImageResult, omitImagePayloads, } from './results.js';
|
|
30
|
+
export { codeModeMetaTools, chainNamespaceExample, META_TOOL_NAMES, CALL_TOOL_CHAIN_MAX_OUTPUT, CALL_TOOL_CHAIN_NAME, CHAIN_FAILURES_RULE, CHAIN_LARGE_RESULTS_RULE, dispatchMetaTool, } from './meta-tools.js';
|
|
31
|
+
export { CHAIN_RUNTIME_PRELUDE, CHAIN_TIMEOUT_DEFAULT_MS, CHAIN_TIMEOUT_MAX_MS, CHAIN_TIMEOUT_MIN_MS, chainNamespaces, chainOutOfMemoryMessage, chainTimeoutMessage, describeChainFailure, runToolChain, unknownNamespaceMessage, withChainRuntime, } from './chain-runtime.js';
|
|
32
|
+
export { chainExample, } from './chain-example.js';
|
|
31
33
|
export { registerManual, dispatchToolCall } from './dispatch.js';
|
|
32
|
-
export { RETIRED_TOOL_MESSAGES, RETIRED_TOOL_NAMES, retiredToolMessage, retiredToolInFailure,
|
|
34
|
+
export { RETIRED_TOOL_MESSAGES, RETIRED_TOOL_NAMES, retiredToolMessage, retiredToolInFailure, } from './retired-tools.js';
|
|
33
35
|
export { isSessionLoss, installSessionRecovery, noteManualReregistered, } from './session-recovery.js';
|
|
34
36
|
export { skillPromptText, } from './skills.js';
|
|
35
37
|
export { utcpNamespacePrefix, utcpNamespacedKey, seedBevelHostedManualVars, } from './utcp-namespace.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAEL,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,wBAAwB,EACxB,qBAAqB,EAErB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,EAEL,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,wBAAwB,EACxB,qBAAqB,EAErB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EAGxB,gBAAgB,GACjB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACpB,oBAAoB,EAGpB,eAAe,EACf,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,uBAAuB,EACvB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAGL,YAAY,GACb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,sBAAsB,GAEvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAGL,eAAe,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,kBAAkB,EAClB,yBAAyB,EACzB,cAAc,EACd,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/meta-tools.d.ts
CHANGED
|
@@ -1,6 +1,105 @@
|
|
|
1
1
|
import type { Tool as McpTool, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
2
|
import type { CodeModeUtcpClient } from '@utcp/code-mode';
|
|
3
|
-
|
|
3
|
+
import { type ChainExampleTool } from './chain-example.js';
|
|
4
|
+
/**
|
|
5
|
+
* Code-mode meta-tools exposed ALONGSIDE the direct tools. They let an external
|
|
6
|
+
* agent batch many Bevel calls into one isolated-vm run (`call_tool_chain`)
|
|
7
|
+
* instead of one MCP round-trip per call — the same efficiency our own agent
|
|
8
|
+
* gets. `call_tool_chain`'s description carries the code-mode protocol, so the
|
|
9
|
+
* client learns the convention from the tool itself; `list_tools`/`tools_info`
|
|
10
|
+
* are how it discovers what to call. There IS a system prompt over MCP now: the
|
|
11
|
+
* platform header and the admin's preamble arrive as `instructions` on the
|
|
12
|
+
* initialize handshake (see core-backend's modules/agent-instructions/compose.ts).
|
|
13
|
+
* The PROTOCOL stays in the description regardless, because several clients
|
|
14
|
+
* (claude.ai on the web, the Agent SDK, Cline) drop that field.
|
|
15
|
+
*
|
|
16
|
+
* What a chain DOES, though — to a failure, to a large result, to an image —
|
|
17
|
+
* is true of every call, and those rules are stated once, in the handshake
|
|
18
|
+
* instructions and in the platform-managed agent guide, rather than on each
|
|
19
|
+
* tool they cover. So on a surface that has those rules the chain description
|
|
20
|
+
* ends with the same pointer sentence every file tool ends with, composed
|
|
21
|
+
* where the tool is served and the guide's configured name is known
|
|
22
|
+
* (core-backend's mcp.service.ts; nothing here may spell `AGENTS.md`, since
|
|
23
|
+
* the name is a deployment setting). A client that drops `instructions` is
|
|
24
|
+
* then still told WHERE the rules are, which is what the guide is for.
|
|
25
|
+
* The standalone bridge in `hexis-mcp` passes no pointer and so serves the
|
|
26
|
+
* description WHOLE, rules included: it proxies a remote knowledge base and
|
|
27
|
+
* does not know that deployment's layout.
|
|
28
|
+
*
|
|
29
|
+
* Security is identical to the direct surface: the chain runs in an isolated-vm
|
|
30
|
+
* but calls tools with the CALLER's credentials against the external catalog —
|
|
31
|
+
* internal-only tools aren't in that catalog, so a chain can't reach them either.
|
|
32
|
+
*
|
|
33
|
+
* These three belong to whichever client holds the registry. A surface that
|
|
34
|
+
* registers ANOTHER Bevel MCP endpoint as one of its manuals therefore has to
|
|
35
|
+
* drop that endpoint's copies from the passthrough (see {@link META_TOOL_NAMES}):
|
|
36
|
+
* the remote trio describes the remote registry, and locally they must describe
|
|
37
|
+
* the merged one.
|
|
38
|
+
*/
|
|
39
|
+
/** The chain tool's name, for the callers that single it out by name. */
|
|
40
|
+
export declare const CALL_TOOL_CHAIN_NAME = "call_tool_chain";
|
|
41
|
+
/**
|
|
42
|
+
* The namespace every example in the three descriptions is written against.
|
|
43
|
+
*
|
|
44
|
+
* It is NOT fixed text, because it is not the same name on every connection:
|
|
45
|
+
* the hosted endpoint registers the knowledge-base tools as `KNOWLEDGE_BASE`,
|
|
46
|
+
* while the local server registers the whole deployment as one `hexis` manual.
|
|
47
|
+
* A description that named the other one taught the agent a namespace the
|
|
48
|
+
* runtime had no binding for, and the example call it copied died of
|
|
49
|
+
* `ReferenceError` — which is how this was reported. So each surface passes
|
|
50
|
+
* the name it actually registers, and the examples are built from it.
|
|
51
|
+
*
|
|
52
|
+
* Sanitized the way the runtime sanitizes it, so the example is callable even
|
|
53
|
+
* when the registered manual's name is not a bare identifier: `@utcp/code-mode`
|
|
54
|
+
* exposes `global.<sanitized manual name>`, and an example spelled any other
|
|
55
|
+
* way would not run.
|
|
56
|
+
*/
|
|
57
|
+
export declare function chainNamespaceExample(namespace: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* What a chain does when it FAILS — one of the rules about a chain that are
|
|
60
|
+
* true of every call, not of how to write one.
|
|
61
|
+
*
|
|
62
|
+
* Exported as text because it is stated in ONE of two places, never both: in
|
|
63
|
+
* the rules every tool shares (the handshake instructions and the managed
|
|
64
|
+
* agent guide, see core-backend's `agent-instructions/shared-file-rules.ts`)
|
|
65
|
+
* on a surface that has them, and in the chain's own description on one that
|
|
66
|
+
* does not. The same sentences either way, so the rule cannot read differently
|
|
67
|
+
* depending on where an agent found it.
|
|
68
|
+
*/
|
|
69
|
+
export declare const CHAIN_FAILURES_RULE = "Failures are answered, never dropped: a chain that throws comes back as an error carrying the reason, and one that outlives `timeout` (default 30000 ms, maximum 120000 ms) comes back saying so \u2014 raise `timeout` or split the work and run it again. Either way the connection stays open and your next call works as usual.";
|
|
70
|
+
/** What a chain does with a result too large to return. Placed as {@link CHAIN_FAILURES_RULE} is. */
|
|
71
|
+
export declare const CHAIN_LARGE_RESULTS_RULE = "Large results: if the combined result+logs exceed `max_output_size` (default 200000 chars) the full JSON is spilled to a shared store and you get back a `__tool_chain_spill__/\u2026` ref instead. Read it with `read_file` (pass that ref as `path` \u2014 `branch` is ignored \u2014 plus `offset`/`limit` to slice it), or better, re-run a narrower chain that returns only what you need.";
|
|
72
|
+
/** What a surface says about itself when it asks for the meta-tools. */
|
|
73
|
+
export interface CodeModeMetaToolsOptions {
|
|
74
|
+
/**
|
|
75
|
+
* The sentence that ends the chain's description on a surface whose
|
|
76
|
+
* knowledge base states the shared rules (see {@link callToolChainDescription}).
|
|
77
|
+
* Opaque text: the caller composes it, because it names the agent guide and
|
|
78
|
+
* that name is a deployment setting — nothing here may spell `AGENTS.md`.
|
|
79
|
+
* Absent, the description carries the chain's rules itself.
|
|
80
|
+
*/
|
|
81
|
+
sharedRulesPointer?: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The three meta-tools, with every example written against the namespace this
|
|
85
|
+
* connection really exposes and a tool name its catalog really has.
|
|
86
|
+
*
|
|
87
|
+
* Built per listing rather than held as a module constant: both belong to the
|
|
88
|
+
* surface, and a description computed once and shared across surfaces is the
|
|
89
|
+
* fixed text this replaces. `tools` is the surface's catalog — pass every tool
|
|
90
|
+
* it serves, names AND input schemas, since the arguments in the example come
|
|
91
|
+
* from the schema (see `chainExample`).
|
|
92
|
+
*
|
|
93
|
+
* `list_tools` and `tools_info` describe the registry, not what a call does,
|
|
94
|
+
* so neither ever carried a shared rule and neither gains the pointer.
|
|
95
|
+
*/
|
|
96
|
+
export declare function codeModeMetaTools(namespace: string, tools?: readonly ChainExampleTool[], options?: CodeModeMetaToolsOptions): McpTool[];
|
|
97
|
+
/**
|
|
98
|
+
* The meta-tool NAMES, which no namespace can change. Kept separate from
|
|
99
|
+
* {@link codeModeMetaTools} because every surface needs them to route a call
|
|
100
|
+
* and to keep a discovered copy out of its listing, and neither of those knows
|
|
101
|
+
* — or should need — the namespace.
|
|
102
|
+
*/
|
|
4
103
|
export declare const META_TOOL_NAMES: ReadonlySet<string>;
|
|
5
104
|
/** Default cap on a `call_tool_chain` result's stringified size before it spills. */
|
|
6
105
|
export declare const CALL_TOOL_CHAIN_MAX_OUTPUT = 200000;
|
package/dist/meta-tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"meta-tools.d.ts","sourceRoot":"","sources":["../src/meta-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,IAAI,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAC1F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"meta-tools.d.ts","sourceRoot":"","sources":["../src/meta-tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,IAAI,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAC1F,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAmC,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAU5F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEH,yEAAyE;AACzE,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AAEtD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,mBAAmB,wUAA8W,CAAC;AAE/Y,qGAAqG;AACrG,eAAO,MAAM,wBAAwB,oYAC+U,CAAC;AAyCrX,wEAAwE;AACxE,MAAM,WAAW,wBAAwB;IACvC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,KAAK,GAAE,SAAS,gBAAgB,EAAO,EACvC,OAAO,GAAE,wBAA6B,GACrC,OAAO,EAAE,CA0CX;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAA+D,CAAC;AAChH,qFAAqF;AACrF,eAAO,MAAM,0BAA0B,SAAU,CAAC;AAgBlD;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC9D;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,kBAAkB,EAC1B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,KAAK,CAAC,EAAE,SAAS,GAChB,OAAO,CAAC,cAAc,CAAC,CAkHzB"}
|