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
This commit is contained in:
2026-10-05 17:01:05 +07:00
parent 442f133930
commit 198fbb7980
78 changed files with 2716 additions and 873 deletions
+6 -4
View File
@@ -85,12 +85,14 @@ function bindable(v) {
/**
* Make a prepared INSERT OR IGNORE that only writes the columns a table
* actually has AND the row actually provides. `omit` drops columns even if
* present (used to strip the non-portable events.id).
* present (used to strip the non-portable events.id); `wrap` names a column
* whose value goes through a SQL function (events.data through
* `trim_event_data`, as every event insert must).
*/
function makeInserter(db, table, { omit = [] } = {}) {
function makeInserter(db, table, { omit = [], wrap = {} } = {}) {
const cols = tableColumns(db, table).filter((c) => !omit.includes(c));
const quoted = cols.map((c) => `"${c}"`).join(", ");
const placeholders = cols.map(() => "?").join(", ");
const placeholders = cols.map((c) => (wrap[c] ? `${wrap[c]}(?)` : "?")).join(", ");
const stmt = db.prepare(`INSERT OR IGNORE INTO ${table} (${quoted}) VALUES (${placeholders})`);
return (row) => stmt.run(cols.map((c) => bindable(row[c])));
}
@@ -175,7 +177,7 @@ function importExportBundle(db, bundle) {
const insert = {
sessions: makeInserter(db, "sessions"),
agents: makeInserter(db, "agents"),
events: makeInserter(db, "events", { omit: ["id"] }),
events: makeInserter(db, "events", { omit: ["id"], wrap: { data: "trim_event_data" } }),
token_usage: makeInserter(db, "token_usage"),
workflows: makeInserter(db, "workflows"),
dashboard_runs: makeInserter(db, "dashboard_runs"),