c0832182f2
- opencode.json / grok.json leave the built-in catalog; opencode-usage.js, its poller, transcript branch and table creation go with it (existing tables and session rows stay as history). - A Grok payload reaching the Claude hook route (Grok runs the Claude hooks itself) is dropped instead of recorded as tool = 'grok'. - quota.js no longer reads Grok or OpenCode Go logins. - Redone on v2.8.22 from c6b2892 (feat/grok-usage, never merged).
84 lines
3.0 KiB
JavaScript
84 lines
3.0 KiB
JavaScript
/**
|
|
* @file Tests POST /api/hooks/event for a hook Grok Build fired through the
|
|
* Claude hooks in `~/.claude/settings.json` (Grok's Claude compatibility): it
|
|
* arrives with no `tool`, is told apart by the camelCase keys only Grok sends
|
|
* (`hookEventName`, `workspaceRoot`), and dropped — Grok is not an AgentHub
|
|
* tool, and taken as Claude's it would bind the claude workspace and name a
|
|
* Grok file as a Claude transcript. A Claude hook is left Claude's. The DB
|
|
* lives in a temp dir.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
|
|
const { describe, it, before, after } = require("node:test");
|
|
const assert = require("node:assert/strict");
|
|
const path = require("node:path");
|
|
const os = require("node:os");
|
|
const fs = require("node:fs");
|
|
|
|
const ROOT = fs.mkdtempSync(path.join(os.tmpdir(), "agenthub-grok-hook-route-"));
|
|
process.env.DASHBOARD_DB_PATH = path.join(ROOT, "dashboard.db");
|
|
process.env.CLAUDE_HOME = path.join(ROOT, "claude");
|
|
process.env.DASHBOARD_LIVENESS_PROBE = "0";
|
|
|
|
const { createApp, startServer } = require("../index");
|
|
const { db } = require("../db");
|
|
const lanes = require("../lib/lanes");
|
|
|
|
let server;
|
|
let BASE;
|
|
const CWD = path.join(fs.realpathSync(ROOT), "repo");
|
|
fs.mkdirSync(CWD, { recursive: true });
|
|
|
|
before(async () => {
|
|
server = await startServer(createApp(), 0);
|
|
BASE = `http://127.0.0.1:${server.address().port}`;
|
|
});
|
|
after(() => {
|
|
server.close();
|
|
fs.rmSync(ROOT, { recursive: true, force: true });
|
|
});
|
|
|
|
const post = (body) =>
|
|
fetch(`${BASE}/api/hooks/event`, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(body),
|
|
}).then((r) => r.json());
|
|
|
|
const grokData = (id, extra = {}) => ({
|
|
hookEventName: "session_start",
|
|
hook_event_name: "SessionStart",
|
|
sessionId: id,
|
|
session_id: id,
|
|
cwd: CWD,
|
|
workspaceRoot: CWD,
|
|
transcript_path: path.join(ROOT, "grok", "sessions", id, "chat_history.jsonl"),
|
|
permissionMode: "default",
|
|
...extra,
|
|
});
|
|
|
|
describe("Grok hooks through the Claude settings", () => {
|
|
it("drops a Grok hook: no session, no event, no workspace bound", async () => {
|
|
const claudeLane = lanes.createLane({ title: "c", cwd: CWD, tool: "claude" });
|
|
const id = "0199f0aa-1111-7222-8333-444455556666";
|
|
const r = await post({ hook_type: "SessionStart", data: grokData(id) });
|
|
assert.equal(r.ignored, true);
|
|
await post({
|
|
hook_type: "UserPromptSubmit",
|
|
data: grokData(id, { hookEventName: "user_prompt_submit", prompt: "fix the bug" }),
|
|
});
|
|
assert.equal(db.prepare("SELECT * FROM sessions WHERE id = ?").get(id), undefined);
|
|
assert.equal(db.prepare("SELECT COUNT(*) n FROM events WHERE session_id = ?").get(id).n, 0);
|
|
assert.equal(lanes.getLane(claudeLane.id).session_id, null);
|
|
});
|
|
|
|
it("leaves a Claude hook Claude's", async () => {
|
|
const id = "0199f0aa-1111-7222-8333-777788889999";
|
|
await post({
|
|
hook_type: "SessionStart",
|
|
data: { hook_event_name: "SessionStart", session_id: id, cwd: CWD },
|
|
});
|
|
assert.equal(db.prepare("SELECT tool FROM sessions WHERE id = ?").get(id).tool, "claude");
|
|
});
|
|
});
|