History

Cover the deno subprocess runtime's tools proxy too

Rhys Sullivan committed 4 months ago

Commit bfcd43c1 parent 4784f3a2 files · +63 −0Browse files

Unified · Split

2 files
  1. packages/kernel/runtime-deno-subprocess/src/deno-subprocess-worker.mjs +12 −0
  2. packages/kernel/runtime-deno-subprocess/src/index.test.ts +51 −0
packages/kernel/runtime-deno-subprocess/src/deno-subprocess-worker.mjs+12−0
@@ -41,6 +41,12 @@ const createToolCaller = (toolPath) => (args) => · 40 unmodified lines
41 });41 });
42 });42 });
43 43
44const toolsEnumerationError = (path) =>
45 new Error(
46 (path.length === 0 ? "tools" : "tools." + path.join(".")) +
47 ' is a lazy proxy and cannot be enumerated. Use tools.search({ query: "..." }) to find tools, or tools.executor.coreTools.connections.list({}) to list saved connections.',
48 );
49
44const createToolsProxy = (path = []) => {50const createToolsProxy = (path = []) => {
45 const callable = () => undefined;51 const callable = () => undefined;
46 52
@@ -50,6 +56,12 @@ const createToolsProxy = (path = []) => { · 3 unmodified lines
50 if (typeof prop !== "string") return undefined;56 if (typeof prop !== "string") return undefined;
51 return createToolsProxy([...path, prop]);57 return createToolsProxy([...path, prop]);
52 },58 },
59 ownKeys() {
60 throw toolsEnumerationError(path);
61 },
62 getOwnPropertyDescriptor() {
63 throw toolsEnumerationError(path);
64 },
53 apply(_target, _thisArg, args) {65 apply(_target, _thisArg, args) {
54 const toolPath = path.join(".");66 const toolPath = path.join(".");
55 if (!toolPath) {67 if (!toolPath) {
packages/kernel/runtime-deno-subprocess/src/index.test.ts+51−0
@@ -309,4 +309,55 @@ describe.skipIf(!isDenoAvailable())("runtime-deno-subprocess", () => { · 308 unmodified lines
309 expect(output.error).toBeUndefined();309 expect(output.error).toBeUndefined();
310 }),310 }),
311 );311 );
312
313 it.effect("tools proxy throws a search hint on enumeration", () =>
314 Effect.gen(function* () {
315 const executor = makeDenoSubprocessExecutor();
316 const toolInvoker = makeTestInvoker({});
317
318 const output = yield* executor.execute(
319 [
320 "const outcomes = {};",
321 "try {",
322 " Object.keys(tools);",
323 ' outcomes.keys = "no error";',
324 "} catch (e) {",
325 " outcomes.keys = e instanceof Error ? e.message : String(e);",
326 "}",
327 "try {",
328 " ({ ...tools.github });",
329 ' outcomes.spread = "no error";',
330 "} catch (e) {",
331 " outcomes.spread = e instanceof Error ? e.message : String(e);",
332 "}",
333 "return outcomes;",
334 ].join("\n"),
335 toolInvoker,
336 );
337
338 expect(output.error).toBeUndefined();
339 expect(output.result).toEqual({
340 keys: 'tools is a lazy proxy and cannot be enumerated. Use tools.search({ query: "..." }) to find tools, or tools.executor.coreTools.connections.list({}) to list saved connections.',
341 spread:
342 'tools.github is a lazy proxy and cannot be enumerated. Use tools.search({ query: "..." }) to find tools, or tools.executor.coreTools.connections.list({}) to list saved connections.',
343 });
344 }),
345 );
346
347 it.effect("tools proxy still invokes after the enumeration traps", () =>
348 Effect.gen(function* () {
349 const executor = makeDenoSubprocessExecutor();
350 const toolInvoker = makeTestInvoker({
351 "a.b.c": () => "a.b.c",
352 });
353
354 const output = yield* executor.execute(
355 ["try { Object.keys(tools); } catch {}", "return tools.a.b.c({});"].join("\n"),
356 toolInvoker,
357 );
358
359 expect(output.error).toBeUndefined();
360 expect(output.result).toBe("a.b.c");
361 }),
362 );
312});363});