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
4141 });
4242 });
4343
44+const 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+
4450 const createToolsProxy = (path = []) => {
4551 const callable = () => undefined;
4652
@@ -50,6 +56,12 @@ const createToolsProxy = (path = []) => { · 3 unmodified lines
5056 if (typeof prop !== "string") return undefined;
5157 return createToolsProxy([...path, prop]);
5258 },
59+ ownKeys() {
60+ throw toolsEnumerationError(path);
61+ },
62+ getOwnPropertyDescriptor() {
63+ throw toolsEnumerationError(path);
64+ },
5365 apply(_target, _thisArg, args) {
5466 const toolPath = path.join(".");
5567 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
309309 expect(output.error).toBeUndefined();
310310 }),
311311 );
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+ );
312363 });