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
+42 -18
View File
@@ -1140,7 +1140,7 @@ const paths = {
tags: ["Settings"],
summary: "Restore (import) a previously exported data bundle",
description:
'Restores a bundle produced by GET /api/settings/export. Supply it either as `multipart/form-data` with a single `file` field (browser upload) or as a JSON body `{ "path": "<absolute path>" }` (the server reads the file from disk — used by the `agenthub import-data` CLI, and it also sidesteps the global 1 MB JSON body cap for large bundles). The restore is idempotent and NON-DESTRUCTIVE: it is session-atomic, so a session already present (matched by its UUID) is skipped whole together with its agents/events/token_usage/workflows, and independent config rows (dashboard_runs, alert_rules, model_pricing) are inserted only when absent. Nothing existing is overwritten — ideal for consolidating several machines into one dashboard. The response reports per-table counts.',
"Restores a bundle produced by GET /api/settings/export, uploaded as `multipart/form-data` with a single `file` field (the dashboard's Restore button and the `agenthub import-data` CLI both upload it; the server never reads a path named by a request). Same-origin only. At most 512 MB (`413 FILE_TOO_LARGE`); a file that is not JSON or not an export answers `400 INVALID_FORMAT` without echoing its text, no file `400 NO_FILE`. The restore is idempotent and NON-DESTRUCTIVE: it is session-atomic, so a session already present (matched by its UUID) is skipped whole together with its agents/events/token_usage/workflows, and independent config rows (dashboard_runs, alert_rules, model_pricing) are inserted only when absent. Restored event payloads are trimmed like every event insert (`trim_event_data`). Nothing existing is overwritten — ideal for consolidating several machines into one dashboard. The response reports per-table counts.",
operationId: "importData",
requestBody: {
required: true,
@@ -1153,20 +1153,6 @@ const paths = {
},
},
},
"application/json": {
schema: {
type: "object",
required: ["path"],
properties: {
path: {
type: "string",
description:
"Absolute path (server-side) to an export .json file. `~` is expanded.",
},
},
},
example: { path: "/Users/you/agenthub-export-2026-06-26.json" },
},
},
},
responses: {
@@ -1194,8 +1180,11 @@ const paths = {
},
},
400: {
description: "Missing file, invalid JSON, or unrecognized export format",
description:
"Missing file (NO_FILE), invalid JSON or unrecognized export format (INVALID_FORMAT)",
},
403: { description: "Cross-origin request (EBADORIGIN)" },
413: { description: "The file is larger than 512 MB (FILE_TOO_LARGE)" },
},
},
},
@@ -1620,9 +1609,19 @@ const paths = {
tags: ["Workflows"],
summary: "Get workflow intelligence aggregates",
description:
"Returns the full workflow-intelligence aggregate powering the Workflows analytics page — 11 sections in one payload: `stats` (headline counters: sessions, agents, subagents, success rate, avg depth/duration, compactions, top tool flow), `orchestration` (subagent-type breakdown + delegation edges + outcomes), `toolFlow` (tool-to-tool transitions + tool counts), `effectiveness` (per-subagent-type success rate, avg duration, weekly trend), `patterns` (frequent subagent sequences + solo-session share), `modelDelegation` (model usage for main/sub agents + tokens by model), `errorPropagation` (errors by depth/type + error rate), `concurrency` (averaged agent swim-lane start/end), `complexity` (per-session agent/token/duration rows), `compaction` (compaction counts + tokens recovered), and `cooccurrence` (directed subagent-after-subagent pairs). The optional `status` query filter scopes every section to sessions of one status. Errors use the SHORT `{ error: { message } }` shape.",
"Returns the full workflow-intelligence aggregate powering the Workflows analytics page — 11 sections in one payload: `stats` (headline counters: sessions, agents, subagents, success rate, avg depth/duration, compactions, top tool flow), `orchestration` (subagent-type breakdown + delegation edges + outcomes), `toolFlow` (tool-to-tool transitions + tool counts), `effectiveness` (per-subagent-type success rate, avg duration, weekly trend), `patterns` (frequent subagent sequences + solo-session share), `modelDelegation` (model usage for main/sub agents + tokens by model), `errorPropagation` (errors by depth/type + error rate), `concurrency` (averaged agent swim-lane start/end), `complexity` (per-session agent/token/duration rows), `compaction` (compaction counts + tokens recovered), and `cooccurrence` (directed subagent-after-subagent pairs). The optional `status` query filter scopes every section to sessions of one status, and `sections` computes and returns only the named ones (`stats.topFlow` is the head of `toolFlow.transitions`, one pass for both). The bundle is computed in a worker thread on its own read-only connection, so it never stalls other requests; identical requests in flight share one run, and one over `AGENTHUB_READ_TIMEOUT_MS` (default 60 s) answers 503 `EREADTIMEOUT`. Errors use the SHORT `{ error: { message } }` shape.",
operationId: "getWorkflowIntelligence",
parameters: [{ $ref: "#/components/parameters/WorkflowStatusQuery" }],
parameters: [
{ $ref: "#/components/parameters/WorkflowStatusQuery" },
{
name: "sections",
in: "query",
required: false,
description:
"Comma-separated subset of the bundle to compute: stats, orchestration, toolFlow, effectiveness, patterns, modelDelegation, errorPropagation, concurrency, complexity, compaction, cooccurrence. Unknown names are ignored; none known is a 400.",
schema: { type: "string", example: "stats,toolFlow" },
},
],
responses: {
200: {
description: "Workflow aggregate data",
@@ -1633,6 +1632,20 @@ const paths = {
},
},
},
400: {
description: "`sections` names no known section",
content: {
"application/json": {
schema: { $ref: "#/components/schemas/ErrorResponse" },
example: {
error: {
code: "INVALID_SECTIONS",
message: "sections must name some of: stats, …",
},
},
},
},
},
500: {
description: "Internal server error",
content: {
@@ -1642,6 +1655,17 @@ const paths = {
},
},
},
503: {
description: "The aggregate ran past `AGENTHUB_READ_TIMEOUT_MS`",
content: {
"application/json": {
schema: { $ref: "#/components/schemas/ErrorResponse" },
example: {
error: { code: "EREADTIMEOUT", message: "read query took over 60000 ms" },
},
},
},
},
},
},
},