@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 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
- scope: { name: "my-app" },
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 }) => Effect.gen(function* () {
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.catchTag(
12
- "ElicitationDeclinedError",
13
- (err) => Effect.fail(
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
- return yield* Effect.fail(r.error);
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) => Effect.gen(function* () {
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
- return 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)).slice(0, limit);
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, options) => Effect.gen(function* () {
232
+ var listExecutorSources = Effect.fn("executor.sources.list")(function* (executor, options) {
159
233
  const normalizedQuery = normalizeSearchText(options?.query ?? "");
160
- const limit = options?.limit ?? 200;
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 withCounts = filtered.map(
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
- return withCounts.sort((left, right) => left.name.localeCompare(right.name) || left.id.localeCompare(right.id)).slice(0, limit);
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, path) => Effect.gen(function* () {
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 tools = yield* executor.tools.list().pipe(Effect2.orDie);
204
- const namespaces = /* @__PURE__ */ new Set();
205
- for (const tool of tools) namespaces.add(tool.sourceId);
206
- return formatDescription([...namespaces], sources);
207
- });
208
- var formatDescription = (namespaces, sources) => {
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, best-first. Use short intent phrases like `github issues`, `repo details`, or `create calendar event`.",
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
- "- Use `tools.executor.sources.list()` to inspect configured sources and their tool counts. Returns `[{ id, toolCount, ... }]`.",
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 (namespaces.length > 0) {
324
+ if (sources.length > 0) {
235
325
  lines.push("");
236
326
  lines.push("## Available namespaces");
237
327
  lines.push("");
238
- const sorted = [...namespaces].sort();
239
- for (const ns of sorted) {
240
- const source = sources.find((s) => s.id === ns);
241
- const label = source?.name ?? ns;
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 = (code) => Effect3.gen(function* () {
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.forkDaemon(codeExecutor.execute(code, invoker));
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 = (executionId, response) => Effect3.gen(function* () {
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: async (code, options) => {
459
- const invoker = makeFullInvoker(executor, {
460
- onElicitation: options.onElicitation
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-BF7CHG2T.js.map
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
@@ -8,7 +8,7 @@ import {
8
8
  listExecutorSources,
9
9
  makeExecutorToolInvoker,
10
10
  searchTools
11
- } from "./chunk-BF7CHG2T.js";
11
+ } from "./chunk-QO23HCJR.js";
12
12
  export {
13
13
  ExecutionToolError,
14
14
  buildExecuteDescription,
@@ -1,5 +1,5 @@
1
1
  import { Effect } from "effect";
2
- import type { Executor } from "@executor-js/sdk";
2
+ import type { Executor } from "@executor-js/sdk/core";
3
3
  /**
4
4
  * Builds a tool description dynamically.
5
5
  *
@@ -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,EAAgB,MAAM,eAAe,CAAC;AAE5D;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,GAAI,UAAU,QAAQ,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAS7E,CAAC"}
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=description.test.d.ts.map
@@ -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 type { Executor, ElicitationHandler, ElicitationContext } from "@executor-js/sdk";
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
- }) => Promise<ExecuteResult>;
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) => Promise<ExecutionResult>;
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) => Promise<ExecutionResult | null>;
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: () => Promise<string>;
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
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,QAAQ,EAGR,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAsB,MAAM,yBAAyB,CAAC;AAe/F,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;CACrC,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;AA6HF,MAAM,MAAM,eAAe,GAAG;IAC5B;;;OAGG;IACH,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;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IAEtE;;;OAGG;IACH,QAAQ,CAAC,MAAM,EAAE,CACf,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,cAAc,KACrB,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAErC;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAChD,CAAC;AAKF,eAAO,MAAM,qBAAqB,GAAI,QAAQ,qBAAqB,KAAG,eA6GrE,CAAC"}
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
@@ -6,5 +6,5 @@ export declare class ExecutionToolError extends ExecutionToolError_base<{
6
6
  readonly cause?: unknown;
7
7
  }> {
8
8
  }
9
- export {};
9
+ export { CodeExecutionError } from "@executor-js/codemode-core";
10
10
  //# sourceMappingURL=errors.d.ts.map
@@ -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-BF7CHG2T.js";
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
- scope: pe.scope,
25
+ scopes: pe.scopes,
13
26
  tools: {
14
- invoke: (id, args, options) => Effect.tryPromise({
15
- try: () => pe.tools.invoke(id, args, options),
16
- catch: (cause) => cause
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: () => Effect.tryPromise({
33
- try: () => pe.sources.list(),
34
- catch: (cause) => cause
35
- }).pipe(Effect.orDie)
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
- const engine = createExecutionEngine({
82
+ var createExecutionEngine2 = (config) => toPromiseExecutionEngine(
83
+ createExecutionEngine({
40
84
  executor: wrapPromiseExecutor(config.executor),
41
85
  codeExecutor: config.codeExecutor
42
- });
43
- return {
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 { ElicitationContext, ElicitationResponse, Executor as PromiseExecutor } from "@executor-js/sdk";
2
- import type { CodeExecutor, ExecuteResult } from "@executor-js/codemode-core";
3
- import { type ExecutionResult, type PausedExecution, type ResumeResponse } from "./engine";
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
- export declare const createExecutionEngine: (config: ExecutionEngineConfig) => ExecutionEngine;
18
- export { formatExecuteResult, formatPausedExecution, } from "./engine";
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";
@@ -1 +1 @@
1
- {"version":3,"file":"promise.d.ts","sourceRoot":"","sources":["../src/promise.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,QAAQ,IAAI,eAAe,EAC5B,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAE3E,OAAO,EAEL,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,GAAG;IAClC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;CACrC,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;AAwCF,eAAO,MAAM,qBAAqB,GAChC,QAAQ,qBAAqB,KAC5B,eAiBF,CAAC;AAMF,OAAO,EACL,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,UAAU,CAAC;AAElB,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"}
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"}
@@ -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?: number, options?: {
56
+ export declare const searchTools: (executor: Executor, query: string, limit?: any, options?: {
29
57
  readonly namespace?: string;
30
- }) => Effect.Effect<ReadonlyArray<ToolDiscoveryResult>>;
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
- }) => Effect.Effect<ReadonlyArray<ExecutorSourceListItem>>;
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?: string;
41
- inputTypeScript?: string;
42
- outputTypeScript?: string;
43
- typeScriptDefinitions?: Record<string, string>;
44
- }, unknown>;
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;AAChC,OAAO,KAAK,EACV,QAAQ,EAIR,aAAa,EAEd,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAGlE;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAClC,UAAU,QAAQ,EAClB,SAAS;IAAE,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAA;CAAE,KACjD,kBA4BD,CAAC;AAEH,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;AAsLF,sDAAsD;AACtD,eAAO,MAAM,WAAW,GACtB,UAAU,QAAQ,EAClB,OAAO,MAAM,EACb,cAAU,EACV,UAAU;IAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,KACxC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAa/C,CAAC;AAEL,qEAAqE;AACrE,eAAO,MAAM,mBAAmB,GAC9B,UAAU,QAAQ,EAClB,UAAU;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,KAC7D,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAqClD,CAAC;AAEL,6DAA6D;AAC7D,eAAO,MAAM,YAAY,GACvB,UAAU,QAAQ,EAClB,MAAM,MAAM,KACX,MAAM,CAAC,MAAM,CACd;IACE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChD,EACD,OAAO,CAuBL,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.1",
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.1",
43
- "@executor-js/sdk": "0.0.1",
44
- "effect": "^3.21.0"
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": "^0.29.0",
48
- "@executor-js/runtime-quickjs": "0.0.1",
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.3"
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"]}