import { describe, expect, it } from "@effect/vitest";import { Effect } from "effect"; import { buildResumeContentTemplate, buildToolPath, filterToolPathChildren, buildInvokeToolCode, buildListSourcesCode, buildSearchToolsCode, extractPausedInteraction, extractExecutionId, extractExecutionResult, inspectToolPath, normalizeCliErrorText, parseJsonObjectInput,} from "../apps/cli/src/tooling"; describe("CLI tooling helpers", () => { it.effect("parses empty input as an empty args object", () => Effect.gen(function* () { const args = yield* parseJsonObjectInput(undefined); expect(args).toEqual({}); }), ); it.effect("parses JSON object input", () => Effect.gen(function* () { const args = yield* parseJsonObjectInput('{"calendarId":"primary"}'); expect(args).toEqual({ calendarId: "primary" }); }), ); it.effect("rejects non-object JSON input", () => Effect.gen(function* () { const error = yield* parseJsonObjectInput("[1,2,3]").pipe(Effect.flip); // oxlint-disable-next-line executor/no-unknown-error-message -- boundary: helper contract returns a native Error for CLI input parsing expect(error.message).toContain("must decode to a JSON object"); }), ); it("builds bracket-safe invocation code for dynamic tool paths", () => { const code = buildInvokeToolCode("google-drive.files.list", { pageSize: 10 }); expect(code).toContain('const __target = tools["google-drive"]["files"]["list"]'); expect(code).toContain("const __args = {"); }); it("builds tool paths from dot or segmented forms", () => { expect(buildToolPath(["github", "issues", "create"])).toBe("github.issues.create"); expect(buildToolPath(["github.issues", "create"])).toBe("github.issues.create"); }); it("rejects invalid tool-path segments", () => { expect(() => buildToolPath(["github", "issues", "create now"])).toThrow(); }); it("builds search and sources code snippets", () => { const searchCode = buildSearchToolsCode({ query: "google calendar events", namespace: "google", limit: 5, }); const sourcesCode = buildListSourcesCode({ query: "google", limit: 20 }); expect(searchCode).toBe( 'return await tools.search({"query":"google calendar events","limit":5,"namespace":"google"});', ); expect(sourcesCode).toBe( 'return await tools.executor.sources.list({"limit":20,"query":"google"});', ); }); it("extracts completed result payload and pause execution id", () => { expect(extractExecutionResult({ status: "completed", result: { ok: true }, logs: [] })).toEqual( { ok: true, }, ); expect(extractExecutionResult({ status: "completed" })).toBeNull(); expect(extractExecutionId({ executionId: "exec_123" })).toBe("exec_123"); expect(extractExecutionId({ executionId: 123 })).toBeUndefined(); }); it("inspects hierarchical tool path prefixes for call help", () => { const view = inspectToolPath({ toolPaths: [ "cloudflare.dns.records.list", "cloudflare.dns.records.create", "cloudflare.dns.analytics", "cloudflare.zones.list", ], rawPrefixParts: ["cloudflare", "dns"], }); expect(view.prefixSegments).toEqual(["cloudflare", "dns"]); expect(view.exactPath).toBeUndefined(); expect(view.matchingToolCount).toBe(3); expect(view.children).toEqual([ { segment: "analytics", invokable: true, hasChildren: false, toolCount: 1 }, { segment: "records", invokable: false, hasChildren: true, toolCount: 2 }, ]); }); it("reports exact matches for leaf tool paths", () => { const view = inspectToolPath({ toolPaths: ["github.issues.create", "github.issues.list"], rawPrefixParts: ["github", "issues", "create"], }); expect(view.prefixSegments).toEqual(["github", "issues", "create"]); expect(view.exactPath).toBe("github.issues.create"); expect(view.matchingToolCount).toBe(1); expect(view.children).toEqual([]); }); it("extracts paused form interaction payload", () => { const interaction = extractPausedInteraction({ status: "waiting_for_interaction", executionId: "exec_1", interaction: { kind: "form", message: "Need approval", requestedSchema: { type: "object", properties: { approved: { type: "boolean" }, }, required: ["approved"], }, }, }); expect(interaction).toEqual({ kind: "form", message: "Need approval", requestedSchema: { type: "object", properties: { approved: { type: "boolean" }, }, required: ["approved"], }, }); }); it("builds resume content template from requested schema", () => { const template = buildResumeContentTemplate({ type: "object", properties: { approved: { type: "boolean" }, note: { type: "string" }, }, required: ["approved"], }); expect(template).toEqual({ approved: false }); }); it("filters child segments with singular/plural matching", () => { const children = [ { segment: "zoneRulesets", invokable: false, hasChildren: true, toolCount: 10 }, { segment: "dnsRecordsForAZone", invokable: false, hasChildren: true, toolCount: 14 }, { segment: "workersAi", invokable: false, hasChildren: true, toolCount: 8 }, ] as const; expect(filterToolPathChildren(children, "zones").map((entry) => entry.segment)).toEqual([ "zoneRulesets", "dnsRecordsForAZone", ]); expect(filterToolPathChildren(children, "worker").map((entry) => entry.segment)).toEqual([ "workersAi", ]); }); it("normalizes stack-heavy CLI error text", () => { const normalized = normalizeCliErrorText(`Error: Error: TypeError: bad at fn1 (/tmp/a.ts:1:1) at fn2 (/tmp/b.ts:2:2)From previous event: at fn3 (/tmp/c.ts:3:3)`); expect(normalized).toBe("TypeError: bad"); });});
import { describe, expect, it } from "@effect/vitest";
import { Effect } from "effect";
import {
buildResumeContentTemplate,
buildToolPath,
filterToolPathChildren,
buildInvokeToolCode,
buildListSourcesCode,
buildSearchToolsCode,
extractPausedInteraction,
extractExecutionId,
extractExecutionResult,
inspectToolPath,
normalizeCliErrorText,
parseJsonObjectInput,
} from "../apps/cli/src/tooling";
describe("CLI tooling helpers", () => {
it.effect("parses empty input as an empty args object", () =>
Effect.gen(function* () {
const args = yield* parseJsonObjectInput(undefined);
expect(args).toEqual({});
}),
);
it.effect("parses JSON object input", () =>
Effect.gen(function* () {
const args = yield* parseJsonObjectInput('{"calendarId":"primary"}');
expect(args).toEqual({ calendarId: "primary" });
}),
);
it.effect("rejects non-object JSON input", () =>
Effect.gen(function* () {
const error = yield* parseJsonObjectInput("[1,2,3]").pipe(Effect.flip);
// oxlint-disable-next-line executor/no-unknown-error-message -- boundary: helper contract returns a native Error for CLI input parsing
expect(error.message).toContain("must decode to a JSON object");
}),
);
it("builds bracket-safe invocation code for dynamic tool paths", () => {
const code = buildInvokeToolCode("google-drive.files.list", { pageSize: 10 });
expect(code).toContain('const __target = tools["google-drive"]["files"]["list"]');
expect(code).toContain("const __args = {");
});
it("builds tool paths from dot or segmented forms", () => {
expect(buildToolPath(["github", "issues", "create"])).toBe("github.issues.create");
expect(buildToolPath(["github.issues", "create"])).toBe("github.issues.create");
});
it("rejects invalid tool-path segments", () => {
expect(() => buildToolPath(["github", "issues", "create now"])).toThrow();
});
it("builds search and sources code snippets", () => {
const searchCode = buildSearchToolsCode({
query: "google calendar events",
namespace: "google",
limit: 5,
});
const sourcesCode = buildListSourcesCode({ query: "google", limit: 20 });
expect(searchCode).toBe(
'return await tools.search({"query":"google calendar events","limit":5,"namespace":"google"});',
);
expect(sourcesCode).toBe(
'return await tools.executor.sources.list({"limit":20,"query":"google"});',
);
});
it("extracts completed result payload and pause execution id", () => {
expect(extractExecutionResult({ status: "completed", result: { ok: true }, logs: [] })).toEqual(
{
ok: true,
},
);
expect(extractExecutionResult({ status: "completed" })).toBeNull();
expect(extractExecutionId({ executionId: "exec_123" })).toBe("exec_123");
expect(extractExecutionId({ executionId: 123 })).toBeUndefined();
});
it("inspects hierarchical tool path prefixes for call help", () => {
const view = inspectToolPath({
toolPaths: [
"cloudflare.dns.records.list",
"cloudflare.dns.records.create",
"cloudflare.dns.analytics",
"cloudflare.zones.list",
],
rawPrefixParts: ["cloudflare", "dns"],
});
expect(view.prefixSegments).toEqual(["cloudflare", "dns"]);
expect(view.exactPath).toBeUndefined();
expect(view.matchingToolCount).toBe(3);
expect(view.children).toEqual([
{ segment: "analytics", invokable: true, hasChildren: false, toolCount: 1 },
{ segment: "records", invokable: false, hasChildren: true, toolCount: 2 },
]);
});
it("reports exact matches for leaf tool paths", () => {
const view = inspectToolPath({
toolPaths: ["github.issues.create", "github.issues.list"],
rawPrefixParts: ["github", "issues", "create"],
});
expect(view.prefixSegments).toEqual(["github", "issues", "create"]);
expect(view.exactPath).toBe("github.issues.create");
expect(view.matchingToolCount).toBe(1);
expect(view.children).toEqual([]);
});
it("extracts paused form interaction payload", () => {
const interaction = extractPausedInteraction({
status: "waiting_for_interaction",
executionId: "exec_1",
interaction: {
kind: "form",
message: "Need approval",
requestedSchema: {
type: "object",
properties: {
approved: { type: "boolean" },
},
required: ["approved"],
},
},
});
expect(interaction).toEqual({
kind: "form",
message: "Need approval",
requestedSchema: {
type: "object",
properties: {
approved: { type: "boolean" },
},
required: ["approved"],
},
});
});
it("builds resume content template from requested schema", () => {
const template = buildResumeContentTemplate({
type: "object",
properties: {
approved: { type: "boolean" },
note: { type: "string" },
},
required: ["approved"],
});
expect(template).toEqual({ approved: false });
});
it("filters child segments with singular/plural matching", () => {
const children = [
{ segment: "zoneRulesets", invokable: false, hasChildren: true, toolCount: 10 },
{ segment: "dnsRecordsForAZone", invokable: false, hasChildren: true, toolCount: 14 },
{ segment: "workersAi", invokable: false, hasChildren: true, toolCount: 8 },
] as const;
expect(filterToolPathChildren(children, "zones").map((entry) => entry.segment)).toEqual([
"zoneRulesets",
"dnsRecordsForAZone",
]);
expect(filterToolPathChildren(children, "worker").map((entry) => entry.segment)).toEqual([
"workersAi",
]);
});
it("normalizes stack-heavy CLI error text", () => {
const normalized = normalizeCliErrorText(`Error: Error: TypeError: bad
at fn1 (/tmp/a.ts:1:1)
at fn2 (/tmp/b.ts:2:2)
From previous event:
at fn3 (/tmp/c.ts:3:3)`);
expect(normalized).toBe("TypeError: bad");
});
});