Files
united-workforce/packages/util-agent/__tests__/adapter-fork-null.test.ts
T
xiaoju d666516ce6
CI / check (pull_request) Successful in 3m20s
feat(util-agent): extend AgentOptions with fork / cleanup (Phase 2a)
Add AgentForkFn and AgentCleanupFn type aliases. Extend AgentOptions
with fork: AgentForkFn | null and cleanup: AgentCleanupFn | null
fields. Add getAskSessionId / setAskSessionId session-cache helpers
using <stepHash>:ask key shape (coexists with exec sessions in the
same per-agent cache file). All four adapters pass fork: null,
cleanup: null — real wiring lands in Phase 2b. Resolves #145.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-07 08:36:58 +00:00

61 lines
2.2 KiB
TypeScript

import { readFile } from "node:fs/promises";
import { join } from "node:path";
import { describe, expect, test } from "vitest";
/**
* Source-level verification that each adapter's `createAgent({...})` call
* includes the new `fork: null` and `cleanup: null` fields.
*
* Adapters are CLI binaries that spawn external processes — runtime testing
* requires real LLM environments — so we use static source inspection here.
* Type-level correctness is enforced separately by `tsc --build`.
*/
const REPO_ROOT = join(__dirname, "..", "..", "..");
const ADAPTERS: Array<{ name: string; path: string }> = [
{ name: "agent-mock", path: "packages/agent-mock/src/mock-agent.ts" },
{ name: "agent-builtin", path: "packages/agent-builtin/src/agent.ts" },
{ name: "agent-hermes", path: "packages/agent-hermes/src/hermes.ts" },
{ name: "agent-claude-code", path: "packages/agent-claude-code/src/claude-code.ts" },
];
/** Find the matching `}` for the `{` at `openIdx` in `source`. */
function findMatchingBrace(source: string, openIdx: number): number {
let depth = 0;
for (let i = openIdx; i < source.length; i++) {
const ch = source[i];
if (ch === "{") {
depth++;
} else if (ch === "}") {
depth--;
if (depth === 0) {
return i;
}
}
}
return -1;
}
/** Extract the `createAgent({...})` block from adapter source. */
function extractCreateAgentBlock(source: string): string {
const startIdx = source.indexOf("createAgent({");
expect(startIdx).toBeGreaterThanOrEqual(0);
const openIdx = source.indexOf("{", startIdx);
const endIdx = findMatchingBrace(source, openIdx);
expect(endIdx).toBeGreaterThan(openIdx);
return source.slice(openIdx, endIdx + 1);
}
describe("adapter createAgent calls include fork: null and cleanup: null", () => {
for (const adapter of ADAPTERS) {
test(`${adapter.name} createAgent call includes fork: null and cleanup: null`, async () => {
const source = await readFile(join(REPO_ROOT, adapter.path), "utf8");
expect(source).toMatch(/createAgent\s*\(\s*\{/);
const block = extractCreateAgentBlock(source);
expect(block).toMatch(/fork:\s*null/);
expect(block).toMatch(/cleanup:\s*null/);
});
}
});