@executor-js/execution 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -10
- package/dist/{chunk-BF7CHG2T.js → chunk-QO23HCJR.js} +197 -56
- package/dist/chunk-QO23HCJR.js.map +1 -0
- package/dist/core.js +1 -1
- package/dist/description.d.ts +1 -1
- package/dist/description.d.ts.map +1 -1
- package/dist/description.test.d.ts +2 -0
- package/dist/description.test.d.ts.map +1 -0
- package/dist/engine.d.ts +16 -9
- package/dist/engine.d.ts.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/index.js +73 -38
- package/dist/index.js.map +1 -1
- package/dist/promise.d.ts +16 -7
- package/dist/promise.d.ts.map +1 -1
- package/dist/tool-invoker.d.ts +56 -9
- package/dist/tool-invoker.d.ts.map +1 -1
- package/package.json +7 -7
- package/dist/chunk-BF7CHG2T.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @executor/execution
|
|
1
|
+
# @executor-js/execution
|
|
2
2
|
|
|
3
3
|
Sandboxed JavaScript execution for an executor. Hands a `tools.<namespace>.<name>(...)` proxy into a code sandbox so an agent (or any caller) can run generated TypeScript/JavaScript that invokes the executor's registered tools.
|
|
4
4
|
|
|
@@ -7,22 +7,22 @@ Supports pause/resume for elicitation-driven flows: tools that need user input (
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
|
-
bun add @executor/sdk @executor/execution @executor/runtime-quickjs
|
|
10
|
+
bun add @executor-js/sdk @executor-js/execution @executor-js/runtime-quickjs
|
|
11
11
|
# or
|
|
12
|
-
npm install @executor/sdk @executor/execution @executor/runtime-quickjs
|
|
12
|
+
npm install @executor-js/sdk @executor-js/execution @executor-js/runtime-quickjs
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
`@executor/runtime-quickjs` is the sandbox runtime. It's not a dependency of `@executor/execution` — you bring your own so consumers with a different runtime don't ship ~13 MB of WASM they never use.
|
|
15
|
+
`@executor-js/runtime-quickjs` is the sandbox runtime. It's not a dependency of `@executor-js/execution` — you bring your own so consumers with a different runtime don't ship ~13 MB of WASM they never use.
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
18
18
|
|
|
19
19
|
```ts
|
|
20
|
-
import { createExecutor } from "@executor/sdk";
|
|
21
|
-
import { createExecutionEngine } from "@executor/execution";
|
|
22
|
-
import { makeQuickJsExecutor } from "@executor/runtime-quickjs";
|
|
20
|
+
import { createExecutor } from "@executor-js/sdk";
|
|
21
|
+
import { createExecutionEngine } from "@executor-js/execution";
|
|
22
|
+
import { makeQuickJsExecutor } from "@executor-js/runtime-quickjs";
|
|
23
23
|
|
|
24
24
|
const executor = await createExecutor({
|
|
25
|
-
|
|
25
|
+
onElicitation: "accept-all",
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
const engine = createExecutionEngine({
|
|
@@ -56,6 +56,11 @@ console.log(result);
|
|
|
56
56
|
When the host doesn't support inline elicitation, use `executeWithPause` to intercept the first request as a pause point:
|
|
57
57
|
|
|
58
58
|
```ts
|
|
59
|
+
import type { ExecutionEngine } from "@executor-js/execution";
|
|
60
|
+
|
|
61
|
+
declare const engine: ExecutionEngine;
|
|
62
|
+
declare const code: string;
|
|
63
|
+
|
|
59
64
|
const started = await engine.executeWithPause(code);
|
|
60
65
|
|
|
61
66
|
if (started.status === "paused") {
|
|
@@ -71,6 +76,10 @@ if (started.status === "paused") {
|
|
|
71
76
|
## Workflow description for LLMs
|
|
72
77
|
|
|
73
78
|
```ts
|
|
79
|
+
import type { ExecutionEngine } from "@executor-js/execution";
|
|
80
|
+
|
|
81
|
+
declare const engine: ExecutionEngine;
|
|
82
|
+
|
|
74
83
|
const docs = await engine.getDescription();
|
|
75
84
|
// Returns the canonical "use tools.search(), then tools.describe.tool(), then call …"
|
|
76
85
|
// workflow prose + per-namespace tool listing. Feed this to an LLM so it knows
|
|
@@ -79,10 +88,10 @@ const docs = await engine.getDescription();
|
|
|
79
88
|
|
|
80
89
|
## Using with Effect
|
|
81
90
|
|
|
82
|
-
If you're building on `@executor/sdk` (the raw Effect entry), import from the `/core` subpath. The returned engine is Effect-native: `execute`, `executeWithPause`, and `resume` all become `Effect.Effect<...>`, and `onElicitation` is an `ElicitationHandler` returning `Effect.Effect<ElicitationResponse>`.
|
|
91
|
+
If you're building on `@executor-js/sdk/core` (the raw Effect entry), import from the `/core` subpath. The returned engine is Effect-native: `execute`, `executeWithPause`, and `resume` all become `Effect.Effect<...>`, and `onElicitation` is an `ElicitationHandler` returning `Effect.Effect<ElicitationResponse>`.
|
|
83
92
|
|
|
84
93
|
```ts
|
|
85
|
-
import { createExecutionEngine } from "@executor/execution";
|
|
94
|
+
import { createExecutionEngine } from "@executor-js/execution/core";
|
|
86
95
|
```
|
|
87
96
|
|
|
88
97
|
## Status
|
|
@@ -1,26 +1,65 @@
|
|
|
1
1
|
// src/errors.ts
|
|
2
2
|
import * as Data from "effect/Data";
|
|
3
|
+
import { CodeExecutionError } from "@executor-js/codemode-core";
|
|
3
4
|
var ExecutionToolError = class extends Data.TaggedError("ExecutionToolError") {
|
|
4
5
|
};
|
|
5
6
|
|
|
6
7
|
// src/tool-invoker.ts
|
|
7
8
|
import { Effect } from "effect";
|
|
9
|
+
import * as Cause from "effect/Cause";
|
|
10
|
+
var extractSourceNamespace = (path) => {
|
|
11
|
+
const idx = path.indexOf(".");
|
|
12
|
+
return idx === -1 ? path : path.slice(0, idx);
|
|
13
|
+
};
|
|
14
|
+
var stringifyUnknown = (value) => {
|
|
15
|
+
try {
|
|
16
|
+
return JSON.stringify(value) ?? String(value);
|
|
17
|
+
} catch {
|
|
18
|
+
return String(value);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
var hasStringMessage = (value) => value !== null && typeof value === "object" && "message" in value && typeof value.message === "string";
|
|
22
|
+
var messageFromErrorLike = (value) => {
|
|
23
|
+
if (value instanceof Error || hasStringMessage(value)) {
|
|
24
|
+
return value.message;
|
|
25
|
+
}
|
|
26
|
+
return void 0;
|
|
27
|
+
};
|
|
28
|
+
var renderToolErrorMessage = (error) => messageFromErrorLike(error) ?? (typeof error === "undefined" ? "Tool execution failed" : stringifyUnknown(error));
|
|
8
29
|
var makeExecutorToolInvoker = (executor, options) => ({
|
|
9
|
-
invoke: ({ path, args })
|
|
30
|
+
invoke: Effect.fn("mcp.tool.dispatch")(function* ({ path, args }) {
|
|
31
|
+
yield* Effect.annotateCurrentSpan({
|
|
32
|
+
"mcp.tool.name": path,
|
|
33
|
+
"mcp.tool.source_id": extractSourceNamespace(path)
|
|
34
|
+
});
|
|
10
35
|
const result = yield* executor.tools.invoke(path, args, options.invokeOptions).pipe(
|
|
11
|
-
Effect.
|
|
12
|
-
|
|
13
|
-
(err)
|
|
36
|
+
Effect.catchCause((cause) => {
|
|
37
|
+
const err = cause.reasons.find(Cause.isFailReason)?.error;
|
|
38
|
+
if (!isElicitationDeclinedError(err)) {
|
|
39
|
+
return Effect.fail(
|
|
40
|
+
new ExecutionToolError({
|
|
41
|
+
message: renderToolErrorMessage(err),
|
|
42
|
+
cause: err ?? cause
|
|
43
|
+
})
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return Effect.fail(
|
|
14
47
|
new ExecutionToolError({
|
|
15
48
|
message: `Tool "${err.toolId}" requires approval but the request was ${err.action === "cancel" ? "cancelled" : "declined"} by the user.`,
|
|
16
49
|
cause: err
|
|
17
50
|
})
|
|
18
|
-
)
|
|
19
|
-
)
|
|
51
|
+
);
|
|
52
|
+
})
|
|
20
53
|
);
|
|
21
54
|
const r = result;
|
|
22
55
|
if (r !== null && typeof r === "object" && "error" in r && r.error !== null && r.error !== void 0) {
|
|
23
|
-
|
|
56
|
+
const error = r.error;
|
|
57
|
+
return yield* Effect.fail(
|
|
58
|
+
new ExecutionToolError({
|
|
59
|
+
message: renderToolErrorMessage(error),
|
|
60
|
+
cause: error
|
|
61
|
+
})
|
|
62
|
+
);
|
|
24
63
|
}
|
|
25
64
|
if (r !== null && typeof r === "object" && "data" in r) {
|
|
26
65
|
return r.data;
|
|
@@ -28,6 +67,20 @@ var makeExecutorToolInvoker = (executor, options) => ({
|
|
|
28
67
|
return r;
|
|
29
68
|
})
|
|
30
69
|
});
|
|
70
|
+
var isElicitationDeclinedError = (value) => value !== null && typeof value === "object" && "_tag" in value && value._tag === "ElicitationDeclinedError" && "toolId" in value && typeof value.toolId === "string" && "action" in value && (value.action === "cancel" || value.action === "decline");
|
|
71
|
+
var paginate = (all, offset, limit) => {
|
|
72
|
+
const total = all.length;
|
|
73
|
+
const start = Math.min(Math.max(offset, 0), total);
|
|
74
|
+
const items = all.slice(start, start + limit);
|
|
75
|
+
const consumed = start + items.length;
|
|
76
|
+
const hasMore = consumed < total;
|
|
77
|
+
return {
|
|
78
|
+
items,
|
|
79
|
+
total,
|
|
80
|
+
hasMore,
|
|
81
|
+
nextOffset: hasMore ? consumed : null
|
|
82
|
+
};
|
|
83
|
+
};
|
|
31
84
|
var SEARCH_FIELD_WEIGHTS = {
|
|
32
85
|
path: 12,
|
|
33
86
|
sourceId: 8,
|
|
@@ -148,27 +201,49 @@ var scoreToolMatch = (tool, query) => {
|
|
|
148
201
|
score
|
|
149
202
|
};
|
|
150
203
|
};
|
|
151
|
-
var searchTools = (executor, query, limit = 12, options)
|
|
204
|
+
var searchTools = Effect.fn("executor.tools.search")(function* (executor, query, limit = 12, options) {
|
|
205
|
+
const offset = options?.offset ?? 0;
|
|
206
|
+
yield* Effect.annotateCurrentSpan({
|
|
207
|
+
"executor.search.query_length": query.length,
|
|
208
|
+
"executor.search.limit": limit,
|
|
209
|
+
"executor.search.offset": offset,
|
|
210
|
+
...options?.namespace ? { "executor.search.namespace": options.namespace } : {}
|
|
211
|
+
});
|
|
212
|
+
const empty = {
|
|
213
|
+
items: [],
|
|
214
|
+
total: 0,
|
|
215
|
+
hasMore: false,
|
|
216
|
+
nextOffset: null
|
|
217
|
+
};
|
|
152
218
|
if (normalizeSearchText(query).length === 0) {
|
|
153
|
-
return
|
|
219
|
+
return empty;
|
|
154
220
|
}
|
|
155
|
-
const all = yield* executor.tools.list().pipe(Effect.orDie);
|
|
156
|
-
|
|
221
|
+
const all = yield* executor.tools.list({ includeAnnotations: false }).pipe(Effect.orDie);
|
|
222
|
+
const ranked = all.filter((tool) => matchesNamespace(tool, options?.namespace)).map((tool) => scoreToolMatch(tool, query)).filter((tool) => tool !== null).sort((left, right) => right.score - left.score || left.path.localeCompare(right.path));
|
|
223
|
+
const page = paginate(ranked, offset, limit);
|
|
224
|
+
yield* Effect.annotateCurrentSpan({
|
|
225
|
+
"executor.search.candidate_count": all.length,
|
|
226
|
+
"executor.search.match_count": ranked.length,
|
|
227
|
+
"executor.search.result_count": page.items.length,
|
|
228
|
+
"executor.search.has_more": page.hasMore
|
|
229
|
+
});
|
|
230
|
+
return page;
|
|
157
231
|
});
|
|
158
|
-
var listExecutorSources = (executor
|
|
232
|
+
var listExecutorSources = Effect.fn("executor.sources.list")(function* (executor, options) {
|
|
159
233
|
const normalizedQuery = normalizeSearchText(options?.query ?? "");
|
|
160
|
-
const limit = options?.limit ??
|
|
234
|
+
const limit = options?.limit ?? 50;
|
|
235
|
+
const offset = options?.offset ?? 0;
|
|
161
236
|
const sources = yield* executor.sources.list().pipe(Effect.orDie);
|
|
162
237
|
const filtered = normalizedQuery.length === 0 ? sources : sources.filter((source) => {
|
|
163
238
|
const haystack = normalizeSearchText([source.id, source.name, source.kind].join(" "));
|
|
164
239
|
return tokenizeSearchText(normalizedQuery).every((token) => haystack.includes(token));
|
|
165
240
|
});
|
|
166
|
-
const allTools = yield* executor.tools.list().pipe(Effect.orDie);
|
|
241
|
+
const allTools = yield* executor.tools.list({ includeAnnotations: false }).pipe(Effect.orDie);
|
|
167
242
|
const toolCountBySource = /* @__PURE__ */ new Map();
|
|
168
243
|
for (const tool of allTools) {
|
|
169
244
|
toolCountBySource.set(tool.sourceId, (toolCountBySource.get(tool.sourceId) ?? 0) + 1);
|
|
170
245
|
}
|
|
171
|
-
const
|
|
246
|
+
const sortedWithCounts = filtered.map(
|
|
172
247
|
(source) => ({
|
|
173
248
|
id: source.id,
|
|
174
249
|
name: source.name,
|
|
@@ -178,10 +253,18 @@ var listExecutorSources = (executor, options) => Effect.gen(function* () {
|
|
|
178
253
|
canRefresh: source.canRefresh,
|
|
179
254
|
toolCount: toolCountBySource.get(source.id) ?? 0
|
|
180
255
|
})
|
|
181
|
-
);
|
|
182
|
-
|
|
256
|
+
).sort((left, right) => left.name.localeCompare(right.name) || left.id.localeCompare(right.id));
|
|
257
|
+
const page = paginate(sortedWithCounts, offset, limit);
|
|
258
|
+
yield* Effect.annotateCurrentSpan({
|
|
259
|
+
"executor.sources.candidate_count": sources.length,
|
|
260
|
+
"executor.sources.match_count": sortedWithCounts.length,
|
|
261
|
+
"executor.sources.result_count": page.items.length,
|
|
262
|
+
"executor.sources.has_more": page.hasMore
|
|
263
|
+
});
|
|
264
|
+
return page;
|
|
183
265
|
});
|
|
184
|
-
var describeTool = (executor
|
|
266
|
+
var describeTool = Effect.fn("executor.tools.describe")(function* (executor, path) {
|
|
267
|
+
yield* Effect.annotateCurrentSpan({ "mcp.tool.name": path });
|
|
185
268
|
const schema = yield* executor.tools.schema(path);
|
|
186
269
|
if (schema === null) {
|
|
187
270
|
return { path, name: path };
|
|
@@ -199,19 +282,25 @@ var describeTool = (executor, path) => Effect.gen(function* () {
|
|
|
199
282
|
// src/description.ts
|
|
200
283
|
import { Effect as Effect2 } from "effect";
|
|
201
284
|
var buildExecuteDescription = (executor) => Effect2.gen(function* () {
|
|
202
|
-
const sources = yield* executor.sources.list().pipe(Effect2.orDie);
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
285
|
+
const sources = yield* executor.sources.list().pipe(Effect2.orDie, Effect2.withSpan("executor.sources.list"));
|
|
286
|
+
const description = yield* Effect2.sync(() => formatDescription(sources)).pipe(
|
|
287
|
+
Effect2.withSpan("schema.compile.description", {
|
|
288
|
+
attributes: { "executor.source_count": sources.length }
|
|
289
|
+
})
|
|
290
|
+
);
|
|
291
|
+
yield* Effect2.annotateCurrentSpan({
|
|
292
|
+
"executor.source_count": sources.length,
|
|
293
|
+
"schema.kind": "execute"
|
|
294
|
+
});
|
|
295
|
+
return description;
|
|
296
|
+
}).pipe(Effect2.withSpan("schema.describe.execute"));
|
|
297
|
+
var formatDescription = (sources) => {
|
|
209
298
|
const lines = [
|
|
210
299
|
"Execute TypeScript in a sandboxed runtime with access to configured API tools.",
|
|
211
300
|
"",
|
|
212
301
|
"## Workflow",
|
|
213
302
|
"",
|
|
214
|
-
'1. `const matches = await tools.search({ query: "<intent + key nouns>", limit: 12 });`',
|
|
303
|
+
'1. `const { items: matches } = await tools.search({ query: "<intent + key nouns>", limit: 12 });`',
|
|
215
304
|
'2. `const path = matches[0]?.path; if (!path) return "No matching tools found.";`',
|
|
216
305
|
"3. `const details = await tools.describe.tool({ path });`",
|
|
217
306
|
"4. Use `details.inputTypeScript` / `details.outputTypeScript` and `details.typeScriptDefinitions` for compact shapes.",
|
|
@@ -220,9 +309,10 @@ var formatDescription = (namespaces, sources) => {
|
|
|
220
309
|
"",
|
|
221
310
|
"## Rules",
|
|
222
311
|
"",
|
|
223
|
-
"- `tools.search()` returns ranked matches,
|
|
312
|
+
"- `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`.",
|
|
224
313
|
'- When you already know the namespace, narrow with `tools.search({ namespace: "github", query: "issues" })`.',
|
|
225
|
-
"-
|
|
314
|
+
"- `tools.executor.sources.list()` returns the same paged shape: `{ items: [{ id, toolCount, ... }], total, hasMore, nextOffset }`.",
|
|
315
|
+
"- If `hasMore` is true and you didn't find what you need, fetch the next page: `tools.search({ query, offset: nextOffset, limit })`. Same `offset` parameter on `tools.executor.sources.list({ offset, limit })`.",
|
|
226
316
|
"- Always use the namespace prefix when calling tools: `tools.<namespace>.<tool>(args)`. Example: `tools.home_assistant_rest_api.states.getState(...)` \u2014 not `tools.states.getState(...)`.",
|
|
227
317
|
"- The `tools` object is a lazy proxy \u2014 `Object.keys(tools)` won't work. Use `tools.search()` or `tools.executor.sources.list()` instead.",
|
|
228
318
|
'- Pass an object to system tools, e.g. `tools.search({ query: "..." })`, `tools.executor.sources.list()`, and `tools.describe.tool({ path })`.',
|
|
@@ -231,15 +321,14 @@ var formatDescription = (namespaces, sources) => {
|
|
|
231
321
|
"- Do not use `fetch` \u2014 all API calls go through `tools.*`.",
|
|
232
322
|
"- If execution pauses for interaction, resume it with the returned `resumePayload`."
|
|
233
323
|
];
|
|
234
|
-
if (
|
|
324
|
+
if (sources.length > 0) {
|
|
235
325
|
lines.push("");
|
|
236
326
|
lines.push("## Available namespaces");
|
|
237
327
|
lines.push("");
|
|
238
|
-
const sorted = [...
|
|
239
|
-
for (const
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
lines.push(`- \`${ns}\`${label !== ns ? ` \u2014 ${label}` : ""}`);
|
|
328
|
+
const sorted = [...sources].sort((a, b) => a.id.localeCompare(b.id));
|
|
329
|
+
for (const source of sorted) {
|
|
330
|
+
const label = source.name;
|
|
331
|
+
lines.push(`- \`${source.id}\`${label !== source.id ? ` \u2014 ${label}` : ""}`);
|
|
243
332
|
}
|
|
244
333
|
}
|
|
245
334
|
return lines.join("\n");
|
|
@@ -320,6 +409,17 @@ var readOptionalLimit = (value, toolName) => {
|
|
|
320
409
|
}
|
|
321
410
|
return Math.floor(value);
|
|
322
411
|
};
|
|
412
|
+
var readOptionalOffset = (value, toolName) => {
|
|
413
|
+
if (value === void 0) {
|
|
414
|
+
return 0;
|
|
415
|
+
}
|
|
416
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
|
|
417
|
+
return new ExecutionToolError({
|
|
418
|
+
message: `${toolName} offset must be a non-negative number when provided`
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
return Math.floor(value);
|
|
422
|
+
};
|
|
323
423
|
var makeFullInvoker = (executor, invokeOptions) => {
|
|
324
424
|
const base = makeExecutorToolInvoker(executor, { invokeOptions });
|
|
325
425
|
return {
|
|
@@ -328,7 +428,7 @@ var makeFullInvoker = (executor, invokeOptions) => {
|
|
|
328
428
|
if (!isRecord(args)) {
|
|
329
429
|
return Effect3.fail(
|
|
330
430
|
new ExecutionToolError({
|
|
331
|
-
message: "tools.search expects an object: { query?: string; namespace?: string; limit?: number }"
|
|
431
|
+
message: "tools.search expects an object: { query?: string; namespace?: string; limit?: number; offset?: number }"
|
|
332
432
|
})
|
|
333
433
|
);
|
|
334
434
|
}
|
|
@@ -350,15 +450,24 @@ var makeFullInvoker = (executor, invokeOptions) => {
|
|
|
350
450
|
if (limit instanceof ExecutionToolError) {
|
|
351
451
|
return Effect3.fail(limit);
|
|
352
452
|
}
|
|
453
|
+
const offset = readOptionalOffset(args.offset, "tools.search");
|
|
454
|
+
if (offset instanceof ExecutionToolError) {
|
|
455
|
+
return Effect3.fail(offset);
|
|
456
|
+
}
|
|
353
457
|
return searchTools(executor, args.query ?? "", limit, {
|
|
354
|
-
namespace: args.namespace
|
|
355
|
-
|
|
458
|
+
namespace: args.namespace,
|
|
459
|
+
offset
|
|
460
|
+
}).pipe(
|
|
461
|
+
Effect3.withSpan("mcp.tool.dispatch", {
|
|
462
|
+
attributes: { "mcp.tool.name": path, "executor.tool.builtin": true }
|
|
463
|
+
})
|
|
464
|
+
);
|
|
356
465
|
}
|
|
357
466
|
if (path === "executor.sources.list") {
|
|
358
467
|
if (args !== void 0 && !isRecord(args)) {
|
|
359
468
|
return Effect3.fail(
|
|
360
469
|
new ExecutionToolError({
|
|
361
|
-
message: "tools.executor.sources.list expects an object: { query?: string; limit?: number }"
|
|
470
|
+
message: "tools.executor.sources.list expects an object: { query?: string; limit?: number; offset?: number }"
|
|
362
471
|
})
|
|
363
472
|
);
|
|
364
473
|
}
|
|
@@ -376,10 +485,22 @@ var makeFullInvoker = (executor, invokeOptions) => {
|
|
|
376
485
|
if (limit instanceof ExecutionToolError) {
|
|
377
486
|
return Effect3.fail(limit);
|
|
378
487
|
}
|
|
488
|
+
const offset = readOptionalOffset(
|
|
489
|
+
isRecord(args) ? args.offset : void 0,
|
|
490
|
+
"tools.executor.sources.list"
|
|
491
|
+
);
|
|
492
|
+
if (offset instanceof ExecutionToolError) {
|
|
493
|
+
return Effect3.fail(offset);
|
|
494
|
+
}
|
|
379
495
|
return listExecutorSources(executor, {
|
|
380
496
|
query: isRecord(args) && typeof args.query === "string" ? args.query : void 0,
|
|
381
|
-
limit
|
|
382
|
-
|
|
497
|
+
limit,
|
|
498
|
+
offset
|
|
499
|
+
}).pipe(
|
|
500
|
+
Effect3.withSpan("mcp.tool.dispatch", {
|
|
501
|
+
attributes: { "mcp.tool.name": path, "executor.tool.builtin": true }
|
|
502
|
+
})
|
|
503
|
+
);
|
|
383
504
|
}
|
|
384
505
|
if (path === "describe.tool") {
|
|
385
506
|
if (!isRecord(args)) {
|
|
@@ -399,27 +520,37 @@ var makeFullInvoker = (executor, invokeOptions) => {
|
|
|
399
520
|
})
|
|
400
521
|
);
|
|
401
522
|
}
|
|
402
|
-
return describeTool(executor, args.path)
|
|
523
|
+
return describeTool(executor, args.path).pipe(
|
|
524
|
+
Effect3.withSpan("mcp.tool.dispatch", {
|
|
525
|
+
attributes: {
|
|
526
|
+
"mcp.tool.name": path,
|
|
527
|
+
"executor.tool.builtin": true,
|
|
528
|
+
"executor.tool.target_path": args.path
|
|
529
|
+
}
|
|
530
|
+
})
|
|
531
|
+
);
|
|
403
532
|
}
|
|
404
533
|
return base.invoke({ path, args });
|
|
405
534
|
}
|
|
406
535
|
};
|
|
407
536
|
};
|
|
408
|
-
var runEffect = (effect) => Effect3.runPromise(effect);
|
|
409
537
|
var createExecutionEngine = (config) => {
|
|
410
538
|
const { executor, codeExecutor } = config;
|
|
411
539
|
const pausedExecutions = /* @__PURE__ */ new Map();
|
|
412
540
|
let nextId = 0;
|
|
413
541
|
const awaitCompletionOrPause = (fiber, pauseSignal) => Effect3.race(
|
|
414
542
|
Fiber.join(fiber).pipe(
|
|
415
|
-
Effect3.orDie,
|
|
416
543
|
Effect3.map((result) => ({ status: "completed", result }))
|
|
417
544
|
),
|
|
418
545
|
Deferred.await(pauseSignal).pipe(
|
|
419
546
|
Effect3.map((paused) => ({ status: "paused", execution: paused }))
|
|
420
547
|
)
|
|
421
548
|
);
|
|
422
|
-
const startPausableExecution =
|
|
549
|
+
const startPausableExecution = Effect3.fn("mcp.execute")(function* (code) {
|
|
550
|
+
yield* Effect3.annotateCurrentSpan({
|
|
551
|
+
"mcp.execute.mode": "pausable",
|
|
552
|
+
"mcp.execute.code_length": code.length
|
|
553
|
+
});
|
|
423
554
|
const pauseSignalRef = yield* Ref.make(yield* Deferred.make());
|
|
424
555
|
let fiber;
|
|
425
556
|
const elicitationHandler = (ctx) => Effect3.gen(function* () {
|
|
@@ -438,11 +569,16 @@ var createExecutionEngine = (config) => {
|
|
|
438
569
|
return yield* Deferred.await(responseDeferred);
|
|
439
570
|
});
|
|
440
571
|
const invoker = makeFullInvoker(executor, { onElicitation: elicitationHandler });
|
|
441
|
-
fiber = yield* Effect3.
|
|
572
|
+
fiber = yield* Effect3.forkDetach(
|
|
573
|
+
codeExecutor.execute(code, invoker).pipe(Effect3.withSpan("executor.code.exec"))
|
|
574
|
+
);
|
|
442
575
|
const initialSignal = yield* Ref.get(pauseSignalRef);
|
|
443
576
|
return yield* awaitCompletionOrPause(fiber, initialSignal);
|
|
444
577
|
});
|
|
445
|
-
const resumeExecution =
|
|
578
|
+
const resumeExecution = Effect3.fn("mcp.execute.resume")(function* (executionId, response) {
|
|
579
|
+
yield* Effect3.annotateCurrentSpan({
|
|
580
|
+
"mcp.execute.resume.action": response.action
|
|
581
|
+
});
|
|
446
582
|
const paused = pausedExecutions.get(executionId);
|
|
447
583
|
if (!paused) return null;
|
|
448
584
|
pausedExecutions.delete(executionId);
|
|
@@ -454,16 +590,21 @@ var createExecutionEngine = (config) => {
|
|
|
454
590
|
});
|
|
455
591
|
return yield* awaitCompletionOrPause(paused.fiber, nextSignal);
|
|
456
592
|
});
|
|
593
|
+
const runInlineExecution = Effect3.fn("mcp.execute")(function* (code, options) {
|
|
594
|
+
yield* Effect3.annotateCurrentSpan({
|
|
595
|
+
"mcp.execute.mode": "inline",
|
|
596
|
+
"mcp.execute.code_length": code.length
|
|
597
|
+
});
|
|
598
|
+
const invoker = makeFullInvoker(executor, {
|
|
599
|
+
onElicitation: options.onElicitation
|
|
600
|
+
});
|
|
601
|
+
return yield* codeExecutor.execute(code, invoker).pipe(Effect3.withSpan("executor.code.exec"));
|
|
602
|
+
});
|
|
457
603
|
return {
|
|
458
|
-
execute:
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
return runEffect(codeExecutor.execute(code, invoker));
|
|
463
|
-
},
|
|
464
|
-
executeWithPause: (code) => runEffect(startPausableExecution(code)),
|
|
465
|
-
resume: (executionId, response) => runEffect(resumeExecution(executionId, response)),
|
|
466
|
-
getDescription: () => runEffect(buildExecuteDescription(executor))
|
|
604
|
+
execute: runInlineExecution,
|
|
605
|
+
executeWithPause: startPausableExecution,
|
|
606
|
+
resume: resumeExecution,
|
|
607
|
+
getDescription: buildExecuteDescription(executor)
|
|
467
608
|
};
|
|
468
609
|
};
|
|
469
610
|
|
|
@@ -478,4 +619,4 @@ export {
|
|
|
478
619
|
formatPausedExecution,
|
|
479
620
|
createExecutionEngine
|
|
480
621
|
};
|
|
481
|
-
//# sourceMappingURL=chunk-
|
|
622
|
+
//# sourceMappingURL=chunk-QO23HCJR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/tool-invoker.ts","../src/description.ts","../src/engine.ts"],"sourcesContent":["import * as Data from \"effect/Data\";\n\nexport class ExecutionToolError extends Data.TaggedError(\"ExecutionToolError\")<{\n readonly message: string;\n readonly cause?: unknown;\n}> {}\n\n// `CodeExecutionError` lives in `@executor-js/codemode-core` — the `CodeExecutor`\n// interface uses it as the default error channel, so the runtime packages\n// can import the same class directly.\nexport { CodeExecutionError } from \"@executor-js/codemode-core\";\n","import { Effect } from \"effect\";\nimport * as Cause from \"effect/Cause\";\nimport type {\n Executor,\n ToolId,\n Tool,\n ToolSchema,\n InvokeOptions,\n Source,\n} from \"@executor-js/sdk/core\";\nimport type { SandboxToolInvoker } from \"@executor-js/codemode-core\";\nimport { ExecutionToolError } from \"./errors\";\n\n/**\n * Extract the source namespace from a tool path. Tool paths look like\n * \"<sourceId>.<op>\" or \"<sourceId>.<group>.<op>\" — we take the first\n * segment as a cheap, non-lookup stand-in for the source id so the span\n * attribute is always populated without hitting `executor.sources.list()`\n * per call.\n */\nconst extractSourceNamespace = (path: string): string => {\n const idx = path.indexOf(\".\");\n return idx === -1 ? path : path.slice(0, idx);\n};\n\nconst stringifyUnknown = (value: unknown): string => {\n try {\n return JSON.stringify(value) ?? String(value);\n } catch {\n return String(value);\n }\n};\n\nconst hasStringMessage = (value: unknown): value is { readonly message: string } =>\n value !== null &&\n typeof value === \"object\" &&\n \"message\" in value &&\n typeof value.message === \"string\";\n\nconst messageFromErrorLike = (value: unknown): string | undefined => {\n if (value instanceof Error || hasStringMessage(value)) {\n return value.message;\n }\n return undefined;\n};\n\nconst renderToolErrorMessage = (error: unknown): string =>\n messageFromErrorLike(error) ??\n (typeof error === \"undefined\" ? \"Tool execution failed\" : stringifyUnknown(error));\n\n/**\n * Bridges QuickJS `tools.someSource.someOp(args)` calls into\n * `executor.tools.invoke(toolId, args)`.\n *\n * Wrapped in `Effect.fn(\"mcp.tool.dispatch\")` so every tool call becomes a\n * span in the Effect tracer. Attributes:\n * - `mcp.tool.name` — full tool path (e.g. \"github.repos.get\")\n * - `mcp.tool.source_id` — first segment of the path (namespace)\n *\n * `mcp.tool.kind` (openapi | mcp | graphql | code) is NOT annotated here\n * because it would require a `sources.list()` lookup on every invocation.\n * Callers that already know the source kind can annotate at their own span.\n */\nexport const makeExecutorToolInvoker = (\n executor: Executor,\n options: { readonly invokeOptions: InvokeOptions },\n): SandboxToolInvoker => ({\n invoke: Effect.fn(\"mcp.tool.dispatch\")(function* ({ path, args }) {\n yield* Effect.annotateCurrentSpan({\n \"mcp.tool.name\": path,\n \"mcp.tool.source_id\": extractSourceNamespace(path),\n });\n\n const result = yield* executor.tools.invoke(path as ToolId, args, options.invokeOptions).pipe(\n Effect.catchCause((cause): Effect.Effect<never, ExecutionToolError> => {\n const err = cause.reasons.find(Cause.isFailReason)?.error;\n if (!isElicitationDeclinedError(err)) {\n return Effect.fail(\n new ExecutionToolError({\n message: renderToolErrorMessage(err),\n cause: err ?? cause,\n }),\n );\n }\n return Effect.fail(\n new ExecutionToolError({\n message: `Tool \"${err.toolId}\" requires approval but the request was ${err.action === \"cancel\" ? \"cancelled\" : \"declined\"} by the user.`,\n cause: err,\n }),\n );\n }),\n );\n const r = result as { readonly error?: unknown; readonly data?: unknown } | unknown;\n if (\n r !== null &&\n typeof r === \"object\" &&\n \"error\" in r &&\n (r as { error?: unknown }).error !== null &&\n (r as { error?: unknown }).error !== undefined\n ) {\n const error = (r as { error: unknown }).error;\n return yield* Effect.fail(\n new ExecutionToolError({\n message: renderToolErrorMessage(error),\n cause: error,\n }),\n );\n }\n if (r !== null && typeof r === \"object\" && \"data\" in r) {\n return (r as { data: unknown }).data;\n }\n return r;\n }),\n});\n\nconst isElicitationDeclinedError = (\n value: unknown,\n): value is { readonly _tag: \"ElicitationDeclinedError\"; readonly toolId: string; readonly action: \"cancel\" | \"decline\" } =>\n value !== null &&\n typeof value === \"object\" &&\n \"_tag\" in value &&\n value._tag === \"ElicitationDeclinedError\" &&\n \"toolId\" in value &&\n typeof value.toolId === \"string\" &&\n \"action\" in value &&\n (value.action === \"cancel\" || value.action === \"decline\");\n\nexport type ToolDiscoveryResult = {\n readonly path: string;\n readonly name: string;\n readonly description?: string;\n readonly sourceId: string;\n readonly score: number;\n};\n\nexport type ExecutorSourceListItem = {\n readonly id: string;\n readonly name: string;\n readonly kind: string;\n readonly runtime?: boolean;\n readonly canRemove?: boolean;\n readonly canRefresh?: boolean;\n readonly toolCount: number;\n};\n\n/**\n * Page of results from a list-style discovery tool. Shared by\n * `tools.search` and `tools.executor.sources.list` so the model sees one\n * consistent shape:\n *\n * - `items` — the page (slice).\n * - `total` — count after filtering, before pagination. The model\n * can use this to detect truncation.\n * - `hasMore` — convenience flag for `(offset + items.length) < total`.\n * - `nextOffset` — concrete offset for the next page when `hasMore`,\n * `null` otherwise. Pre-computing it removes a class of\n * off-by-one mistakes when the model paginates.\n */\nexport type PagedResult<T> = {\n readonly items: readonly T[];\n readonly total: number;\n readonly hasMore: boolean;\n readonly nextOffset: number | null;\n};\n\nconst paginate = <T>(all: readonly T[], offset: number, limit: number): PagedResult<T> => {\n const total = all.length;\n const start = Math.min(Math.max(offset, 0), total);\n const items = all.slice(start, start + limit);\n const consumed = start + items.length;\n const hasMore = consumed < total;\n return {\n items,\n total,\n hasMore,\n nextOffset: hasMore ? consumed : null,\n };\n};\n\ntype SearchableTool = Pick<Tool, \"id\" | \"sourceId\" | \"name\" | \"description\">;\n\ntype PreparedField = {\n readonly raw: string;\n readonly tokens: readonly string[];\n};\n\nconst SEARCH_FIELD_WEIGHTS = {\n path: 12,\n sourceId: 8,\n name: 10,\n description: 5,\n} as const;\n\nconst normalizeSearchText = (value: string): string =>\n value\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .replace(/[_./:-]+/g, \" \")\n .toLowerCase()\n .trim();\n\nconst tokenizeSearchText = (value: string): string[] =>\n normalizeSearchText(value)\n .split(/[^a-z0-9]+/)\n .map((token) => token.trim())\n .filter(Boolean);\n\nconst prepareField = (value?: string): PreparedField => ({\n raw: normalizeSearchText(value ?? \"\"),\n tokens: tokenizeSearchText(value ?? \"\"),\n});\n\nconst scorePreparedField = (\n query: string,\n queryTokens: readonly string[],\n field: PreparedField,\n weight: number,\n): {\n readonly score: number;\n readonly matchedTokens: ReadonlySet<string>;\n readonly exactPhraseMatch: boolean;\n} => {\n if (field.raw.length === 0) {\n return {\n score: 0,\n matchedTokens: new Set<string>(),\n exactPhraseMatch: false,\n };\n }\n\n let score = 0;\n const matchedTokens = new Set<string>();\n const exactPhraseMatch = query.length > 0 && field.raw.includes(query);\n\n if (query.length > 0) {\n if (field.raw === query) {\n score += weight * 14;\n } else if (field.raw.startsWith(query)) {\n score += weight * 9;\n } else if (exactPhraseMatch) {\n score += weight * 6;\n }\n }\n\n for (const token of queryTokens) {\n if (field.tokens.includes(token)) {\n score += weight * 4;\n matchedTokens.add(token);\n continue;\n }\n\n if (\n field.tokens.some((candidate) => candidate.startsWith(token) || token.startsWith(candidate))\n ) {\n score += weight * 2;\n matchedTokens.add(token);\n continue;\n }\n\n if (field.raw.includes(token)) {\n score += weight;\n matchedTokens.add(token);\n }\n }\n\n return {\n score,\n matchedTokens,\n exactPhraseMatch,\n };\n};\n\nconst matchesNamespace = (tool: SearchableTool, namespace?: string): boolean => {\n if (!namespace || normalizeSearchText(namespace).length === 0) {\n return true;\n }\n\n const namespaceTokens = tokenizeSearchText(namespace);\n if (namespaceTokens.length === 0) {\n return true;\n }\n\n const sourceTokens = tokenizeSearchText(tool.sourceId);\n const pathTokens = tokenizeSearchText(tool.id);\n\n const isPrefixMatch = (tokens: readonly string[]): boolean =>\n namespaceTokens.every((token, index) => tokens[index] === token);\n\n return isPrefixMatch(sourceTokens) || isPrefixMatch(pathTokens);\n};\n\nconst scoreToolMatch = (tool: SearchableTool, query: string): ToolDiscoveryResult | null => {\n const normalizedQuery = normalizeSearchText(query);\n const queryTokens = tokenizeSearchText(query);\n\n if (normalizedQuery.length === 0 || queryTokens.length === 0) {\n return null;\n }\n\n const path = prepareField(tool.id);\n const sourceId = prepareField(tool.sourceId);\n const name = prepareField(tool.name);\n const description = prepareField(tool.description);\n\n const fieldScores = [\n scorePreparedField(normalizedQuery, queryTokens, path, SEARCH_FIELD_WEIGHTS.path),\n scorePreparedField(normalizedQuery, queryTokens, sourceId, SEARCH_FIELD_WEIGHTS.sourceId),\n scorePreparedField(normalizedQuery, queryTokens, name, SEARCH_FIELD_WEIGHTS.name),\n scorePreparedField(normalizedQuery, queryTokens, description, SEARCH_FIELD_WEIGHTS.description),\n ];\n\n const matchedTokens = new Set<string>();\n let score = 0;\n let exactPhraseMatch = false;\n\n for (const fieldScore of fieldScores) {\n score += fieldScore.score;\n exactPhraseMatch ||= fieldScore.exactPhraseMatch;\n for (const token of fieldScore.matchedTokens) {\n matchedTokens.add(token);\n }\n }\n\n if (matchedTokens.size === 0) {\n return null;\n }\n\n const coverage = matchedTokens.size / queryTokens.length;\n const minimumCoverage = queryTokens.length <= 2 ? 1 : 0.6;\n\n if (coverage < minimumCoverage && !exactPhraseMatch) {\n return null;\n }\n\n if (coverage === 1) {\n score += 25;\n } else {\n score += Math.round(coverage * 10);\n }\n\n if (path.tokens[0] === queryTokens[0] || name.tokens[0] === queryTokens[0]) {\n score += 8;\n }\n\n if (\n normalizeSearchText(tool.id) === normalizedQuery ||\n normalizeSearchText(tool.name) === normalizedQuery\n ) {\n score += 20;\n }\n\n return {\n path: tool.id,\n name: tool.name,\n description: tool.description,\n sourceId: tool.sourceId,\n score,\n };\n};\n\n/** What `tools.search()` calls inside the sandbox. */\nexport const searchTools = Effect.fn(\"executor.tools.search\")(function* (\n executor: Executor,\n query: string,\n limit = 12,\n options?: { readonly namespace?: string; readonly offset?: number },\n) {\n const offset = options?.offset ?? 0;\n yield* Effect.annotateCurrentSpan({\n \"executor.search.query_length\": query.length,\n \"executor.search.limit\": limit,\n \"executor.search.offset\": offset,\n ...(options?.namespace ? { \"executor.search.namespace\": options.namespace } : {}),\n });\n\n const empty: PagedResult<ToolDiscoveryResult> = {\n items: [],\n total: 0,\n hasMore: false,\n nextOffset: null,\n };\n\n if (normalizeSearchText(query).length === 0) {\n return empty;\n }\n\n const all = yield* executor.tools.list({ includeAnnotations: false }).pipe(Effect.orDie);\n const ranked = all\n .filter((tool: Tool) => matchesNamespace(tool, options?.namespace))\n .map((tool: Tool) => scoreToolMatch(tool, query))\n .filter((tool): tool is ToolDiscoveryResult => tool !== null)\n .sort((left, right) => right.score - left.score || left.path.localeCompare(right.path));\n\n const page = paginate(ranked, offset, limit);\n\n yield* Effect.annotateCurrentSpan({\n \"executor.search.candidate_count\": all.length,\n \"executor.search.match_count\": ranked.length,\n \"executor.search.result_count\": page.items.length,\n \"executor.search.has_more\": page.hasMore,\n });\n return page;\n});\n\n/** What `tools.executor.sources.list()` calls inside the sandbox. */\nexport const listExecutorSources = Effect.fn(\"executor.sources.list\")(function* (\n executor: Executor,\n options?: {\n readonly query?: string;\n readonly limit?: number;\n readonly offset?: number;\n },\n) {\n const normalizedQuery = normalizeSearchText(options?.query ?? \"\");\n const limit = options?.limit ?? 50;\n const offset = options?.offset ?? 0;\n const sources = yield* executor.sources.list().pipe(Effect.orDie);\n\n const filtered =\n normalizedQuery.length === 0\n ? sources\n : sources.filter((source: Source) => {\n const haystack = normalizeSearchText([source.id, source.name, source.kind].join(\" \"));\n return tokenizeSearchText(normalizedQuery).every((token) => haystack.includes(token));\n });\n\n // Single query for all tools, then count per source in memory.\n const allTools = yield* executor.tools.list({ includeAnnotations: false }).pipe(Effect.orDie);\n const toolCountBySource = new Map<string, number>();\n for (const tool of allTools) {\n toolCountBySource.set(tool.sourceId, (toolCountBySource.get(tool.sourceId) ?? 0) + 1);\n }\n\n const sortedWithCounts = filtered\n .map(\n (source: Source) =>\n ({\n id: source.id,\n name: source.name,\n kind: source.kind,\n runtime: source.runtime,\n canRemove: source.canRemove,\n canRefresh: source.canRefresh,\n toolCount: toolCountBySource.get(source.id) ?? 0,\n }) satisfies ExecutorSourceListItem,\n )\n .sort((left, right) => left.name.localeCompare(right.name) || left.id.localeCompare(right.id));\n\n const page = paginate(sortedWithCounts, offset, limit);\n\n yield* Effect.annotateCurrentSpan({\n \"executor.sources.candidate_count\": sources.length,\n \"executor.sources.match_count\": sortedWithCounts.length,\n \"executor.sources.result_count\": page.items.length,\n \"executor.sources.has_more\": page.hasMore,\n });\n return page;\n});\n\n/** What `tools.describe.tool()` calls inside the sandbox. */\nexport const describeTool = Effect.fn(\"executor.tools.describe\")(function* (\n executor: Executor,\n path: string,\n) {\n yield* Effect.annotateCurrentSpan({ \"mcp.tool.name\": path });\n\n // Single tools.schema() call — it already fetches the tool row\n // internally. No need to also call tools.list() just for name/description.\n const schema: ToolSchema | null = yield* executor.tools.schema(path);\n\n // tools.schema() returns null if the tool doesn't exist. Fall back to\n // a minimal stub so callers can still render something.\n if (schema === null) {\n return { path, name: path };\n }\n\n // The schema's id is the tool path; name/description come from the\n // tool row which tools.schema() already loaded.\n return {\n path,\n name: schema.name ?? path,\n description: schema.description,\n inputTypeScript: schema.inputTypeScript,\n outputTypeScript: schema.outputTypeScript,\n typeScriptDefinitions: schema.typeScriptDefinitions,\n };\n});\n","import { Effect } from \"effect\";\nimport type { Executor, Source } from \"@executor-js/sdk/core\";\n\n/**\n * Builds a tool description dynamically.\n *\n * Structure:\n * 1. Workflow (top — critical, least likely to be truncated)\n * 2. Available namespaces (bottom)\n */\nexport const buildExecuteDescription = (executor: Executor): Effect.Effect<string> =>\n Effect.gen(function* () {\n const sources: readonly Source[] = yield* executor.sources\n .list()\n .pipe(Effect.orDie, Effect.withSpan(\"executor.sources.list\"));\n\n const description = yield* Effect.sync(() => formatDescription(sources)).pipe(\n Effect.withSpan(\"schema.compile.description\", {\n attributes: { \"executor.source_count\": sources.length },\n }),\n );\n\n yield* Effect.annotateCurrentSpan({\n \"executor.source_count\": sources.length,\n \"schema.kind\": \"execute\",\n });\n\n return description;\n }).pipe(Effect.withSpan(\"schema.describe.execute\"));\n\nconst formatDescription = (sources: readonly Source[]): string => {\n const lines: string[] = [\n \"Execute TypeScript in a sandboxed runtime with access to configured API tools.\",\n \"\",\n \"## Workflow\",\n \"\",\n '1. `const { items: matches } = await tools.search({ query: \"<intent + key nouns>\", limit: 12 });`',\n '2. `const path = matches[0]?.path; if (!path) return \"No matching tools found.\";`',\n \"3. `const details = await tools.describe.tool({ path });`\",\n \"4. Use `details.inputTypeScript` / `details.outputTypeScript` and `details.typeScriptDefinitions` for compact shapes.\",\n \"5. Use `tools.executor.sources.list()` when you need configured source inventory.\",\n \"6. Call the tool: `const result = await tools.<path>(input);`\",\n \"\",\n \"## Rules\",\n \"\",\n \"- `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`.\",\n '- When you already know the namespace, narrow with `tools.search({ namespace: \"github\", query: \"issues\" })`.',\n \"- `tools.executor.sources.list()` returns the same paged shape: `{ items: [{ id, toolCount, ... }], total, hasMore, nextOffset }`.\",\n \"- If `hasMore` is true and you didn't find what you need, fetch the next page: `tools.search({ query, offset: nextOffset, limit })`. Same `offset` parameter on `tools.executor.sources.list({ offset, limit })`.\",\n \"- Always use the namespace prefix when calling tools: `tools.<namespace>.<tool>(args)`. Example: `tools.home_assistant_rest_api.states.getState(...)` — not `tools.states.getState(...)`.\",\n \"- The `tools` object is a lazy proxy — `Object.keys(tools)` won't work. Use `tools.search()` or `tools.executor.sources.list()` instead.\",\n '- Pass an object to system tools, e.g. `tools.search({ query: \"...\" })`, `tools.executor.sources.list()`, and `tools.describe.tool({ path })`.',\n \"- `tools.describe.tool()` returns compact TypeScript shapes. Use `inputTypeScript`, `outputTypeScript`, and `typeScriptDefinitions`.\",\n \"- For tools that return large collections (e.g. `getStates`, `getAll`), filter results in code rather than calling per-item tools.\",\n \"- Do not use `fetch` — all API calls go through `tools.*`.\",\n \"- If execution pauses for interaction, resume it with the returned `resumePayload`.\",\n ];\n\n if (sources.length > 0) {\n lines.push(\"\");\n lines.push(\"## Available namespaces\");\n lines.push(\"\");\n const sorted = [...sources].sort((a, b) => a.id.localeCompare(b.id));\n for (const source of sorted) {\n const label = source.name;\n lines.push(`- \\`${source.id}\\`${label !== source.id ? ` — ${label}` : \"\"}`);\n }\n }\n\n return lines.join(\"\\n\");\n};\n","import { Deferred, Effect, Fiber, Ref } from \"effect\";\nimport type * as Cause from \"effect/Cause\";\n\nimport type {\n Executor,\n InvokeOptions,\n ElicitationResponse,\n ElicitationHandler,\n ElicitationContext,\n} from \"@executor-js/sdk/core\";\nimport { CodeExecutionError } from \"@executor-js/codemode-core\";\nimport type { CodeExecutor, ExecuteResult, SandboxToolInvoker } from \"@executor-js/codemode-core\";\n\nimport {\n makeExecutorToolInvoker,\n searchTools,\n listExecutorSources,\n describeTool,\n} from \"./tool-invoker\";\nimport { ExecutionToolError } from \"./errors\";\nimport { buildExecuteDescription } from \"./description\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type ExecutionEngineConfig<\n E extends Cause.YieldableError = CodeExecutionError,\n> = {\n readonly executor: Executor;\n readonly codeExecutor: CodeExecutor<E>;\n};\n\nexport type ExecutionResult =\n | { readonly status: \"completed\"; readonly result: ExecuteResult }\n | { readonly status: \"paused\"; readonly execution: PausedExecution };\n\nexport type PausedExecution = {\n readonly id: string;\n readonly elicitationContext: ElicitationContext;\n};\n\n/** Internal representation with Effect runtime state for pause/resume. */\ntype InternalPausedExecution<E> = PausedExecution & {\n readonly response: Deferred.Deferred<typeof ElicitationResponse.Type>;\n readonly fiber: Fiber.Fiber<ExecuteResult, E>;\n readonly pauseSignalRef: Ref.Ref<Deferred.Deferred<InternalPausedExecution<E>>>;\n};\n\nexport type ResumeResponse = {\n readonly action: \"accept\" | \"decline\" | \"cancel\";\n readonly content?: Record<string, unknown>;\n};\n\n// ---------------------------------------------------------------------------\n// Result formatting\n// ---------------------------------------------------------------------------\n\nconst MAX_PREVIEW_CHARS = 30_000;\n\nconst truncate = (value: string, max: number): string =>\n value.length > max\n ? `${value.slice(0, max)}\\n... [truncated ${value.length - max} chars]`\n : value;\n\nexport const formatExecuteResult = (\n result: ExecuteResult,\n): {\n text: string;\n structured: Record<string, unknown>;\n isError: boolean;\n} => {\n const resultText =\n result.result != null\n ? typeof result.result === \"string\"\n ? result.result\n : JSON.stringify(result.result, null, 2)\n : null;\n\n const logText = result.logs && result.logs.length > 0 ? result.logs.join(\"\\n\") : null;\n\n if (result.error) {\n const parts = [`Error: ${result.error}`, ...(logText ? [`\\nLogs:\\n${logText}`] : [])];\n return {\n text: truncate(parts.join(\"\\n\"), MAX_PREVIEW_CHARS),\n structured: { status: \"error\", error: result.error, logs: result.logs ?? [] },\n isError: true,\n };\n }\n\n const parts = [\n ...(resultText ? [truncate(resultText, MAX_PREVIEW_CHARS)] : [\"(no result)\"]),\n ...(logText ? [`\\nLogs:\\n${logText}`] : []),\n ];\n return {\n text: parts.join(\"\\n\"),\n structured: { status: \"completed\", result: result.result ?? null, logs: result.logs ?? [] },\n isError: false,\n };\n};\n\nexport const formatPausedExecution = (\n paused: PausedExecution,\n): {\n text: string;\n structured: Record<string, unknown>;\n} => {\n const req = paused.elicitationContext.request;\n const lines: string[] = [`Execution paused: ${req.message}`];\n\n if (req._tag === \"UrlElicitation\") {\n lines.push(`\\nOpen this URL in a browser:\\n${req.url}`);\n lines.push(\"\\nAfter the browser flow, resume with the executionId below:\");\n } else {\n lines.push(\"\\nResume with the executionId below and a response matching the requested schema:\");\n const schema = req.requestedSchema;\n if (schema && Object.keys(schema).length > 0) {\n lines.push(`\\nRequested schema:\\n${JSON.stringify(schema, null, 2)}`);\n }\n }\n\n lines.push(`\\nexecutionId: ${paused.id}`);\n\n return {\n text: lines.join(\"\\n\"),\n structured: {\n status: \"waiting_for_interaction\",\n executionId: paused.id,\n interaction: {\n kind: req._tag === \"UrlElicitation\" ? \"url\" : \"form\",\n message: req.message,\n ...(req._tag === \"UrlElicitation\" ? { url: req.url } : {}),\n ...(req._tag === \"FormElicitation\" ? { requestedSchema: req.requestedSchema } : {}),\n },\n },\n };\n};\n\n// ---------------------------------------------------------------------------\n// Full invoker (base + discover + describe)\n// ---------------------------------------------------------------------------\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst readOptionalLimit = (value: unknown, toolName: string): number | ExecutionToolError => {\n if (value === undefined) {\n return 12;\n }\n\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n return new ExecutionToolError({\n message: `${toolName} limit must be a positive number when provided`,\n });\n }\n\n return Math.floor(value);\n};\n\nconst readOptionalOffset = (value: unknown, toolName: string): number | ExecutionToolError => {\n if (value === undefined) {\n return 0;\n }\n\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n return new ExecutionToolError({\n message: `${toolName} offset must be a non-negative number when provided`,\n });\n }\n\n return Math.floor(value);\n};\n\nconst makeFullInvoker = (executor: Executor, invokeOptions: InvokeOptions): SandboxToolInvoker => {\n const base = makeExecutorToolInvoker(executor, { invokeOptions });\n return {\n invoke: ({ path, args }) => {\n if (path === \"search\") {\n if (!isRecord(args)) {\n return Effect.fail(\n new ExecutionToolError({\n message:\n \"tools.search expects an object: { query?: string; namespace?: string; limit?: number; offset?: number }\",\n }),\n );\n }\n\n if (args.query !== undefined && typeof args.query !== \"string\") {\n return Effect.fail(\n new ExecutionToolError({\n message: \"tools.search query must be a string when provided\",\n }),\n );\n }\n\n if (args.namespace !== undefined && typeof args.namespace !== \"string\") {\n return Effect.fail(\n new ExecutionToolError({\n message: \"tools.search namespace must be a string when provided\",\n }),\n );\n }\n\n const limit = readOptionalLimit(args.limit, \"tools.search\");\n if (limit instanceof ExecutionToolError) {\n return Effect.fail(limit);\n }\n\n const offset = readOptionalOffset(args.offset, \"tools.search\");\n if (offset instanceof ExecutionToolError) {\n return Effect.fail(offset);\n }\n\n return searchTools(executor, args.query ?? \"\", limit, {\n namespace: args.namespace,\n offset,\n }).pipe(\n Effect.withSpan(\"mcp.tool.dispatch\", {\n attributes: { \"mcp.tool.name\": path, \"executor.tool.builtin\": true },\n }),\n );\n }\n if (path === \"executor.sources.list\") {\n if (args !== undefined && !isRecord(args)) {\n return Effect.fail(\n new ExecutionToolError({\n message:\n \"tools.executor.sources.list expects an object: { query?: string; limit?: number; offset?: number }\",\n }),\n );\n }\n\n if (isRecord(args) && args.query !== undefined && typeof args.query !== \"string\") {\n return Effect.fail(\n new ExecutionToolError({\n message: \"tools.executor.sources.list query must be a string when provided\",\n }),\n );\n }\n\n const limit = readOptionalLimit(\n isRecord(args) ? args.limit : undefined,\n \"tools.executor.sources.list\",\n );\n if (limit instanceof ExecutionToolError) {\n return Effect.fail(limit);\n }\n\n const offset = readOptionalOffset(\n isRecord(args) ? args.offset : undefined,\n \"tools.executor.sources.list\",\n );\n if (offset instanceof ExecutionToolError) {\n return Effect.fail(offset);\n }\n\n return listExecutorSources(executor, {\n query: isRecord(args) && typeof args.query === \"string\" ? args.query : undefined,\n limit,\n offset,\n }).pipe(\n Effect.withSpan(\"mcp.tool.dispatch\", {\n attributes: { \"mcp.tool.name\": path, \"executor.tool.builtin\": true },\n }),\n );\n }\n if (path === \"describe.tool\") {\n if (!isRecord(args)) {\n return Effect.fail(\n new ExecutionToolError({\n message: \"tools.describe.tool expects an object: { path: string }\",\n }),\n );\n }\n\n if (typeof args.path !== \"string\" || args.path.trim().length === 0) {\n return Effect.fail(new ExecutionToolError({ message: \"describe.tool requires a path\" }));\n }\n\n if (\"includeSchemas\" in args) {\n return Effect.fail(\n new ExecutionToolError({\n message: \"tools.describe.tool no longer accepts includeSchemas\",\n }),\n );\n }\n\n return describeTool(executor, args.path).pipe(\n Effect.withSpan(\"mcp.tool.dispatch\", {\n attributes: {\n \"mcp.tool.name\": path,\n \"executor.tool.builtin\": true,\n \"executor.tool.target_path\": args.path,\n },\n }),\n );\n }\n return base.invoke({ path, args });\n },\n };\n};\n\n// ---------------------------------------------------------------------------\n// Execution Engine\n// ---------------------------------------------------------------------------\n\nexport type ExecutionEngine<E extends Cause.YieldableError = CodeExecutionError> = {\n /**\n * Execute code with elicitation handled inline by the provided handler.\n * Use this when the host supports elicitation (e.g. MCP with elicitation capability).\n *\n * Fails with the code executor's typed error `E` (defaults to\n * `CodeExecutionError`). Runtimes surface their own `Data.TaggedError`\n * subclass, which flows through here unchanged.\n */\n readonly execute: (\n code: string,\n options: { readonly onElicitation: ElicitationHandler },\n ) => Effect.Effect<ExecuteResult, E>;\n\n /**\n * Execute code, intercepting the first elicitation as a pause point.\n * Use this when the host doesn't support inline elicitation.\n * Returns either a completed result or a paused execution that can be resumed.\n */\n readonly executeWithPause: (code: string) => Effect.Effect<ExecutionResult, E>;\n\n /**\n * Resume a paused execution. Returns a completed result, a new pause, or\n * null if the executionId was not found.\n */\n readonly resume: (\n executionId: string,\n response: ResumeResponse,\n ) => Effect.Effect<ExecutionResult | null, E>;\n\n /**\n * Get the dynamic tool description (workflow + namespaces).\n */\n readonly getDescription: Effect.Effect<string>;\n};\n\nexport const createExecutionEngine = <\n E extends Cause.YieldableError = CodeExecutionError,\n>(\n config: ExecutionEngineConfig<E>,\n): ExecutionEngine<E> => {\n const { executor, codeExecutor } = config;\n const pausedExecutions = new Map<string, InternalPausedExecution<E>>();\n let nextId = 0;\n\n /**\n * Race a running fiber against a pause signal. Returns when either\n * the fiber completes or an elicitation handler fires (whichever\n * comes first). Re-used by both executeWithPause and resume.\n */\n const awaitCompletionOrPause = (\n fiber: Fiber.Fiber<ExecuteResult, E>,\n pauseSignal: Deferred.Deferred<InternalPausedExecution<E>>,\n ): Effect.Effect<ExecutionResult, E> =>\n Effect.race(\n Fiber.join(fiber).pipe(\n Effect.map((result): ExecutionResult => ({ status: \"completed\", result })),\n ),\n Deferred.await(pauseSignal).pipe(\n Effect.map((paused): ExecutionResult => ({ status: \"paused\", execution: paused })),\n ),\n );\n\n /**\n * Start an execution in pause/resume mode.\n *\n * The sandbox is forked as a daemon because paused executions can outlive the\n * caller scope that returned the first pause, such as an HTTP request handler.\n */\n const startPausableExecution = Effect.fn(\"mcp.execute\")(function* (code: string) {\n yield* Effect.annotateCurrentSpan({\n \"mcp.execute.mode\": \"pausable\",\n \"mcp.execute.code_length\": code.length,\n });\n\n // Ref holds the current pause signal. The elicitation handler reads\n // it each time it fires, so resume() can swap in a fresh Deferred\n // before unblocking the fiber.\n const pauseSignalRef = yield* Ref.make(yield* Deferred.make<InternalPausedExecution<E>>());\n\n // Will be set once the fiber is forked.\n let fiber: Fiber.Fiber<ExecuteResult, E>;\n\n const elicitationHandler: ElicitationHandler = (ctx) =>\n Effect.gen(function* () {\n const responseDeferred = yield* Deferred.make<typeof ElicitationResponse.Type>();\n const id = `exec_${++nextId}`;\n\n const paused: InternalPausedExecution<E> = {\n id,\n elicitationContext: ctx,\n response: responseDeferred,\n fiber: fiber!,\n pauseSignalRef,\n };\n pausedExecutions.set(id, paused);\n\n const currentSignal = yield* Ref.get(pauseSignalRef);\n yield* Deferred.succeed(currentSignal, paused);\n\n // Suspend until resume() completes responseDeferred.\n return yield* Deferred.await(responseDeferred);\n });\n\n const invoker = makeFullInvoker(executor, { onElicitation: elicitationHandler });\n fiber = yield* Effect.forkDetach(\n codeExecutor.execute(code, invoker).pipe(Effect.withSpan(\"executor.code.exec\")),\n );\n\n const initialSignal = yield* Ref.get(pauseSignalRef);\n return (yield* awaitCompletionOrPause(fiber, initialSignal)) as ExecutionResult;\n });\n\n /**\n * Resume a paused execution. Swaps in a fresh pause signal, completes\n * the response Deferred to unblock the fiber, then races completion\n * against the next pause.\n */\n const resumeExecution = Effect.fn(\"mcp.execute.resume\")(function* (\n executionId: string,\n response: ResumeResponse,\n ) {\n yield* Effect.annotateCurrentSpan({\n \"mcp.execute.resume.action\": response.action,\n });\n\n const paused = pausedExecutions.get(executionId);\n if (!paused) return null;\n pausedExecutions.delete(executionId);\n\n // Swap in a fresh pause signal BEFORE unblocking the fiber, so the\n // next elicitation handler call signals this new Deferred.\n const nextSignal = yield* Deferred.make<InternalPausedExecution<E>>();\n yield* Ref.set(paused.pauseSignalRef, nextSignal);\n\n yield* Deferred.succeed(paused.response, {\n action: response.action as typeof ElicitationResponse.Type.action,\n content: response.content,\n });\n\n return (yield* awaitCompletionOrPause(paused.fiber, nextSignal)) as ExecutionResult;\n });\n\n /**\n * Inline-elicitation execute path. Wrapped so every call produces an\n * `mcp.execute` span with the inner `executor.code.exec` as a child.\n */\n const runInlineExecution = Effect.fn(\"mcp.execute\")(function* (\n code: string,\n options: { readonly onElicitation: ElicitationHandler },\n ) {\n yield* Effect.annotateCurrentSpan({\n \"mcp.execute.mode\": \"inline\",\n \"mcp.execute.code_length\": code.length,\n });\n const invoker = makeFullInvoker(executor, {\n onElicitation: options.onElicitation,\n });\n return yield* codeExecutor\n .execute(code, invoker)\n .pipe(Effect.withSpan(\"executor.code.exec\"));\n });\n\n return {\n execute: runInlineExecution,\n executeWithPause: startPausableExecution,\n resume: resumeExecution,\n getDescription: buildExecuteDescription(executor),\n };\n};\n"],"mappings":"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","names":["Effect","Effect","parts","Effect"]}
|
package/dist/core.js
CHANGED
package/dist/description.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"description.d.ts","sourceRoot":"","sources":["../src/description.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,QAAQ,
|
|
1
|
+
{"version":3,"file":"description.d.ts","sourceRoot":"","sources":["../src/description.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,QAAQ,EAAU,MAAM,uBAAuB,CAAC;AAE9D;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,GAAI,UAAU,QAAQ,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAkB5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"description.test.d.ts","sourceRoot":"","sources":["../src/description.test.ts"],"names":[],"mappings":""}
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import type * as Cause from "effect/Cause";
|
|
3
|
+
import type { Executor, ElicitationHandler, ElicitationContext } from "@executor-js/sdk/core";
|
|
4
|
+
import { CodeExecutionError } from "@executor-js/codemode-core";
|
|
2
5
|
import type { CodeExecutor, ExecuteResult } from "@executor-js/codemode-core";
|
|
3
|
-
export type ExecutionEngineConfig = {
|
|
6
|
+
export type ExecutionEngineConfig<E extends Cause.YieldableError = CodeExecutionError> = {
|
|
4
7
|
readonly executor: Executor;
|
|
5
|
-
readonly codeExecutor: CodeExecutor
|
|
8
|
+
readonly codeExecutor: CodeExecutor<E>;
|
|
6
9
|
};
|
|
7
10
|
export type ExecutionResult = {
|
|
8
11
|
readonly status: "completed";
|
|
@@ -28,29 +31,33 @@ export declare const formatPausedExecution: (paused: PausedExecution) => {
|
|
|
28
31
|
text: string;
|
|
29
32
|
structured: Record<string, unknown>;
|
|
30
33
|
};
|
|
31
|
-
export type ExecutionEngine = {
|
|
34
|
+
export type ExecutionEngine<E extends Cause.YieldableError = CodeExecutionError> = {
|
|
32
35
|
/**
|
|
33
36
|
* Execute code with elicitation handled inline by the provided handler.
|
|
34
37
|
* Use this when the host supports elicitation (e.g. MCP with elicitation capability).
|
|
38
|
+
*
|
|
39
|
+
* Fails with the code executor's typed error `E` (defaults to
|
|
40
|
+
* `CodeExecutionError`). Runtimes surface their own `Data.TaggedError`
|
|
41
|
+
* subclass, which flows through here unchanged.
|
|
35
42
|
*/
|
|
36
43
|
readonly execute: (code: string, options: {
|
|
37
44
|
readonly onElicitation: ElicitationHandler;
|
|
38
|
-
}) =>
|
|
45
|
+
}) => Effect.Effect<ExecuteResult, E>;
|
|
39
46
|
/**
|
|
40
47
|
* Execute code, intercepting the first elicitation as a pause point.
|
|
41
48
|
* Use this when the host doesn't support inline elicitation.
|
|
42
49
|
* Returns either a completed result or a paused execution that can be resumed.
|
|
43
50
|
*/
|
|
44
|
-
readonly executeWithPause: (code: string) =>
|
|
51
|
+
readonly executeWithPause: (code: string) => Effect.Effect<ExecutionResult, E>;
|
|
45
52
|
/**
|
|
46
53
|
* Resume a paused execution. Returns a completed result, a new pause, or
|
|
47
54
|
* null if the executionId was not found.
|
|
48
55
|
*/
|
|
49
|
-
readonly resume: (executionId: string, response: ResumeResponse) =>
|
|
56
|
+
readonly resume: (executionId: string, response: ResumeResponse) => Effect.Effect<ExecutionResult | null, E>;
|
|
50
57
|
/**
|
|
51
58
|
* Get the dynamic tool description (workflow + namespaces).
|
|
52
59
|
*/
|
|
53
|
-
readonly getDescription:
|
|
60
|
+
readonly getDescription: Effect.Effect<string>;
|
|
54
61
|
};
|
|
55
|
-
export declare const createExecutionEngine: (config: ExecutionEngineConfig) => ExecutionEngine
|
|
62
|
+
export declare const createExecutionEngine: <E extends Cause.YieldableError = CodeExecutionError>(config: ExecutionEngineConfig<E>) => ExecutionEngine<E>;
|
|
56
63
|
//# sourceMappingURL=engine.d.ts.map
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,EAAc,MAAM,QAAQ,CAAC;AACtD,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,EACV,QAAQ,EAGR,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAsB,MAAM,4BAA4B,CAAC;AAelG,MAAM,MAAM,qBAAqB,CAC/B,CAAC,SAAS,KAAK,CAAC,cAAc,GAAG,kBAAkB,IACjD;IACF,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GAChE;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAA;CAAE,CAAC;AAEvE,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;CACjD,CAAC;AASF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC5C,CAAC;AAaF,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,aAAa,KACpB;IACD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,EAAE,OAAO,CAAC;CA6BlB,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,QAAQ,eAAe,KACtB;IACD,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CA+BrC,CAAC;AA0KF,MAAM,MAAM,eAAe,CAAC,CAAC,SAAS,KAAK,CAAC,cAAc,GAAG,kBAAkB,IAAI;IACjF;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,EAAE,CAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QAAE,QAAQ,CAAC,aAAa,EAAE,kBAAkB,CAAA;KAAE,KACpD,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IAErC;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC;IAE/E;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,CACf,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,cAAc,KACrB,MAAM,CAAC,MAAM,CAAC,eAAe,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;IAE9C;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;CAChD,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,CAAC,SAAS,KAAK,CAAC,cAAc,GAAG,kBAAkB,EAEnD,QAAQ,qBAAqB,CAAC,CAAC,CAAC,KAC/B,eAAe,CAAC,CAAC,CAiInB,CAAC"}
|
package/dist/errors.d.ts
CHANGED
package/dist/errors.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAEA,qBAAa,kBAAmB,SAAQ,wBAAuC;IAC7E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;CAAG"}
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAEA,qBAAa,kBAAmB,SAAQ,wBAAuC;IAC7E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;CAAG;AAKL,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,58 +4,93 @@ import {
|
|
|
4
4
|
createExecutionEngine,
|
|
5
5
|
formatExecuteResult,
|
|
6
6
|
formatPausedExecution
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QO23HCJR.js";
|
|
8
8
|
|
|
9
9
|
// src/promise.ts
|
|
10
10
|
import { Effect } from "effect";
|
|
11
|
+
import { ToolId } from "@executor-js/sdk/core";
|
|
12
|
+
var fromPromise = (try_) => Effect.tryPromise({ try: try_, catch: (cause) => cause }).pipe(Effect.orDie);
|
|
13
|
+
var toPromiseInvokeOptions = (options) => {
|
|
14
|
+
const onElicitation = options?.onElicitation;
|
|
15
|
+
if (!onElicitation) return void 0;
|
|
16
|
+
if (onElicitation === "accept-all") return { onElicitation };
|
|
17
|
+
return {
|
|
18
|
+
onElicitation: (ctx) => onElicitation({
|
|
19
|
+
...ctx,
|
|
20
|
+
toolId: ToolId.make(ctx.toolId)
|
|
21
|
+
})
|
|
22
|
+
};
|
|
23
|
+
};
|
|
11
24
|
var wrapPromiseExecutor = (pe) => ({
|
|
12
|
-
|
|
25
|
+
scopes: pe.scopes,
|
|
13
26
|
tools: {
|
|
14
|
-
invoke: (id, args, options) =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
list: (filter) => Effect.tryPromise({
|
|
19
|
-
try: () => pe.tools.list(filter),
|
|
20
|
-
catch: (cause) => cause
|
|
21
|
-
}).pipe(Effect.orDie),
|
|
22
|
-
schema: (id) => Effect.tryPromise({
|
|
23
|
-
try: () => pe.tools.schema(id),
|
|
24
|
-
catch: (cause) => cause
|
|
25
|
-
}),
|
|
26
|
-
definitions: () => Effect.tryPromise({
|
|
27
|
-
try: () => pe.tools.definitions(),
|
|
28
|
-
catch: (cause) => cause
|
|
29
|
-
}).pipe(Effect.orDie)
|
|
27
|
+
invoke: (id, args, options) => fromPromise(() => pe.tools.invoke(id, args, toPromiseInvokeOptions(options))),
|
|
28
|
+
list: (filter) => fromPromise(() => pe.tools.list(filter)),
|
|
29
|
+
schema: (id) => fromPromise(() => pe.tools.schema(id)),
|
|
30
|
+
definitions: () => fromPromise(() => pe.tools.definitions())
|
|
30
31
|
},
|
|
31
32
|
sources: {
|
|
32
|
-
list: () =>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
list: () => fromPromise(() => pe.sources.list()),
|
|
34
|
+
remove: (id) => fromPromise(() => pe.sources.remove(id)),
|
|
35
|
+
refresh: (id) => fromPromise(() => pe.sources.refresh(id)),
|
|
36
|
+
detect: (url) => fromPromise(() => pe.sources.detect(url)),
|
|
37
|
+
definitions: (id) => fromPromise(() => pe.sources.definitions(id))
|
|
38
|
+
},
|
|
39
|
+
secrets: {
|
|
40
|
+
get: (id) => fromPromise(() => pe.secrets.get(id)),
|
|
41
|
+
status: (id) => fromPromise(() => pe.secrets.status(id)),
|
|
42
|
+
set: (input) => fromPromise(() => pe.secrets.set(input)),
|
|
43
|
+
remove: (id) => fromPromise(() => pe.secrets.remove(id)),
|
|
44
|
+
list: () => fromPromise(() => pe.secrets.list()),
|
|
45
|
+
providers: () => fromPromise(() => pe.secrets.providers())
|
|
46
|
+
},
|
|
47
|
+
connections: {
|
|
48
|
+
get: (id) => fromPromise(() => pe.connections.get(id)),
|
|
49
|
+
list: () => fromPromise(() => pe.connections.list()),
|
|
50
|
+
create: (input) => fromPromise(() => pe.connections.create(input)),
|
|
51
|
+
updateTokens: (input) => fromPromise(() => pe.connections.updateTokens(input)),
|
|
52
|
+
setIdentityLabel: (id, label) => fromPromise(() => pe.connections.setIdentityLabel(id, label)),
|
|
53
|
+
accessToken: (id) => fromPromise(() => pe.connections.accessToken(id)),
|
|
54
|
+
remove: (id) => fromPromise(() => pe.connections.remove(id)),
|
|
55
|
+
providers: () => fromPromise(() => pe.connections.providers())
|
|
56
|
+
},
|
|
57
|
+
oauth: {
|
|
58
|
+
probe: (input) => fromPromise(() => pe.oauth.probe(input)),
|
|
59
|
+
start: (input) => fromPromise(() => pe.oauth.start(input)),
|
|
60
|
+
complete: (input) => fromPromise(() => pe.oauth.complete(input)),
|
|
61
|
+
cancel: (sessionId, tokenScope) => fromPromise(() => pe.oauth.cancel(sessionId, tokenScope))
|
|
62
|
+
},
|
|
63
|
+
policies: {
|
|
64
|
+
list: () => fromPromise(() => pe.policies.list()),
|
|
65
|
+
create: (input) => fromPromise(() => pe.policies.create(input)),
|
|
66
|
+
update: (input) => fromPromise(() => pe.policies.update(input)),
|
|
67
|
+
remove: (id) => fromPromise(() => pe.policies.remove(id)),
|
|
68
|
+
resolve: (id) => fromPromise(() => pe.policies.resolve(id))
|
|
69
|
+
},
|
|
70
|
+
close: () => fromPromise(() => pe.close())
|
|
71
|
+
});
|
|
72
|
+
var toPromiseExecutionEngine = (engine) => ({
|
|
73
|
+
execute: (code, options) => Effect.runPromise(
|
|
74
|
+
engine.execute(code, {
|
|
75
|
+
onElicitation: (ctx) => Effect.tryPromise(() => options.onElicitation(ctx)).pipe(Effect.orDie)
|
|
76
|
+
})
|
|
77
|
+
),
|
|
78
|
+
executeWithPause: (code) => Effect.runPromise(engine.executeWithPause(code)),
|
|
79
|
+
resume: (executionId, response) => Effect.runPromise(engine.resume(executionId, response)),
|
|
80
|
+
getDescription: () => Effect.runPromise(engine.getDescription)
|
|
37
81
|
});
|
|
38
|
-
var createExecutionEngine2 = (config) =>
|
|
39
|
-
|
|
82
|
+
var createExecutionEngine2 = (config) => toPromiseExecutionEngine(
|
|
83
|
+
createExecutionEngine({
|
|
40
84
|
executor: wrapPromiseExecutor(config.executor),
|
|
41
85
|
codeExecutor: config.codeExecutor
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
execute: (code, options) => engine.execute(code, {
|
|
45
|
-
onElicitation: (ctx) => Effect.tryPromise(() => options.onElicitation(ctx)).pipe(
|
|
46
|
-
Effect.orDie
|
|
47
|
-
)
|
|
48
|
-
}),
|
|
49
|
-
executeWithPause: (code) => engine.executeWithPause(code),
|
|
50
|
-
resume: (executionId, response) => engine.resume(executionId, response),
|
|
51
|
-
getDescription: () => engine.getDescription()
|
|
52
|
-
};
|
|
53
|
-
};
|
|
86
|
+
})
|
|
87
|
+
);
|
|
54
88
|
export {
|
|
55
89
|
ExecutionToolError,
|
|
56
90
|
buildExecuteDescription,
|
|
57
91
|
createExecutionEngine2 as createExecutionEngine,
|
|
58
92
|
formatExecuteResult,
|
|
59
|
-
formatPausedExecution
|
|
93
|
+
formatPausedExecution,
|
|
94
|
+
toPromiseExecutionEngine
|
|
60
95
|
};
|
|
61
96
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/promise.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// @executor/execution/promise — Promise-native surface for the execution\n// engine. Accepts a Promise-style Executor (from @executor/sdk) and an\n// async `onElicitation` handler — no Effect imports required by callers.\n//\n// Under the hood the engine is Effect-based, so we wrap the incoming\n// Promise executor into the minimal Effect shape the engine consumes,\n// and bridge the elicitation handler via `Effect.tryPromise`.\n// ---------------------------------------------------------------------------\n\nimport { Effect } from \"effect\";\n\nimport type {\n ElicitationContext,\n ElicitationResponse,\n Executor as PromiseExecutor,\n} from \"@executor/sdk\";\nimport type { CodeExecutor, ExecuteResult } from \"@executor/codemode-core\";\n\nimport {\n createExecutionEngine as createEffectExecutionEngine,\n type ExecutionResult,\n type PausedExecution,\n type ResumeResponse,\n} from \"./engine\";\n\nexport type ElicitationHandler = (\n ctx: ElicitationContext,\n) => Promise<ElicitationResponse>;\n\nexport type ExecutionEngineConfig = {\n readonly executor: PromiseExecutor;\n readonly codeExecutor: CodeExecutor;\n};\n\nexport type ExecutionEngine = {\n readonly execute: (\n code: string,\n options: { readonly onElicitation: ElicitationHandler },\n ) => Promise<ExecuteResult>;\n readonly executeWithPause: (code: string) => Promise<ExecutionResult>;\n readonly resume: (\n executionId: string,\n response: ResumeResponse,\n ) => Promise<ExecutionResult | null>;\n readonly getDescription: () => Promise<string>;\n};\n\n/**\n * Wrap a Promise-style executor into the Effect shape the engine consumes.\n * Only the four method families the engine actually touches need wrapping:\n * `tools.{invoke,list,schema}` and `sources.list`.\n */\nconst wrapPromiseExecutor = (pe: PromiseExecutor): any => ({\n scope: (pe as any).scope,\n tools: {\n invoke: (id: unknown, args: unknown, options: unknown) =>\n Effect.tryPromise({\n try: () => (pe.tools as any).invoke(id, args, options),\n catch: (cause) => cause,\n }),\n list: (filter?: unknown) =>\n Effect.tryPromise({\n try: () => (pe.tools as any).list(filter),\n catch: (cause) => cause,\n }).pipe(Effect.orDie),\n schema: (id: unknown) =>\n Effect.tryPromise({\n try: () => (pe.tools as any).schema(id),\n catch: (cause) => cause,\n }),\n definitions: () =>\n Effect.tryPromise({\n try: () => (pe.tools as any).definitions(),\n catch: (cause) => cause,\n }).pipe(Effect.orDie),\n },\n sources: {\n list: () =>\n Effect.tryPromise({\n try: () => (pe.sources as any).list(),\n catch: (cause) => cause,\n }).pipe(Effect.orDie),\n },\n});\n\nexport const createExecutionEngine = (\n config: ExecutionEngineConfig,\n): ExecutionEngine => {\n const engine = createEffectExecutionEngine({\n executor: wrapPromiseExecutor(config.executor),\n codeExecutor: config.codeExecutor,\n });\n return {\n execute: (code, options) =>\n engine.execute(code, {\n onElicitation: (ctx) =>\n Effect.tryPromise(() => options.onElicitation(ctx)).pipe(\n Effect.orDie,\n ),\n }),\n executeWithPause: (code) => engine.executeWithPause(code),\n resume: (executionId, response) => engine.resume(executionId, response),\n getDescription: () => engine.getDescription(),\n };\n};\n\n// ---------------------------------------------------------------------------\n// Re-exports — plain types/helpers that don't carry Effect signatures.\n// ---------------------------------------------------------------------------\n\nexport {\n formatExecuteResult,\n formatPausedExecution,\n} from \"./engine\";\n\nexport type { ExecutionResult, PausedExecution, ResumeResponse };\n\nexport { buildExecuteDescription } from \"./description\";\nexport { ExecutionToolError } from \"./errors\";\n"],"mappings":";;;;;;;;;AAUA,SAAS,cAAc;AA2CvB,IAAM,sBAAsB,CAAC,QAA8B;AAAA,EACzD,OAAQ,GAAW;AAAA,EACnB,OAAO;AAAA,IACL,QAAQ,CAAC,IAAa,MAAe,YACnC,OAAO,WAAW;AAAA,MAChB,KAAK,MAAO,GAAG,MAAc,OAAO,IAAI,MAAM,OAAO;AAAA,MACrD,OAAO,CAAC,UAAU;AAAA,IACpB,CAAC;AAAA,IACH,MAAM,CAAC,WACL,OAAO,WAAW;AAAA,MAChB,KAAK,MAAO,GAAG,MAAc,KAAK,MAAM;AAAA,MACxC,OAAO,CAAC,UAAU;AAAA,IACpB,CAAC,EAAE,KAAK,OAAO,KAAK;AAAA,IACtB,QAAQ,CAAC,OACP,OAAO,WAAW;AAAA,MAChB,KAAK,MAAO,GAAG,MAAc,OAAO,EAAE;AAAA,MACtC,OAAO,CAAC,UAAU;AAAA,IACpB,CAAC;AAAA,IACH,aAAa,MACX,OAAO,WAAW;AAAA,MAChB,KAAK,MAAO,GAAG,MAAc,YAAY;AAAA,MACzC,OAAO,CAAC,UAAU;AAAA,IACpB,CAAC,EAAE,KAAK,OAAO,KAAK;AAAA,EACxB;AAAA,EACA,SAAS;AAAA,IACP,MAAM,MACJ,OAAO,WAAW;AAAA,MAChB,KAAK,MAAO,GAAG,QAAgB,KAAK;AAAA,MACpC,OAAO,CAAC,UAAU;AAAA,IACpB,CAAC,EAAE,KAAK,OAAO,KAAK;AAAA,EACxB;AACF;AAEO,IAAMA,yBAAwB,CACnC,WACoB;AACpB,QAAM,SAAS,sBAA4B;AAAA,IACzC,UAAU,oBAAoB,OAAO,QAAQ;AAAA,IAC7C,cAAc,OAAO;AAAA,EACvB,CAAC;AACD,SAAO;AAAA,IACL,SAAS,CAAC,MAAM,YACd,OAAO,QAAQ,MAAM;AAAA,MACnB,eAAe,CAAC,QACd,OAAO,WAAW,MAAM,QAAQ,cAAc,GAAG,CAAC,EAAE;AAAA,QAClD,OAAO;AAAA,MACT;AAAA,IACJ,CAAC;AAAA,IACH,kBAAkB,CAAC,SAAS,OAAO,iBAAiB,IAAI;AAAA,IACxD,QAAQ,CAAC,aAAa,aAAa,OAAO,OAAO,aAAa,QAAQ;AAAA,IACtE,gBAAgB,MAAM,OAAO,eAAe;AAAA,EAC9C;AACF;","names":["createExecutionEngine"]}
|
|
1
|
+
{"version":3,"sources":["../src/promise.ts"],"sourcesContent":["// ---------------------------------------------------------------------------\n// @executor-js/execution/promise — Promise-native surface for the execution\n// engine.\n// ---------------------------------------------------------------------------\n//\n// `engine.ts` is Effect-native; this module runs each method with\n// `Effect.runPromise` at the boundary so hosts that can't compose Effects\n// (the MCP SDK tool handlers, plain async call sites) can still use the\n// engine. Callers already inside an Effect context should import directly\n// from `@executor-js/execution` to keep trace context intact.\n// ---------------------------------------------------------------------------\n\nimport { Effect } from \"effect\";\nimport type * as Cause from \"effect/Cause\";\n\nimport type {\n ElicitationContext,\n ElicitationResponse,\n Executor as EffectExecutor,\n} from \"@executor-js/sdk/core\";\nimport { ToolId } from \"@executor-js/sdk/core\";\nimport type { Executor as PromiseExecutor } from \"@executor-js/sdk/promise\";\nimport type { CodeExecutionError, CodeExecutor, ExecuteResult } from \"@executor-js/codemode-core\";\n\nimport {\n createExecutionEngine as createEffectExecutionEngine,\n type ExecutionEngine as EffectExecutionEngine,\n type ExecutionResult,\n type PausedExecution,\n type ResumeResponse,\n} from \"./engine\";\n\nexport type ElicitationHandler = (\n ctx: ElicitationContext,\n) => Promise<ElicitationResponse>;\n\nexport type ExecutionEngineConfig<\n E extends Cause.YieldableError = CodeExecutionError,\n> = {\n readonly executor: PromiseExecutor;\n readonly codeExecutor: CodeExecutor<E>;\n};\n\nexport type ExecutionEngine = {\n readonly execute: (\n code: string,\n options: { readonly onElicitation: ElicitationHandler },\n ) => Promise<ExecuteResult>;\n readonly executeWithPause: (code: string) => Promise<ExecutionResult>;\n readonly resume: (\n executionId: string,\n response: ResumeResponse,\n ) => Promise<ExecutionResult | null>;\n readonly getDescription: () => Promise<string>;\n};\n\n/**\n * Wrap a Promise-style executor into the Effect shape the engine consumes.\n */\nconst fromPromise = <A>(try_: () => Promise<A>): Effect.Effect<A> =>\n Effect.tryPromise({ try: try_, catch: (cause) => cause }).pipe(Effect.orDie);\n\ntype EffectInvokeOptions = Parameters<EffectExecutor[\"tools\"][\"invoke\"]>[2];\ntype PromiseInvokeOptions = Parameters<PromiseExecutor[\"tools\"][\"invoke\"]>[2];\n\nconst toPromiseInvokeOptions = (\n options: EffectInvokeOptions,\n): PromiseInvokeOptions => {\n const onElicitation = options?.onElicitation;\n if (!onElicitation) return undefined;\n if (onElicitation === \"accept-all\") return { onElicitation };\n\n return {\n onElicitation: (ctx) =>\n onElicitation({\n ...ctx,\n toolId: ToolId.make(ctx.toolId),\n }),\n };\n};\n\nconst wrapPromiseExecutor = (pe: PromiseExecutor): EffectExecutor => ({\n scopes: pe.scopes,\n tools: {\n invoke: (id, args, options) =>\n fromPromise(() => pe.tools.invoke(id, args, toPromiseInvokeOptions(options))),\n list: (filter) => fromPromise(() => pe.tools.list(filter)),\n schema: (id) => fromPromise(() => pe.tools.schema(id)),\n definitions: () => fromPromise(() => pe.tools.definitions()),\n },\n sources: {\n list: () => fromPromise(() => pe.sources.list()),\n remove: (id) => fromPromise(() => pe.sources.remove(id)),\n refresh: (id) => fromPromise(() => pe.sources.refresh(id)),\n detect: (url) => fromPromise(() => pe.sources.detect(url)),\n definitions: (id) => fromPromise(() => pe.sources.definitions(id)),\n },\n secrets: {\n get: (id) => fromPromise(() => pe.secrets.get(id)),\n status: (id) => fromPromise(() => pe.secrets.status(id)),\n set: (input) => fromPromise(() => pe.secrets.set(input)),\n remove: (id) => fromPromise(() => pe.secrets.remove(id)),\n list: () => fromPromise(() => pe.secrets.list()),\n providers: () => fromPromise(() => pe.secrets.providers()),\n },\n connections: {\n get: (id) => fromPromise(() => pe.connections.get(id)),\n list: () => fromPromise(() => pe.connections.list()),\n create: (input) => fromPromise(() => pe.connections.create(input)),\n updateTokens: (input) => fromPromise(() => pe.connections.updateTokens(input)),\n setIdentityLabel: (id, label) => fromPromise(() => pe.connections.setIdentityLabel(id, label)),\n accessToken: (id) => fromPromise(() => pe.connections.accessToken(id)),\n remove: (id) => fromPromise(() => pe.connections.remove(id)),\n providers: () => fromPromise(() => pe.connections.providers()),\n },\n oauth: {\n probe: (input) => fromPromise(() => pe.oauth.probe(input)),\n start: (input) => fromPromise(() => pe.oauth.start(input)),\n complete: (input) => fromPromise(() => pe.oauth.complete(input)),\n cancel: (sessionId, tokenScope) => fromPromise(() => pe.oauth.cancel(sessionId, tokenScope)),\n },\n policies: {\n list: () => fromPromise(() => pe.policies.list()),\n create: (input) => fromPromise(() => pe.policies.create(input)),\n update: (input) => fromPromise(() => pe.policies.update(input)),\n remove: (id) => fromPromise(() => pe.policies.remove(id)),\n resolve: (id) => fromPromise(() => pe.policies.resolve(id)),\n },\n close: () => fromPromise(() => pe.close()),\n});\n\n/**\n * Promise-wrap an Effect-native `ExecutionEngine` (from `./engine`).\n * Exposed separately so callers that already hold an Effect engine\n * (apps/cloud's execution-stack composes both) can convert it for hosts\n * that need the Promise surface (host-mcp).\n */\nexport const toPromiseExecutionEngine = <E extends Cause.YieldableError>(\n engine: EffectExecutionEngine<E>,\n): ExecutionEngine => ({\n execute: (code, options) =>\n Effect.runPromise(\n engine.execute(code, {\n onElicitation: (ctx) =>\n Effect.tryPromise(() => options.onElicitation(ctx)).pipe(Effect.orDie),\n }),\n ),\n executeWithPause: (code) => Effect.runPromise(engine.executeWithPause(code)),\n resume: (executionId, response) => Effect.runPromise(engine.resume(executionId, response)),\n getDescription: () => Effect.runPromise(engine.getDescription),\n});\n\nexport const createExecutionEngine = <\n E extends Cause.YieldableError = CodeExecutionError,\n>(\n config: ExecutionEngineConfig<E>,\n): ExecutionEngine =>\n toPromiseExecutionEngine(\n createEffectExecutionEngine({\n executor: wrapPromiseExecutor(config.executor),\n codeExecutor: config.codeExecutor,\n }),\n );\n\n// ---------------------------------------------------------------------------\n// Re-exports — plain types/helpers that don't carry Effect signatures.\n// ---------------------------------------------------------------------------\n\nexport { formatExecuteResult, formatPausedExecution } from \"./engine\";\n\nexport type { ExecutionResult, PausedExecution, ResumeResponse };\n\nexport { buildExecuteDescription } from \"./description\";\nexport { ExecutionToolError } from \"./errors\";\n"],"mappings":"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","names":["createExecutionEngine"]}
|
package/dist/promise.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type {
|
|
3
|
-
import
|
|
1
|
+
import type * as Cause from "effect/Cause";
|
|
2
|
+
import type { ElicitationContext, ElicitationResponse } from "@executor-js/sdk/core";
|
|
3
|
+
import type { Executor as PromiseExecutor } from "@executor-js/sdk/promise";
|
|
4
|
+
import type { CodeExecutionError, CodeExecutor, ExecuteResult } from "@executor-js/codemode-core";
|
|
5
|
+
import { type ExecutionEngine as EffectExecutionEngine, type ExecutionResult, type PausedExecution, type ResumeResponse } from "./engine";
|
|
4
6
|
export type ElicitationHandler = (ctx: ElicitationContext) => Promise<ElicitationResponse>;
|
|
5
|
-
export type ExecutionEngineConfig = {
|
|
7
|
+
export type ExecutionEngineConfig<E extends Cause.YieldableError = CodeExecutionError> = {
|
|
6
8
|
readonly executor: PromiseExecutor;
|
|
7
|
-
readonly codeExecutor: CodeExecutor
|
|
9
|
+
readonly codeExecutor: CodeExecutor<E>;
|
|
8
10
|
};
|
|
9
11
|
export type ExecutionEngine = {
|
|
10
12
|
readonly execute: (code: string, options: {
|
|
@@ -14,8 +16,15 @@ export type ExecutionEngine = {
|
|
|
14
16
|
readonly resume: (executionId: string, response: ResumeResponse) => Promise<ExecutionResult | null>;
|
|
15
17
|
readonly getDescription: () => Promise<string>;
|
|
16
18
|
};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Promise-wrap an Effect-native `ExecutionEngine` (from `./engine`).
|
|
21
|
+
* Exposed separately so callers that already hold an Effect engine
|
|
22
|
+
* (apps/cloud's execution-stack composes both) can convert it for hosts
|
|
23
|
+
* that need the Promise surface (host-mcp).
|
|
24
|
+
*/
|
|
25
|
+
export declare const toPromiseExecutionEngine: <E extends Cause.YieldableError>(engine: EffectExecutionEngine<E>) => ExecutionEngine;
|
|
26
|
+
export declare const createExecutionEngine: <E extends Cause.YieldableError = CodeExecutionError>(config: ExecutionEngineConfig<E>) => ExecutionEngine;
|
|
27
|
+
export { formatExecuteResult, formatPausedExecution } from "./engine";
|
|
19
28
|
export type { ExecutionResult, PausedExecution, ResumeResponse };
|
|
20
29
|
export { buildExecuteDescription } from "./description";
|
|
21
30
|
export { ExecutionToolError } from "./errors";
|
package/dist/promise.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promise.d.ts","sourceRoot":"","sources":["../src/promise.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"promise.d.ts","sourceRoot":"","sources":["../src/promise.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,KAAK,KAAK,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EAEpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,QAAQ,IAAI,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAE,kBAAkB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAElG,OAAO,EAEL,KAAK,eAAe,IAAI,qBAAqB,EAC7C,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,cAAc,EACpB,MAAM,UAAU,CAAC;AAElB,MAAM,MAAM,kBAAkB,GAAG,CAC/B,GAAG,EAAE,kBAAkB,KACpB,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAElC,MAAM,MAAM,qBAAqB,CAC/B,CAAC,SAAS,KAAK,CAAC,cAAc,GAAG,kBAAkB,IACjD;IACF,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,OAAO,EAAE,CAChB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QAAE,QAAQ,CAAC,aAAa,EAAE,kBAAkB,CAAA;KAAE,KACpD,OAAO,CAAC,aAAa,CAAC,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IACtE,QAAQ,CAAC,MAAM,EAAE,CACf,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,cAAc,KACrB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IACrC,QAAQ,CAAC,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAChD,CAAC;AA6EF;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,GAAI,CAAC,SAAS,KAAK,CAAC,cAAc,EACrE,QAAQ,qBAAqB,CAAC,CAAC,CAAC,KAC/B,eAWD,CAAC;AAEH,eAAO,MAAM,qBAAqB,GAChC,CAAC,SAAS,KAAK,CAAC,cAAc,GAAG,kBAAkB,EAEnD,QAAQ,qBAAqB,CAAC,CAAC,CAAC,KAC/B,eAMA,CAAC;AAMJ,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEtE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC;AAEjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/tool-invoker.d.ts
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { Effect } from "effect";
|
|
2
|
-
import type { Executor, InvokeOptions } from "@executor-js/sdk";
|
|
2
|
+
import type { Executor, InvokeOptions } from "@executor-js/sdk/core";
|
|
3
3
|
import type { SandboxToolInvoker } from "@executor-js/codemode-core";
|
|
4
4
|
/**
|
|
5
5
|
* Bridges QuickJS `tools.someSource.someOp(args)` calls into
|
|
6
6
|
* `executor.tools.invoke(toolId, args)`.
|
|
7
|
+
*
|
|
8
|
+
* Wrapped in `Effect.fn("mcp.tool.dispatch")` so every tool call becomes a
|
|
9
|
+
* span in the Effect tracer. Attributes:
|
|
10
|
+
* - `mcp.tool.name` — full tool path (e.g. "github.repos.get")
|
|
11
|
+
* - `mcp.tool.source_id` — first segment of the path (namespace)
|
|
12
|
+
*
|
|
13
|
+
* `mcp.tool.kind` (openapi | mcp | graphql | code) is NOT annotated here
|
|
14
|
+
* because it would require a `sources.list()` lookup on every invocation.
|
|
15
|
+
* Callers that already know the source kind can annotate at their own span.
|
|
7
16
|
*/
|
|
8
17
|
export declare const makeExecutorToolInvoker: (executor: Executor, options: {
|
|
9
18
|
readonly invokeOptions: InvokeOptions;
|
|
@@ -24,22 +33,60 @@ export type ExecutorSourceListItem = {
|
|
|
24
33
|
readonly canRefresh?: boolean;
|
|
25
34
|
readonly toolCount: number;
|
|
26
35
|
};
|
|
36
|
+
/**
|
|
37
|
+
* Page of results from a list-style discovery tool. Shared by
|
|
38
|
+
* `tools.search` and `tools.executor.sources.list` so the model sees one
|
|
39
|
+
* consistent shape:
|
|
40
|
+
*
|
|
41
|
+
* - `items` — the page (slice).
|
|
42
|
+
* - `total` — count after filtering, before pagination. The model
|
|
43
|
+
* can use this to detect truncation.
|
|
44
|
+
* - `hasMore` — convenience flag for `(offset + items.length) < total`.
|
|
45
|
+
* - `nextOffset` — concrete offset for the next page when `hasMore`,
|
|
46
|
+
* `null` otherwise. Pre-computing it removes a class of
|
|
47
|
+
* off-by-one mistakes when the model paginates.
|
|
48
|
+
*/
|
|
49
|
+
export type PagedResult<T> = {
|
|
50
|
+
readonly items: readonly T[];
|
|
51
|
+
readonly total: number;
|
|
52
|
+
readonly hasMore: boolean;
|
|
53
|
+
readonly nextOffset: number | null;
|
|
54
|
+
};
|
|
27
55
|
/** What `tools.search()` calls inside the sandbox. */
|
|
28
|
-
export declare const searchTools: (executor: Executor, query: string, limit?:
|
|
56
|
+
export declare const searchTools: (executor: Executor, query: string, limit?: any, options?: {
|
|
29
57
|
readonly namespace?: string;
|
|
30
|
-
|
|
58
|
+
readonly offset?: number;
|
|
59
|
+
} | undefined) => Effect.Effect<PagedResult<ToolDiscoveryResult>, never, never>;
|
|
31
60
|
/** What `tools.executor.sources.list()` calls inside the sandbox. */
|
|
32
61
|
export declare const listExecutorSources: (executor: Executor, options?: {
|
|
33
62
|
readonly query?: string;
|
|
34
63
|
readonly limit?: number;
|
|
35
|
-
|
|
64
|
+
readonly offset?: number;
|
|
65
|
+
} | undefined) => Effect.Effect<PagedResult<{
|
|
66
|
+
id: string;
|
|
67
|
+
name: string;
|
|
68
|
+
kind: string;
|
|
69
|
+
runtime: boolean;
|
|
70
|
+
canRemove: boolean;
|
|
71
|
+
canRefresh: boolean;
|
|
72
|
+
toolCount: number;
|
|
73
|
+
}>, never, never>;
|
|
36
74
|
/** What `tools.describe.tool()` calls inside the sandbox. */
|
|
37
75
|
export declare const describeTool: (executor: Executor, path: string) => Effect.Effect<{
|
|
38
76
|
path: string;
|
|
39
77
|
name: string;
|
|
40
|
-
description?:
|
|
41
|
-
inputTypeScript?:
|
|
42
|
-
outputTypeScript?:
|
|
43
|
-
typeScriptDefinitions?:
|
|
44
|
-
}
|
|
78
|
+
description?: undefined;
|
|
79
|
+
inputTypeScript?: undefined;
|
|
80
|
+
outputTypeScript?: undefined;
|
|
81
|
+
typeScriptDefinitions?: undefined;
|
|
82
|
+
} | {
|
|
83
|
+
path: string;
|
|
84
|
+
name: string;
|
|
85
|
+
description: string | undefined;
|
|
86
|
+
inputTypeScript: string | undefined;
|
|
87
|
+
outputTypeScript: string | undefined;
|
|
88
|
+
typeScriptDefinitions: {
|
|
89
|
+
readonly [x: string]: string;
|
|
90
|
+
} | undefined;
|
|
91
|
+
}, import("@executor-js/storage-core").StorageFailure, never>;
|
|
45
92
|
//# sourceMappingURL=tool-invoker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-invoker.d.ts","sourceRoot":"","sources":["../src/tool-invoker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-invoker.d.ts","sourceRoot":"","sources":["../src/tool-invoker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EACV,QAAQ,EAIR,aAAa,EAEd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAwCrE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB,GAClC,UAAU,QAAQ,EAClB,SAAS;IAAE,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAA;CAAE,KACjD,kBA+CD,CAAC;AAcH,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC,CAAC;AAoMF,sDAAsD;AACtD,eAAO,MAAM,WAAW;yBAIW,MAAM;sBAAoB,MAAM;+EAqCjE,CAAC;AAEH,qEAAqE;AACrE,eAAO,MAAM,mBAAmB;qBAGX,MAAM;qBACN,MAAM;sBACL,MAAM;;;;;;;;;iBA+C1B,CAAC;AAEH,6DAA6D;AAC7D,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;6DA0BvB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@executor-js/execution",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"homepage": "https://github.com/RhysSullivan/executor/tree/main/packages/core/execution",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/RhysSullivan/executor/issues"
|
|
@@ -39,17 +39,17 @@
|
|
|
39
39
|
"typecheck:slow": "bunx tsc --noEmit -p tsconfig.json"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@executor-js/codemode-core": "0.0
|
|
43
|
-
"@executor-js/sdk": "0.0
|
|
44
|
-
"effect": "
|
|
42
|
+
"@executor-js/codemode-core": "0.1.0",
|
|
43
|
+
"@executor-js/sdk": "0.1.0",
|
|
44
|
+
"effect": "4.0.0-beta.59"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
-
"@effect/vitest": "
|
|
48
|
-
"@executor-js/runtime-quickjs": "0.0
|
|
47
|
+
"@effect/vitest": "4.0.0-beta.59",
|
|
48
|
+
"@executor-js/runtime-quickjs": "0.1.0",
|
|
49
49
|
"@types/node": "^24.3.1",
|
|
50
50
|
"bun-types": "^1.2.22",
|
|
51
51
|
"tsup": "^8.5.0",
|
|
52
52
|
"typescript": "^5.9.3",
|
|
53
|
-
"vitest": "^4.1.
|
|
53
|
+
"vitest": "^4.1.5"
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/tool-invoker.ts","../src/description.ts","../src/engine.ts"],"sourcesContent":["import * as Data from \"effect/Data\";\n\nexport class ExecutionToolError extends Data.TaggedError(\"ExecutionToolError\")<{\n readonly message: string;\n readonly cause?: unknown;\n}> {}\n","import { Effect } from \"effect\";\nimport type {\n Executor,\n ToolId,\n Tool,\n ToolSchema,\n InvokeOptions,\n Source,\n} from \"@executor/sdk\";\nimport type { SandboxToolInvoker } from \"@executor/codemode-core\";\nimport { ExecutionToolError } from \"./errors\";\n\n/**\n * Bridges QuickJS `tools.someSource.someOp(args)` calls into\n * `executor.tools.invoke(toolId, args)`.\n */\nexport const makeExecutorToolInvoker = (\n executor: Executor,\n options: { readonly invokeOptions: InvokeOptions },\n): SandboxToolInvoker => ({\n invoke: ({ path, args }) =>\n Effect.gen(function* () {\n const result = yield* executor.tools.invoke(path as ToolId, args, options.invokeOptions).pipe(\n Effect.catchTag(\"ElicitationDeclinedError\", (err) =>\n Effect.fail(\n new ExecutionToolError({\n message: `Tool \"${err.toolId}\" requires approval but the request was ${err.action === \"cancel\" ? \"cancelled\" : \"declined\"} by the user.`,\n cause: err,\n }),\n ),\n ),\n );\n const r = result as { readonly error?: unknown; readonly data?: unknown } | unknown;\n if (\n r !== null &&\n typeof r === \"object\" &&\n \"error\" in r &&\n (r as { error?: unknown }).error !== null &&\n (r as { error?: unknown }).error !== undefined\n ) {\n return yield* Effect.fail((r as { error: unknown }).error);\n }\n if (r !== null && typeof r === \"object\" && \"data\" in r) {\n return (r as { data: unknown }).data;\n }\n return r;\n }),\n});\n\nexport type ToolDiscoveryResult = {\n readonly path: string;\n readonly name: string;\n readonly description?: string;\n readonly sourceId: string;\n readonly score: number;\n};\n\nexport type ExecutorSourceListItem = {\n readonly id: string;\n readonly name: string;\n readonly kind: string;\n readonly runtime?: boolean;\n readonly canRemove?: boolean;\n readonly canRefresh?: boolean;\n readonly toolCount: number;\n};\n\ntype SearchableTool = Pick<Tool, \"id\" | \"sourceId\" | \"name\" | \"description\">;\n\ntype PreparedField = {\n readonly raw: string;\n readonly tokens: readonly string[];\n};\n\nconst SEARCH_FIELD_WEIGHTS = {\n path: 12,\n sourceId: 8,\n name: 10,\n description: 5,\n} as const;\n\nconst normalizeSearchText = (value: string): string =>\n value\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .replace(/[_./:-]+/g, \" \")\n .toLowerCase()\n .trim();\n\nconst tokenizeSearchText = (value: string): string[] =>\n normalizeSearchText(value)\n .split(/[^a-z0-9]+/)\n .map((token) => token.trim())\n .filter(Boolean);\n\nconst prepareField = (value?: string): PreparedField => ({\n raw: normalizeSearchText(value ?? \"\"),\n tokens: tokenizeSearchText(value ?? \"\"),\n});\n\nconst scorePreparedField = (\n query: string,\n queryTokens: readonly string[],\n field: PreparedField,\n weight: number,\n): {\n readonly score: number;\n readonly matchedTokens: ReadonlySet<string>;\n readonly exactPhraseMatch: boolean;\n} => {\n if (field.raw.length === 0) {\n return {\n score: 0,\n matchedTokens: new Set<string>(),\n exactPhraseMatch: false,\n };\n }\n\n let score = 0;\n const matchedTokens = new Set<string>();\n const exactPhraseMatch = query.length > 0 && field.raw.includes(query);\n\n if (query.length > 0) {\n if (field.raw === query) {\n score += weight * 14;\n } else if (field.raw.startsWith(query)) {\n score += weight * 9;\n } else if (exactPhraseMatch) {\n score += weight * 6;\n }\n }\n\n for (const token of queryTokens) {\n if (field.tokens.includes(token)) {\n score += weight * 4;\n matchedTokens.add(token);\n continue;\n }\n\n if (\n field.tokens.some((candidate) => candidate.startsWith(token) || token.startsWith(candidate))\n ) {\n score += weight * 2;\n matchedTokens.add(token);\n continue;\n }\n\n if (field.raw.includes(token)) {\n score += weight;\n matchedTokens.add(token);\n }\n }\n\n return {\n score,\n matchedTokens,\n exactPhraseMatch,\n };\n};\n\nconst matchesNamespace = (tool: SearchableTool, namespace?: string): boolean => {\n if (!namespace || normalizeSearchText(namespace).length === 0) {\n return true;\n }\n\n const namespaceTokens = tokenizeSearchText(namespace);\n if (namespaceTokens.length === 0) {\n return true;\n }\n\n const sourceTokens = tokenizeSearchText(tool.sourceId);\n const pathTokens = tokenizeSearchText(tool.id);\n\n const isPrefixMatch = (tokens: readonly string[]): boolean =>\n namespaceTokens.every((token, index) => tokens[index] === token);\n\n return isPrefixMatch(sourceTokens) || isPrefixMatch(pathTokens);\n};\n\nconst scoreToolMatch = (tool: SearchableTool, query: string): ToolDiscoveryResult | null => {\n const normalizedQuery = normalizeSearchText(query);\n const queryTokens = tokenizeSearchText(query);\n\n if (normalizedQuery.length === 0 || queryTokens.length === 0) {\n return null;\n }\n\n const path = prepareField(tool.id);\n const sourceId = prepareField(tool.sourceId);\n const name = prepareField(tool.name);\n const description = prepareField(tool.description);\n\n const fieldScores = [\n scorePreparedField(normalizedQuery, queryTokens, path, SEARCH_FIELD_WEIGHTS.path),\n scorePreparedField(normalizedQuery, queryTokens, sourceId, SEARCH_FIELD_WEIGHTS.sourceId),\n scorePreparedField(normalizedQuery, queryTokens, name, SEARCH_FIELD_WEIGHTS.name),\n scorePreparedField(normalizedQuery, queryTokens, description, SEARCH_FIELD_WEIGHTS.description),\n ];\n\n const matchedTokens = new Set<string>();\n let score = 0;\n let exactPhraseMatch = false;\n\n for (const fieldScore of fieldScores) {\n score += fieldScore.score;\n exactPhraseMatch ||= fieldScore.exactPhraseMatch;\n for (const token of fieldScore.matchedTokens) {\n matchedTokens.add(token);\n }\n }\n\n if (matchedTokens.size === 0) {\n return null;\n }\n\n const coverage = matchedTokens.size / queryTokens.length;\n const minimumCoverage = queryTokens.length <= 2 ? 1 : 0.6;\n\n if (coverage < minimumCoverage && !exactPhraseMatch) {\n return null;\n }\n\n if (coverage === 1) {\n score += 25;\n } else {\n score += Math.round(coverage * 10);\n }\n\n if (path.tokens[0] === queryTokens[0] || name.tokens[0] === queryTokens[0]) {\n score += 8;\n }\n\n if (\n normalizeSearchText(tool.id) === normalizedQuery ||\n normalizeSearchText(tool.name) === normalizedQuery\n ) {\n score += 20;\n }\n\n return {\n path: tool.id,\n name: tool.name,\n description: tool.description,\n sourceId: tool.sourceId,\n score,\n };\n};\n\n/** What `tools.search()` calls inside the sandbox. */\nexport const searchTools = (\n executor: Executor,\n query: string,\n limit = 12,\n options?: { readonly namespace?: string },\n): Effect.Effect<ReadonlyArray<ToolDiscoveryResult>> =>\n Effect.gen(function* () {\n if (normalizeSearchText(query).length === 0) {\n return [];\n }\n\n const all = yield* executor.tools.list().pipe(Effect.orDie);\n return all\n .filter((tool: Tool) => matchesNamespace(tool, options?.namespace))\n .map((tool: Tool) => scoreToolMatch(tool, query))\n .filter((tool): tool is ToolDiscoveryResult => tool !== null)\n .sort((left, right) => right.score - left.score || left.path.localeCompare(right.path))\n .slice(0, limit);\n });\n\n/** What `tools.executor.sources.list()` calls inside the sandbox. */\nexport const listExecutorSources = (\n executor: Executor,\n options?: { readonly query?: string; readonly limit?: number },\n): Effect.Effect<ReadonlyArray<ExecutorSourceListItem>> =>\n Effect.gen(function* () {\n const normalizedQuery = normalizeSearchText(options?.query ?? \"\");\n const limit = options?.limit ?? 200;\n const sources = yield* executor.sources.list().pipe(Effect.orDie);\n\n const filtered =\n normalizedQuery.length === 0\n ? sources\n : sources.filter((source: Source) => {\n const haystack = normalizeSearchText([source.id, source.name, source.kind].join(\" \"));\n return tokenizeSearchText(normalizedQuery).every((token) => haystack.includes(token));\n });\n\n // Single query for all tools, then count per source in memory.\n const allTools = yield* executor.tools.list().pipe(Effect.orDie);\n const toolCountBySource = new Map<string, number>();\n for (const tool of allTools) {\n toolCountBySource.set(tool.sourceId, (toolCountBySource.get(tool.sourceId) ?? 0) + 1);\n }\n\n const withCounts = filtered.map(\n (source: Source) =>\n ({\n id: source.id,\n name: source.name,\n kind: source.kind,\n runtime: source.runtime,\n canRemove: source.canRemove,\n canRefresh: source.canRefresh,\n toolCount: toolCountBySource.get(source.id) ?? 0,\n }) satisfies ExecutorSourceListItem,\n );\n\n return withCounts\n .sort((left, right) => left.name.localeCompare(right.name) || left.id.localeCompare(right.id))\n .slice(0, limit);\n });\n\n/** What `tools.describe.tool()` calls inside the sandbox. */\nexport const describeTool = (\n executor: Executor,\n path: string,\n): Effect.Effect<\n {\n path: string;\n name: string;\n description?: string;\n inputTypeScript?: string;\n outputTypeScript?: string;\n typeScriptDefinitions?: Record<string, string>;\n },\n unknown\n> =>\n Effect.gen(function* () {\n // Single tools.schema() call — it already fetches the tool row\n // internally. No need to also call tools.list() just for name/description.\n const schema: ToolSchema | null = yield* executor.tools.schema(path);\n\n // tools.schema() returns null if the tool doesn't exist. Fall back to\n // a minimal stub so callers can still render something.\n if (schema === null) {\n return { path, name: path };\n }\n\n // The schema's id is the tool path; name/description come from the\n // tool row which tools.schema() already loaded.\n return {\n path,\n name: schema.name ?? path,\n description: schema.description,\n inputTypeScript: schema.inputTypeScript,\n outputTypeScript: schema.outputTypeScript,\n typeScriptDefinitions: schema.typeScriptDefinitions,\n };\n });\n","import { Effect } from \"effect\";\nimport type { Executor, Tool, Source } from \"@executor/sdk\";\n\n/**\n * Builds a tool description dynamically.\n *\n * Structure:\n * 1. Workflow (top — critical, least likely to be truncated)\n * 2. Available namespaces (bottom)\n */\nexport const buildExecuteDescription = (executor: Executor): Effect.Effect<string> =>\n Effect.gen(function* () {\n const sources: readonly Source[] = yield* executor.sources.list().pipe(Effect.orDie);\n const tools: readonly Tool[] = yield* executor.tools.list().pipe(Effect.orDie);\n\n const namespaces = new Set<string>();\n for (const tool of tools) namespaces.add(tool.sourceId);\n\n return formatDescription([...namespaces], sources);\n });\n\nconst formatDescription = (namespaces: readonly string[], sources: readonly Source[]): string => {\n const lines: string[] = [\n \"Execute TypeScript in a sandboxed runtime with access to configured API tools.\",\n \"\",\n \"## Workflow\",\n \"\",\n '1. `const matches = await tools.search({ query: \"<intent + key nouns>\", limit: 12 });`',\n '2. `const path = matches[0]?.path; if (!path) return \"No matching tools found.\";`',\n \"3. `const details = await tools.describe.tool({ path });`\",\n \"4. Use `details.inputTypeScript` / `details.outputTypeScript` and `details.typeScriptDefinitions` for compact shapes.\",\n \"5. Use `tools.executor.sources.list()` when you need configured source inventory.\",\n \"6. Call the tool: `const result = await tools.<path>(input);`\",\n \"\",\n \"## Rules\",\n \"\",\n \"- `tools.search()` returns ranked matches, best-first. Use short intent phrases like `github issues`, `repo details`, or `create calendar event`.\",\n '- When you already know the namespace, narrow with `tools.search({ namespace: \"github\", query: \"issues\" })`.',\n \"- Use `tools.executor.sources.list()` to inspect configured sources and their tool counts. Returns `[{ id, toolCount, ... }]`.\",\n \"- Always use the namespace prefix when calling tools: `tools.<namespace>.<tool>(args)`. Example: `tools.home_assistant_rest_api.states.getState(...)` — not `tools.states.getState(...)`.\",\n \"- The `tools` object is a lazy proxy — `Object.keys(tools)` won't work. Use `tools.search()` or `tools.executor.sources.list()` instead.\",\n '- Pass an object to system tools, e.g. `tools.search({ query: \"...\" })`, `tools.executor.sources.list()`, and `tools.describe.tool({ path })`.',\n \"- `tools.describe.tool()` returns compact TypeScript shapes. Use `inputTypeScript`, `outputTypeScript`, and `typeScriptDefinitions`.\",\n \"- For tools that return large collections (e.g. `getStates`, `getAll`), filter results in code rather than calling per-item tools.\",\n \"- Do not use `fetch` — all API calls go through `tools.*`.\",\n \"- If execution pauses for interaction, resume it with the returned `resumePayload`.\",\n ];\n\n if (namespaces.length > 0) {\n lines.push(\"\");\n lines.push(\"## Available namespaces\");\n lines.push(\"\");\n const sorted = [...namespaces].sort();\n for (const ns of sorted) {\n const source = sources.find((s) => s.id === ns);\n const label = source?.name ?? ns;\n lines.push(`- \\`${ns}\\`${label !== ns ? ` — ${label}` : \"\"}`);\n }\n }\n\n return lines.join(\"\\n\");\n};\n","import { Deferred, Effect, Fiber, Ref } from \"effect\";\n\nimport type {\n Executor,\n InvokeOptions,\n ElicitationResponse,\n ElicitationHandler,\n ElicitationContext,\n} from \"@executor/sdk\";\nimport type { CodeExecutor, ExecuteResult, SandboxToolInvoker } from \"@executor/codemode-core\";\n\nimport {\n makeExecutorToolInvoker,\n searchTools,\n listExecutorSources,\n describeTool,\n} from \"./tool-invoker\";\nimport { ExecutionToolError } from \"./errors\";\nimport { buildExecuteDescription } from \"./description\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type ExecutionEngineConfig = {\n readonly executor: Executor;\n readonly codeExecutor: CodeExecutor;\n};\n\nexport type ExecutionResult =\n | { readonly status: \"completed\"; readonly result: ExecuteResult }\n | { readonly status: \"paused\"; readonly execution: PausedExecution };\n\nexport type PausedExecution = {\n readonly id: string;\n readonly elicitationContext: ElicitationContext;\n};\n\n/** Internal representation with Effect runtime state for pause/resume. */\ntype InternalPausedExecution = PausedExecution & {\n readonly response: Deferred.Deferred<typeof ElicitationResponse.Type>;\n readonly fiber: Fiber.Fiber<ExecuteResult, unknown>;\n readonly pauseSignalRef: Ref.Ref<Deferred.Deferred<InternalPausedExecution>>;\n};\n\nexport type ResumeResponse = {\n readonly action: \"accept\" | \"decline\" | \"cancel\";\n readonly content?: Record<string, unknown>;\n};\n\n// ---------------------------------------------------------------------------\n// Result formatting\n// ---------------------------------------------------------------------------\n\nconst MAX_PREVIEW_CHARS = 30_000;\n\nconst truncate = (value: string, max: number): string =>\n value.length > max\n ? `${value.slice(0, max)}\\n... [truncated ${value.length - max} chars]`\n : value;\n\nexport const formatExecuteResult = (\n result: ExecuteResult,\n): {\n text: string;\n structured: Record<string, unknown>;\n isError: boolean;\n} => {\n const resultText =\n result.result != null\n ? typeof result.result === \"string\"\n ? result.result\n : JSON.stringify(result.result, null, 2)\n : null;\n\n const logText = result.logs && result.logs.length > 0 ? result.logs.join(\"\\n\") : null;\n\n if (result.error) {\n const parts = [`Error: ${result.error}`, ...(logText ? [`\\nLogs:\\n${logText}`] : [])];\n return {\n text: truncate(parts.join(\"\\n\"), MAX_PREVIEW_CHARS),\n structured: { status: \"error\", error: result.error, logs: result.logs ?? [] },\n isError: true,\n };\n }\n\n const parts = [\n ...(resultText ? [truncate(resultText, MAX_PREVIEW_CHARS)] : [\"(no result)\"]),\n ...(logText ? [`\\nLogs:\\n${logText}`] : []),\n ];\n return {\n text: parts.join(\"\\n\"),\n structured: { status: \"completed\", result: result.result ?? null, logs: result.logs ?? [] },\n isError: false,\n };\n};\n\nexport const formatPausedExecution = (\n paused: PausedExecution,\n): {\n text: string;\n structured: Record<string, unknown>;\n} => {\n const req = paused.elicitationContext.request;\n const lines: string[] = [`Execution paused: ${req.message}`];\n\n if (req._tag === \"UrlElicitation\") {\n lines.push(`\\nOpen this URL in a browser:\\n${req.url}`);\n lines.push(\"\\nAfter the browser flow, resume with the executionId below:\");\n } else {\n lines.push(\"\\nResume with the executionId below and a response matching the requested schema:\");\n const schema = req.requestedSchema;\n if (schema && Object.keys(schema).length > 0) {\n lines.push(`\\nRequested schema:\\n${JSON.stringify(schema, null, 2)}`);\n }\n }\n\n lines.push(`\\nexecutionId: ${paused.id}`);\n\n return {\n text: lines.join(\"\\n\"),\n structured: {\n status: \"waiting_for_interaction\",\n executionId: paused.id,\n interaction: {\n kind: req._tag === \"UrlElicitation\" ? \"url\" : \"form\",\n message: req.message,\n ...(req._tag === \"UrlElicitation\" ? { url: req.url } : {}),\n ...(req._tag === \"FormElicitation\" ? { requestedSchema: req.requestedSchema } : {}),\n },\n },\n };\n};\n\n// ---------------------------------------------------------------------------\n// Full invoker (base + discover + describe)\n// ---------------------------------------------------------------------------\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst readOptionalLimit = (value: unknown, toolName: string): number | ExecutionToolError => {\n if (value === undefined) {\n return 12;\n }\n\n if (typeof value !== \"number\" || !Number.isFinite(value) || value <= 0) {\n return new ExecutionToolError({\n message: `${toolName} limit must be a positive number when provided`,\n });\n }\n\n return Math.floor(value);\n};\n\nconst makeFullInvoker = (executor: Executor, invokeOptions: InvokeOptions): SandboxToolInvoker => {\n const base = makeExecutorToolInvoker(executor, { invokeOptions });\n return {\n invoke: ({ path, args }) => {\n if (path === \"search\") {\n if (!isRecord(args)) {\n return Effect.fail(\n new ExecutionToolError({\n message:\n \"tools.search expects an object: { query?: string; namespace?: string; limit?: number }\",\n }),\n );\n }\n\n if (args.query !== undefined && typeof args.query !== \"string\") {\n return Effect.fail(\n new ExecutionToolError({\n message: \"tools.search query must be a string when provided\",\n }),\n );\n }\n\n if (args.namespace !== undefined && typeof args.namespace !== \"string\") {\n return Effect.fail(\n new ExecutionToolError({\n message: \"tools.search namespace must be a string when provided\",\n }),\n );\n }\n\n const limit = readOptionalLimit(args.limit, \"tools.search\");\n if (limit instanceof ExecutionToolError) {\n return Effect.fail(limit);\n }\n\n return searchTools(executor, args.query ?? \"\", limit, {\n namespace: args.namespace,\n });\n }\n if (path === \"executor.sources.list\") {\n if (args !== undefined && !isRecord(args)) {\n return Effect.fail(\n new ExecutionToolError({\n message:\n \"tools.executor.sources.list expects an object: { query?: string; limit?: number }\",\n }),\n );\n }\n\n if (isRecord(args) && args.query !== undefined && typeof args.query !== \"string\") {\n return Effect.fail(\n new ExecutionToolError({\n message: \"tools.executor.sources.list query must be a string when provided\",\n }),\n );\n }\n\n const limit = readOptionalLimit(\n isRecord(args) ? args.limit : undefined,\n \"tools.executor.sources.list\",\n );\n if (limit instanceof ExecutionToolError) {\n return Effect.fail(limit);\n }\n\n return listExecutorSources(executor, {\n query: isRecord(args) && typeof args.query === \"string\" ? args.query : undefined,\n limit,\n });\n }\n if (path === \"describe.tool\") {\n if (!isRecord(args)) {\n return Effect.fail(\n new ExecutionToolError({\n message: \"tools.describe.tool expects an object: { path: string }\",\n }),\n );\n }\n\n if (typeof args.path !== \"string\" || args.path.trim().length === 0) {\n return Effect.fail(new ExecutionToolError({ message: \"describe.tool requires a path\" }));\n }\n\n if (\"includeSchemas\" in args) {\n return Effect.fail(\n new ExecutionToolError({\n message: \"tools.describe.tool no longer accepts includeSchemas\",\n }),\n );\n }\n\n return describeTool(executor, args.path);\n }\n return base.invoke({ path, args });\n },\n };\n};\n\n// ---------------------------------------------------------------------------\n// Execution Engine\n// ---------------------------------------------------------------------------\n\nexport type ExecutionEngine = {\n /**\n * Execute code with elicitation handled inline by the provided handler.\n * Use this when the host supports elicitation (e.g. MCP with elicitation capability).\n */\n readonly execute: (\n code: string,\n options: { readonly onElicitation: ElicitationHandler },\n ) => Promise<ExecuteResult>;\n\n /**\n * Execute code, intercepting the first elicitation as a pause point.\n * Use this when the host doesn't support inline elicitation.\n * Returns either a completed result or a paused execution that can be resumed.\n */\n readonly executeWithPause: (code: string) => Promise<ExecutionResult>;\n\n /**\n * Resume a paused execution. Returns a completed result, a new pause, or\n * null if the executionId was not found.\n */\n readonly resume: (\n executionId: string,\n response: ResumeResponse,\n ) => Promise<ExecutionResult | null>;\n\n /**\n * Get the dynamic tool description (workflow + namespaces).\n */\n readonly getDescription: () => Promise<string>;\n};\n\nconst runEffect = <A>(effect: Effect.Effect<A, unknown>): Promise<A> =>\n Effect.runPromise(effect as Effect.Effect<A, never>);\n\nexport const createExecutionEngine = (config: ExecutionEngineConfig): ExecutionEngine => {\n const { executor, codeExecutor } = config;\n const pausedExecutions = new Map<string, InternalPausedExecution>();\n let nextId = 0;\n\n /**\n * Race a running fiber against a pause signal. Returns when either\n * the fiber completes or an elicitation handler fires (whichever\n * comes first). Re-used by both executeWithPause and resume.\n */\n const awaitCompletionOrPause = (\n fiber: Fiber.Fiber<ExecuteResult, unknown>,\n pauseSignal: Deferred.Deferred<InternalPausedExecution>,\n ): Effect.Effect<ExecutionResult> =>\n Effect.race(\n Fiber.join(fiber).pipe(\n Effect.orDie,\n Effect.map((result): ExecutionResult => ({ status: \"completed\", result })),\n ),\n Deferred.await(pauseSignal).pipe(\n Effect.map((paused): ExecutionResult => ({ status: \"paused\", execution: paused })),\n ),\n );\n\n /**\n * Start an execution in pause/resume mode.\n *\n * The sandbox is forked as a daemon because paused executions can outlive the\n * caller scope that returned the first pause, such as an HTTP request handler.\n */\n const startPausableExecution = (code: string): Effect.Effect<ExecutionResult> =>\n Effect.gen(function* () {\n // Ref holds the current pause signal. The elicitation handler reads\n // it each time it fires, so resume() can swap in a fresh Deferred\n // before unblocking the fiber.\n const pauseSignalRef = yield* Ref.make(yield* Deferred.make<InternalPausedExecution>());\n\n // Will be set once the fiber is forked.\n let fiber: Fiber.Fiber<ExecuteResult, unknown>;\n\n const elicitationHandler: ElicitationHandler = (ctx) =>\n Effect.gen(function* () {\n const responseDeferred = yield* Deferred.make<typeof ElicitationResponse.Type>();\n const id = `exec_${++nextId}`;\n\n const paused: InternalPausedExecution = {\n id,\n elicitationContext: ctx,\n response: responseDeferred,\n fiber: fiber!,\n pauseSignalRef,\n };\n pausedExecutions.set(id, paused);\n\n const currentSignal = yield* Ref.get(pauseSignalRef);\n yield* Deferred.succeed(currentSignal, paused);\n\n // Suspend until resume() completes responseDeferred.\n return yield* Deferred.await(responseDeferred);\n });\n\n const invoker = makeFullInvoker(executor, { onElicitation: elicitationHandler });\n fiber = yield* Effect.forkDaemon(codeExecutor.execute(code, invoker));\n\n const initialSignal = yield* Ref.get(pauseSignalRef);\n return yield* awaitCompletionOrPause(fiber, initialSignal);\n });\n\n /**\n * Resume a paused execution. Swaps in a fresh pause signal, completes\n * the response Deferred to unblock the fiber, then races completion\n * against the next pause.\n */\n const resumeExecution = (\n executionId: string,\n response: ResumeResponse,\n ): Effect.Effect<ExecutionResult | null> =>\n Effect.gen(function* () {\n const paused = pausedExecutions.get(executionId);\n if (!paused) return null;\n pausedExecutions.delete(executionId);\n\n // Swap in a fresh pause signal BEFORE unblocking the fiber, so the\n // next elicitation handler call signals this new Deferred.\n const nextSignal = yield* Deferred.make<InternalPausedExecution>();\n yield* Ref.set(paused.pauseSignalRef, nextSignal);\n\n yield* Deferred.succeed(paused.response, {\n action: response.action,\n content: response.content,\n });\n\n return yield* awaitCompletionOrPause(paused.fiber, nextSignal);\n });\n\n return {\n execute: async (code, options) => {\n const invoker = makeFullInvoker(executor, {\n onElicitation: options.onElicitation,\n });\n return runEffect(codeExecutor.execute(code, invoker));\n },\n\n executeWithPause: (code) => runEffect(startPausableExecution(code)),\n\n resume: (executionId, response) => runEffect(resumeExecution(executionId, response)),\n\n getDescription: () => runEffect(buildExecuteDescription(executor)),\n };\n};\n"],"mappings":"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","names":["Effect","Effect","parts","Effect"]}
|