Merge branch 'chore/510-open-source-readiness'

This commit is contained in:
2026-05-25 10:29:09 +00:00
11 changed files with 89 additions and 80 deletions
+1 -1
View File
@@ -25,4 +25,4 @@ jobs:
run: bunx biome check . run: bunx biome check .
- name: Test - name: Test
run: bun run --filter './packages/*' test run: bun run test:ci
+1
View File
@@ -11,6 +11,7 @@
"typecheck": "bunx tsc --build", "typecheck": "bunx tsc --build",
"format": "biome format --write .", "format": "biome format --write .",
"test": "bun run --filter './packages/*' test", "test": "bun run --filter './packages/*' test",
"test:ci": "bun run --filter './packages/*' test:ci",
"changeset": "bunx changeset", "changeset": "bunx changeset",
"version": "bunx changeset version", "version": "bunx changeset version",
"release": "bun run build && bun test && node scripts/publish-all.mjs" "release": "bun run build && bun test && node scripts/publish-all.mjs"
+2 -1
View File
@@ -22,7 +22,8 @@
"yaml": "^2.8.4" "yaml": "^2.8.4"
}, },
"scripts": { "scripts": {
"test": "vitest run" "test": "vitest run",
"test:ci": "vitest run"
}, },
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
+2 -1
View File
@@ -18,7 +18,8 @@
} }
}, },
"scripts": { "scripts": {
"test": "bun test" "test": "bun test",
"test:ci": "bun test"
}, },
"dependencies": { "dependencies": {
"@uncaged/json-cas": "^0.5.2", "@uncaged/json-cas": "^0.5.2",
@@ -18,7 +18,8 @@
} }
}, },
"scripts": { "scripts": {
"test": "bun test" "test": "bun test",
"test:ci": "bun test"
}, },
"dependencies": { "dependencies": {
"@uncaged/json-cas": "^0.5.2", "@uncaged/json-cas": "^0.5.2",
@@ -2,8 +2,6 @@ import { afterEach, beforeEach, describe, expect, it } from "bun:test";
import { HermesAcpClient } from "../src/acp-client.js"; import { HermesAcpClient } from "../src/acp-client.js";
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
describe("handleSessionUpdate — helper extraction", () => { describe("handleSessionUpdate — helper extraction", () => {
let client: HermesAcpClient; let client: HermesAcpClient;
@@ -94,75 +92,4 @@ describe("handleSessionUpdate — helper extraction", () => {
}); });
}); });
describe("HermesAcpClient", () => {
let client: HermesAcpClient;
beforeEach(() => {
client = new HermesAcpClient();
});
afterEach(async () => {
await client.close();
});
it(
"connect() returns a UUID sessionId",
async () => {
const sessionId = await client.connect(process.cwd());
expect(typeof sessionId).toBe("string");
expect(sessionId).toMatch(UUID_RE);
},
{ timeout: 2 * 60 * 1000 },
);
it(
"prompt() returns a non-empty text response",
async () => {
await client.connect(process.cwd());
const result = await client.prompt("Reply with exactly the word: PONG");
expect(typeof result.text).toBe("string");
expect(result.text.length).toBeGreaterThan(0);
expect(typeof result.sessionId).toBe("string");
expect(result.sessionId).toMatch(UUID_RE);
},
{ timeout: 2 * 60 * 1000 },
);
it(
"prompt() can be called twice on the same session (resume)",
async () => {
await client.connect(process.cwd());
const first = await client.prompt("Say the word ALPHA and nothing else.");
expect(first.text.length).toBeGreaterThan(0);
const second = await client.prompt("Now say the word BETA and nothing else.");
expect(second.text.length).toBeGreaterThan(0);
expect(first.sessionId).toBe(second.sessionId);
},
{ timeout: 2 * 60 * 1000 },
);
// TODO(#435): flaky — depends on live LLM; mock or move to integration suite
it.skip(
"prompt() collects structured messages including tool calls",
async () => {
await client.connect(process.cwd());
const result = await client.prompt("Run this command: echo TOOL_DETAIL_TEST");
expect(result.messages.length).toBeGreaterThan(0);
// Should have at least one tool message (the echo command)
const toolMessages = result.messages.filter((m) => m.role === "tool");
expect(toolMessages.length).toBeGreaterThan(0);
// Tool message should contain the output
const toolContent = toolMessages[0]?.content ?? "";
expect(toolContent).toContain("TOOL_DETAIL_TEST");
// Should have assistant messages with tool_calls
const assistantWithTools = result.messages.filter(
(m) => m.role === "assistant" && m.tool_calls !== null,
);
expect(assistantWithTools.length).toBeGreaterThan(0);
},
{ timeout: 2 * 60 * 1000 },
);
});
@@ -0,0 +1,75 @@
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
import { HermesAcpClient } from "../../src/acp-client.js";
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
describe("HermesAcpClient", () => {
let client: HermesAcpClient;
beforeEach(() => {
client = new HermesAcpClient();
});
afterEach(async () => {
await client.close();
});
it(
"connect() returns a UUID sessionId",
async () => {
const sessionId = await client.connect(process.cwd());
expect(typeof sessionId).toBe("string");
expect(sessionId).toMatch(UUID_RE);
},
{ timeout: 2 * 60 * 1000 },
);
it(
"prompt() returns a non-empty text response",
async () => {
await client.connect(process.cwd());
const result = await client.prompt("Reply with exactly the word: PONG");
expect(typeof result.text).toBe("string");
expect(result.text.length).toBeGreaterThan(0);
expect(typeof result.sessionId).toBe("string");
expect(result.sessionId).toMatch(UUID_RE);
},
{ timeout: 2 * 60 * 1000 },
);
it(
"prompt() can be called twice on the same session (resume)",
async () => {
await client.connect(process.cwd());
const first = await client.prompt("Say the word ALPHA and nothing else.");
expect(first.text.length).toBeGreaterThan(0);
const second = await client.prompt("Now say the word BETA and nothing else.");
expect(second.text.length).toBeGreaterThan(0);
expect(first.sessionId).toBe(second.sessionId);
},
{ timeout: 2 * 60 * 1000 },
);
// TODO(#435): flaky — depends on live LLM; mock or move to integration suite
it.skip(
"prompt() collects structured messages including tool calls",
async () => {
await client.connect(process.cwd());
const result = await client.prompt("Run this command: echo TOOL_DETAIL_TEST");
expect(result.messages.length).toBeGreaterThan(0);
const toolMessages = result.messages.filter((m) => m.role === "tool");
expect(toolMessages.length).toBeGreaterThan(0);
const toolContent = toolMessages[0]?.content ?? "";
expect(toolContent).toContain("TOOL_DETAIL_TEST");
const assistantWithTools = result.messages.filter(
(m) => m.role === "assistant" && m.tool_calls !== null,
);
expect(assistantWithTools.length).toBeGreaterThan(0);
},
{ timeout: 2 * 60 * 1000 },
);
});
+2 -1
View File
@@ -18,7 +18,8 @@
} }
}, },
"scripts": { "scripts": {
"test": "bun test" "test": "bun test",
"test:ci": "bun test __tests__/*.test.ts"
}, },
"dependencies": { "dependencies": {
"@uncaged/json-cas": "^0.5.2", "@uncaged/json-cas": "^0.5.2",
+2 -1
View File
@@ -15,7 +15,8 @@
} }
}, },
"scripts": { "scripts": {
"test": "bun test" "test": "bun test",
"test:ci": "bun test"
}, },
"dependencies": { "dependencies": {
"@uncaged/json-cas": "^0.5.2", "@uncaged/json-cas": "^0.5.2",
+2 -1
View File
@@ -15,7 +15,8 @@
} }
}, },
"scripts": { "scripts": {
"test": "bun test" "test": "bun test",
"test:ci": "bun test"
}, },
"dependencies": { "dependencies": {
"@uncaged/workflow-protocol": "workspace:^", "@uncaged/workflow-protocol": "workspace:^",