feat(ai-tools): drop OpenCode and Grok Build

- 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).
This commit is contained in:
2026-10-23 13:44:24 +07:00
parent 9ea7758abb
commit c0832182f2
31 changed files with 116 additions and 1277 deletions
-69
View File
@@ -843,25 +843,6 @@ router.get("/:id/transcripts", async (req, res) => {
: [];
return res.json({ transcripts: list });
}
// OpenCode: a subagent is a child session of the store, tied to the agent
// row its poller made.
if (session.tool === "opencode") {
const list = [
{ id: "main", name: "Main Agent", type: "main", has_transcript: true, db_agent_id: null },
];
for (const sub of require("../lib/opencode-usage").subagentSessions(req.params.id)) {
list.push({
id: sub.id,
name: sub.name,
type: "subagent",
subagent_type: "task",
has_transcript: true,
db_agent_id: stmts.getAgent.get(sub.rowId) ? sub.rowId : null,
});
}
return res.json({ transcripts: list });
}
const result = [];
// Query database agent list for db_agent_id association
@@ -1101,20 +1082,6 @@ router.get("/:id/transcript", async (req, res) => {
const isCursor = session.tool === "cursor";
// An agy conversation's step log (`transcript_full.jsonl`), found by antigravity-usage.js.
const isAgy = session.tool === "antigravity";
// An OpenCode conversation lives in its SQLite store, not a JSONL file: read
// whole (one session's rows), then paged like the files below.
if (session.tool === "opencode") {
let all = null;
try {
all = require("../lib/opencode-usage").transcriptMessages(
req.params.id,
isSubagentFile ? agentId : null
);
} catch {
all = null;
}
return res.json(pageMessages(all || [], { limit, afterLine, beforeLine, offset }));
}
if (isOmp) {
jsonlPath = require("../lib/omp-usage").journalPath(req.params.id, agentId || "");
} else if (isCursor) {
@@ -1592,42 +1559,6 @@ function agyMessage(entry, num) {
}
}
/**
* The transcript route's paging over a conversation already in memory (an
* OpenCode store): message N is "line" N, so `after`/`before`/`offset` and the
* default latest-`limit` window answer exactly as they do over a file.
*/
function pageMessages(all, { limit, afterLine, beforeLine, offset }) {
const lined = all.map((m, i) => ({ ...m, line: i + 1 }));
let picked;
let hasMore;
if (afterLine !== null) {
const rest = lined.filter((m) => m.line > afterLine);
picked = rest.slice(0, limit);
hasMore = rest.length > limit;
} else if (beforeLine !== null) {
const older = lined.filter((m) => m.line < beforeLine);
picked = older.slice(-limit);
hasMore = older.length > limit;
} else if (offset > 0) {
picked = lined.slice(offset, offset + limit);
hasMore = lined.length > offset + limit;
} else {
picked = lined.slice(-limit);
hasMore = lined.length > limit;
}
const lastLine = picked.length ? picked[picked.length - 1].line : 0;
const firstLine = picked.length ? picked[0].line : 0;
for (const m of picked) delete m.line;
return {
messages: picked,
total: lined.length,
has_more: hasMore,
last_line: lastLine,
first_line: firstLine,
};
}
module.exports = router;
module.exports.sessionStats = sessionStats;
// Exported for unit tests — sender attribution is correctness-critical.