969b06253c
Part B: Model Pricing, Hook Configuration and CLAUDE_HOME move from Settings → Dashboard to the Claude Code tab's AgentHub sub-tab (ClaudeAgentHubSettings.tsx); CODEX_HOME is editable in Codex → AgentHub. A home that is or contains the OS home is refused (EBADHOME). Settings persistence: dashboard-saved settings go to ~/.config/agenthub/settings.env (AGENTHUB_SETTINGS_FILE), outside the plugin cache an update wipes. Load order: real env > the checkout's .env > that file. The first CLAUDE_HOME change pins DASHBOARD_DATA_DIR so the DB stays put. C1: codex-usage.js reads Codex rollout journals into sessions (new column tool) and token_usage, tracked per file in codex_rollouts; forks deduped by total vector, sub-agent threads folded into the root; pricing-sync also prices OpenAI models; PricingSettings with a vendor filter. C2: codex-hooks.js installs AgentHub's hooks into $CODEX_HOME/hooks.json on a click, through a stable forwarder; Codex trust is never written. The hook route creates tool='codex' sessions and folds sub-agent hooks into the root. D: antigravity-usage.js reads agy's per-conversation SQLite files (tokens from ModelUsageStats) into tool='antigravity' sessions; antigravity-hooks.js installs the named hook `agenthub` (PreInvocation, PostToolUse, Stop — never PreToolUse) into ~/.gemini/config/hooks.json; Settings → Antigravity tab; Gemini pricing. Whole-change review fixes: sameOriginGuard on both home PUTs, routers.missing on a CLAUDE_HOME change, reset-pricing scope, GET /api/sessions?tool=, clear-data covering the new tables, Codex child-thread events moving no status, hooks owning status only while current, EFOREIGN for a forwarder that is not ours, agy quiet window and turn rules, AGENTHUB_SETTINGS_FILE honoured from .env. Docs, OpenAPI and the CLAUDE.md marker updated. Server 2141, client 779.
58 lines
2.4 KiB
JavaScript
58 lines
2.4 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* @file test-server.js
|
|
* @description Runs the server test suite against a PRIVATE tmux server.
|
|
* Several suites start real `agenthub-lane-<id>` tmux sessions and then kill
|
|
* or reset them, with lane ids from their own throwaway database — on the
|
|
* user's default tmux server those names collide with the dashboard's real
|
|
* lane panes, and a test run kills whichever live session shares an id
|
|
* (including the pane the test was launched from). Dropping `TMUX` and
|
|
* pointing `TMUX_TMPDIR` at a fresh directory gives every tmux call — the
|
|
* app's own and the tests' direct `execFileSync("tmux", …)` — its own socket.
|
|
* It also points `DASHBOARD_PIPELINES_DIR` at `server/__tests__/fixtures/
|
|
* pipelines/`: AgentHub ships no pipeline template any more, and the two old
|
|
* ones kept there are what the dormant stage/detection code is tested against.
|
|
* `AGENTHUB_SETTINGS_FILE` goes to the same temp dir, so a suite that saves a
|
|
* setting never writes the developer's real `~/.config/agenthub/settings.env`,
|
|
* and `AGENTHUB_PRICING_SYNC=0` keeps every suite off the network.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
|
|
const { spawnSync } = require("node:child_process");
|
|
const fs = require("node:fs");
|
|
const os = require("node:os");
|
|
const path = require("node:path");
|
|
|
|
const root = path.join(__dirname, "..");
|
|
const dir = path.join(root, "server", "__tests__");
|
|
const files = fs
|
|
.readdirSync(dir)
|
|
.filter((f) => f.endsWith(".test.js"))
|
|
.map((f) => path.join(dir, f));
|
|
const args = process.argv.slice(2);
|
|
|
|
const tmuxDir = fs.mkdtempSync(path.join(os.tmpdir(), "agenthub-test-tmux-"));
|
|
const env = {
|
|
...process.env,
|
|
TMUX_TMPDIR: tmuxDir,
|
|
// Never the developer's real ~/.config/agenthub/settings.env: it can pin
|
|
// DASHBOARD_DATA_DIR at their live database.
|
|
AGENTHUB_SETTINGS_FILE: path.join(tmuxDir, "settings.env"),
|
|
// No suite may fetch LiteLLM's price list (reset-pricing syncs at once).
|
|
AGENTHUB_PRICING_SYNC: "0",
|
|
DASHBOARD_PIPELINES_DIR: path.join(dir, "fixtures", "pipelines"),
|
|
};
|
|
delete env.TMUX;
|
|
delete env.TMUX_PANE;
|
|
|
|
const result = spawnSync(process.execPath, ["--test", ...args, ...(args.length ? [] : files)], {
|
|
stdio: "inherit",
|
|
env,
|
|
cwd: root,
|
|
});
|
|
|
|
// Whatever a test leaked dies with the private server, never a real pane.
|
|
spawnSync("tmux", ["kill-server"], { env, stdio: "ignore" });
|
|
fs.rmSync(tmuxDir, { recursive: true, force: true });
|
|
process.exit(result.status ?? 1);
|