handmux 0.23.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -8
- package/README.zh-CN.md +31 -8
- package/bin/handmux.js +14 -688
- package/bin/node-version.js +20 -0
- package/dist/bin/handmux.js +1015 -0
- package/dist/connectors/bridgeClient.js +385 -0
- package/dist/connectors/claude/index.js +476 -0
- package/dist/connectors/pi/bridgeClient.js +8 -0
- package/dist/connectors/pi/index.js +851 -0
- package/dist/hooks/handmux-notify.sh +64 -0
- package/{hooks → dist/hooks}/handmux-statusline.cjs +28 -6
- package/dist/hooks/handmux-write.cjs +264 -0
- package/dist/package.json +127 -0
- package/dist/public/assets/index-CTrqTqtT.css +32 -0
- package/dist/public/assets/index-DmjeMSQA.js +346 -0
- package/dist/public/assets/pcm-worklet-CxcDy7PB.js +1 -0
- package/{public → dist/public}/index.html +5 -4
- package/dist/src/agent-runtime/adapter.js +204 -0
- package/dist/src/agent-runtime/bridge.js +1006 -0
- package/dist/src/agent-runtime/bridgeStore.js +25 -0
- package/dist/src/agent-runtime/bridgeTransport.js +619 -0
- package/dist/src/agent-runtime/bridgeTypes.js +13 -0
- package/dist/src/agent-runtime/builtinRuntime.js +193 -0
- package/dist/src/agent-runtime/conversation.js +2179 -0
- package/dist/src/agent-runtime/conversationActivation.js +75 -0
- package/dist/src/agent-runtime/conversationActivity.js +69 -0
- package/dist/src/agent-runtime/conversationControls.js +206 -0
- package/dist/src/agent-runtime/conversationLiveHub.js +276 -0
- package/dist/src/agent-runtime/conversationStore.js +352 -0
- package/dist/src/agent-runtime/conversationTypes.js +1 -0
- package/dist/src/agent-runtime/conversationValidation.js +339 -0
- package/dist/src/agent-runtime/inbox.js +973 -0
- package/dist/src/agent-runtime/inboxPushProjection.js +69 -0
- package/dist/src/agent-runtime/inboxStore.js +25 -0
- package/dist/src/agent-runtime/inboxTypes.js +1 -0
- package/dist/src/agent-runtime/interaction.js +829 -0
- package/dist/src/agent-runtime/interactionLiveHub.js +225 -0
- package/dist/src/agent-runtime/interactionStore.js +18 -0
- package/dist/src/agent-runtime/interactionTypes.js +1 -0
- package/dist/src/agent-runtime/legacyInboxProjection.js +70 -0
- package/dist/src/agent-runtime/migrateLegacyCodexOutbox.js +336 -0
- package/dist/src/agent-runtime/resourceTypes.js +1 -0
- package/dist/src/agent-runtime/resources.js +245 -0
- package/dist/src/agent-runtime/run.js +328 -0
- package/dist/src/agent-runtime/runtime.js +793 -0
- package/dist/src/agent-runtime/sessionControl.js +164 -0
- package/dist/src/agent-runtime/subscriptionUsage.js +190 -0
- package/dist/src/agent-runtime/subscriptionUsageLegacy.js +18 -0
- package/dist/src/agent-runtime/tmuxRuntime.js +156 -0
- package/dist/src/agents/claude.js +203 -0
- package/dist/src/agents/claudeConversation.js +362 -0
- package/dist/src/agents/claudeInteraction.js +134 -0
- package/dist/src/agents/claudeSubscriptionUsage.js +61 -0
- package/dist/src/agents/codex.js +262 -0
- package/dist/src/agents/codexConversation.js +1103 -0
- package/dist/src/agents/codexConversationActivation.js +121 -0
- package/dist/src/agents/codexConversationControls.js +256 -0
- package/dist/src/agents/codexInteraction.js +306 -0
- package/dist/src/agents/codexSessionControl.js +118 -0
- package/dist/src/agents/codexSubscriptionUsage.js +313 -0
- package/dist/src/agents/codexTerminalControl.js +23 -0
- package/dist/src/agents/conversationProjectionSafety.js +416 -0
- package/dist/src/agents/index.js +39 -0
- package/dist/src/agents/nativeInbox.js +264 -0
- package/dist/src/agents/nativeInboxSources.js +115 -0
- package/dist/src/agents/pi.js +28 -0
- package/dist/src/agents/piConversation.js +523 -0
- package/dist/src/agents/piConversationHistory.js +502 -0
- package/dist/src/agents/piInboxBridge.js +368 -0
- package/dist/src/agents/piSessionControl.js +32 -0
- package/dist/src/agents/processIdentity.js +94 -0
- package/dist/src/agents/scanUtils.js +262 -0
- package/dist/src/apiAccountProviders.js +194 -0
- package/dist/src/apiAccounts.js +592 -0
- package/dist/src/apiErrors.js +86 -0
- package/{src → dist/src}/appName.js +12 -13
- package/dist/src/asr/iflyConfig.js +7 -0
- package/dist/src/asr/iflySign.js +14 -0
- package/dist/src/auth.js +27 -0
- package/dist/src/browser/bootstrap.js +72 -0
- package/dist/src/browser/cookieProfiles.js +413 -0
- package/dist/src/browser/coordinator.js +51 -0
- package/dist/src/browser/hammerheadCompat.js +104 -0
- package/dist/src/browser/hammerheadRedirectCompat.js +37 -0
- package/dist/src/browser/manager.js +560 -0
- package/dist/src/browser/originLabel.js +15 -0
- package/dist/src/browser/profilePersistence.js +235 -0
- package/dist/src/browser/publicProxy.js +176 -0
- package/dist/src/browser/routes.js +159 -0
- package/dist/src/browser/sessionStore.js +72 -0
- package/dist/src/browser/siteVersion.js +121 -0
- package/dist/src/browser/targetPolicy.js +163 -0
- package/{src → dist/src}/browser/worker.js +14 -18
- package/dist/src/browser/workerClient.js +286 -0
- package/dist/src/browser/workerServer.js +91 -0
- package/dist/src/captureBackground.js +95 -0
- package/dist/src/claudeEvents.js +525 -0
- package/dist/src/cli/agentIntegration.js +131 -0
- package/dist/src/cli/agentLauncher.js +26 -0
- package/dist/src/cli/claudeHooks.js +290 -0
- package/{src → dist/src}/cli/cloudflareUrl.js +2 -3
- package/dist/src/cli/cloudflared.js +106 -0
- package/dist/src/cli/codexManaged.js +80 -0
- package/{src → dist/src}/cli/cpolarUrl.js +8 -9
- package/dist/src/cli/drivers.js +98 -0
- package/dist/src/cli/hookScaffold.js +39 -0
- package/dist/src/cli/i18n/en.js +392 -0
- package/{src → dist/src}/cli/i18n/index.js +27 -25
- package/dist/src/cli/i18n/zh.js +391 -0
- package/dist/src/cli/legacyCodexHooks.js +52 -0
- package/{src → dist/src}/cli/natappUrl.js +2 -3
- package/dist/src/cli/options.js +245 -0
- package/dist/src/cli/piExtension.js +155 -0
- package/dist/src/cli/probe.js +16 -0
- package/{src → dist/src}/cli/prompt.js +4 -6
- package/dist/src/cli/pushCmd.js +102 -0
- package/{src → dist/src}/cli/qr.js +19 -19
- package/dist/src/cli/service.js +154 -0
- package/dist/src/cli/setupModel.js +194 -0
- package/dist/src/cli/setupWizard.js +647 -0
- package/dist/src/cli/shortcutEditor.js +351 -0
- package/dist/src/cli/sshTunnel.js +18 -0
- package/dist/src/cli/state.js +117 -0
- package/dist/src/cli/statusLine.js +115 -0
- package/dist/src/cli/supervisor.js +278 -0
- package/dist/src/cli/supervisorHealth.js +21 -0
- package/dist/src/cli/supervisorLaunch.js +148 -0
- package/dist/src/cli/supervisorProcesses.js +62 -0
- package/dist/src/cli/supervisorState.js +62 -0
- package/dist/src/cli/tmuxVersion.js +53 -0
- package/{src → dist/src}/cli/tunlite.js +7 -10
- package/dist/src/cli/tunnelClients.js +72 -0
- package/{src → dist/src}/cli/updateCheck.js +98 -69
- package/{src → dist/src}/cli/urlHost.js +8 -4
- package/dist/src/cli/workspaceCmd.js +347 -0
- package/dist/src/codexAppServer.js +3436 -0
- package/dist/src/codexConversationProjection.js +199 -0
- package/dist/src/codexDiff.js +118 -0
- package/dist/src/codexMessageIdentity.js +18 -0
- package/dist/src/codexPlan.js +30 -0
- package/dist/src/codexQueueProtocol.js +137 -0
- package/dist/src/codexStreamProtocol.js +207 -0
- package/dist/src/codexToolProtocol.js +68 -0
- package/dist/src/codexTranscriptParse.js +835 -0
- package/dist/src/codexUsageSnapshot.js +228 -0
- package/dist/src/config.js +8 -0
- package/{src → dist/src}/docPath.js +22 -24
- package/dist/src/docs.js +337 -0
- package/dist/src/git.js +284 -0
- package/dist/src/healthProtocol.js +97 -0
- package/dist/src/httpApi.js +96 -0
- package/dist/src/jsonStore.js +15 -0
- package/{src → dist/src}/keyNames.js +3 -3
- package/dist/src/notifications.js +111 -0
- package/dist/src/orphans.js +167 -0
- package/dist/src/paneInput.js +42 -0
- package/dist/src/pendingPrompt.js +194 -0
- package/dist/src/previewServer.js +202 -0
- package/dist/src/previews.js +179 -0
- package/dist/src/privateStateStore.js +124 -0
- package/dist/src/projectTask/backup.js +224 -0
- package/dist/src/projectTask/lock.js +108 -0
- package/dist/src/projectTask/migrations.js +90 -0
- package/dist/src/projectTask/routes.js +155 -0
- package/dist/src/projectTask/runtime.js +182 -0
- package/dist/src/projectTask/schema.js +56 -0
- package/dist/src/projectTask/store.js +457 -0
- package/dist/src/push.js +224 -0
- package/dist/src/routes/agents.js +631 -0
- package/dist/src/routes/apiAccounts.js +82 -0
- package/dist/src/routes/files.js +230 -0
- package/dist/src/routes/git.js +89 -0
- package/dist/src/routes/health.js +16 -0
- package/dist/src/routes/notifications.js +16 -0
- package/dist/src/routes/previews.js +43 -0
- package/dist/src/routes/push.js +145 -0
- package/dist/src/routes/sessions.js +244 -0
- package/dist/src/routes/system.js +220 -0
- package/dist/src/routes/terminal.js +244 -0
- package/dist/src/routes/workspace.js +267 -0
- package/dist/src/server.js +315 -0
- package/dist/src/shortcutConfig.js +83 -0
- package/{src → dist/src}/staticCache.js +5 -3
- package/{src → dist/src}/staticCompression.js +5 -6
- package/dist/src/terminalStream.js +441 -0
- package/{src → dist/src}/tmux/commands.js +185 -172
- package/dist/src/tmux/format.js +47 -0
- package/dist/src/transcriptParse.js +261 -0
- package/dist/src/transcriptReader.js +209 -0
- package/{src → dist/src}/trimCapture.js +11 -11
- package/dist/src/uploadTypes.js +31 -0
- package/dist/src/urlPolicy.js +18 -0
- package/dist/src/usagePaths.js +15 -0
- package/dist/src/workspace/agentRunner.js +301 -0
- package/dist/src/workspace/atomicJson.js +31 -0
- package/dist/src/workspace/capture.js +139 -0
- package/dist/src/workspace/checkpointer.js +228 -0
- package/dist/src/workspace/environment.js +71 -0
- package/dist/src/workspace/lock.js +137 -0
- package/dist/src/workspace/mapping.js +128 -0
- package/dist/src/workspace/operations.js +271 -0
- package/dist/src/workspace/paths.js +15 -0
- package/dist/src/workspace/planner.js +292 -0
- package/dist/src/workspace/restore.js +363 -0
- package/dist/src/workspace/runtime.js +318 -0
- package/dist/src/workspace/schema.js +156 -0
- package/dist/src/workspace/store.js +464 -0
- package/dist/src/workspace/tmuxAdapter.js +704 -0
- package/dist/src/workspaceProtocol.js +158 -0
- package/package.json +30 -17
- package/hooks/handmux-notify.sh +0 -22
- package/hooks/handmux-write.cjs +0 -78
- package/public/assets/index-C3N7OkyP.css +0 -32
- package/public/assets/index-D1DWcC5u.js +0 -337
- package/src/.gitkeep +0 -0
- package/src/agents/claude.js +0 -159
- package/src/agents/codex.js +0 -168
- package/src/agents/index.js +0 -21
- package/src/agents/processIdentity.js +0 -72
- package/src/agents/scanUtils.js +0 -225
- package/src/asr/iflyConfig.js +0 -10
- package/src/asr/iflySign.js +0 -16
- package/src/auth.js +0 -30
- package/src/browser/bootstrap.js +0 -68
- package/src/browser/cookieProfiles.js +0 -403
- package/src/browser/coordinator.js +0 -47
- package/src/browser/hammerheadCompat.js +0 -86
- package/src/browser/hammerheadRedirectCompat.js +0 -38
- package/src/browser/manager.js +0 -556
- package/src/browser/originLabel.js +0 -17
- package/src/browser/profilePersistence.js +0 -241
- package/src/browser/publicProxy.js +0 -175
- package/src/browser/routes.js +0 -154
- package/src/browser/sessionStore.js +0 -78
- package/src/browser/siteVersion.js +0 -124
- package/src/browser/targetPolicy.js +0 -137
- package/src/browser/workerClient.js +0 -253
- package/src/browser/workerServer.js +0 -98
- package/src/captureBackground.js +0 -93
- package/src/claudeEvents.js +0 -399
- package/src/cli/claudeHooks.js +0 -206
- package/src/cli/cloudflared.js +0 -99
- package/src/cli/codexManaged.js +0 -77
- package/src/cli/drivers.js +0 -97
- package/src/cli/hookScaffold.js +0 -33
- package/src/cli/i18n/en.js +0 -385
- package/src/cli/i18n/zh.js +0 -384
- package/src/cli/legacyCodexHooks.js +0 -49
- package/src/cli/options.js +0 -211
- package/src/cli/probe.js +0 -16
- package/src/cli/pushCmd.js +0 -60
- package/src/cli/service.js +0 -126
- package/src/cli/setupModel.js +0 -154
- package/src/cli/setupWizard.js +0 -506
- package/src/cli/shortcutEditor.js +0 -288
- package/src/cli/sshTunnel.js +0 -12
- package/src/cli/state.js +0 -90
- package/src/cli/statusLine.js +0 -90
- package/src/cli/supervisor.js +0 -183
- package/src/cli/supervisorProcesses.js +0 -57
- package/src/cli/tmuxVersion.js +0 -49
- package/src/cli/tunnelClients.js +0 -62
- package/src/cli/workspaceCmd.js +0 -300
- package/src/codexAppServer.js +0 -1620
- package/src/codexDiff.js +0 -108
- package/src/codexTranscriptParse.js +0 -413
- package/src/codexUsageSnapshot.cjs +0 -129
- package/src/config.js +0 -9
- package/src/docs.js +0 -228
- package/src/git.js +0 -208
- package/src/httpApi.js +0 -72
- package/src/jsonStore.js +0 -24
- package/src/notifications.js +0 -68
- package/src/orphans.js +0 -152
- package/src/pendingPrompt.js +0 -163
- package/src/previewServer.js +0 -168
- package/src/previews.js +0 -116
- package/src/push.js +0 -183
- package/src/routes/codex.js +0 -473
- package/src/routes/files.js +0 -172
- package/src/routes/git.js +0 -57
- package/src/routes/notifications.js +0 -19
- package/src/routes/previews.js +0 -35
- package/src/routes/push.js +0 -119
- package/src/routes/sessions.js +0 -168
- package/src/routes/system.js +0 -132
- package/src/routes/terminal.js +0 -210
- package/src/routes/transcript.js +0 -171
- package/src/routes/workspace.js +0 -267
- package/src/server.js +0 -186
- package/src/shortcutConfig.js +0 -75
- package/src/terminalStream.js +0 -391
- package/src/tmux/format.js +0 -45
- package/src/transcriptParse.js +0 -180
- package/src/transcriptReader.js +0 -101
- package/src/uploadTypes.js +0 -30
- package/src/urlPolicy.js +0 -14
- package/src/usage.js +0 -260
- package/src/workspace/agentRunner.js +0 -188
- package/src/workspace/atomicJson.js +0 -32
- package/src/workspace/capture.js +0 -139
- package/src/workspace/checkpointer.js +0 -187
- package/src/workspace/environment.js +0 -75
- package/src/workspace/lock.js +0 -128
- package/src/workspace/mapping.js +0 -124
- package/src/workspace/operations.js +0 -252
- package/src/workspace/paths.js +0 -16
- package/src/workspace/planner.js +0 -247
- package/src/workspace/restore.js +0 -279
- package/src/workspace/runtime.js +0 -314
- package/src/workspace/schema.js +0 -136
- package/src/workspace/store.js +0 -382
- package/src/workspace/tmuxAdapter.js +0 -554
- /package/{public → dist/public}/fonts/JetBrainsMonoNerdFontMono-Regular.woff2 +0 -0
- /package/{public → dist/public}/fonts/TWUnifont.woff2 +0 -0
- /package/{public → dist/public}/icons/apple-touch-icon.png +0 -0
- /package/{public → dist/public}/icons/badge-96.png +0 -0
- /package/{public → dist/public}/icons/icon-192-maskable.png +0 -0
- /package/{public → dist/public}/icons/icon-192.png +0 -0
- /package/{public → dist/public}/icons/icon-512-maskable.png +0 -0
- /package/{public → dist/public}/icons/icon-512.png +0 -0
- /package/{public → dist/public}/icons/logo.svg +0 -0
- /package/{public → dist/public}/manifest.webmanifest +0 -0
- /package/{public → dist/public}/offline.html +0 -0
- /package/{public → dist/public}/sw.js +0 -0
- /package/{src → dist/src}/browser/protocol.js +0 -0
- /package/{src → dist/src}/cli/cfNamed.js +0 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import http from 'node:http';
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import { tokenEquals } from '../auth.js';
|
|
4
|
+
import { createBrowserPreviewManager } from './manager.js';
|
|
5
|
+
import { createBrowserBootstrapStore } from './bootstrap.js';
|
|
6
|
+
import { createBrowserPublicProxy } from './publicProxy.js';
|
|
7
|
+
import { browserRoutes } from './routes.js';
|
|
8
|
+
import { BROWSER_INTERNAL_HEADER } from './protocol.js';
|
|
9
|
+
const defaultManagerFactory = createBrowserPreviewManager;
|
|
10
|
+
const defaultBrowserPublicFactory = createBrowserPublicProxy;
|
|
11
|
+
const workerBrowserRoutes = browserRoutes;
|
|
12
|
+
function isLoopback(address) {
|
|
13
|
+
return address === '127.0.0.1' || address === '::1' || String(address || '').startsWith('::ffff:127.');
|
|
14
|
+
}
|
|
15
|
+
function authenticated(req, token) {
|
|
16
|
+
const provided = req.headers[BROWSER_INTERNAL_HEADER];
|
|
17
|
+
return isLoopback(req.socket?.remoteAddress)
|
|
18
|
+
&& typeof provided === 'string'
|
|
19
|
+
&& tokenEquals(provided, token);
|
|
20
|
+
}
|
|
21
|
+
export async function createBrowserWorkerServer({ internalToken, previewDomain = null, handmuxOrigin = 'http://127.0.0.1', browser: suppliedBrowser = null, managerFactory = defaultManagerFactory, browserPublicFactory = defaultBrowserPublicFactory, host = '127.0.0.1', port = 0, }) {
|
|
22
|
+
if (!internalToken)
|
|
23
|
+
throw new Error('browser worker internal token required');
|
|
24
|
+
const browserBootstrap = createBrowserBootstrapStore();
|
|
25
|
+
const browser = suppliedBrowser || await managerFactory({
|
|
26
|
+
handmuxOrigin,
|
|
27
|
+
previewDomain,
|
|
28
|
+
browserBootstrap,
|
|
29
|
+
});
|
|
30
|
+
const browserPublic = browserPublicFactory({ browser, browserBootstrap });
|
|
31
|
+
const app = express();
|
|
32
|
+
app.use((req, res, next) => {
|
|
33
|
+
if (!authenticated(req, internalToken))
|
|
34
|
+
return res.status(401).json({ error: 'browser worker unauthorized' });
|
|
35
|
+
delete req.headers[BROWSER_INTERNAL_HEADER];
|
|
36
|
+
return next();
|
|
37
|
+
});
|
|
38
|
+
app.get('/_browser-worker/health', (_req, res) => res.json({ ok: true }));
|
|
39
|
+
app.use('/api/browser-proxy', express.json(), workerBrowserRoutes({ browser, previewDomain, browserBootstrap }));
|
|
40
|
+
app.use(browserPublic.handler);
|
|
41
|
+
const server = http.createServer(app);
|
|
42
|
+
const sockets = new Set();
|
|
43
|
+
server.on('connection', (socket) => {
|
|
44
|
+
sockets.add(socket);
|
|
45
|
+
socket.once('close', () => sockets.delete(socket));
|
|
46
|
+
});
|
|
47
|
+
server.on('upgrade', (req, socket, head) => {
|
|
48
|
+
if (!authenticated(req, internalToken)) {
|
|
49
|
+
socket.end('HTTP/1.1 401 Unauthorized\r\nConnection: close\r\n\r\n');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
delete req.headers[BROWSER_INTERNAL_HEADER];
|
|
53
|
+
if (!browserPublic.onUpgrade(req, socket, head))
|
|
54
|
+
socket.destroy();
|
|
55
|
+
});
|
|
56
|
+
await new Promise((resolve, reject) => {
|
|
57
|
+
const onError = (error) => { server.off('listening', onListening); reject(error); };
|
|
58
|
+
const onListening = () => { server.off('error', onError); resolve(); };
|
|
59
|
+
server.once('error', onError);
|
|
60
|
+
server.once('listening', onListening);
|
|
61
|
+
server.listen(port, host);
|
|
62
|
+
});
|
|
63
|
+
const address = server.address();
|
|
64
|
+
if (!address || typeof address === 'string')
|
|
65
|
+
throw new Error('browser worker did not bind a TCP port');
|
|
66
|
+
let closePromise = null;
|
|
67
|
+
return {
|
|
68
|
+
host,
|
|
69
|
+
port: address.port,
|
|
70
|
+
server,
|
|
71
|
+
browser,
|
|
72
|
+
close() {
|
|
73
|
+
if (!closePromise) {
|
|
74
|
+
closePromise = (async () => {
|
|
75
|
+
const stopped = new Promise((resolve) => server.close(resolve));
|
|
76
|
+
server.closeIdleConnections?.();
|
|
77
|
+
for (const socket of sockets)
|
|
78
|
+
socket.destroy();
|
|
79
|
+
try {
|
|
80
|
+
await browser.close?.();
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
server.closeAllConnections?.();
|
|
84
|
+
await stopped;
|
|
85
|
+
}
|
|
86
|
+
})();
|
|
87
|
+
}
|
|
88
|
+
return closePromise;
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const CSI = /\x1b\[([0-9;]*)m/g;
|
|
2
|
+
const ANSI = /\x1b(?:\[[0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1b\\))/g;
|
|
3
|
+
function backgroundAfter(line, initial) {
|
|
4
|
+
let background = initial;
|
|
5
|
+
const sgr = new RegExp(CSI.source, 'g');
|
|
6
|
+
let match = sgr.exec(line);
|
|
7
|
+
while (match) {
|
|
8
|
+
const rawParams = match[1] ?? '';
|
|
9
|
+
const params = rawParams === '' ? [0] : rawParams.split(';').map(Number);
|
|
10
|
+
for (let i = 0; i < params.length; i += 1) {
|
|
11
|
+
const value = params[i] ?? 0;
|
|
12
|
+
if (value === 0 || value === 49)
|
|
13
|
+
background = false;
|
|
14
|
+
else if ((value >= 40 && value <= 47) || (value >= 100 && value <= 107))
|
|
15
|
+
background = true;
|
|
16
|
+
else if (value === 38 || value === 48) {
|
|
17
|
+
const isBackground = value === 48;
|
|
18
|
+
if (params[i + 1] === 5) {
|
|
19
|
+
i += 2;
|
|
20
|
+
if (isBackground)
|
|
21
|
+
background = true;
|
|
22
|
+
}
|
|
23
|
+
else if (params[i + 1] === 2) {
|
|
24
|
+
i += 4;
|
|
25
|
+
if (isBackground)
|
|
26
|
+
background = true;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
match = sgr.exec(line);
|
|
31
|
+
}
|
|
32
|
+
return background;
|
|
33
|
+
}
|
|
34
|
+
function paintsBackground(line) {
|
|
35
|
+
let background = false;
|
|
36
|
+
let offset = 0;
|
|
37
|
+
const sgr = new RegExp(CSI.source, 'g');
|
|
38
|
+
let match = sgr.exec(line);
|
|
39
|
+
while (match) {
|
|
40
|
+
if (background && match.index > offset)
|
|
41
|
+
return true;
|
|
42
|
+
background = backgroundAfter(match[0], background);
|
|
43
|
+
offset = sgr.lastIndex;
|
|
44
|
+
match = sgr.exec(line);
|
|
45
|
+
}
|
|
46
|
+
return background && offset < line.length;
|
|
47
|
+
}
|
|
48
|
+
const isBlank = (line) => line.replace(ANSI, '').trim() === '';
|
|
49
|
+
// `capture-pane -e -N` compresses SGR state across newlines. A default blank row after a shaded
|
|
50
|
+
// row (Claude) and a genuinely shaded padding row (Codex) therefore look identical in the combined
|
|
51
|
+
// capture. Capturing just that row makes tmux emit the row's real starting attributes. Only those
|
|
52
|
+
// ambiguous rows need the extra read; ordinary rows keep the single fast combined capture.
|
|
53
|
+
export function ambiguousBackgroundRows(lines) {
|
|
54
|
+
const indexes = [];
|
|
55
|
+
let background = false;
|
|
56
|
+
let inBlankRun = false;
|
|
57
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
58
|
+
const line = lines[index] ?? '';
|
|
59
|
+
const ambiguous = background && isBlank(line);
|
|
60
|
+
// One row resolves the whole trailing run: default closes it before the first LF; shaded is the
|
|
61
|
+
// one real padding row the client preserves and seals before clearing any additional blanks.
|
|
62
|
+
if (ambiguous && !inBlankRun)
|
|
63
|
+
indexes.push(index);
|
|
64
|
+
inBlankRun = ambiguous;
|
|
65
|
+
background = backgroundAfter(line, background);
|
|
66
|
+
}
|
|
67
|
+
return indexes;
|
|
68
|
+
}
|
|
69
|
+
export async function restoreBlankRowBackgrounds(lines, historyLines, readRow) {
|
|
70
|
+
const restored = [...lines];
|
|
71
|
+
const indexes = ambiguousBackgroundRows(lines);
|
|
72
|
+
await Promise.all(indexes.map(async (index) => {
|
|
73
|
+
const row = index - historyLines;
|
|
74
|
+
const exact = await readRow(row);
|
|
75
|
+
// A separately-captured default row has no background SGR. Explicitly close the combined
|
|
76
|
+
// stream's inherited background before replaying it. A real padding row starts with its own
|
|
77
|
+
// background SGR and is preserved verbatim.
|
|
78
|
+
restored[index] = paintsBackground(exact) ? exact : `\x1b[49m${exact}`;
|
|
79
|
+
}));
|
|
80
|
+
return restored;
|
|
81
|
+
}
|
|
82
|
+
export async function restoreCaptureBackgrounds(capture, paneHeight, readRow) {
|
|
83
|
+
const trailingNewline = capture.endsWith('\n');
|
|
84
|
+
const body = trailingNewline ? capture.slice(0, -1) : capture;
|
|
85
|
+
const lines = body.split('\n');
|
|
86
|
+
const historyLines = Math.max(0, lines.length - paneHeight);
|
|
87
|
+
const restored = await restoreBlankRowBackgrounds(lines, historyLines, async (row) => {
|
|
88
|
+
const exact = await readRow(row);
|
|
89
|
+
return exact.endsWith('\n') ? exact.slice(0, -1) : exact;
|
|
90
|
+
});
|
|
91
|
+
return {
|
|
92
|
+
ansi: restored.join('\n') + (trailingNewline ? '\n' : ''),
|
|
93
|
+
historyLines,
|
|
94
|
+
};
|
|
95
|
+
}
|