e5e6de2fad
- Replace bun:test with vitest across all packages - Replace bun build with esbuild - Replace bun:sqlite with better-sqlite3 - Fix OCAS Store API: store.put/get → store.cas.put/get - Fix vitest vi.mock hoisting (vi.hoisted) - Add pnpm-workspace.yaml and pnpm-lock.yaml - Update all package.json test/build scripts WIP: 8 failures remain in agent-hermes (bun engines check + sqlite migration) Refs #26
115 lines
4.1 KiB
TypeScript
115 lines
4.1 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, test } from 'vitest';
|
|
import { mkdir, mkdtemp, rm } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { type CasRef, createThreadIndexEntry, type ThreadId } from "@united-workforce/protocol";
|
|
import { resolveHeadHash } from "../commands/shared.js";
|
|
import { addHistoryEntry, createUwfStore, setThread } from "../store.js";
|
|
|
|
let tmpDir: string;
|
|
|
|
beforeEach(async () => {
|
|
tmpDir = await mkdtemp(join(tmpdir(), "cli-uwf-resolve-head-"));
|
|
const casDir = join(tmpDir, "cas");
|
|
await mkdir(casDir, { recursive: true });
|
|
process.env.OCAS_DIR = casDir;
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await rm(tmpDir, { recursive: true, force: true });
|
|
});
|
|
|
|
describe("resolveHeadHash", () => {
|
|
test("returns head hash from variable store for active thread", async () => {
|
|
const threadId = "01JTEST0000000000000000001" as ThreadId;
|
|
const uwf = await createUwfStore(tmpDir);
|
|
const headHash = (await uwf.store.cas.put(uwf.schemas.text, "active")) as CasRef;
|
|
setThread(uwf.varStore, threadId, createThreadIndexEntry(headHash as CasRef));
|
|
|
|
const result = await resolveHeadHash(tmpDir, threadId);
|
|
|
|
expect(result).toBe(headHash);
|
|
});
|
|
|
|
test("falls back to history variable when thread not in active index", async () => {
|
|
const threadId = "01JTEST0000000000000000002" as ThreadId;
|
|
const workflowHash = "workflow_hash_789" as CasRef;
|
|
|
|
const uwf = await createUwfStore(tmpDir);
|
|
const headHash = (await uwf.store.cas.put(uwf.schemas.text, "completed-head")) as CasRef;
|
|
addHistoryEntry(uwf.varStore, {
|
|
thread: threadId,
|
|
workflow: workflowHash,
|
|
head: headHash,
|
|
completedAt: Date.now(),
|
|
reason: null,
|
|
});
|
|
|
|
const result = await resolveHeadHash(tmpDir, threadId);
|
|
|
|
expect(result).toBe(headHash);
|
|
});
|
|
|
|
// Note: Testing the error case requires CLI-level testing because resolveHeadHash
|
|
// calls fail() which does process.exit(1), terminating the test runner.
|
|
// The error behavior is tested in integration tests below via CLI invocation.
|
|
|
|
test("prioritizes active thread over history when thread exists in both", async () => {
|
|
const threadId = "01JTEST0000000000000000004" as ThreadId;
|
|
const workflowHash = "workflow_hash_xyz" as CasRef;
|
|
|
|
const uwf = await createUwfStore(tmpDir);
|
|
const activeHead = (await uwf.store.cas.put(uwf.schemas.text, "active-v2")) as CasRef;
|
|
const historicalHash = (await uwf.store.cas.put(uwf.schemas.text, "historical-v1")) as CasRef;
|
|
setThread(uwf.varStore, threadId, createThreadIndexEntry(activeHead));
|
|
addHistoryEntry(uwf.varStore, {
|
|
thread: threadId,
|
|
workflow: workflowHash,
|
|
head: historicalHash,
|
|
completedAt: Date.now(),
|
|
reason: null,
|
|
});
|
|
|
|
const result = await resolveHeadHash(tmpDir, threadId);
|
|
|
|
// Should return the active head, not the historical one
|
|
expect(result).toBe(activeHead);
|
|
});
|
|
|
|
test("finds thread from multiple history entries", async () => {
|
|
const threadId1 = "01JTEST0000000000000000005" as ThreadId;
|
|
const threadId2 = "01JTEST0000000000000000006" as ThreadId;
|
|
const threadId3 = "01JTEST0000000000000000007" as ThreadId;
|
|
const workflowHash = "workflow_hash_abc" as CasRef;
|
|
const uwf = await createUwfStore(tmpDir);
|
|
const hash1 = (await uwf.store.cas.put(uwf.schemas.text, "hash-thread1")) as CasRef;
|
|
const hash2 = (await uwf.store.cas.put(uwf.schemas.text, "hash-thread2")) as CasRef;
|
|
const hash3 = (await uwf.store.cas.put(uwf.schemas.text, "hash-thread3")) as CasRef;
|
|
addHistoryEntry(uwf.varStore, {
|
|
thread: threadId1,
|
|
workflow: workflowHash,
|
|
head: hash1,
|
|
completedAt: Date.now() - 2000,
|
|
reason: null,
|
|
});
|
|
addHistoryEntry(uwf.varStore, {
|
|
thread: threadId2,
|
|
workflow: workflowHash,
|
|
head: hash2,
|
|
completedAt: Date.now() - 1000,
|
|
reason: null,
|
|
});
|
|
addHistoryEntry(uwf.varStore, {
|
|
thread: threadId3,
|
|
workflow: workflowHash,
|
|
head: hash3,
|
|
completedAt: Date.now(),
|
|
reason: null,
|
|
});
|
|
|
|
const result = await resolveHeadHash(tmpDir, threadId2);
|
|
|
|
expect(result).toBe(hash2);
|
|
});
|
|
});
|