chapterhouse 0.3.25 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/server-runtime.js +1 -1
- package/dist/api/server.js +13 -1
- package/dist/api/server.test.js +68 -54
- package/dist/api/sse.integration.test.js +4 -46
- package/dist/api/turn-sse.integration.test.js +20 -47
- package/dist/config.js +81 -1
- package/dist/config.test.js +123 -0
- package/dist/copilot/agents.js +27 -4
- package/dist/copilot/agents.test.js +7 -0
- package/dist/copilot/oneshot.js +54 -0
- package/dist/copilot/orchestrator.js +228 -4
- package/dist/copilot/orchestrator.test.js +373 -1
- package/dist/copilot/system-message.js +4 -0
- package/dist/copilot/system-message.test.js +24 -0
- package/dist/copilot/tools.agent.test.js +23 -0
- package/dist/copilot/tools.js +350 -4
- package/dist/copilot/tools.memory.test.js +248 -0
- package/dist/copilot/turn-event-log-env.test.js +19 -0
- package/dist/copilot/turn-event-log.js +22 -23
- package/dist/copilot/turn-event-log.test.js +61 -2
- package/dist/memory/active-scope.js +69 -0
- package/dist/memory/active-scope.test.js +76 -0
- package/dist/memory/checkpoint-prompt.js +71 -0
- package/dist/memory/checkpoint.js +257 -0
- package/dist/memory/checkpoint.test.js +255 -0
- package/dist/memory/decisions.js +53 -0
- package/dist/memory/decisions.test.js +92 -0
- package/dist/memory/entities.js +59 -0
- package/dist/memory/entities.test.js +65 -0
- package/dist/memory/eot.js +219 -0
- package/dist/memory/eot.test.js +263 -0
- package/dist/memory/hot-tier.js +187 -0
- package/dist/memory/hot-tier.test.js +197 -0
- package/dist/memory/housekeeping.js +352 -0
- package/dist/memory/housekeeping.test.js +280 -0
- package/dist/memory/inbox.js +73 -0
- package/dist/memory/index.js +11 -0
- package/dist/memory/observations.js +46 -0
- package/dist/memory/observations.test.js +86 -0
- package/dist/memory/recall.js +197 -0
- package/dist/memory/recall.test.js +196 -0
- package/dist/memory/scopes.js +89 -0
- package/dist/memory/scopes.test.js +201 -0
- package/dist/memory/tiering.js +193 -0
- package/dist/memory/types.js +2 -0
- package/dist/paths.js +7 -1
- package/dist/store/db.js +423 -17
- package/dist/store/db.test.js +94 -7
- package/dist/test/api-server.js +50 -0
- package/dist/test/api-server.test.js +57 -0
- package/dist/test/setup-env.js +25 -0
- package/dist/test/setup-env.test.js +38 -0
- package/package.json +1 -1
- package/web/dist/assets/{index-BRPJa1DK.js → index-DmYLALt0.js} +70 -70
- package/web/dist/assets/index-DmYLALt0.js.map +1 -0
- package/web/dist/index.html +1 -1
- package/web/dist/assets/index-BRPJa1DK.js.map +0 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { createServer } from "node:http";
|
|
2
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
3
|
+
import assert from "node:assert/strict";
|
|
4
|
+
export const DEFAULT_API_SERVER_STARTUP_TIMEOUT_MS = 60_000;
|
|
5
|
+
export const STANDALONE_API_SERVER_STARTUP_TIMEOUT_MS = 60_000;
|
|
6
|
+
export const API_SERVER_STARTUP_POLL_INTERVAL_MS = 100;
|
|
7
|
+
export async function getFreePort() {
|
|
8
|
+
const server = createServer();
|
|
9
|
+
await new Promise((resolve) => server.listen(0, "127.0.0.1", () => resolve()));
|
|
10
|
+
const address = server.address();
|
|
11
|
+
assert.ok(address && typeof address === "object", "server should expose a bound address");
|
|
12
|
+
await new Promise((resolve, reject) => {
|
|
13
|
+
server.close((error) => (error ? reject(error) : resolve()));
|
|
14
|
+
});
|
|
15
|
+
return address.port;
|
|
16
|
+
}
|
|
17
|
+
export async function stopChild(child) {
|
|
18
|
+
if (child.exitCode !== null) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
child.kill("SIGTERM");
|
|
22
|
+
await new Promise((resolve) => {
|
|
23
|
+
child.once("exit", () => resolve());
|
|
24
|
+
setTimeout(() => {
|
|
25
|
+
if (child.exitCode === null) {
|
|
26
|
+
child.kill("SIGKILL");
|
|
27
|
+
}
|
|
28
|
+
}, 2_000);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export async function waitForApiServerReady({ child, baseUrl, logs, timeoutMs = DEFAULT_API_SERVER_STARTUP_TIMEOUT_MS, pollIntervalMs = API_SERVER_STARTUP_POLL_INTERVAL_MS, timeoutMessage = "Timed out waiting for API server to start", exitMessage = "API server exited early", }) {
|
|
32
|
+
const deadline = Date.now() + timeoutMs;
|
|
33
|
+
while (Date.now() < deadline) {
|
|
34
|
+
if (child.exitCode !== null) {
|
|
35
|
+
throw new Error(`${exitMessage}:\n${logs.join("")}`);
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetch(`${baseUrl}/status`);
|
|
39
|
+
if (response.ok) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Server is still starting.
|
|
45
|
+
}
|
|
46
|
+
await delay(pollIntervalMs);
|
|
47
|
+
}
|
|
48
|
+
throw new Error(`${timeoutMessage}:\n${logs.join("")}`);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=api-server.js.map
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { createServer } from "node:http";
|
|
3
|
+
import test from "node:test";
|
|
4
|
+
import { DEFAULT_API_SERVER_STARTUP_TIMEOUT_MS, STANDALONE_API_SERVER_STARTUP_TIMEOUT_MS, waitForApiServerReady, } from "./api-server.js";
|
|
5
|
+
async function listen(server) {
|
|
6
|
+
await new Promise((resolve) => server.listen(0, "127.0.0.1", () => resolve()));
|
|
7
|
+
const address = server.address();
|
|
8
|
+
assert.ok(address && typeof address === "object");
|
|
9
|
+
return address.port;
|
|
10
|
+
}
|
|
11
|
+
async function close(server) {
|
|
12
|
+
if (!server.listening) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
await new Promise((resolve, reject) => {
|
|
16
|
+
server.close((error) => (error ? reject(error) : resolve()));
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
test("waitForApiServerReady waits until /status responds with ok", async () => {
|
|
20
|
+
let ready = false;
|
|
21
|
+
const server = createServer((req, res) => {
|
|
22
|
+
if (req.url !== "/status") {
|
|
23
|
+
res.writeHead(404).end();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (!ready) {
|
|
27
|
+
res.writeHead(503).end("starting");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
res.writeHead(200, { "content-type": "application/json" });
|
|
31
|
+
res.end(JSON.stringify({ status: "ok" }));
|
|
32
|
+
});
|
|
33
|
+
const port = await listen(server);
|
|
34
|
+
const child = { exitCode: null };
|
|
35
|
+
setTimeout(() => {
|
|
36
|
+
ready = true;
|
|
37
|
+
}, 200);
|
|
38
|
+
const startedAt = Date.now();
|
|
39
|
+
try {
|
|
40
|
+
await waitForApiServerReady({
|
|
41
|
+
child,
|
|
42
|
+
baseUrl: `http://127.0.0.1:${port}`,
|
|
43
|
+
logs: [],
|
|
44
|
+
timeoutMs: 1_000,
|
|
45
|
+
pollIntervalMs: 25,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
await close(server);
|
|
50
|
+
}
|
|
51
|
+
assert.ok(Date.now() - startedAt >= 150);
|
|
52
|
+
});
|
|
53
|
+
test("API server startup timeouts leave headroom for slow CI runners", () => {
|
|
54
|
+
assert.equal(DEFAULT_API_SERVER_STARTUP_TIMEOUT_MS, 60_000);
|
|
55
|
+
assert.equal(STANDALONE_API_SERVER_STARTUP_TIMEOUT_MS, 60_000);
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=api-server.test.js.map
|
package/dist/test/setup-env.js
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
const RUNTIME_OVERRIDE_ENV_VARS = [
|
|
2
|
+
"CHAPTERHOUSE_MODE",
|
|
3
|
+
"CHAPTERHOUSE_SELF_EDIT",
|
|
4
|
+
"CHAPTERHOUSE_WORKIQ_AUTO_INSTALL",
|
|
5
|
+
"CHAPTERHOUSE_CHAT_SSE",
|
|
6
|
+
"CHAPTERHOUSE_SSE_BUFFER_CAPACITY",
|
|
7
|
+
"CHAPTERHOUSE_SSE_REPLAY_LIMIT",
|
|
8
|
+
"CHAPTERHOUSE_MEMORY_CHECKPOINT_ENABLED",
|
|
9
|
+
"CHAPTERHOUSE_MEMORY_CHECKPOINT_TURNS",
|
|
10
|
+
"CHAPTERHOUSE_MEMORY_CHECKPOINT_ON_SCOPE_CHANGE",
|
|
11
|
+
"CHAPTERHOUSE_MEMORY_CHECKPOINT_MIN_TURNS_FOR_SCOPE_FIRE",
|
|
12
|
+
"CHAPTERHOUSE_MEMORY_INJECT",
|
|
13
|
+
"CHAPTERHOUSE_MEMORY_AUTO_ACCEPT",
|
|
14
|
+
"CHAPTERHOUSE_MEMORY_EOT_HOOK_ENABLED",
|
|
15
|
+
"CHAPTERHOUSE_MEMORY_HOUSEKEEPING_ENABLED",
|
|
16
|
+
"CHAPTERHOUSE_MEMORY_HOUSEKEEPING_TURNS",
|
|
17
|
+
"CHAPTERHOUSE_MEMORY_DECAY_DAYS",
|
|
18
|
+
"CHAPTERHOUSE_MEMORY_INBOX_RETENTION_DAYS",
|
|
19
|
+
"CHAPTERHOUSE_MEMORY_TIERING_ENABLED",
|
|
20
|
+
"CHAPTERHOUSE_MEMORY_HOT_RECALL_BOOST",
|
|
21
|
+
"CHAPTERHOUSE_MEMORY_HOT_AGE_DAYS",
|
|
22
|
+
];
|
|
23
|
+
for (const name of RUNTIME_OVERRIDE_ENV_VARS) {
|
|
24
|
+
delete process.env[name];
|
|
25
|
+
}
|
|
1
26
|
process.env.CHAPTERHOUSE_DISABLE_DOTENV = "1";
|
|
2
27
|
export {};
|
|
3
28
|
//# sourceMappingURL=setup-env.js.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
const RUNTIME_OVERRIDE_ENV_VARS = [
|
|
4
|
+
"CHAPTERHOUSE_MODE",
|
|
5
|
+
"CHAPTERHOUSE_SELF_EDIT",
|
|
6
|
+
"CHAPTERHOUSE_WORKIQ_AUTO_INSTALL",
|
|
7
|
+
"CHAPTERHOUSE_CHAT_SSE",
|
|
8
|
+
"CHAPTERHOUSE_SSE_BUFFER_CAPACITY",
|
|
9
|
+
"CHAPTERHOUSE_SSE_REPLAY_LIMIT",
|
|
10
|
+
];
|
|
11
|
+
test("setup-env clears ambient Chapterhouse runtime overrides", async () => {
|
|
12
|
+
const originalValues = new Map(["CHAPTERHOUSE_DISABLE_DOTENV", ...RUNTIME_OVERRIDE_ENV_VARS].map((name) => [name, process.env[name]]));
|
|
13
|
+
try {
|
|
14
|
+
process.env.CHAPTERHOUSE_DISABLE_DOTENV = "0";
|
|
15
|
+
process.env.CHAPTERHOUSE_MODE = "team";
|
|
16
|
+
process.env.CHAPTERHOUSE_SELF_EDIT = "1";
|
|
17
|
+
process.env.CHAPTERHOUSE_WORKIQ_AUTO_INSTALL = "false";
|
|
18
|
+
process.env.CHAPTERHOUSE_CHAT_SSE = "0";
|
|
19
|
+
process.env.CHAPTERHOUSE_SSE_BUFFER_CAPACITY = "3";
|
|
20
|
+
process.env.CHAPTERHOUSE_SSE_REPLAY_LIMIT = "9";
|
|
21
|
+
await import(`./setup-env.js?cache-bust=${Date.now()}`);
|
|
22
|
+
assert.equal(process.env.CHAPTERHOUSE_DISABLE_DOTENV, "1");
|
|
23
|
+
for (const name of RUNTIME_OVERRIDE_ENV_VARS) {
|
|
24
|
+
assert.equal(process.env[name], undefined, `${name} should be cleared by setup-env`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
for (const [name, value] of originalValues) {
|
|
29
|
+
if (value === undefined) {
|
|
30
|
+
delete process.env[name];
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
process.env[name] = value;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=setup-env.test.js.map
|
package/package.json
CHANGED