@executor-js/execution 1.4.32 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/dist/{chunk-OLPHXJSA.js → chunk-Q2R6Q3HF.js} +191 -71
- 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 +31 -25
- package/dist/tool-invoker.d.ts.map +1 -1
- package/package.json +8 -5
- package/dist/chunk-OLPHXJSA.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,56 @@ 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;
|
|
33
|
+
var BUILTIN_TOOL_DESCRIPTIONS = /* @__PURE__ */ new Map([
|
|
34
|
+
[
|
|
35
|
+
"search",
|
|
36
|
+
{
|
|
37
|
+
path: "search",
|
|
38
|
+
name: "search",
|
|
39
|
+
description: "Search available Executor tools.",
|
|
40
|
+
inputTypeScript: "{ query: string; namespace?: string; limit?: number; offset?: number; }",
|
|
41
|
+
outputTypeScript: "{ items: ToolDiscoveryResult[]; total: number; hasMore: boolean; nextOffset: number | null; }",
|
|
42
|
+
typeScriptDefinitions: {
|
|
43
|
+
ToolDiscoveryResult: "{ path: string; name: string; description?: string; integration: string; score: number; }"
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
[
|
|
48
|
+
"executor.sources.list",
|
|
49
|
+
{
|
|
50
|
+
path: "executor.sources.list",
|
|
51
|
+
name: "executor.sources.list",
|
|
52
|
+
description: "List configured Executor integrations.",
|
|
53
|
+
inputTypeScript: "{ query?: string; limit?: number; offset?: number; }",
|
|
54
|
+
outputTypeScript: "{ items: ExecutorSourceListItem[]; total: number; hasMore: boolean; nextOffset: number | null; }",
|
|
55
|
+
typeScriptDefinitions: {
|
|
56
|
+
ExecutorSourceListItem: "{ id: string; name: string; kind: string; canRemove?: boolean; canRefresh?: boolean; toolCount: number; }"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
"describe.tool",
|
|
62
|
+
{
|
|
63
|
+
path: "describe.tool",
|
|
64
|
+
name: "describe.tool",
|
|
65
|
+
description: "Describe a tool's compact TypeScript input and output shapes.",
|
|
66
|
+
inputTypeScript: "{ path: string; }",
|
|
67
|
+
outputTypeScript: "DescribedTool",
|
|
68
|
+
typeScriptDefinitions: {
|
|
69
|
+
DescribedTool: "{ path: string; name: string; description?: string; inputTypeScript?: string; outputTypeScript?: string; typeScriptDefinitions?: { [k: string]: string; }; }"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
]);
|
|
18
74
|
var newCorrelationId = () => {
|
|
19
75
|
return Math.floor(Math.random() * 4294967296).toString(16).padStart(8, "0");
|
|
20
76
|
};
|
|
@@ -23,19 +79,28 @@ var validationIssues = (value) => {
|
|
|
23
79
|
const issues = value.issues;
|
|
24
80
|
return Array.isArray(issues) ? issues : null;
|
|
25
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
|
+
});
|
|
26
90
|
var expectedToolFailure = (value) => {
|
|
27
|
-
if (Predicate.isTagged(value, "ToolNotFoundError") && "
|
|
28
|
-
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));
|
|
29
94
|
return {
|
|
30
95
|
code: "tool_not_found",
|
|
31
|
-
message: `Tool not found: ${
|
|
32
|
-
details: {
|
|
96
|
+
message: `Tool not found: ${address}`,
|
|
97
|
+
details: { path: address, ...suggestions ? { suggestions } : {} }
|
|
33
98
|
};
|
|
34
99
|
}
|
|
35
|
-
if (Predicate.isTagged(value, "ToolBlockedError") && "
|
|
100
|
+
if (Predicate.isTagged(value, "ToolBlockedError") && "address" in value) {
|
|
36
101
|
return {
|
|
37
102
|
code: "tool_blocked",
|
|
38
|
-
message: `Tool blocked by policy: ${String(value.
|
|
103
|
+
message: `Tool blocked by policy: ${addressToPath(String(value.address))}`,
|
|
39
104
|
details: value
|
|
40
105
|
};
|
|
41
106
|
}
|
|
@@ -51,17 +116,29 @@ var expectedToolFailure = (value) => {
|
|
|
51
116
|
}
|
|
52
117
|
return null;
|
|
53
118
|
};
|
|
54
|
-
var
|
|
55
|
-
const
|
|
56
|
-
|
|
119
|
+
var extractNamespace = (path) => {
|
|
120
|
+
const normalized = addressToPath(path);
|
|
121
|
+
const idx = normalized.indexOf(".");
|
|
122
|
+
return idx === -1 ? normalized : normalized.slice(0, idx);
|
|
57
123
|
};
|
|
58
124
|
var makeExecutorToolInvoker = (executor, options) => ({
|
|
59
125
|
invoke: Effect.fn("mcp.tool.dispatch")(function* ({ path, args }) {
|
|
60
126
|
yield* Effect.annotateCurrentSpan({
|
|
61
127
|
"mcp.tool.name": path,
|
|
62
|
-
"mcp.tool.
|
|
128
|
+
"mcp.tool.integration": extractNamespace(path)
|
|
63
129
|
});
|
|
64
|
-
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
|
+
),
|
|
65
142
|
Effect.catchCause((cause) => {
|
|
66
143
|
const err = cause.reasons.find(Cause.isFailReason)?.error;
|
|
67
144
|
const expected = expectedToolFailure(err);
|
|
@@ -71,7 +148,7 @@ var makeExecutorToolInvoker = (executor, options) => ({
|
|
|
71
148
|
if (isElicitationDeclinedError(err)) {
|
|
72
149
|
return Effect.fail(
|
|
73
150
|
new ExecutionToolError({
|
|
74
|
-
message: `Tool "${err.
|
|
151
|
+
message: `Tool "${addressToPath(String(err.address))}" requires approval but the request was ${err.action === "cancel" ? "cancelled" : "declined"} by the user.`,
|
|
75
152
|
cause: err
|
|
76
153
|
})
|
|
77
154
|
);
|
|
@@ -99,7 +176,7 @@ var makeExecutorToolInvoker = (executor, options) => ({
|
|
|
99
176
|
return { ok: true, data: result };
|
|
100
177
|
})
|
|
101
178
|
});
|
|
102
|
-
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");
|
|
103
180
|
var paginate = (all, offset, limit) => {
|
|
104
181
|
const total = all.length;
|
|
105
182
|
const start = Math.min(Math.max(offset, 0), total);
|
|
@@ -113,9 +190,15 @@ var paginate = (all, offset, limit) => {
|
|
|
113
190
|
nextOffset: hasMore ? consumed : null
|
|
114
191
|
};
|
|
115
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
|
+
});
|
|
116
199
|
var SEARCH_FIELD_WEIGHTS = {
|
|
117
200
|
path: 12,
|
|
118
|
-
|
|
201
|
+
integration: 8,
|
|
119
202
|
name: 10,
|
|
120
203
|
description: 5
|
|
121
204
|
};
|
|
@@ -175,10 +258,10 @@ var matchesNamespace = (tool, namespace) => {
|
|
|
175
258
|
if (namespaceTokens.length === 0) {
|
|
176
259
|
return true;
|
|
177
260
|
}
|
|
178
|
-
const
|
|
179
|
-
const pathTokens = tokenizeSearchText(tool.
|
|
261
|
+
const integrationTokens = tokenizeSearchText(tool.integration);
|
|
262
|
+
const pathTokens = tokenizeSearchText(tool.path);
|
|
180
263
|
const isPrefixMatch = (tokens) => namespaceTokens.every((token, index) => tokens[index] === token);
|
|
181
|
-
return isPrefixMatch(
|
|
264
|
+
return isPrefixMatch(integrationTokens) || isPrefixMatch(pathTokens);
|
|
182
265
|
};
|
|
183
266
|
var scoreToolMatch = (tool, query) => {
|
|
184
267
|
const normalizedQuery = normalizeSearchText(query);
|
|
@@ -186,13 +269,13 @@ var scoreToolMatch = (tool, query) => {
|
|
|
186
269
|
if (normalizedQuery.length === 0 || queryTokens.length === 0) {
|
|
187
270
|
return null;
|
|
188
271
|
}
|
|
189
|
-
const path = prepareField(tool.
|
|
190
|
-
const
|
|
272
|
+
const path = prepareField(tool.path);
|
|
273
|
+
const integration = prepareField(tool.integration);
|
|
191
274
|
const name = prepareField(tool.name);
|
|
192
275
|
const description = prepareField(tool.description);
|
|
193
276
|
const fieldScores = [
|
|
194
277
|
scorePreparedField(normalizedQuery, queryTokens, path, SEARCH_FIELD_WEIGHTS.path),
|
|
195
|
-
scorePreparedField(normalizedQuery, queryTokens,
|
|
278
|
+
scorePreparedField(normalizedQuery, queryTokens, integration, SEARCH_FIELD_WEIGHTS.integration),
|
|
196
279
|
scorePreparedField(normalizedQuery, queryTokens, name, SEARCH_FIELD_WEIGHTS.name),
|
|
197
280
|
scorePreparedField(normalizedQuery, queryTokens, description, SEARCH_FIELD_WEIGHTS.description)
|
|
198
281
|
];
|
|
@@ -222,14 +305,14 @@ var scoreToolMatch = (tool, query) => {
|
|
|
222
305
|
if (path.tokens[0] === queryTokens[0] || name.tokens[0] === queryTokens[0]) {
|
|
223
306
|
score += 8;
|
|
224
307
|
}
|
|
225
|
-
if (normalizeSearchText(tool.
|
|
308
|
+
if (normalizeSearchText(tool.path) === normalizedQuery || normalizeSearchText(tool.name) === normalizedQuery) {
|
|
226
309
|
score += 20;
|
|
227
310
|
}
|
|
228
311
|
return {
|
|
229
|
-
path: tool.
|
|
312
|
+
path: tool.path,
|
|
230
313
|
name: tool.name,
|
|
231
314
|
description: tool.description,
|
|
232
|
-
|
|
315
|
+
integration: tool.integration,
|
|
233
316
|
score
|
|
234
317
|
};
|
|
235
318
|
};
|
|
@@ -258,7 +341,8 @@ var searchTools = Effect.fn("executor.tools.search")(function* (executor, query,
|
|
|
258
341
|
})
|
|
259
342
|
)
|
|
260
343
|
);
|
|
261
|
-
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));
|
|
262
346
|
const page = paginate(ranked, offset, limit);
|
|
263
347
|
yield* Effect.annotateCurrentSpan({
|
|
264
348
|
"executor.search.candidate_count": all.length,
|
|
@@ -268,48 +352,53 @@ var searchTools = Effect.fn("executor.tools.search")(function* (executor, query,
|
|
|
268
352
|
});
|
|
269
353
|
return page;
|
|
270
354
|
});
|
|
355
|
+
var defaultToolDiscoveryProvider = {
|
|
356
|
+
searchTools: ({ executor, query, namespace, limit, offset }) => searchTools(executor, query, limit, { namespace, offset })
|
|
357
|
+
};
|
|
271
358
|
var listExecutorSources = Effect.fn("executor.sources.list")(function* (executor, options) {
|
|
272
359
|
const normalizedQuery = normalizeSearchText(options?.query ?? "");
|
|
273
360
|
const limit = options?.limit ?? 50;
|
|
274
361
|
const offset = options?.offset ?? 0;
|
|
275
|
-
const
|
|
362
|
+
const integrations = yield* executor.integrations.list().pipe(
|
|
276
363
|
Effect.mapError(
|
|
277
364
|
(cause) => new ExecutionToolError({
|
|
278
|
-
message: "Failed to list executor
|
|
365
|
+
message: "Failed to list executor integrations",
|
|
279
366
|
cause
|
|
280
367
|
})
|
|
281
368
|
)
|
|
282
369
|
);
|
|
283
|
-
const filtered = normalizedQuery.length === 0 ?
|
|
284
|
-
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
|
+
);
|
|
285
374
|
return tokenizeSearchText(normalizedQuery).every((token) => haystack.includes(token));
|
|
286
375
|
});
|
|
287
376
|
const allTools = yield* executor.tools.list({ includeAnnotations: false }).pipe(
|
|
288
377
|
Effect.mapError(
|
|
289
378
|
(cause) => new ExecutionToolError({
|
|
290
|
-
message: "Failed to list tools for
|
|
379
|
+
message: "Failed to list tools for integration counts",
|
|
291
380
|
cause
|
|
292
381
|
})
|
|
293
382
|
)
|
|
294
383
|
);
|
|
295
|
-
const
|
|
384
|
+
const toolCountByIntegration = /* @__PURE__ */ new Map();
|
|
296
385
|
for (const tool of allTools) {
|
|
297
|
-
|
|
386
|
+
const key = String(tool.integration);
|
|
387
|
+
toolCountByIntegration.set(key, (toolCountByIntegration.get(key) ?? 0) + 1);
|
|
298
388
|
}
|
|
299
389
|
const sortedWithCounts = filtered.map(
|
|
300
|
-
(
|
|
301
|
-
id:
|
|
302
|
-
name:
|
|
303
|
-
kind:
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
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
|
|
308
397
|
})
|
|
309
398
|
).sort((left, right) => left.name.localeCompare(right.name) || left.id.localeCompare(right.id));
|
|
310
399
|
const page = paginate(sortedWithCounts, offset, limit);
|
|
311
400
|
yield* Effect.annotateCurrentSpan({
|
|
312
|
-
"executor.sources.candidate_count":
|
|
401
|
+
"executor.sources.candidate_count": integrations.length,
|
|
313
402
|
"executor.sources.match_count": sortedWithCounts.length,
|
|
314
403
|
"executor.sources.result_count": page.items.length,
|
|
315
404
|
"executor.sources.has_more": page.hasMore
|
|
@@ -318,7 +407,10 @@ var listExecutorSources = Effect.fn("executor.sources.list")(function* (executor
|
|
|
318
407
|
});
|
|
319
408
|
var describeTool = Effect.fn("executor.tools.describe")(function* (executor, path) {
|
|
320
409
|
yield* Effect.annotateCurrentSpan({ "mcp.tool.name": path });
|
|
321
|
-
const
|
|
410
|
+
const builtin = BUILTIN_TOOL_DESCRIPTIONS.get(path);
|
|
411
|
+
if (builtin) return builtin;
|
|
412
|
+
const address = pathToAddress(path);
|
|
413
|
+
const schema = yield* executor.tools.schema(address);
|
|
322
414
|
if (schema === null) {
|
|
323
415
|
return { path, name: path };
|
|
324
416
|
}
|
|
@@ -335,23 +427,38 @@ var describeTool = Effect.fn("executor.tools.describe")(function* (executor, pat
|
|
|
335
427
|
// src/description.ts
|
|
336
428
|
import { Effect as Effect2 } from "effect";
|
|
337
429
|
var buildExecuteDescription = (executor) => Effect2.gen(function* () {
|
|
338
|
-
const
|
|
430
|
+
const connections = yield* executor.connections.list().pipe(
|
|
339
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
|
|
340
432
|
Effect2.orDie,
|
|
341
|
-
Effect2.withSpan("executor.
|
|
433
|
+
Effect2.withSpan("executor.connections.list")
|
|
342
434
|
);
|
|
343
|
-
const description = yield* Effect2.sync(
|
|
435
|
+
const description = yield* Effect2.sync(
|
|
436
|
+
() => formatDescription(connections.map((connection) => connectionPath(connection)))
|
|
437
|
+
).pipe(
|
|
344
438
|
Effect2.withSpan("schema.compile.description", {
|
|
345
|
-
attributes: { "executor.
|
|
439
|
+
attributes: { "executor.connection_count": connections.length }
|
|
346
440
|
})
|
|
347
441
|
);
|
|
348
442
|
yield* Effect2.annotateCurrentSpan({
|
|
349
|
-
"executor.
|
|
350
|
-
"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(",")
|
|
351
454
|
});
|
|
352
455
|
return description;
|
|
353
456
|
}).pipe(Effect2.withSpan("schema.describe.execute"));
|
|
354
|
-
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) => {
|
|
355
462
|
const lines = [
|
|
356
463
|
"Execute TypeScript in a sandboxed runtime with access to configured API tools.",
|
|
357
464
|
"",
|
|
@@ -361,35 +468,36 @@ var formatDescription = (sources) => {
|
|
|
361
468
|
'2. `const path = matches[0]?.path; if (!path) return "No matching tools found.";`',
|
|
362
469
|
"3. `const details = await tools.describe.tool({ path });`",
|
|
363
470
|
"4. Use `details.inputTypeScript` / `details.outputTypeScript` and `details.typeScriptDefinitions` for compact shapes.",
|
|
364
|
-
"5. Use `tools.executor.
|
|
471
|
+
"5. Use `tools.executor.coreTools.connections.list({})` when you need live saved-connection inventory.",
|
|
365
472
|
"6. Call the tool: `const result = await tools.<path>(input);`",
|
|
366
473
|
"",
|
|
367
474
|
"## Rules",
|
|
368
475
|
"",
|
|
369
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`.",
|
|
370
477
|
'- When you already know the namespace, narrow with `tools.search({ namespace: "github", query: "issues" })`.',
|
|
371
|
-
"- `tools.executor.
|
|
478
|
+
"- `tools.executor.coreTools.connections.list({})` returns saved connections with `{ address, integration, owner, name, ... }`. The `address` field includes the leading `tools.` root.",
|
|
372
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`.",
|
|
373
|
-
"- If `
|
|
374
|
-
"- Always use the
|
|
375
|
-
"- The `tools` object is a lazy proxy \u2014 `Object.keys(tools)` won't work. Use `tools.search()` or `tools.executor.
|
|
376
|
-
'- 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 })`.',
|
|
377
484
|
"- `tools.describe.tool()` returns compact TypeScript shapes. Use `inputTypeScript`, `outputTypeScript`, and `typeScriptDefinitions`.",
|
|
378
485
|
"- For tools that return large collections (e.g. `getStates`, `getAll`), filter results in code rather than calling per-item tools.",
|
|
379
486
|
"- Do not use `fetch` \u2014 all API calls go through `tools.*`.",
|
|
380
487
|
"- If execution pauses for interaction, resume it with the returned `resumePayload`.",
|
|
381
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."
|
|
382
489
|
];
|
|
383
|
-
if (
|
|
490
|
+
if (connectionPrefixes.length > 0) {
|
|
384
491
|
lines.push("");
|
|
385
|
-
lines.push("## Available
|
|
492
|
+
lines.push("## Available connection prefixes");
|
|
386
493
|
lines.push("");
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
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}\``);
|
|
390
498
|
}
|
|
391
|
-
if (
|
|
392
|
-
lines.push(`- ... ${
|
|
499
|
+
if (connectionPrefixes.length > sorted.length) {
|
|
500
|
+
lines.push(`- ... ${connectionPrefixes.length - sorted.length} more`);
|
|
393
501
|
}
|
|
394
502
|
}
|
|
395
503
|
return lines.join("\n");
|
|
@@ -463,7 +571,7 @@ instructions: ${instructions}`);
|
|
|
463
571
|
kind: isUrlElicitation ? "url" : "form",
|
|
464
572
|
message: req.message,
|
|
465
573
|
instructions,
|
|
466
|
-
|
|
574
|
+
address: String(paused.elicitationContext.address),
|
|
467
575
|
args: paused.elicitationContext.args,
|
|
468
576
|
...isUrlElicitation ? { url: req.url } : {},
|
|
469
577
|
...isFormElicitation ? { requestedSchema: req.requestedSchema } : {}
|
|
@@ -494,7 +602,7 @@ var readOptionalOffset = (value, toolName) => {
|
|
|
494
602
|
}
|
|
495
603
|
return Math.floor(value);
|
|
496
604
|
};
|
|
497
|
-
var makeFullInvoker = (executor, invokeOptions) => {
|
|
605
|
+
var makeFullInvoker = (executor, invokeOptions, toolDiscoveryProvider) => {
|
|
498
606
|
const base = makeExecutorToolInvoker(executor, { invokeOptions });
|
|
499
607
|
return {
|
|
500
608
|
invoke: ({ path, args }) => {
|
|
@@ -528,7 +636,10 @@ var makeFullInvoker = (executor, invokeOptions) => {
|
|
|
528
636
|
if (Predicate2.isTagged(offset, "ExecutionToolError")) {
|
|
529
637
|
return Effect3.fail(offset);
|
|
530
638
|
}
|
|
531
|
-
return searchTools(
|
|
639
|
+
return toolDiscoveryProvider.searchTools({
|
|
640
|
+
executor,
|
|
641
|
+
query: args.query ?? "",
|
|
642
|
+
limit,
|
|
532
643
|
namespace: args.namespace,
|
|
533
644
|
offset
|
|
534
645
|
}).pipe(
|
|
@@ -609,7 +720,7 @@ var makeFullInvoker = (executor, invokeOptions) => {
|
|
|
609
720
|
};
|
|
610
721
|
};
|
|
611
722
|
var createExecutionEngine = (config) => {
|
|
612
|
-
const { executor, codeExecutor } = config;
|
|
723
|
+
const { executor, codeExecutor, toolDiscoveryProvider = defaultToolDiscoveryProvider } = config;
|
|
613
724
|
const pausedExecutions = /* @__PURE__ */ new Map();
|
|
614
725
|
let nextId = 0;
|
|
615
726
|
const awaitCompletionOrPause = (fiber, pauseQueue) => Effect3.raceFirst(
|
|
@@ -641,7 +752,11 @@ var createExecutionEngine = (config) => {
|
|
|
641
752
|
yield* Queue.offer(pauseQueue, paused);
|
|
642
753
|
return yield* Deferred.await(responseDeferred);
|
|
643
754
|
});
|
|
644
|
-
const invoker = makeFullInvoker(
|
|
755
|
+
const invoker = makeFullInvoker(
|
|
756
|
+
executor,
|
|
757
|
+
{ onElicitation: elicitationHandler },
|
|
758
|
+
toolDiscoveryProvider
|
|
759
|
+
);
|
|
645
760
|
fiber = yield* Effect3.forkDetach(
|
|
646
761
|
codeExecutor.execute(code, invoker).pipe(Effect3.withSpan("executor.code.exec"))
|
|
647
762
|
);
|
|
@@ -665,9 +780,13 @@ var createExecutionEngine = (config) => {
|
|
|
665
780
|
"mcp.execute.mode": "inline",
|
|
666
781
|
"mcp.execute.code_length": code.length
|
|
667
782
|
});
|
|
668
|
-
const invoker = makeFullInvoker(
|
|
669
|
-
|
|
670
|
-
|
|
783
|
+
const invoker = makeFullInvoker(
|
|
784
|
+
executor,
|
|
785
|
+
{
|
|
786
|
+
onElicitation: options.onElicitation
|
|
787
|
+
},
|
|
788
|
+
toolDiscoveryProvider
|
|
789
|
+
);
|
|
671
790
|
return yield* codeExecutor.execute(code, invoker).pipe(Effect3.withSpan("executor.code.exec"));
|
|
672
791
|
});
|
|
673
792
|
return {
|
|
@@ -683,6 +802,7 @@ export {
|
|
|
683
802
|
ExecutionToolError,
|
|
684
803
|
makeExecutorToolInvoker,
|
|
685
804
|
searchTools,
|
|
805
|
+
defaultToolDiscoveryProvider,
|
|
686
806
|
listExecutorSources,
|
|
687
807
|
describeTool,
|
|
688
808
|
buildExecuteDescription,
|
|
@@ -690,4 +810,4 @@ export {
|
|
|
690
810
|
formatPausedExecution,
|
|
691
811
|
createExecutionEngine
|
|
692
812
|
};
|
|
693
|
-
//# sourceMappingURL=chunk-
|
|
813
|
+
//# sourceMappingURL=chunk-Q2R6Q3HF.js.map
|