feat(workflow-utils): add dryRunDefaults option to llmExtract

Lets workflow authors provide semantically meaningful mock data for dryRun mode. Falls back to schemaDefaults() when not provided.

Fixes #130

小橘 🍊(NEKO Team)

Made-with: Cursor
This commit is contained in:
2026-04-25 04:40:32 +00:00
parent ce20d73ab6
commit 21be4997df
2 changed files with 27 additions and 1 deletions
@@ -127,4 +127,25 @@ describe("llmExtract", () => {
}
expect(result.value).toEqual({ n: 0 });
});
it("dryRun applies dryRunDefaults over schema stub values", async () => {
const fetchMock = vi.fn();
vi.stubGlobal("fetch", fetchMock);
const schema = z.object({ n: z.number() });
const result = await llmExtract({
text: "ignored",
schema,
provider: { baseUrl: "https://example.com", apiKey: "k", model: "m" },
dryRun: true,
dryRunDefaults: { n: 42 },
});
expect(fetchMock).not.toHaveBeenCalled();
expect(result.ok).toBe(true);
if (!result.ok) {
return;
}
expect(result.value).toEqual({ n: 42 });
});
});
+6 -1
View File
@@ -14,6 +14,7 @@ export type LlmExtractOptions<T> = {
schema: z.ZodType<T>;
provider: LlmProvider;
dryRun: boolean;
dryRunDefaults?: Partial<T>;
};
type LlmExtractOptionsInput<T> = LlmExtractOptions<T> | Omit<LlmExtractOptions<T>, "dryRun">;
@@ -22,6 +23,10 @@ function resolveLlmExtractDryRun<T>(options: LlmExtractOptionsInput<T>): boolean
return "dryRun" in options ? options.dryRun : false;
}
function buildLlmExtractDryRunValue<T>(options: LlmExtractOptionsInput<T>): T {
return { ...schemaDefaults(options.schema), ...(options.dryRunDefaults ?? {}) } as T;
}
export type LlmError =
| { kind: "http_error"; status: number; body: string }
| { kind: "invalid_response_json"; message: string }
@@ -104,7 +109,7 @@ export async function llmExtract<T>(
): Promise<Result<T, LlmError>> {
const dryRun = resolveLlmExtractDryRun(options);
if (dryRun) {
return ok(schemaDefaults(options.schema) as T);
return ok(buildLlmExtractDryRunValue(options));
}
const rawJsonSchema = toJSONSchema(options.schema) as Record<string, unknown>;