diff --git a/package.json b/package.json index ebe622a..2628729 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ ], "scripts": { "build": "bun run --filter '*' build", - "check": "biome check .", + "check": "bunx tsc --build && biome check .", + "typecheck": "bunx tsc --build", "format": "biome format --write .", "test": "bun run --filter '*' test" }, diff --git a/packages/workflow-role-committer/package.json b/packages/workflow-role-committer/package.json index ed1b50f..7ee3649 100644 --- a/packages/workflow-role-committer/package.json +++ b/packages/workflow-role-committer/package.json @@ -12,8 +12,5 @@ "@uncaged/workflow": "workspace:*", "@uncaged/workflow-util-role": "workspace:*", "zod": "^4.0.0" - }, - "devDependencies": { - "@types/node": "^25.6.0" } } diff --git a/packages/workflow-role-llm/__tests__/create-llm-adapter.test.ts b/packages/workflow-role-llm/__tests__/create-llm-adapter.test.ts index 73a8c98..df410a1 100644 --- a/packages/workflow-role-llm/__tests__/create-llm-adapter.test.ts +++ b/packages/workflow-role-llm/__tests__/create-llm-adapter.test.ts @@ -19,13 +19,13 @@ describe("createLlmAdapter", () => { const originalFetch = globalThis.fetch; test("posts system + user (start.content) and returns assistant text", async () => { - globalThis.fetch = () => + globalThis.fetch = (() => Promise.resolve( new Response(JSON.stringify({ choices: [{ message: { content: "model reply" } }] }), { status: 200, headers: { "Content-Type": "application/json" }, }), - ); + )) as unknown as typeof fetch; const provider = { baseUrl: "https://api.example/v1", apiKey: "k", model: "m" }; const adapter = createLlmAdapter(provider); @@ -37,13 +37,13 @@ describe("createLlmAdapter", () => { }); test("throws on non-ok fetch response", async () => { - globalThis.fetch = () => + globalThis.fetch = (() => Promise.resolve( new Response("Internal Server Error", { status: 500, headers: { "Content-Type": "text/plain" }, }), - ); + )) as unknown as typeof fetch; const provider = { baseUrl: "https://api.example/v1", apiKey: "k", model: "m" }; const adapter = createLlmAdapter(provider); @@ -53,7 +53,7 @@ describe("createLlmAdapter", () => { }); test("throws on fetch network failure", async () => { - globalThis.fetch = () => Promise.reject(new Error("ECONNREFUSED")); + globalThis.fetch = (() => Promise.reject(new Error("ECONNREFUSED"))) as unknown as typeof fetch; const provider = { baseUrl: "https://api.example/v1", apiKey: "k", model: "m" }; const adapter = createLlmAdapter(provider); diff --git a/packages/workflow-role-reviewer/__tests__/reviewer.test.ts b/packages/workflow-role-reviewer/__tests__/reviewer.test.ts index 5db315f..8711a70 100644 --- a/packages/workflow-role-reviewer/__tests__/reviewer.test.ts +++ b/packages/workflow-role-reviewer/__tests__/reviewer.test.ts @@ -50,7 +50,10 @@ describe("createReviewerRole", () => { }); test("runs reviewer extract", async () => { - globalThis.fetch = () => Promise.resolve(toolCallResponse(JSON.stringify({ approved: true }))); + globalThis.fetch = (() => + Promise.resolve( + toolCallResponse(JSON.stringify({ approved: true })), + )) as unknown as typeof fetch; const agent: AgentFn = async (_ctx, prompt) => { expect(prompt).toContain("git diff"); @@ -68,7 +71,10 @@ describe("createReviewerRole", () => { }); test("includes uncaged-workflow thread hint when threadId set", async () => { - globalThis.fetch = () => Promise.resolve(toolCallResponse(JSON.stringify({ approved: false }))); + globalThis.fetch = (() => + Promise.resolve( + toolCallResponse(JSON.stringify({ approved: false })), + )) as unknown as typeof fetch; let seen = ""; const agent: AgentFn = async (_ctx, prompt) => { diff --git a/packages/workflow-template-solve-issue/__tests__/solve-issue-template.test.ts b/packages/workflow-template-solve-issue/__tests__/solve-issue-template.test.ts index eec7026..981d91d 100644 --- a/packages/workflow-template-solve-issue/__tests__/solve-issue-template.test.ts +++ b/packages/workflow-template-solve-issue/__tests__/solve-issue-template.test.ts @@ -115,7 +115,7 @@ describe("createSolveIssueRoles", () => { expect(typeof roles.committer).toBe("function"); const ctx = makeCtx(10, []); - const plannerOut = await roles.planner(ctx); + const plannerOut = await roles.planner(ctx as unknown as ThreadContext); expect(plannerOut.meta.plan).toBe(""); expect(Array.isArray(plannerOut.meta.files)).toBe(true); }); diff --git a/packages/workflow-util-agent/package.json b/packages/workflow-util-agent/package.json index eb65c00..de22ea5 100644 --- a/packages/workflow-util-agent/package.json +++ b/packages/workflow-util-agent/package.json @@ -4,6 +4,12 @@ "type": "module", "main": "src/index.ts", "types": "src/index.ts", + "exports": { + ".": { + "types": "./src/index.ts", + "default": "./src/index.ts" + } + }, "scripts": { "build": "echo 'TODO'", "test": "bun test" diff --git a/packages/workflow-util-role/__tests__/create-role.test.ts b/packages/workflow-util-role/__tests__/create-role.test.ts index 299059a..6501cf7 100644 --- a/packages/workflow-util-role/__tests__/create-role.test.ts +++ b/packages/workflow-util-role/__tests__/create-role.test.ts @@ -55,7 +55,8 @@ describe("createRole", () => { }); test("runs AgentFn then structured extract", async () => { - globalThis.fetch = () => Promise.resolve(toolCallResponse(JSON.stringify({ n: 3 }))); + globalThis.fetch = (() => + Promise.resolve(toolCallResponse(JSON.stringify({ n: 3 })))) as unknown as typeof fetch; const schema = z.object({ n: z.number() }); const agent: AgentFn = async (_ctx, prompt) => prompt; @@ -73,7 +74,8 @@ describe("createRole", () => { }); test("passes ThreadContext to AgentFn", async () => { - globalThis.fetch = () => Promise.resolve(toolCallResponse(JSON.stringify({ n: 0 }))); + globalThis.fetch = (() => + Promise.resolve(toolCallResponse(JSON.stringify({ n: 0 })))) as unknown as typeof fetch; const seen: ThreadContext[] = []; const agent: AgentFn = async (ctx, _prompt) => { @@ -94,7 +96,8 @@ describe("createRole", () => { }); test("resolves dynamic systemPrompt functions before AgentFn", async () => { - globalThis.fetch = () => Promise.resolve(toolCallResponse(JSON.stringify({ n: 99 }))); + globalThis.fetch = (() => + Promise.resolve(toolCallResponse(JSON.stringify({ n: 99 })))) as unknown as typeof fetch; const schema = z.object({ n: z.number() }); const agent: AgentFn = async (_ctx, prompt) => prompt; diff --git a/packages/workflow-util-role/__tests__/extract-meta.test.ts b/packages/workflow-util-role/__tests__/extract-meta.test.ts index d61fe3f..6e3de1a 100644 --- a/packages/workflow-util-role/__tests__/extract-meta.test.ts +++ b/packages/workflow-util-role/__tests__/extract-meta.test.ts @@ -14,10 +14,10 @@ describe("extractMetaOrThrow", () => { test("dryRun returns dryRunMeta without calling fetch", async () => { let calls = 0; - globalThis.fetch = () => { + globalThis.fetch = (() => { calls += 1; return Promise.resolve(new Response("{}", { status: 200 })); - }; + }) as unknown as typeof fetch; const schema = z.object({ n: z.number() }); const out = await extractMetaOrThrow("r", "raw", schema, { @@ -33,7 +33,7 @@ describe("extractMetaOrThrow", () => { }); test("throws when extraction fails after retry", async () => { - globalThis.fetch = () => + globalThis.fetch = (() => Promise.resolve( new Response( JSON.stringify({ @@ -49,7 +49,7 @@ describe("extractMetaOrThrow", () => { }), { status: 200, headers: { "Content-Type": "application/json" } }, ), - ); + )) as unknown as typeof fetch; const schema = z.object({ n: z.number() }); @@ -61,7 +61,7 @@ describe("extractMetaOrThrow", () => { }); test("returns validated meta on successful tool call", async () => { - globalThis.fetch = () => + globalThis.fetch = (() => Promise.resolve( new Response( JSON.stringify({ @@ -82,7 +82,7 @@ describe("extractMetaOrThrow", () => { }), { status: 200, headers: { "Content-Type": "application/json" } }, ), - ); + )) as unknown as typeof fetch; const schema = z.object({ branch: z.string(), diff --git a/packages/workflow-util-role/__tests__/llm-extract.test.ts b/packages/workflow-util-role/__tests__/llm-extract.test.ts index 55c55de..836ebab 100644 --- a/packages/workflow-util-role/__tests__/llm-extract.test.ts +++ b/packages/workflow-util-role/__tests__/llm-extract.test.ts @@ -17,7 +17,7 @@ describe("llmExtract", () => { let capturedUrl: string | null = null; let capturedInit: RequestInit | null = null; - globalThis.fetch = (input: RequestInfo | URL, init?: RequestInit) => { + globalThis.fetch = ((input: Request | string | URL, init?: RequestInit) => { capturedUrl = typeof input === "string" ? input : input.toString(); capturedInit = init ?? null; return Promise.resolve( @@ -44,7 +44,7 @@ describe("llmExtract", () => { { status: 200, headers: { "Content-Type": "application/json" } }, ), ); - }; + }) as unknown as typeof fetch; const result = await llmExtract({ text: "some plan", @@ -66,13 +66,13 @@ describe("llmExtract", () => { } expect(result.value).toEqual({ name: "cpu-usage", description: "CPU load" }); - expect(capturedUrl).toBe("https://example.com/v1/chat/completions"); - expect(capturedInit?.method).toBe("POST"); - expect(capturedInit?.headers).toMatchObject({ + expect(capturedUrl!).toBe("https://example.com/v1/chat/completions"); + expect(capturedInit!.method).toBe("POST"); + expect(capturedInit!.headers).toMatchObject({ Authorization: "Bearer k", "Content-Type": "application/json", }); - const body = JSON.parse(capturedInit?.body as string) as { + const body = JSON.parse(capturedInit!.body as string) as { model: string; tool_choice: { function: { name: string } }; }; @@ -83,7 +83,7 @@ describe("llmExtract", () => { test("returns schema_validation_failed when arguments do not match the schema", async () => { const schema = z.object({ n: z.number() }); - globalThis.fetch = () => + globalThis.fetch = (() => Promise.resolve( new Response( JSON.stringify({ @@ -99,7 +99,7 @@ describe("llmExtract", () => { }), { status: 200, headers: { "Content-Type": "application/json" } }, ), - ); + )) as unknown as typeof fetch; const result = await llmExtract({ text: "x", @@ -120,10 +120,10 @@ describe("llmExtract", () => { test("dryRun skips fetch and returns dryRunMeta", async () => { let calls = 0; - globalThis.fetch = () => { + globalThis.fetch = (() => { calls += 1; return Promise.resolve(new Response("{}", { status: 200 })); - }; + }) as unknown as typeof fetch; const schema = z.object({ n: z.number() }); const result = await llmExtract({