chore: add node-pty/xterm deps, tmux in Docker, dashboard_runs.tmux_session column

This commit is contained in:
2026-08-12 09:29:44 +07:00
parent 00f6338d4c
commit d96d552428
6 changed files with 51 additions and 1 deletions
+4
View File
@@ -35,6 +35,10 @@ RUN npm run build
FROM node:22-alpine FROM node:22-alpine
WORKDIR /app WORKDIR /app
# Runs Claude Code sessions inside a named tmux session per lane so both the
# dashboard (via node-pty attach) and a real terminal can share one live pane.
RUN apk add --no-cache tmux
COPY --from=server-deps /app/node_modules ./node_modules/ COPY --from=server-deps /app/node_modules ./node_modules/
COPY package.json ./ COPY package.json ./
COPY server/ ./server/ COPY server/ ./server/
+17
View File
@@ -10,6 +10,8 @@
"dependencies": { "dependencies": {
"@fontsource/inter": "^5.2.8", "@fontsource/inter": "^5.2.8",
"@fontsource/jetbrains-mono": "^5.2.8", "@fontsource/jetbrains-mono": "^5.2.8",
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0",
"d3": "^7.9.0", "d3": "^7.9.0",
"d3-sankey": "^0.12.3", "d3-sankey": "^0.12.3",
"i18next": "^26.0.8", "i18next": "^26.0.8",
@@ -2100,6 +2102,21 @@
"url": "https://opencollective.com/vitest" "url": "https://opencollective.com/vitest"
} }
}, },
"node_modules/@xterm/addon-fit": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.10.0.tgz",
"integrity": "sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==",
"license": "MIT",
"peerDependencies": {
"@xterm/xterm": "^5.0.0"
}
},
"node_modules/@xterm/xterm": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==",
"license": "MIT"
},
"node_modules/agent-base": { "node_modules/agent-base": {
"version": "7.1.4", "version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+2
View File
@@ -13,6 +13,8 @@
"dependencies": { "dependencies": {
"@fontsource/inter": "^5.2.8", "@fontsource/inter": "^5.2.8",
"@fontsource/jetbrains-mono": "^5.2.8", "@fontsource/jetbrains-mono": "^5.2.8",
"@xterm/addon-fit": "^0.10.0",
"@xterm/xterm": "^5.5.0",
"d3": "^7.9.0", "d3": "^7.9.0",
"d3-sankey": "^0.12.3", "d3-sankey": "^0.12.3",
"i18next": "^26.0.8", "i18next": "^26.0.8",
+17
View File
@@ -15,6 +15,7 @@
"cross-spawn": "^7.0.6", "cross-spawn": "^7.0.6",
"express": "^4.21.2", "express": "^4.21.2",
"multer": "^2.0.0", "multer": "^2.0.0",
"node-pty": "^1.1.0",
"redoc": "^2.5.3", "redoc": "^2.5.3",
"swagger-ui-express": "^5.0.1", "swagger-ui-express": "^5.0.1",
"tar": "^7.4.3", "tar": "^7.4.3",
@@ -1669,6 +1670,12 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/node-addon-api": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
"license": "MIT"
},
"node_modules/node-fetch": { "node_modules/node-fetch": {
"version": "2.7.0", "version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
@@ -1701,6 +1708,16 @@
"node": "4.x || >=6.0.0" "node": "4.x || >=6.0.0"
} }
}, },
"node_modules/node-pty": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/node-pty/-/node-pty-1.1.0.tgz",
"integrity": "sha512-20JqtutY6JPXTUnL0ij1uad7Qe1baT46lyolh2sSENDd4sTzKZ4nmAFkeAARDKwmlLjPx6XKRlwRUxwjOy+lUg==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"node-addon-api": "^7.1.0"
}
},
"node_modules/node-readfiles": { "node_modules/node-readfiles": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz", "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz",
+1
View File
@@ -94,6 +94,7 @@
"cross-spawn": "^7.0.6", "cross-spawn": "^7.0.6",
"express": "^4.21.2", "express": "^4.21.2",
"multer": "^2.0.0", "multer": "^2.0.0",
"node-pty": "^1.1.0",
"redoc": "^2.5.3", "redoc": "^2.5.3",
"swagger-ui-express": "^5.0.1", "swagger-ui-express": "^5.0.1",
"tar": "^7.4.3", "tar": "^7.4.3",
+10 -1
View File
@@ -248,7 +248,7 @@ db.exec(`
CREATE TABLE IF NOT EXISTS dashboard_runs ( CREATE TABLE IF NOT EXISTS dashboard_runs (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
session_id TEXT, session_id TEXT,
mode TEXT NOT NULL, mode TEXT,
cwd TEXT NOT NULL, cwd TEXT NOT NULL,
model TEXT, model TEXT,
permission_mode TEXT, permission_mode TEXT,
@@ -496,6 +496,15 @@ try {
} }
db.prepare("CREATE INDEX IF NOT EXISTS idx_dashboard_runs_lane ON dashboard_runs(lane_id)").run(); db.prepare("CREATE INDEX IF NOT EXISTS idx_dashboard_runs_lane ON dashboard_runs(lane_id)").run();
// Migrate: tmux session name backing this run (tmux+PTY terminal design,
// 2026-08-11). Additive and nullable — historical rows spawned via the old
// stream-json mode have no tmux session and are display-only history now.
try {
db.prepare("SELECT tmux_session FROM dashboard_runs LIMIT 1").get();
} catch {
db.prepare("ALTER TABLE dashboard_runs ADD COLUMN tmux_session TEXT").run();
}
// Migrate: add stage-detection columns to lanes. Inference is never evidence — // Migrate: add stage-detection columns to lanes. Inference is never evidence —
// these are additive columns separate from `stage` (the declared stage), so // these are additive columns separate from `stage` (the declared stage), so
// `stage`'s meaning is untouched and turning the feature off loses nothing. // `stage`'s meaning is untouched and turning the feature off loses nothing.