Files
AgentHub/server/__tests__/compat-sqlite.test.js
T
nntrivi2001 198fbb7980 fix: event-loop freezes, plugin-install boot crash, tmux attach/scrollbar, Codex transcripts
- GET /api/workflows: one LEAD() window pass in a read worker (read-pool.js,
  workflow-stats.js); idx_events_session restored, idx_events_tool added
- compat-sqlite gains function/pluck/readonly so a plugin install without a
  better-sqlite3 build boots again; antigravity-usage uses db.js's Database
- install-hooks adds no checkout hooks while the agenthub plugin is enabled
  (events were doubled)
- terminal attach runs the live tmux server's own binary; the pane scrollbar
  gets a visible 2-column style, and claude panes start with
  CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1 so tmux keeps history to scroll
- Codex sessions' conversation in GET /api/sessions/:id/transcript
- Codex/Antigravity sessions claimed by their workspace without hooks
- UI-audit follow-ups, docs and OpenAPI
2026-10-05 17:01:05 +07:00

77 lines
3.3 KiB
JavaScript

/**
* @file Tests server/compat-sqlite.js, the node:sqlite stand-in a plugin
* install runs on (better-sqlite3 has no native build there): every
* better-sqlite3 API the server uses — `function`, `pluck`, `readonly` /
* `fileMustExist` — and a real `server/db.js` boot in a child process with
* better-sqlite3 blocked, since the rest of the suite only ever runs on
* better-sqlite3 and a missing method there crashes the dashboard at start.
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
*/
const { describe, it, after } = require("node:test");
const assert = require("node:assert/strict");
const fs = require("fs");
const os = require("os");
const path = require("path");
const { spawnSync } = require("child_process");
const Database = require("../compat-sqlite");
const TMP = fs.mkdtempSync(path.join(os.tmpdir(), "agenthub-compat-"));
after(() => fs.rmSync(TMP, { recursive: true, force: true }));
describe("compat-sqlite", () => {
it("registers a SQL function like better-sqlite3's db.function", () => {
const db = new Database(":memory:");
db.function("twice", { deterministic: true }, (s) => `${s}${s}`);
db.function("one", () => 1);
assert.equal(db.prepare("SELECT twice('ab') AS v, one() AS o").get().v, "abab");
db.close();
});
it("pluck() returns the first column from get, all and iterate", () => {
const db = new Database(":memory:");
db.exec("CREATE TABLE t (a, b); INSERT INTO t VALUES (1, 'x'), (2, 'y');");
const s = db.prepare("SELECT a, b FROM t ORDER BY a").pluck();
assert.equal(s.get(), 1);
assert.deepEqual(s.all(), [1, 2]);
assert.deepEqual([...s.iterate()], [1, 2]);
assert.equal(db.prepare("SELECT a FROM t WHERE a = 9").pluck().get(), undefined);
db.close();
});
it("boots server/db.js and its trim/sweep paths with better-sqlite3 unavailable", () => {
const block = path.join(TMP, "no-bs3.js");
fs.writeFileSync(
block,
`const M = require("module"); const load = M._load;
M._load = function (r, ...a) { if (r === "better-sqlite3") throw new Error("blocked"); return load.call(this, r, ...a); };`
);
const script = `
const { db, Database } = require("./server/db");
if (Database !== require("./server/compat-sqlite")) throw new Error("not on compat");
const big = JSON.stringify({ tool_input: { content: "x".repeat(20000) } });
db.prepare("INSERT INTO sessions (id) VALUES ('s1')").run();
db.prepare("INSERT INTO events (session_id, event_type, tool_name, data) VALUES ('s1', 'PreToolUse', 'Write', ?)").run(big);
require("./server/lib/event-payload").sweepEventPayloads(db).then((r) => {
const len = db.prepare("SELECT length(trim_event_data(?)) AS n").get(big).n;
console.log(JSON.stringify({ swept: r.rows >= 0, trimmedShorter: len < big.length }));
process.exit(0);
});`;
const r = spawnSync(process.execPath, ["-r", block, "-e", script], {
cwd: path.join(__dirname, "..", ".."),
env: {
...process.env,
DASHBOARD_DB_PATH: path.join(TMP, "boot.db"),
AGENTHUB_PRICING_SYNC: "0",
},
encoding: "utf8",
timeout: 60_000,
});
assert.equal(r.status, 0, r.stderr);
assert.deepEqual(JSON.parse(r.stdout.trim().split("\n").pop()), {
swept: true,
trimmedShorter: true,
});
});
});