@executor-js/execution 1.4.33 → 1.5.1
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 +19 -0
- package/dist/{chunk-NJPJNVEN.js → chunk-Q2R6Q3HF.js} +151 -74
- package/dist/chunk-Q2R6Q3HF.js.map +1 -0
- package/dist/core.js +3 -1
- package/dist/description.d.ts +5 -1
- package/dist/description.d.ts.map +1 -1
- package/dist/engine.d.ts +2 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -84
- package/dist/index.js.map +1 -1
- package/dist/promise.d.ts +1 -1
- package/dist/promise.d.ts.map +1 -1
- package/dist/tool-invoker.d.ts +21 -10
- package/dist/tool-invoker.d.ts.map +1 -1
- package/package.json +8 -5
- package/dist/chunk-NJPJNVEN.js.map +0 -1
package/README.md
CHANGED
|
@@ -51,6 +51,25 @@ console.log(result);
|
|
|
51
51
|
// { result: 12, logs: [...] }
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
+
## Custom tool discovery
|
|
55
|
+
|
|
56
|
+
`tools.search(...)` uses Executor's built-in lexical tool discovery by default. Hosts can provide their own implementation, such as an indexed or semantic search provider, without replacing the sandbox runtime:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { createExecutionEngine, type ToolDiscoveryProvider } from "@executor-js/execution";
|
|
60
|
+
|
|
61
|
+
const toolDiscoveryProvider: ToolDiscoveryProvider = {
|
|
62
|
+
searchTools: ({ query, namespace, limit, offset }) =>
|
|
63
|
+
mySearchIndex.searchTools({ query, namespace, limit, offset }),
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const engine = createExecutionEngine({
|
|
67
|
+
executor,
|
|
68
|
+
codeExecutor: makeQuickJsExecutor(),
|
|
69
|
+
toolDiscoveryProvider,
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
54
73
|
## Pause/resume for elicitation
|
|
55
74
|
|
|
56
75
|
When the host doesn't support inline elicitation, use `executeWithPause` to intercept the first request as a pause point:
|
|
@@ -7,7 +7,13 @@ var ExecutionToolError = class extends Data.TaggedError("ExecutionToolError") {
|
|
|
7
7
|
// src/tool-invoker.ts
|
|
8
8
|
import { Effect, Predicate } from "effect";
|
|
9
9
|
import * as Cause from "effect/Cause";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
authToolFailure,
|
|
12
|
+
isToolResult,
|
|
13
|
+
ToolResult,
|
|
14
|
+
ToolAddress,
|
|
15
|
+
parseToolAddress
|
|
16
|
+
} from "@executor-js/sdk/core";
|
|
11
17
|
var OPAQUE_DEFECT_MESSAGE = "Internal tool error";
|
|
12
18
|
var TOOL_ERROR_TYPESCRIPT = "{ code: string; message: string; status?: number; details?: unknown; retryable?: boolean }";
|
|
13
19
|
var wrapOutputTypeScript = (outputTypeScript) => `{ ok: true; data: ${outputTypeScript ?? "unknown"} } | { ok: false; error: ToolError }`;
|
|
@@ -15,6 +21,15 @@ var withToolResultDefinitions = (definitions) => ({
|
|
|
15
21
|
...definitions ?? {},
|
|
16
22
|
ToolError: TOOL_ERROR_TYPESCRIPT
|
|
17
23
|
});
|
|
24
|
+
var ADDRESS_PREFIX = "tools.";
|
|
25
|
+
var pathToAddress = (path) => {
|
|
26
|
+
if (path.startsWith(ADDRESS_PREFIX)) return ToolAddress.make(path);
|
|
27
|
+
if (parseToolAddress(`${ADDRESS_PREFIX}${path}`)) {
|
|
28
|
+
return ToolAddress.make(`${ADDRESS_PREFIX}${path}`);
|
|
29
|
+
}
|
|
30
|
+
return ToolAddress.make(path);
|
|
31
|
+
};
|
|
32
|
+
var addressToPath = (address) => address.startsWith(ADDRESS_PREFIX) ? address.slice(ADDRESS_PREFIX.length) : address;
|
|
18
33
|
var BUILTIN_TOOL_DESCRIPTIONS = /* @__PURE__ */ new Map([
|
|
19
34
|
[
|
|
20
35
|
"search",
|
|
@@ -25,7 +40,7 @@ var BUILTIN_TOOL_DESCRIPTIONS = /* @__PURE__ */ new Map([
|
|
|
25
40
|
inputTypeScript: "{ query: string; namespace?: string; limit?: number; offset?: number; }",
|
|
26
41
|
outputTypeScript: "{ items: ToolDiscoveryResult[]; total: number; hasMore: boolean; nextOffset: number | null; }",
|
|
27
42
|
typeScriptDefinitions: {
|
|
28
|
-
ToolDiscoveryResult: "{ path: string; name: string; description?: string;
|
|
43
|
+
ToolDiscoveryResult: "{ path: string; name: string; description?: string; integration: string; score: number; }"
|
|
29
44
|
}
|
|
30
45
|
}
|
|
31
46
|
],
|
|
@@ -34,11 +49,11 @@ var BUILTIN_TOOL_DESCRIPTIONS = /* @__PURE__ */ new Map([
|
|
|
34
49
|
{
|
|
35
50
|
path: "executor.sources.list",
|
|
36
51
|
name: "executor.sources.list",
|
|
37
|
-
description: "List configured
|
|
52
|
+
description: "List configured Executor integrations.",
|
|
38
53
|
inputTypeScript: "{ query?: string; limit?: number; offset?: number; }",
|
|
39
54
|
outputTypeScript: "{ items: ExecutorSourceListItem[]; total: number; hasMore: boolean; nextOffset: number | null; }",
|
|
40
55
|
typeScriptDefinitions: {
|
|
41
|
-
ExecutorSourceListItem: "{ id: string; name: string; kind: string;
|
|
56
|
+
ExecutorSourceListItem: "{ id: string; name: string; kind: string; canRemove?: boolean; canRefresh?: boolean; toolCount: number; }"
|
|
42
57
|
}
|
|
43
58
|
}
|
|
44
59
|
],
|
|
@@ -64,19 +79,28 @@ var validationIssues = (value) => {
|
|
|
64
79
|
const issues = value.issues;
|
|
65
80
|
return Array.isArray(issues) ? issues : null;
|
|
66
81
|
};
|
|
82
|
+
var credentialResolutionToolFailure = (input) => authToolFailure({
|
|
83
|
+
code: input.reauthRequired === true ? "oauth_reauth_required" : "oauth_refresh_failed",
|
|
84
|
+
message: input.reauthRequired === true ? `OAuth connection "${input.label}" requires reauthorization: ${input.message}` : `OAuth connection "${input.label}" could not be resolved: ${input.message}`,
|
|
85
|
+
credential: {
|
|
86
|
+
kind: "oauth",
|
|
87
|
+
label: input.label
|
|
88
|
+
}
|
|
89
|
+
});
|
|
67
90
|
var expectedToolFailure = (value) => {
|
|
68
|
-
if (Predicate.isTagged(value, "ToolNotFoundError") && "
|
|
69
|
-
const suggestions = "suggestions" in value && Array.isArray(value.suggestions) ? value.suggestions : void 0;
|
|
91
|
+
if (Predicate.isTagged(value, "ToolNotFoundError") && "address" in value) {
|
|
92
|
+
const suggestions = "suggestions" in value && Array.isArray(value.suggestions) ? value.suggestions.map((suggestion) => addressToPath(String(suggestion))) : void 0;
|
|
93
|
+
const address = addressToPath(String(value.address));
|
|
70
94
|
return {
|
|
71
95
|
code: "tool_not_found",
|
|
72
|
-
message: `Tool not found: ${
|
|
73
|
-
details: {
|
|
96
|
+
message: `Tool not found: ${address}`,
|
|
97
|
+
details: { path: address, ...suggestions ? { suggestions } : {} }
|
|
74
98
|
};
|
|
75
99
|
}
|
|
76
|
-
if (Predicate.isTagged(value, "ToolBlockedError") && "
|
|
100
|
+
if (Predicate.isTagged(value, "ToolBlockedError") && "address" in value) {
|
|
77
101
|
return {
|
|
78
102
|
code: "tool_blocked",
|
|
79
|
-
message: `Tool blocked by policy: ${String(value.
|
|
103
|
+
message: `Tool blocked by policy: ${addressToPath(String(value.address))}`,
|
|
80
104
|
details: value
|
|
81
105
|
};
|
|
82
106
|
}
|
|
@@ -92,17 +116,29 @@ var expectedToolFailure = (value) => {
|
|
|
92
116
|
}
|
|
93
117
|
return null;
|
|
94
118
|
};
|
|
95
|
-
var
|
|
96
|
-
const
|
|
97
|
-
|
|
119
|
+
var extractNamespace = (path) => {
|
|
120
|
+
const normalized = addressToPath(path);
|
|
121
|
+
const idx = normalized.indexOf(".");
|
|
122
|
+
return idx === -1 ? normalized : normalized.slice(0, idx);
|
|
98
123
|
};
|
|
99
124
|
var makeExecutorToolInvoker = (executor, options) => ({
|
|
100
125
|
invoke: Effect.fn("mcp.tool.dispatch")(function* ({ path, args }) {
|
|
101
126
|
yield* Effect.annotateCurrentSpan({
|
|
102
127
|
"mcp.tool.name": path,
|
|
103
|
-
"mcp.tool.
|
|
128
|
+
"mcp.tool.integration": extractNamespace(path)
|
|
104
129
|
});
|
|
105
|
-
const
|
|
130
|
+
const address = pathToAddress(path);
|
|
131
|
+
const result = yield* executor.execute(address, args, options.invokeOptions).pipe(
|
|
132
|
+
Effect.catchTag(
|
|
133
|
+
"CredentialResolutionError",
|
|
134
|
+
(err) => Effect.succeed(
|
|
135
|
+
credentialResolutionToolFailure({
|
|
136
|
+
label: `${err.integration}.${err.owner}.${err.name}`,
|
|
137
|
+
message: err.message,
|
|
138
|
+
reauthRequired: err.reauthRequired
|
|
139
|
+
})
|
|
140
|
+
)
|
|
141
|
+
),
|
|
106
142
|
Effect.catchCause((cause) => {
|
|
107
143
|
const err = cause.reasons.find(Cause.isFailReason)?.error;
|
|
108
144
|
const expected = expectedToolFailure(err);
|
|
@@ -112,7 +148,7 @@ var makeExecutorToolInvoker = (executor, options) => ({
|
|
|
112
148
|
if (isElicitationDeclinedError(err)) {
|
|
113
149
|
return Effect.fail(
|
|
114
150
|
new ExecutionToolError({
|
|
115
|
-
message: `Tool "${err.
|
|
151
|
+
message: `Tool "${addressToPath(String(err.address))}" requires approval but the request was ${err.action === "cancel" ? "cancelled" : "declined"} by the user.`,
|
|
116
152
|
cause: err
|
|
117
153
|
})
|
|
118
154
|
);
|
|
@@ -140,7 +176,7 @@ var makeExecutorToolInvoker = (executor, options) => ({
|
|
|
140
176
|
return { ok: true, data: result };
|
|
141
177
|
})
|
|
142
178
|
});
|
|
143
|
-
var isElicitationDeclinedError = (value) => Predicate.isTagged(value, "ElicitationDeclinedError") && value !== null && typeof value === "object" && "
|
|
179
|
+
var isElicitationDeclinedError = (value) => Predicate.isTagged(value, "ElicitationDeclinedError") && value !== null && typeof value === "object" && "address" in value && typeof value.address === "string" && "action" in value && (value.action === "cancel" || value.action === "decline");
|
|
144
180
|
var paginate = (all, offset, limit) => {
|
|
145
181
|
const total = all.length;
|
|
146
182
|
const start = Math.min(Math.max(offset, 0), total);
|
|
@@ -154,9 +190,15 @@ var paginate = (all, offset, limit) => {
|
|
|
154
190
|
nextOffset: hasMore ? consumed : null
|
|
155
191
|
};
|
|
156
192
|
};
|
|
193
|
+
var toSearchableTool = (tool) => ({
|
|
194
|
+
path: addressToPath(String(tool.address)),
|
|
195
|
+
integration: String(tool.integration),
|
|
196
|
+
name: String(tool.name),
|
|
197
|
+
description: tool.description
|
|
198
|
+
});
|
|
157
199
|
var SEARCH_FIELD_WEIGHTS = {
|
|
158
200
|
path: 12,
|
|
159
|
-
|
|
201
|
+
integration: 8,
|
|
160
202
|
name: 10,
|
|
161
203
|
description: 5
|
|
162
204
|
};
|
|
@@ -216,10 +258,10 @@ var matchesNamespace = (tool, namespace) => {
|
|
|
216
258
|
if (namespaceTokens.length === 0) {
|
|
217
259
|
return true;
|
|
218
260
|
}
|
|
219
|
-
const
|
|
220
|
-
const pathTokens = tokenizeSearchText(tool.
|
|
261
|
+
const integrationTokens = tokenizeSearchText(tool.integration);
|
|
262
|
+
const pathTokens = tokenizeSearchText(tool.path);
|
|
221
263
|
const isPrefixMatch = (tokens) => namespaceTokens.every((token, index) => tokens[index] === token);
|
|
222
|
-
return isPrefixMatch(
|
|
264
|
+
return isPrefixMatch(integrationTokens) || isPrefixMatch(pathTokens);
|
|
223
265
|
};
|
|
224
266
|
var scoreToolMatch = (tool, query) => {
|
|
225
267
|
const normalizedQuery = normalizeSearchText(query);
|
|
@@ -227,13 +269,13 @@ var scoreToolMatch = (tool, query) => {
|
|
|
227
269
|
if (normalizedQuery.length === 0 || queryTokens.length === 0) {
|
|
228
270
|
return null;
|
|
229
271
|
}
|
|
230
|
-
const path = prepareField(tool.
|
|
231
|
-
const
|
|
272
|
+
const path = prepareField(tool.path);
|
|
273
|
+
const integration = prepareField(tool.integration);
|
|
232
274
|
const name = prepareField(tool.name);
|
|
233
275
|
const description = prepareField(tool.description);
|
|
234
276
|
const fieldScores = [
|
|
235
277
|
scorePreparedField(normalizedQuery, queryTokens, path, SEARCH_FIELD_WEIGHTS.path),
|
|
236
|
-
scorePreparedField(normalizedQuery, queryTokens,
|
|
278
|
+
scorePreparedField(normalizedQuery, queryTokens, integration, SEARCH_FIELD_WEIGHTS.integration),
|
|
237
279
|
scorePreparedField(normalizedQuery, queryTokens, name, SEARCH_FIELD_WEIGHTS.name),
|
|
238
280
|
scorePreparedField(normalizedQuery, queryTokens, description, SEARCH_FIELD_WEIGHTS.description)
|
|
239
281
|
];
|
|
@@ -263,14 +305,14 @@ var scoreToolMatch = (tool, query) => {
|
|
|
263
305
|
if (path.tokens[0] === queryTokens[0] || name.tokens[0] === queryTokens[0]) {
|
|
264
306
|
score += 8;
|
|
265
307
|
}
|
|
266
|
-
if (normalizeSearchText(tool.
|
|
308
|
+
if (normalizeSearchText(tool.path) === normalizedQuery || normalizeSearchText(tool.name) === normalizedQuery) {
|
|
267
309
|
score += 20;
|
|
268
310
|
}
|
|
269
311
|
return {
|
|
270
|
-
path: tool.
|
|
312
|
+
path: tool.path,
|
|
271
313
|
name: tool.name,
|
|
272
314
|
description: tool.description,
|
|
273
|
-
|
|
315
|
+
integration: tool.integration,
|
|
274
316
|
score
|
|
275
317
|
};
|
|
276
318
|
};
|
|
@@ -299,7 +341,8 @@ var searchTools = Effect.fn("executor.tools.search")(function* (executor, query,
|
|
|
299
341
|
})
|
|
300
342
|
)
|
|
301
343
|
);
|
|
302
|
-
const
|
|
344
|
+
const searchable = all.map(toSearchableTool);
|
|
345
|
+
const ranked = searchable.filter((tool) => matchesNamespace(tool, options?.namespace)).map((tool) => scoreToolMatch(tool, query)).filter(Predicate.isNotNull).sort((left, right) => right.score - left.score || left.path.localeCompare(right.path));
|
|
303
346
|
const page = paginate(ranked, offset, limit);
|
|
304
347
|
yield* Effect.annotateCurrentSpan({
|
|
305
348
|
"executor.search.candidate_count": all.length,
|
|
@@ -309,48 +352,53 @@ var searchTools = Effect.fn("executor.tools.search")(function* (executor, query,
|
|
|
309
352
|
});
|
|
310
353
|
return page;
|
|
311
354
|
});
|
|
355
|
+
var defaultToolDiscoveryProvider = {
|
|
356
|
+
searchTools: ({ executor, query, namespace, limit, offset }) => searchTools(executor, query, limit, { namespace, offset })
|
|
357
|
+
};
|
|
312
358
|
var listExecutorSources = Effect.fn("executor.sources.list")(function* (executor, options) {
|
|
313
359
|
const normalizedQuery = normalizeSearchText(options?.query ?? "");
|
|
314
360
|
const limit = options?.limit ?? 50;
|
|
315
361
|
const offset = options?.offset ?? 0;
|
|
316
|
-
const
|
|
362
|
+
const integrations = yield* executor.integrations.list().pipe(
|
|
317
363
|
Effect.mapError(
|
|
318
364
|
(cause) => new ExecutionToolError({
|
|
319
|
-
message: "Failed to list executor
|
|
365
|
+
message: "Failed to list executor integrations",
|
|
320
366
|
cause
|
|
321
367
|
})
|
|
322
368
|
)
|
|
323
369
|
);
|
|
324
|
-
const filtered = normalizedQuery.length === 0 ?
|
|
325
|
-
const haystack = normalizeSearchText(
|
|
370
|
+
const filtered = normalizedQuery.length === 0 ? integrations : integrations.filter((integration) => {
|
|
371
|
+
const haystack = normalizeSearchText(
|
|
372
|
+
[String(integration.slug), integration.description, integration.kind].join(" ")
|
|
373
|
+
);
|
|
326
374
|
return tokenizeSearchText(normalizedQuery).every((token) => haystack.includes(token));
|
|
327
375
|
});
|
|
328
376
|
const allTools = yield* executor.tools.list({ includeAnnotations: false }).pipe(
|
|
329
377
|
Effect.mapError(
|
|
330
378
|
(cause) => new ExecutionToolError({
|
|
331
|
-
message: "Failed to list tools for
|
|
379
|
+
message: "Failed to list tools for integration counts",
|
|
332
380
|
cause
|
|
333
381
|
})
|
|
334
382
|
)
|
|
335
383
|
);
|
|
336
|
-
const
|
|
384
|
+
const toolCountByIntegration = /* @__PURE__ */ new Map();
|
|
337
385
|
for (const tool of allTools) {
|
|
338
|
-
|
|
386
|
+
const key = String(tool.integration);
|
|
387
|
+
toolCountByIntegration.set(key, (toolCountByIntegration.get(key) ?? 0) + 1);
|
|
339
388
|
}
|
|
340
389
|
const sortedWithCounts = filtered.map(
|
|
341
|
-
(
|
|
342
|
-
id:
|
|
343
|
-
name:
|
|
344
|
-
kind:
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
toolCount: toolCountBySource.get(source.id) ?? 0
|
|
390
|
+
(integration) => ({
|
|
391
|
+
id: String(integration.slug),
|
|
392
|
+
name: String(integration.slug),
|
|
393
|
+
kind: integration.kind,
|
|
394
|
+
canRemove: integration.canRemove,
|
|
395
|
+
canRefresh: integration.canRefresh,
|
|
396
|
+
toolCount: toolCountByIntegration.get(String(integration.slug)) ?? 0
|
|
349
397
|
})
|
|
350
398
|
).sort((left, right) => left.name.localeCompare(right.name) || left.id.localeCompare(right.id));
|
|
351
399
|
const page = paginate(sortedWithCounts, offset, limit);
|
|
352
400
|
yield* Effect.annotateCurrentSpan({
|
|
353
|
-
"executor.sources.candidate_count":
|
|
401
|
+
"executor.sources.candidate_count": integrations.length,
|
|
354
402
|
"executor.sources.match_count": sortedWithCounts.length,
|
|
355
403
|
"executor.sources.result_count": page.items.length,
|
|
356
404
|
"executor.sources.has_more": page.hasMore
|
|
@@ -361,7 +409,8 @@ var describeTool = Effect.fn("executor.tools.describe")(function* (executor, pat
|
|
|
361
409
|
yield* Effect.annotateCurrentSpan({ "mcp.tool.name": path });
|
|
362
410
|
const builtin = BUILTIN_TOOL_DESCRIPTIONS.get(path);
|
|
363
411
|
if (builtin) return builtin;
|
|
364
|
-
const
|
|
412
|
+
const address = pathToAddress(path);
|
|
413
|
+
const schema = yield* executor.tools.schema(address);
|
|
365
414
|
if (schema === null) {
|
|
366
415
|
return { path, name: path };
|
|
367
416
|
}
|
|
@@ -378,23 +427,38 @@ var describeTool = Effect.fn("executor.tools.describe")(function* (executor, pat
|
|
|
378
427
|
// src/description.ts
|
|
379
428
|
import { Effect as Effect2 } from "effect";
|
|
380
429
|
var buildExecuteDescription = (executor) => Effect2.gen(function* () {
|
|
381
|
-
const
|
|
430
|
+
const connections = yield* executor.connections.list().pipe(
|
|
382
431
|
// oxlint-disable-next-line executor/no-effect-escape-hatch -- boundary: ExecutionEngine.getDescription currently exposes no error channel; engine typed-error widening is covered separately
|
|
383
432
|
Effect2.orDie,
|
|
384
|
-
Effect2.withSpan("executor.
|
|
433
|
+
Effect2.withSpan("executor.connections.list")
|
|
385
434
|
);
|
|
386
|
-
const description = yield* Effect2.sync(
|
|
435
|
+
const description = yield* Effect2.sync(
|
|
436
|
+
() => formatDescription(connections.map((connection) => connectionPath(connection)))
|
|
437
|
+
).pipe(
|
|
387
438
|
Effect2.withSpan("schema.compile.description", {
|
|
388
|
-
attributes: { "executor.
|
|
439
|
+
attributes: { "executor.connection_count": connections.length }
|
|
389
440
|
})
|
|
390
441
|
);
|
|
391
442
|
yield* Effect2.annotateCurrentSpan({
|
|
392
|
-
"executor.
|
|
393
|
-
"schema.kind": "execute"
|
|
443
|
+
"executor.connection_count": connections.length,
|
|
444
|
+
"schema.kind": "execute",
|
|
445
|
+
// Connection inventory so a failing session build (which runs this during
|
|
446
|
+
// init) names the callable prefixes it resolved without listing tools.
|
|
447
|
+
"executor.connection_addresses": connections.map((connection) => connectionPath(connection)).slice(0, 50).join(","),
|
|
448
|
+
"executor.connection_integrations": [
|
|
449
|
+
...new Set(connections.map((connection) => String(connection.integration)))
|
|
450
|
+
].join(","),
|
|
451
|
+
"executor.connection_owners": [
|
|
452
|
+
...new Set(connections.map((connection) => connection.owner))
|
|
453
|
+
].join(",")
|
|
394
454
|
});
|
|
395
455
|
return description;
|
|
396
456
|
}).pipe(Effect2.withSpan("schema.describe.execute"));
|
|
397
|
-
var
|
|
457
|
+
var connectionPath = (connection) => {
|
|
458
|
+
const address = String(connection.address);
|
|
459
|
+
return address.startsWith("tools.") ? address.slice("tools.".length) : address;
|
|
460
|
+
};
|
|
461
|
+
var formatDescription = (connectionPrefixes) => {
|
|
398
462
|
const lines = [
|
|
399
463
|
"Execute TypeScript in a sandboxed runtime with access to configured API tools.",
|
|
400
464
|
"",
|
|
@@ -404,35 +468,36 @@ var formatDescription = (sources) => {
|
|
|
404
468
|
'2. `const path = matches[0]?.path; if (!path) return "No matching tools found.";`',
|
|
405
469
|
"3. `const details = await tools.describe.tool({ path });`",
|
|
406
470
|
"4. Use `details.inputTypeScript` / `details.outputTypeScript` and `details.typeScriptDefinitions` for compact shapes.",
|
|
407
|
-
"5. Use `tools.executor.
|
|
471
|
+
"5. Use `tools.executor.coreTools.connections.list({})` when you need live saved-connection inventory.",
|
|
408
472
|
"6. Call the tool: `const result = await tools.<path>(input);`",
|
|
409
473
|
"",
|
|
410
474
|
"## Rules",
|
|
411
475
|
"",
|
|
412
476
|
"- `tools.search()` returns paginated, ranked matches: `{ items, total, hasMore, nextOffset }`. Best-first. Use short intent phrases like `github issues`, `repo details`, or `create calendar event`.",
|
|
413
477
|
'- When you already know the namespace, narrow with `tools.search({ namespace: "github", query: "issues" })`.',
|
|
414
|
-
"- `tools.executor.
|
|
478
|
+
"- `tools.executor.coreTools.connections.list({})` returns saved connections with `{ address, integration, owner, name, ... }`. The `address` field includes the leading `tools.` root.",
|
|
415
479
|
"- Tool calls return a value union: `{ ok: true, data }` for success or `{ ok: false, error: { code, message, status?, details?, retryable? } }` for expected tool/domain failures. Branch on `result.ok`.",
|
|
416
|
-
"- If `
|
|
417
|
-
"- Always use the
|
|
418
|
-
"- The `tools` object is a lazy proxy \u2014 `Object.keys(tools)` won't work. Use `tools.search()` or `tools.executor.
|
|
419
|
-
'- Pass an object to system tools, e.g. `tools.search({ query: "..." })`, `tools.executor.
|
|
480
|
+
"- If `tools.search()` returns `hasMore: true` and you didn't find what you need, fetch the next page: `tools.search({ query, offset: nextOffset, limit })`.",
|
|
481
|
+
"- Always use the full address when calling tools: `tools.<integration>.<owner>.<connection>.<tool>(args)`. The `path` returned by `tools.search()` / `tools.describe.tool()` is already the exact path under `tools` \u2014 call `tools[path]` rather than guessing segments.",
|
|
482
|
+
"- The `tools` object is a lazy proxy \u2014 `Object.keys(tools)` won't work. Use `tools.search()` or `tools.executor.coreTools.connections.list({})` instead.",
|
|
483
|
+
'- Pass an object to system tools, e.g. `tools.search({ query: "..." })`, `tools.executor.coreTools.connections.list({})`, and `tools.describe.tool({ path })`.',
|
|
420
484
|
"- `tools.describe.tool()` returns compact TypeScript shapes. Use `inputTypeScript`, `outputTypeScript`, and `typeScriptDefinitions`.",
|
|
421
485
|
"- For tools that return large collections (e.g. `getStates`, `getAll`), filter results in code rather than calling per-item tools.",
|
|
422
486
|
"- Do not use `fetch` \u2014 all API calls go through `tools.*`.",
|
|
423
487
|
"- If execution pauses for interaction, resume it with the returned `resumePayload`.",
|
|
424
488
|
"- TypeScript type syntax (`: T`, `as T`, generics, interfaces, type aliases) is stripped before execution \u2014 feel free to write idiomatic TypeScript using the shapes from `tools.describe.tool()`. Decorators and `enum` are not supported."
|
|
425
489
|
];
|
|
426
|
-
if (
|
|
490
|
+
if (connectionPrefixes.length > 0) {
|
|
427
491
|
lines.push("");
|
|
428
|
-
lines.push("## Available
|
|
492
|
+
lines.push("## Available connection prefixes");
|
|
429
493
|
lines.push("");
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
494
|
+
lines.push("These are paths under `tools.`; append the final tool segment.");
|
|
495
|
+
const sorted = [...connectionPrefixes].sort((a, b) => a.localeCompare(b)).slice(0, 50);
|
|
496
|
+
for (const prefix of sorted) {
|
|
497
|
+
lines.push(`- \`${prefix}\``);
|
|
433
498
|
}
|
|
434
|
-
if (
|
|
435
|
-
lines.push(`- ... ${
|
|
499
|
+
if (connectionPrefixes.length > sorted.length) {
|
|
500
|
+
lines.push(`- ... ${connectionPrefixes.length - sorted.length} more`);
|
|
436
501
|
}
|
|
437
502
|
}
|
|
438
503
|
return lines.join("\n");
|
|
@@ -506,7 +571,7 @@ instructions: ${instructions}`);
|
|
|
506
571
|
kind: isUrlElicitation ? "url" : "form",
|
|
507
572
|
message: req.message,
|
|
508
573
|
instructions,
|
|
509
|
-
|
|
574
|
+
address: String(paused.elicitationContext.address),
|
|
510
575
|
args: paused.elicitationContext.args,
|
|
511
576
|
...isUrlElicitation ? { url: req.url } : {},
|
|
512
577
|
...isFormElicitation ? { requestedSchema: req.requestedSchema } : {}
|
|
@@ -537,7 +602,7 @@ var readOptionalOffset = (value, toolName) => {
|
|
|
537
602
|
}
|
|
538
603
|
return Math.floor(value);
|
|
539
604
|
};
|
|
540
|
-
var makeFullInvoker = (executor, invokeOptions) => {
|
|
605
|
+
var makeFullInvoker = (executor, invokeOptions, toolDiscoveryProvider) => {
|
|
541
606
|
const base = makeExecutorToolInvoker(executor, { invokeOptions });
|
|
542
607
|
return {
|
|
543
608
|
invoke: ({ path, args }) => {
|
|
@@ -571,7 +636,10 @@ var makeFullInvoker = (executor, invokeOptions) => {
|
|
|
571
636
|
if (Predicate2.isTagged(offset, "ExecutionToolError")) {
|
|
572
637
|
return Effect3.fail(offset);
|
|
573
638
|
}
|
|
574
|
-
return searchTools(
|
|
639
|
+
return toolDiscoveryProvider.searchTools({
|
|
640
|
+
executor,
|
|
641
|
+
query: args.query ?? "",
|
|
642
|
+
limit,
|
|
575
643
|
namespace: args.namespace,
|
|
576
644
|
offset
|
|
577
645
|
}).pipe(
|
|
@@ -652,7 +720,7 @@ var makeFullInvoker = (executor, invokeOptions) => {
|
|
|
652
720
|
};
|
|
653
721
|
};
|
|
654
722
|
var createExecutionEngine = (config) => {
|
|
655
|
-
const { executor, codeExecutor } = config;
|
|
723
|
+
const { executor, codeExecutor, toolDiscoveryProvider = defaultToolDiscoveryProvider } = config;
|
|
656
724
|
const pausedExecutions = /* @__PURE__ */ new Map();
|
|
657
725
|
let nextId = 0;
|
|
658
726
|
const awaitCompletionOrPause = (fiber, pauseQueue) => Effect3.raceFirst(
|
|
@@ -684,7 +752,11 @@ var createExecutionEngine = (config) => {
|
|
|
684
752
|
yield* Queue.offer(pauseQueue, paused);
|
|
685
753
|
return yield* Deferred.await(responseDeferred);
|
|
686
754
|
});
|
|
687
|
-
const invoker = makeFullInvoker(
|
|
755
|
+
const invoker = makeFullInvoker(
|
|
756
|
+
executor,
|
|
757
|
+
{ onElicitation: elicitationHandler },
|
|
758
|
+
toolDiscoveryProvider
|
|
759
|
+
);
|
|
688
760
|
fiber = yield* Effect3.forkDetach(
|
|
689
761
|
codeExecutor.execute(code, invoker).pipe(Effect3.withSpan("executor.code.exec"))
|
|
690
762
|
);
|
|
@@ -708,9 +780,13 @@ var createExecutionEngine = (config) => {
|
|
|
708
780
|
"mcp.execute.mode": "inline",
|
|
709
781
|
"mcp.execute.code_length": code.length
|
|
710
782
|
});
|
|
711
|
-
const invoker = makeFullInvoker(
|
|
712
|
-
|
|
713
|
-
|
|
783
|
+
const invoker = makeFullInvoker(
|
|
784
|
+
executor,
|
|
785
|
+
{
|
|
786
|
+
onElicitation: options.onElicitation
|
|
787
|
+
},
|
|
788
|
+
toolDiscoveryProvider
|
|
789
|
+
);
|
|
714
790
|
return yield* codeExecutor.execute(code, invoker).pipe(Effect3.withSpan("executor.code.exec"));
|
|
715
791
|
});
|
|
716
792
|
return {
|
|
@@ -726,6 +802,7 @@ export {
|
|
|
726
802
|
ExecutionToolError,
|
|
727
803
|
makeExecutorToolInvoker,
|
|
728
804
|
searchTools,
|
|
805
|
+
defaultToolDiscoveryProvider,
|
|
729
806
|
listExecutorSources,
|
|
730
807
|
describeTool,
|
|
731
808
|
buildExecuteDescription,
|
|
@@ -733,4 +810,4 @@ export {
|
|
|
733
810
|
formatPausedExecution,
|
|
734
811
|
createExecutionEngine
|
|
735
812
|
};
|
|
736
|
-
//# sourceMappingURL=chunk-
|
|
813
|
+
//# sourceMappingURL=chunk-Q2R6Q3HF.js.map
|