aicodeman 1.40.0 → 1.41.1
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 +81 -13
- package/dist/attachment-registry.d.ts +2 -0
- package/dist/attachment-registry.d.ts.map +1 -1
- package/dist/attachment-registry.js +14 -3
- package/dist/attachment-registry.js.map +1 -1
- package/dist/cli-agent.d.ts +227 -0
- package/dist/cli-agent.d.ts.map +1 -0
- package/dist/cli-agent.js +771 -0
- package/dist/cli-agent.js.map +1 -0
- package/dist/cli.d.ts +25 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +103 -41
- package/dist/cli.js.map +1 -1
- package/dist/codeman-credentials.d.ts +27 -0
- package/dist/codeman-credentials.d.ts.map +1 -0
- package/dist/codeman-credentials.js +66 -0
- package/dist/codeman-credentials.js.map +1 -0
- package/dist/config/buffer-limits.d.ts +9 -0
- package/dist/config/buffer-limits.d.ts.map +1 -1
- package/dist/config/buffer-limits.js +9 -0
- package/dist/config/buffer-limits.js.map +1 -1
- package/dist/config/cli-registry/schema.d.ts +10 -0
- package/dist/config/cli-registry/schema.d.ts.map +1 -1
- package/dist/config/cli-registry/schema.js +15 -0
- package/dist/config/cli-registry/schema.js.map +1 -1
- package/dist/config/cli-registry/stock.d.ts.map +1 -1
- package/dist/config/cli-registry/stock.js +47 -0
- package/dist/config/cli-registry/stock.js.map +1 -1
- package/dist/config/cli-registry/types.d.ts +47 -1
- package/dist/config/cli-registry/types.d.ts.map +1 -1
- package/dist/folder-listing.d.ts +94 -0
- package/dist/folder-listing.d.ts.map +1 -0
- package/dist/folder-listing.js +241 -0
- package/dist/folder-listing.js.map +1 -0
- package/dist/git-clone.d.ts.map +1 -1
- package/dist/git-clone.js +4 -0
- package/dist/git-clone.js.map +1 -1
- package/dist/hooks-config.d.ts +36 -16
- package/dist/hooks-config.d.ts.map +1 -1
- package/dist/hooks-config.js +45 -20
- package/dist/hooks-config.js.map +1 -1
- package/dist/html-view-capabilities.d.ts +54 -0
- package/dist/html-view-capabilities.d.ts.map +1 -0
- package/dist/html-view-capabilities.js +103 -0
- package/dist/html-view-capabilities.js.map +1 -0
- package/dist/image-watcher.d.ts.map +1 -1
- package/dist/image-watcher.js +6 -2
- package/dist/image-watcher.js.map +1 -1
- package/dist/mcp-server.d.ts +114 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +917 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/mcp-sync-targets.d.ts +34 -0
- package/dist/mcp-sync-targets.d.ts.map +1 -0
- package/dist/mcp-sync-targets.js +55 -0
- package/dist/mcp-sync-targets.js.map +1 -0
- package/dist/mcp-sync.d.ts +7 -1
- package/dist/mcp-sync.d.ts.map +1 -1
- package/dist/mcp-sync.js +113 -6
- package/dist/mcp-sync.js.map +1 -1
- package/dist/mux-interface.d.ts +36 -1
- package/dist/mux-interface.d.ts.map +1 -1
- package/dist/remote-files.d.ts +37 -0
- package/dist/remote-files.d.ts.map +1 -1
- package/dist/remote-files.js +103 -0
- package/dist/remote-files.js.map +1 -1
- package/dist/remote-pane-history.d.ts +103 -0
- package/dist/remote-pane-history.d.ts.map +1 -0
- package/dist/remote-pane-history.js +258 -0
- package/dist/remote-pane-history.js.map +1 -0
- package/dist/remote-ssh-limiter.d.ts +16 -3
- package/dist/remote-ssh-limiter.d.ts.map +1 -1
- package/dist/remote-ssh-limiter.js +37 -6
- package/dist/remote-ssh-limiter.js.map +1 -1
- package/dist/session.d.ts +29 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +63 -4
- package/dist/session.js.map +1 -1
- package/dist/subagent-watcher.d.ts.map +1 -1
- package/dist/subagent-watcher.js +29 -6
- package/dist/subagent-watcher.js.map +1 -1
- package/dist/tab-layout-legacy-order.d.ts.map +1 -1
- package/dist/tab-layout-legacy-order.js +72 -13
- package/dist/tab-layout-legacy-order.js.map +1 -1
- package/dist/tab-layout-service.d.ts +33 -2
- package/dist/tab-layout-service.d.ts.map +1 -1
- package/dist/tab-layout-service.js +102 -7
- package/dist/tab-layout-service.js.map +1 -1
- package/dist/tab-layout.d.ts +9 -0
- package/dist/tab-layout.d.ts.map +1 -1
- package/dist/tab-layout.js +15 -2
- package/dist/tab-layout.js.map +1 -1
- package/dist/templates/case-template.md +2 -0
- package/dist/tmux-manager.d.ts +76 -2
- package/dist/tmux-manager.d.ts.map +1 -1
- package/dist/tmux-manager.js +216 -40
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tui/tui-client.d.ts +3 -17
- package/dist/tui/tui-client.d.ts.map +1 -1
- package/dist/tui/tui-client.js +3 -44
- package/dist/tui/tui-client.js.map +1 -1
- package/dist/types/session.d.ts +53 -0
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js.map +1 -1
- package/dist/usage-telemetry.d.ts +44 -7
- package/dist/usage-telemetry.d.ts.map +1 -1
- package/dist/usage-telemetry.js +72 -7
- package/dist/usage-telemetry.js.map +1 -1
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +1 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/process-exit-wait.d.ts +40 -0
- package/dist/utils/process-exit-wait.d.ts.map +1 -0
- package/dist/utils/process-exit-wait.js +68 -0
- package/dist/utils/process-exit-wait.js.map +1 -0
- package/dist/web/approval-inbox.d.ts +12 -0
- package/dist/web/approval-inbox.d.ts.map +1 -1
- package/dist/web/approval-inbox.js +1 -0
- package/dist/web/approval-inbox.js.map +1 -1
- package/dist/web/middleware/auth.d.ts.map +1 -1
- package/dist/web/middleware/auth.js +33 -0
- package/dist/web/middleware/auth.js.map +1 -1
- package/dist/web/paste-image-gc.d.ts +46 -6
- package/dist/web/paste-image-gc.d.ts.map +1 -1
- package/dist/web/paste-image-gc.js +106 -32
- package/dist/web/paste-image-gc.js.map +1 -1
- package/dist/web/ports/session-port.d.ts +8 -1
- package/dist/web/ports/session-port.d.ts.map +1 -1
- package/dist/web/public/admin-ui.js.gz +0 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/app.24689381.js +43 -0
- package/dist/web/public/app.24689381.js.br +0 -0
- package/dist/web/public/app.24689381.js.gz +0 -0
- package/dist/web/public/approvals-ui.js +4 -0
- package/dist/web/public/approvals-ui.js.br +0 -0
- package/dist/web/public/approvals-ui.js.gz +0 -0
- package/dist/web/public/{constants.c0f8f9de.js → constants.17d77b65.js} +690 -35
- package/dist/web/public/constants.17d77b65.js.br +0 -0
- package/dist/web/public/constants.17d77b65.js.gz +0 -0
- package/dist/web/public/cron-ui.js.gz +0 -0
- package/dist/web/public/entrance-animations.js +490 -43
- package/dist/web/public/entrance-animations.js.br +0 -0
- package/dist/web/public/entrance-animations.js.gz +0 -0
- package/dist/web/public/gesture/gesture-codeman.js +112 -6
- package/dist/web/public/git-status-ui.js.gz +0 -0
- package/dist/web/public/home-sessions.js +2 -1
- package/dist/web/public/home-sessions.js.br +0 -0
- package/dist/web/public/home-sessions.js.gz +0 -0
- package/dist/web/public/host-wake-ui.js.gz +0 -0
- package/dist/web/public/i18n.9afd8e4d.js +2 -0
- package/dist/web/public/i18n.9afd8e4d.js.br +0 -0
- package/dist/web/public/i18n.9afd8e4d.js.gz +0 -0
- package/dist/web/public/image-input.9ed1d0d2.js +453 -0
- package/dist/web/public/image-input.9ed1d0d2.js.br +0 -0
- package/dist/web/public/image-input.9ed1d0d2.js.gz +0 -0
- package/dist/web/public/index.html +223 -46
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
- package/dist/web/public/{keyboard-accessory.c1e7c7b7.js → keyboard-accessory.c458eea8.js} +115 -35
- package/dist/web/public/keyboard-accessory.c458eea8.js.br +0 -0
- package/dist/web/public/keyboard-accessory.c458eea8.js.gz +0 -0
- package/dist/web/public/mobile-handlers.0ef9c311.js.gz +0 -0
- package/dist/web/public/mobile-ime-preview.2dbaf262.js.gz +0 -0
- package/dist/web/public/mobile-overview.js +11 -2
- package/dist/web/public/mobile-overview.js.br +0 -0
- package/dist/web/public/mobile-overview.js.gz +0 -0
- package/dist/web/public/mobile.2dff1580.css +1 -0
- package/dist/web/public/mobile.2dff1580.css.br +0 -0
- package/dist/web/public/mobile.2dff1580.css.gz +0 -0
- package/dist/web/public/{notification-manager.50bb87d8.js → notification-manager.feb82c04.js} +19 -2
- package/dist/web/public/notification-manager.feb82c04.js.br +0 -0
- package/dist/web/public/notification-manager.feb82c04.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/{panels-ui.4735dfc2.js → panels-ui.73ec0137.js} +87 -87
- package/dist/web/public/panels-ui.73ec0137.js.br +0 -0
- package/dist/web/public/panels-ui.73ec0137.js.gz +0 -0
- package/dist/web/public/ralph-panel.b350e2ef.js.gz +0 -0
- package/dist/web/public/ralph-wizard.b6c0dd19.js.gz +0 -0
- package/dist/web/public/readmymind-ui.js.gz +0 -0
- package/dist/web/public/reboot-restore-ui.js.gz +0 -0
- package/dist/web/public/respawn-ui.ff0dae4c.js.gz +0 -0
- package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
- package/dist/web/public/session-lineage.js.gz +0 -0
- package/dist/web/public/{session-ui.f731602c.js → session-ui.dbc6819b.js} +33 -33
- package/dist/web/public/session-ui.dbc6819b.js.br +0 -0
- package/dist/web/public/session-ui.dbc6819b.js.gz +0 -0
- package/dist/web/public/settings-ui.81ac264e.js +97 -0
- package/dist/web/public/settings-ui.81ac264e.js.br +0 -0
- package/dist/web/public/settings-ui.81ac264e.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview-worker.js +11 -0
- package/dist/web/public/spreadsheet-preview-worker.js.br +0 -0
- package/dist/web/public/spreadsheet-preview-worker.js.gz +0 -0
- package/dist/web/public/{spreadsheet-preview.af82fa2f.js → spreadsheet-preview.75c751de.js} +1 -1
- package/dist/web/public/spreadsheet-preview.75c751de.js.br +0 -0
- package/dist/web/public/spreadsheet-preview.75c751de.js.gz +0 -0
- package/dist/web/public/spreadsheet-xlsx-core.js +110 -0
- package/dist/web/public/spreadsheet-xlsx-core.js.br +0 -0
- package/dist/web/public/spreadsheet-xlsx-core.js.gz +0 -0
- package/dist/web/public/styles.900a28e4.css +1 -0
- package/dist/web/public/styles.900a28e4.css.br +0 -0
- package/dist/web/public/styles.900a28e4.css.gz +0 -0
- package/dist/web/public/{subagent-windows.e6ca799f.js → subagent-windows.07277a58.js} +7 -5
- package/dist/web/public/subagent-windows.07277a58.js.br +0 -0
- package/dist/web/public/subagent-windows.07277a58.js.gz +0 -0
- package/dist/web/public/sw.js +6 -2
- package/dist/web/public/sw.js.br +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/tab-layout-browser.2d6189f7.js +1 -0
- package/dist/web/public/tab-layout-browser.2d6189f7.js.br +0 -0
- package/dist/web/public/tab-layout-browser.2d6189f7.js.gz +0 -0
- package/dist/web/public/{tab-rail-resize.a5867793.js → tab-rail-resize.7157e0bd.js} +1 -1
- package/dist/web/public/tab-rail-resize.7157e0bd.js.br +0 -0
- package/dist/web/public/tab-rail-resize.7157e0bd.js.gz +0 -0
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.gz +0 -0
- package/dist/web/public/terminal-split.js.gz +0 -0
- package/dist/web/public/terminal-tile.js +135 -38
- package/dist/web/public/terminal-tile.js.br +0 -0
- package/dist/web/public/terminal-tile.js.gz +0 -0
- package/dist/web/public/terminal-ui.858f5da5.js +2 -0
- package/dist/web/public/terminal-ui.858f5da5.js.br +0 -0
- package/dist/web/public/terminal-ui.858f5da5.js.gz +0 -0
- package/dist/web/public/tile-grid.js +769 -137
- package/dist/web/public/tile-grid.js.br +0 -0
- package/dist/web/public/tile-grid.js.gz +0 -0
- package/dist/web/public/ultracode-panel.js.gz +0 -0
- package/dist/web/public/ultracode-windows.js +9 -6
- package/dist/web/public/ultracode-windows.js.br +0 -0
- package/dist/web/public/ultracode-windows.js.gz +0 -0
- package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
- package/dist/web/public/vendor/exceljs.min.js.gz +0 -0
- package/dist/web/public/vendor/fflate.min.js.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.ae5e3d5d.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js +4 -0
- package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.br +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.0b69623c.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/voice-input.2342c37b.js.gz +0 -0
- package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
- package/dist/web/public/webview-tabs.js +12 -0
- package/dist/web/public/webview-tabs.js.br +0 -0
- package/dist/web/public/webview-tabs.js.gz +0 -0
- package/dist/web/route-helpers.d.ts +8 -0
- package/dist/web/route-helpers.d.ts.map +1 -1
- package/dist/web/route-helpers.js +8 -0
- package/dist/web/route-helpers.js.map +1 -1
- package/dist/web/routes/admin-routes.d.ts.map +1 -1
- package/dist/web/routes/admin-routes.js +4 -1
- package/dist/web/routes/admin-routes.js.map +1 -1
- package/dist/web/routes/approval-routes.d.ts.map +1 -1
- package/dist/web/routes/approval-routes.js +6 -8
- package/dist/web/routes/approval-routes.js.map +1 -1
- package/dist/web/routes/case-routes.js +1 -1
- package/dist/web/routes/case-routes.js.map +1 -1
- package/dist/web/routes/cli-registry-routes.d.ts +23 -4
- package/dist/web/routes/cli-registry-routes.d.ts.map +1 -1
- package/dist/web/routes/cli-registry-routes.js +92 -7
- package/dist/web/routes/cli-registry-routes.js.map +1 -1
- package/dist/web/routes/file-routes.d.ts +46 -1
- package/dist/web/routes/file-routes.d.ts.map +1 -1
- package/dist/web/routes/file-routes.js +214 -27
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/routes/hook-event-routes.d.ts.map +1 -1
- package/dist/web/routes/hook-event-routes.js +8 -1
- package/dist/web/routes/hook-event-routes.js.map +1 -1
- package/dist/web/routes/html-view-routes.d.ts +60 -0
- package/dist/web/routes/html-view-routes.d.ts.map +1 -0
- package/dist/web/routes/html-view-routes.js +288 -0
- package/dist/web/routes/html-view-routes.js.map +1 -0
- package/dist/web/routes/index.d.ts +1 -0
- package/dist/web/routes/index.d.ts.map +1 -1
- package/dist/web/routes/index.js +1 -0
- package/dist/web/routes/index.js.map +1 -1
- package/dist/web/routes/mcp-sync-routes.d.ts +7 -2
- package/dist/web/routes/mcp-sync-routes.d.ts.map +1 -1
- package/dist/web/routes/mcp-sync-routes.js +10 -3
- package/dist/web/routes/mcp-sync-routes.js.map +1 -1
- package/dist/web/routes/reboot-restore-routes.js +3 -3
- package/dist/web/routes/reboot-restore-routes.js.map +1 -1
- package/dist/web/routes/session-routes.d.ts +1 -0
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +345 -90
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/routes/status-telemetry-routes.d.ts.map +1 -1
- package/dist/web/routes/status-telemetry-routes.js +16 -2
- package/dist/web/routes/status-telemetry-routes.js.map +1 -1
- package/dist/web/schemas.d.ts +32 -0
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +74 -0
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/server.d.ts +7 -2
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +77 -24
- package/dist/web/server.js.map +1 -1
- package/dist/web/sse-events.d.ts +5 -2
- package/dist/web/sse-events.d.ts.map +1 -1
- package/dist/web/sse-events.js +5 -2
- package/dist/web/sse-events.js.map +1 -1
- package/package.json +5 -4
- package/skills/codeman/SKILL.md +30 -7
- package/README.zh-CN.md +0 -1147
- package/dist/web/public/app.abadc970.js +0 -43
- package/dist/web/public/app.abadc970.js.br +0 -0
- package/dist/web/public/app.abadc970.js.gz +0 -0
- package/dist/web/public/constants.c0f8f9de.js.br +0 -0
- package/dist/web/public/constants.c0f8f9de.js.gz +0 -0
- package/dist/web/public/i18n.a31747a9.js +0 -2
- package/dist/web/public/i18n.a31747a9.js.br +0 -0
- package/dist/web/public/i18n.a31747a9.js.gz +0 -0
- package/dist/web/public/image-input.898a538b.js +0 -281
- package/dist/web/public/image-input.898a538b.js.br +0 -0
- package/dist/web/public/image-input.898a538b.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.c1e7c7b7.js.br +0 -0
- package/dist/web/public/keyboard-accessory.c1e7c7b7.js.gz +0 -0
- package/dist/web/public/mobile.111b187d.css +0 -1
- package/dist/web/public/mobile.111b187d.css.br +0 -0
- package/dist/web/public/mobile.111b187d.css.gz +0 -0
- package/dist/web/public/notification-manager.50bb87d8.js.br +0 -0
- package/dist/web/public/notification-manager.50bb87d8.js.gz +0 -0
- package/dist/web/public/panels-ui.4735dfc2.js.br +0 -0
- package/dist/web/public/panels-ui.4735dfc2.js.gz +0 -0
- package/dist/web/public/session-ui.f731602c.js.br +0 -0
- package/dist/web/public/session-ui.f731602c.js.gz +0 -0
- package/dist/web/public/settings-ui.a97ab16f.js +0 -97
- package/dist/web/public/settings-ui.a97ab16f.js.br +0 -0
- package/dist/web/public/settings-ui.a97ab16f.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview.af82fa2f.js.br +0 -0
- package/dist/web/public/spreadsheet-preview.af82fa2f.js.gz +0 -0
- package/dist/web/public/styles.8ee12666.css +0 -1
- package/dist/web/public/styles.8ee12666.css.br +0 -0
- package/dist/web/public/styles.8ee12666.css.gz +0 -0
- package/dist/web/public/subagent-windows.e6ca799f.js.br +0 -0
- package/dist/web/public/subagent-windows.e6ca799f.js.gz +0 -0
- package/dist/web/public/tab-layout-browser.065fcba4.js +0 -1
- package/dist/web/public/tab-layout-browser.065fcba4.js.br +0 -0
- package/dist/web/public/tab-layout-browser.065fcba4.js.gz +0 -0
- package/dist/web/public/tab-rail-resize.a5867793.js.br +0 -0
- package/dist/web/public/tab-rail-resize.a5867793.js.gz +0 -0
- package/dist/web/public/terminal-ui.5059b30e.js +0 -2
- package/dist/web/public/terminal-ui.5059b30e.js.br +0 -0
- package/dist/web/public/terminal-ui.5059b30e.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.bbb5f84c.js +0 -4
- package/dist/web/public/vendor/xterm-zerolag-input.bbb5f84c.js.br +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.bbb5f84c.js.gz +0 -0
|
Binary file
|
|
Binary file
|
|
@@ -283,12 +283,14 @@ Object.assign(CodemanApp.prototype, {
|
|
|
283
283
|
wizardRect = wizardContent.getBoundingClientRect();
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
-
// Read tab rects for normal mode (only tabs that are actually needed)
|
|
286
|
+
// Read tab rects for normal mode (only tabs that are actually needed).
|
|
287
|
+
// Only a painted row is cached: a row a search or filter hid has no line
|
|
288
|
+
// (_paintedSessionTab), rather than one drawn from the viewport's corner.
|
|
287
289
|
if (!wizardOpen) {
|
|
288
290
|
for (const { agentId } of visibleSubagentWindows) {
|
|
289
291
|
const parentSessionId = this.subagentParentMap.get(agentId);
|
|
290
292
|
if (!parentSessionId || rects.has('tab:' + parentSessionId)) continue;
|
|
291
|
-
const tab =
|
|
293
|
+
const tab = this._paintedSessionTab(parentSessionId);
|
|
292
294
|
if (tab) rects.set('tab:' + parentSessionId, tab.getBoundingClientRect());
|
|
293
295
|
}
|
|
294
296
|
}
|
|
@@ -397,7 +399,7 @@ Object.assign(CodemanApp.prototype, {
|
|
|
397
399
|
|
|
398
400
|
const tabRect = rects.get('tab:' + parentSessionId);
|
|
399
401
|
if (!tabRect) {
|
|
400
|
-
// Tab not
|
|
402
|
+
// Tab not painted (session closed, collapsed group, or hidden by a search)
|
|
401
403
|
continue;
|
|
402
404
|
}
|
|
403
405
|
|
|
@@ -691,8 +693,8 @@ Object.assign(CodemanApp.prototype, {
|
|
|
691
693
|
}
|
|
692
694
|
}
|
|
693
695
|
|
|
694
|
-
// Get parent TAB element for spawn animation
|
|
695
|
-
const parentTab =
|
|
696
|
+
// Get parent TAB element for spawn animation (a hidden row spawns normally)
|
|
697
|
+
const parentTab = this._paintedSessionTab(parentSessionId);
|
|
696
698
|
|
|
697
699
|
// Create window element
|
|
698
700
|
const win = document.createElement('div');
|
|
Binary file
|
|
Binary file
|
package/dist/web/public/sw.js
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
// not the current one, so the old constant key meant that cleanup never deleted
|
|
27
27
|
// anything — hashed assets from every release ever deployed accumulated in one
|
|
28
28
|
// bucket until the origin hit its storage quota.
|
|
29
|
-
const BUILD_ID = '
|
|
29
|
+
const BUILD_ID = '95cf4ad0cf5b';
|
|
30
30
|
const CACHE_NAME = `codeman-${BUILD_ID}`;
|
|
31
31
|
|
|
32
32
|
// Reverse-proxy base path: the worker is served at `<base>/sw.js`, so its own
|
|
@@ -48,7 +48,7 @@ const B = (p) => (p && p[0] === '/' ? SW_BASE + p : p);
|
|
|
48
48
|
// handler caches every successful GET at runtime, but the precache warmed
|
|
49
49
|
// nothing while looking like it did. Deriving it from the same manifest that
|
|
50
50
|
// renames the files is the only thing that keeps the two from drifting again.
|
|
51
|
-
const HASHED_ASSETS = ["styles.
|
|
51
|
+
const HASHED_ASSETS = ["styles.900a28e4.css", "mobile.2dff1580.css", "constants.17d77b65.js", "i18n.9afd8e4d.js", "mobile-handlers.0ef9c311.js", "voice-input.2342c37b.js", "notification-manager.feb82c04.js", "keyboard-accessory.c458eea8.js", "input-cjk.8bc46081.js", "mobile-ime-preview.2dbaf262.js", "terminal-keycode229-recovery.af09f99a.js", "sanitize-html.e7147e76.js", "tab-layout-browser.2d6189f7.js", "app.24689381.js", "tab-rail-resize.7157e0bd.js", "terminal-ui.858f5da5.js", "respawn-ui.ff0dae4c.js", "ralph-panel.b350e2ef.js", "settings-ui.81ac264e.js", "panels-ui.73ec0137.js", "session-ui.dbc6819b.js", "ralph-wizard.b6c0dd19.js", "api-client.c9b1cddc.js", "subagent-windows.07277a58.js", "image-input.9ed1d0d2.js", "spreadsheet-preview.75c751de.js", "vendor/xterm-zerolag-input.0b69623c.js", "vendor/xterm-predictive-echo.ae5e3d5d.js"];
|
|
52
52
|
|
|
53
53
|
// Core app shell -- cached on install for instant startup
|
|
54
54
|
const APP_SHELL = [
|
|
@@ -101,6 +101,10 @@ self.addEventListener('fetch', (event) => {
|
|
|
101
101
|
if (request.headers.get('upgrade') === 'websocket') return;
|
|
102
102
|
if (request.headers.get('accept') === 'text/event-stream') return;
|
|
103
103
|
if (request.url.includes('/api/')) return;
|
|
104
|
+
// A rendered HTML page is served `no-store` behind a capability that logout
|
|
105
|
+
// revokes; caching a popped-out page here would let the offline fallback
|
|
106
|
+
// serve it after the capability is gone.
|
|
107
|
+
if (request.url.includes('/html-view/')) return;
|
|
104
108
|
|
|
105
109
|
event.respondWith(
|
|
106
110
|
fetch(request)
|
package/dist/web/public/sw.js.br
CHANGED
|
Binary file
|
package/dist/web/public/sw.js.gz
CHANGED
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";(function(Y){"use strict";const K="codeman:tab-groups-collapsed",H="codeman:tab-focus-collapsed",c=t=>`${t.kind}:${t.id}`,R=t=>!!t&&(t.kind==="session"||t.kind==="webview")&&typeof t.id=="string"&&t.id.length>0,_=t=>Array.isArray(t)?t.filter(n=>typeof n=="string"&&n):[],G=t=>[...new Set(_(t))],E=t=>{const n={kind:t.kind,id:t.id};return t.placement==="manual"&&(n.placement="manual"),t.focus===!0&&(n.focus=!0),n},X=t=>Array.isArray(t)?t.filter(R).map(E):[];function m(t){if(!t||typeof t!="object")throw new Error("Invalid tab layout");const n=Array.isArray(t.groups)?t.groups:[];return{version:Number.isSafeInteger(t.version)&&t.version>=0?t.version:0,updatedAt:typeof t.updatedAt=="string"?t.updatedAt:"",groups:n.filter(e=>e&&typeof e.id=="string"&&e.id.length>0).map(e=>({id:e.id,name:typeof e.name=="string"?e.name:"",refs:X(e.refs)})),ungrouped:X(t.ungrouped)}}function U(t){return!!t&&Array.isArray(t.groups)&&t.groups.length>0}function Q(t){if(t===null)return[];try{const n=JSON.parse(t);return Array.isArray(n)?G(n):null}catch{return null}}function Z(t,n){try{const e=Q(t.getItem(K)),r=e||[];if(n===void 0)return{ids:r,ok:!0};const o=new Set(G(n)),s=r.filter(a=>o.has(a));return(!e||s.length!==r.length)&&t.setItem(K,JSON.stringify(s)),{ids:s,ok:!0}}catch{return{ids:[],ok:!1}}}function ee(t){try{return{collapsed:t.getItem(H)==="true",ok:!0}}catch{return{collapsed:!1,ok:!1}}}function te(t,n){try{return t.setItem(H,n===!0?"true":"false"),{collapsed:n===!0,ok:!0}}catch{return{collapsed:!1,ok:!1}}}function B(t,n={}){if(!t)return[];const e=m(t),r=new Set(_(n.liveSessionIds)),o=new Set(_(n.openWebviewIds)),s=new Set,a=[];for(const i of[...e.groups.flatMap(u=>u.refs),...e.ungrouped]){if(i.focus!==!0||!(i.kind==="session"?r.has(i.id):o.has(i.id)))continue;const u=c(i);s.has(u)||(s.add(u),a.push({kind:i.kind,id:i.id}))}return a}function ne(t,n){const e=G(n);try{return t.setItem(K,JSON.stringify(e)),{ids:e,ok:!0}}catch{return{ids:[],ok:!1}}}function re(t,n={}){if(!t)return null;const e=m(t);if(!U(e))return null;const r=G(n.liveSessionIds),o=G(n.openWebviewIds),s=new Set(r),a=new Set(o),i=new Set(_(n.collapsedGroupIds)),u=n.activeWebviewId?`webview:${n.activeWebviewId}`:n.activeSessionId?`session:${n.activeSessionId}`:"",f=h=>h.kind==="session"?s.has(h.id):a.has(h.id),p=se(e,r,n.parents),d=new Set,y=[],b={},v={},l=[],g=(h,k,J)=>{const O=[],F=[];let V=0;for(const C of h){const M=c(C);if(d.has(M)||!f(C))continue;d.add(M),v[M]=k,V++;const W={kind:C.kind,id:C.id};if(J&&M!==u){b[M]=k,F.push(W);continue}O.push(W),y.push(W)}return{shown:O,hidden:F,count:V}};for(const h of e.groups){const k=i.has(h.id),{shown:J,hidden:O,count:F}=g(p(h.refs),h.id,k);l.push({id:h.id,name:h.name,refs:J,hidden:O,count:F,collapsed:k})}const S=[...r.map(h=>({kind:"session",id:h})),...o.map(h=>({kind:"webview",id:h}))],I=g([...p(e.ungrouped),...S],null,!1);return I.count>0&&l.push({id:null,name:"",refs:I.shown,hidden:[],count:I.count,collapsed:!1}),{sections:l,visibleRefs:y,hiddenTabGroupByRef:b,sectionByRef:v,focusRefs:B(e,n)}}const D={action:2,idle:1};function oe(t,n){const e={},r=t&&Array.isArray(t.sections)?t.sections:[];for(const o of r){if(o.id===null||!Array.isArray(o.hidden))continue;let s=null;for(const a of o.hidden){if(a.kind!=="session")continue;const i=n(a.id);D[i]&&(!s||D[i]>D[s])&&(s=i)}s&&(e[o.id]=s)}return e}function se(t,n,e){if(!e||typeof e!="object")return a=>a;const r=new Set(A(t).map(a=>c(a.ref))),o=new Set,s=new Map;for(let a=!0;a;){a=!1;for(const i of n){const u=`session:${i}`,f=e[i];if(r.has(u)||o.has(u)||typeof f!="string"||f===i)continue;const p=`session:${f}`;!r.has(p)&&!o.has(p)||(o.add(u),s.has(p)||s.set(p,[]),s.get(p).push({kind:"session",id:i}),a=!0)}}return s.size?a=>{const i=[...a];for(const[u,f]of s){const p=$(t,{kind:"session",id:u.slice(8)},e);let d=-1;i.forEach((y,b)=>{p.has(c(y))&&(d=b)}),d>=0&&i.splice(d+1,0,...f)}return i}:a=>a}function ae(t,n,e){return n?JSON.stringify({collapsed:G(e).sort(),sections:n.sections.map(r=>[r.id,r.name,r.count,r.refs.map(c),(r.hidden||[]).map(c)])}):null}function ie(t,n,e){return(t&&Array.isArray(t.sections)?t.sections:[]).map((o,s)=>{const a=o.refs.map(b=>n(b)).join("");if(o.id===null)return`<section class="tab-layout-group tab-layout-ungrouped" role="presentation" data-tab-group-id=""><div class="tab-layout-group-header tab-layout-ungrouped-header" aria-hidden="true"><span class="tab-layout-group-name">Ungrouped</span><span class="tab-layout-group-count">${o.count}</span></div><div class="tab-layout-group-refs" role="presentation">${a}</div></section>`;const i=e(o.id),u=`tab-layout-group-refs-${s}`,f=`tab-layout-group-name-${s}`,p=o.count===0,d=!o.collapsed&&!p,y=p?"":` aria-expanded="${d?"true":"false"}"`;return`<section class="tab-layout-group${o.collapsed?" tab-layout-group--collapsed":""}" role="presentation" data-tab-group-id="${i}"><div class="tab-layout-group-header tab-layout-group-toggle" role="treeitem" tabindex="-1" data-tab-group-header="${i}"${y}${d?` aria-owns="${u}"`:""} onclick="app.toggleTabGroupCollapsed(this.dataset.tabGroupHeader)" oncontextmenu="event.preventDefault(); app.openTabGroupMenu(event, this.dataset.tabGroupHeader)"><span class="tab-layout-group-chevron" aria-hidden="true"></span><span class="tab-layout-group-name" id="${f}" data-i18n-skip>${e(o.name)}</span><span class="tab-layout-group-count">${o.count}</span><span class="tab-layout-group-menu" aria-hidden="true" title="Group actions" onclick="event.stopPropagation(); app.openTabGroupMenu(event, this.closest('[data-tab-group-header]').dataset.tabGroupHeader)">⋯</span></div><div class="tab-layout-group-refs" id="${u}" ${d?`role="group" aria-labelledby="${f}"`:'role="presentation"'}>${a}</div></section>`}).join("")}function ue(t){const n=Number.isFinite(t.retryDelayMs)?t.retryDelayMs:5e3,e=Number.isFinite(t.maxRetryDelayMs)?t.maxRetryDelayMs:6e4,r=Number.isSafeInteger(t.maxRetries)?t.maxRetries:4;let o=0,s=!1,a=null,i=0;const u=()=>{a!==null&&t.cancelRetry&&t.cancelRetry(a),a=null},f=async()=>{if(s)return!1;const p=++o;u();try{const d=await t.fetchLayout();return s||p!==o?!1:(i=0,t.applyLayout(d),!0)}catch{if(s||p!==o)return!1;if(i++,t.applyFallback(),i<=r){const y=Math.min(e,n*2**(i-1));a=t.scheduleRetry(()=>f(),y)}return!1}};return{load:f,dispose(){s=!0,o++,u()}}}function w(t){throw new Error(`Tab layout edit failed: ${t}`)}const P=(t,n)=>Number.isInteger(t)?Math.max(0,Math.min(t,n)):n;function q(t){const n=typeof t=="string"?t.trim():"";return(!n||n.length>60)&&w("group name must be 1-60 characters"),n}function A(t){return[...t.groups.flatMap(n=>n.refs.map(e=>({groupId:n.id,ref:e}))),...t.ungrouped.map(n=>({groupId:null,ref:n}))]}function T(t,n){if(n===null)return t.ungrouped;const e=t.groups.find(r=>r.id===n);return e||w("unknown group"),e.refs}function $(t,n,e){const r=new Map(A(t).map(i=>[c(i.ref),i.ref])),o=new Map;for(const[i,u]of Object.entries(e||{})){const f=r.get(`session:${i}`);!f||f.placement==="manual"||!r.has(`session:${u}`)||(o.has(u)||o.set(u,[]),o.get(u).push(i))}const s=new Set,a=i=>{if(!s.has(i)&&(s.add(i),i.startsWith("session:")))for(const u of o.get(i.slice(8))||[])a(`session:${u}`)};return a(c(n)),s}function j(t,n,e){const r=m(t);if(!R(n)||n.kind!=="session")return null;const o=e?.[n.id];if(typeof o!="string"||!o||o===n.id)return null;const s=new Map(A(r).map(u=>[c(u.ref),u.ref])),a=s.get(c(n));if(!a)return null;if(!s.has(`session:${o}`))return{state:"dangling",parentId:o,canFollow:!1};const i=new Set([n.id]);for(let u=o;u&&s.has(`session:${u}`);u=e[u]){if(i.has(u))return{state:"cycle",parentId:o,canFollow:!1};i.add(u)}return a.placement==="manual"?{state:"manual",parentId:o,canFollow:!0}:{state:"inherited",parentId:o,canFollow:!1}}function z(t,n,e,r,o,s){const a=m(t),i=$(a,n,s),u=T(a,e).filter(p=>!i.has(c(p)));if(!r)return{groupId:e};const f=u.findIndex(p=>c(p)===c(r));return f<0?{groupId:e}:{groupId:e,index:o==="after"?f+1:f}}function le(t,n,e,r){const o=m(t);if(!n||!e)return null;if(n.type==="group"){const d=o.groups.findIndex(v=>v.id===n.groupId);if(d<0)return null;const y=e.type==="ungrouped"?null:e.groupId??null,b=y===null?o.groups.length-1:o.groups.findIndex(v=>v.id===y);return b<0||b===d?null:{type:"reorderGroup",groupId:n.groupId,index:b}}if(n.type!=="ref"||!R(n.ref))return null;const s=A(o).find(d=>c(d.ref)===c(n.ref));if(!s)return null;let a,i=null,u="before";if(e.type==="ref"&&R(e.ref)){if($(o,n.ref,r).has(c(e.ref)))return null;a=e.groupId??null,i=e.ref,u=e.placement==="after"?"after":"before"}else if(e.type==="group"){if(a=e.groupId??null,a===s.groupId)return null}else if(e.type==="ungrouped"){if(a=null,s.groupId===null)return null}else return null;if(a!==null&&!o.groups.some(d=>d.id===a))return null;const f=z(o,n.ref,a,i,u,r),p={type:"moveRef",ref:{kind:n.ref.kind,id:n.ref.id},groupId:f.groupId,...f.index===void 0?{}:{index:f.index},parents:r||{}};return x(L(o,p))===x(o)?null:p}function L(t,n){const e=m(t),r=n||{},o=e.groups.findIndex(s=>s.id===r.groupId);switch(r.type){case"createGroup":{(typeof r.id!="string"||!r.id)&&w("invalid group id");const s=q(r.name);return e.groups.some(a=>a.id===r.id)||(e.groups.length>=32&&w("group limit reached"),e.groups.splice(P(r.index,e.groups.length),0,{id:r.id,name:s,refs:[]})),e}case"renameGroup":return o<0&&w("unknown group"),e.groups[o].name=q(r.name),e;case"deleteGroup":{if(o<0)return e;const[s]=e.groups.splice(o,1);return e.ungrouped.push(...s.refs),e}case"reorderGroup":{o<0&&w("unknown group");const[s]=e.groups.splice(o,1);return e.groups.splice(P(r.index,e.groups.length),0,s),e}case"setFocus":{R(r.ref)||w("invalid row"),typeof r.focused!="boolean"&&w("invalid Focus state");const s=A(e).find(a=>c(a.ref)===c(r.ref));return s||w("unknown row"),r.focused?s.ref.focus=!0:delete s.ref.focus,e}case"moveRef":{R(r.ref)||w("invalid row");const s=c(r.ref);A(e).some(d=>c(d.ref)===s)||w("unknown row");const a=r.groupId??null;T(e,a);const i=$(e,r.ref,r.parents),u=A(e).filter(d=>i.has(c(d.ref))).map(d=>E(d.ref)),f=u.find(d=>c(d)===s);r.ref.kind==="session"&&r.parents?.[r.ref.id]&&(f.placement="manual"),u.sort((d,y)=>d===f?-1:y===f?1:0);for(const d of e.groups)d.refs=d.refs.filter(y=>!i.has(c(y)));e.ungrouped=e.ungrouped.filter(d=>!i.has(c(d)));const p=T(e,a);return p.splice(P(r.index,p.length),0,...u),e}case"followParent":{const s=j(e,r.ref,r.parents);if((!s||s.state==="dangling"||s.state==="cycle")&&w("no parent to follow"),s.state!=="manual")return e;const a=c(r.ref),i=l=>{if(c(l)!==a)return l;const g=E(l);return delete g.placement,g};for(const l of e.groups)l.refs=l.refs.map(i);e.ungrouped=e.ungrouped.map(i);const u=new Set;for(const l of $(e,r.ref,r.parents))u.add(l);const f=A(e).filter(l=>u.has(c(l.ref))).map(l=>E(l.ref));f.sort((l,g)=>c(l)===a?-1:c(g)===a?1:0);for(const l of e.groups)l.refs=l.refs.filter(g=>!u.has(c(g)));e.ungrouped=e.ungrouped.filter(l=>!u.has(c(l)));const p={kind:"session",id:s.parentId},d=A(e).find(l=>c(l.ref)===c(p)),y=T(e,d.groupId),b=$(e,p,r.parents);let v=-1;return y.forEach((l,g)=>{b.has(c(l))&&(v=g)}),y.splice(v+1,0,...f),e}default:return w(`unknown operation ${r.type}`)}}function x(t){const n=m(t);return JSON.stringify([n.groups,n.ungrouped])}function N(t,n){let e=m(t);const r=[];let o=0;for(const s of n)try{e=L(e,s),r.push(s)}catch{o++}return{layout:e,kept:r,dropped:o}}function de(t){let n=m(t.initialLayout),e=n,r=[],o=[],s=!1,a=null,i=!1;const u=t.schedule||(l=>setTimeout(l,0)),f=t.cancel||(l=>clearTimeout(l)),p=t.maxAttempts||3,d=l=>t.reportError?.(l),y=l=>t.applyLayout(m(e),l),b=()=>{a===null&&(a=u(v))};async function v(){if(a=null,i||s||r.length===0)return;s=!0,o=r,r=[];let l=!1,g=!1,S=!1;try{for(let I=0;I<p&&o.length;I++){const h=N(n,o);if(o=h.kept,h.dropped&&!g&&(g=!0,d("Tab groups changed elsewhere; part of your edit no longer applies.")),!o.length||x(h.layout)===x(n)){o=[];break}const k=await t.put({baseVersion:n.version,layout:h.layout});if(i)return;if(k?.ok&&k.layout)n=m(k.layout),o=[];else if(k?.status===409&&k.layout)n=m(k.layout);else if(k?.status===400&&t.fetchLayout&&!S){if(S=!0,n=m(await t.fetchLayout()),i)return}else throw new Error("Tab layout save failed")}o.length&&(l=!0,d("Tab groups kept changing elsewhere; your edit was not saved."))}catch{l=!0,d("Could not save tab groups.")}finally{if(o=[],s=!1,!i){const I=N(n,r);I.dropped&&!l&&!g&&d("Tab groups changed elsewhere; part of your edit no longer applies."),r=I.kept,e=I.layout,y({authoritative:!0}),l&&t.onFailure?.(),r.length?b():t.onSettled?.()}}}return{enqueue(l){return e=L(e,l),r.push(l),y({optimistic:!0}),b(),m(e)},restore(l){const g=N(e,Array.isArray(l)?l:[]);return!g.kept.length||x(g.layout)===x(e)?!1:(e=g.layout,r.push(...g.kept),y({optimistic:!0}),b(),!0)},adoptExternal(l){if(i||s)return!1;const g=m(l);if(g.version<n.version)return!1;n=g;const S=N(g,r);return S.dropped&&d("Tab groups changed elsewhere; part of your edit no longer applies."),r=S.kept,e=S.layout,y({authoritative:!0,external:!0}),!0},flush:v,isWriting:()=>s,hasPending:()=>s||r.length>0,pendingOperations:()=>JSON.parse(JSON.stringify([...o,...r])),baseVersion:()=>n.version,getLayout:()=>m(e),dispose(){i=!0,a!==null&&f(a),a=null,r=[]}}}Y.CodemanTabLayout={normalizeLayout:m,hasGroups:U,project:re,hiddenGroupAlerts:oe,structureKey:ae,renderProjection:ie,applyOperation:L,moveDestination:z,movingRefKeys:(t,n,e)=>[...$(m(t),n,e)],placementState:j,dropOperation:le,contentKey:x,createEditCoordinator:de,createLoadCoordinator:ue,loadCollapsedGroupIds:Z,saveCollapsedGroupIds:ne,focusRefs:B,loadFocusCollapsed:ee,saveFocusCollapsed:te,MAX_GROUPS:32}})(typeof window<"u"?window:globalThis);
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.assign(CodemanApp.prototype,{_getTabRailMinimumTerminalWidth(){const t=this.terminal?._core?._renderService?.dimensions?.css?.cell?.width;return Number.isFinite(t)&&t>0?Math.ceil(t*40+24):420},_getTabRailBounds(){const t=document.querySelector(".main");return{viewportWidth:window.innerWidth,mainWidth:t?.clientWidth||window.innerWidth,minTerminalWidth:this._getTabRailMinimumTerminalWidth()}},_getCurrentTabRailWidth(){const t=Number.parseFloat(document.documentElement.style.getPropertyValue("--tab-rail-width"));if(Number.isFinite(t))return t;const e=document.getElementById("tabRail")?.getBoundingClientRect?.().width;return Number.isFinite(e)&&e>0?e:window.CodemanTabRail?.DEFAULT_WIDTH||256},readTabRailWidthSetting(){const t=document.getElementById("appSettingsTabRailWidth");return t?t.value==="custom"?Number(t.dataset.currentWidth)||this._getCurrentTabRailWidth():Number(t.value)||window.CodemanTabRail?.DEFAULT_WIDTH||256:this._getCurrentTabRailWidth()},syncTabRailWidthSetting(t){const e=document.getElementById("appSettingsTabRailWidth");if(!e)return;const i=Math.round(t);if(e.dataset.currentWidth=String(i),e.querySelector(`option[value="${i}"]`)){e.value=String(i);return}const n=e.querySelector('option[value="custom"]');n&&(n.textContent=`Custom (${i}px)`),e.value="custom"},_setTabRailWidth(t){const e=window.CodemanTabRail;if(!e)return 256;const i=e.resolveWidth({width:t}),a=this._getTabRailBounds(),n=e.resolveWidth({width:i,...a}),h=e.resolveWidth({width:e.MAX_WIDTH,...a}),r=document.documentElement;r.style.setProperty("--tab-rail-width",`${n}px`);const o=r.classList.contains("tab-rail-compact"),s=n<240;if(r.classList.toggle("tab-rail-compact",s),r.classList.toggle("tab-rail-tight",n<288),o!==s){const d=this._tallTabsEnabled;this.applyTabWrapSettings?.(),d!==void 0&&this._tallTabsEnabled!==d||this._fullRenderSessionTabs?.()}const l=document.getElementById("tabRailResizeHandle");return l&&(l.setAttribute("aria-valuemax",String(h)),l.setAttribute("aria-valuenow",String(n))),this.syncTabRailWidthSetting(i),n},_persistTabRailWidth(t){const e=this.loadAppSettingsFromStorage();e.tabRailWidth!==t&&(e.tabRailWidth=t,this.saveAppSettingsToStorage(e))},_claimTabRailResize(){this._tabRailResizeOwnsObserver=!0,clearTimeout(this._tabRailResizeWatchdog),clearTimeout(this._tabRailReleaseTimer),this._tabRailReleaseRaf&&cancelAnimationFrame(this._tabRailReleaseRaf),this._armTabRailResizeWatchdog(),this._resizeRaf&&cancelAnimationFrame(this._resizeRaf),this._resizeTimeout&&clearTimeout(this._resizeTimeout),this._resizeRaf=null,this._resizeTimeout=null},_armTabRailResizeWatchdog(){this._tabRailResizeWatchdog=setTimeout(()=>{if(this._tabRailResizeWatchdog=null,document.body.classList.contains("tab-rail-resizing")){this._armTabRailResizeWatchdog();return}this._tabRailResizeOwnsObserver=!1},1e3)},_releaseTabRailResize(){clearTimeout(this._tabRailResizeWatchdog),this._tabRailResizeWatchdog=null;const t=()=>{clearTimeout(this._tabRailReleaseTimer),this._tabRailReleaseTimer=null,this._tabRailReleaseRaf=null,this._tabRailResizeOwnsObserver=!1};typeof requestAnimationFrame=="function"?(this._tabRailReleaseRaf=requestAnimationFrame(()=>{this._tabRailReleaseRaf=requestAnimationFrame(t)}),this._tabRailReleaseTimer=setTimeout(t,250)):t()},_scheduleTabRailSettle(t,e=t){clearTimeout(this._tabRailSettleTimer),this._tabRailSettleTimer=setTimeout(async()=>{this._tabRailSettleTimer=null,this._persistTabRailWidth(e);try{this.activeSessionId&&this.sendResize?await this.sendResize(this.activeSessionId):this.syncTerminalGeometry?.(),this._updateConnectionLinesImmediate?.()}catch(i){console.warn("Failed to resize terminal after rail resize:",i)}finally{this._releaseTabRailResize()}},150)},_defaultTabRailWidth(){return document.documentElement.dataset.tabRailDetail!=="simple"?window.CodemanTabRail?.RICH_DEFAULT_WIDTH??320:window.CodemanTabRail?.DEFAULT_WIDTH??256},applyTabRailWidth(t={}){const i=this.loadAppSettingsFromStorage().tabRailWidth??this._defaultTabRailWidth(),a=window.CodemanTabRail?.resolveWidth({width:i})??256;t.settle&&this._claimTabRailResize();const n=this._setTabRailWidth(a);return t.persist!==!1&&i!==a&&this._persistTabRailWidth(a),t.settle&&this._scheduleTabRailSettle(n,a),n},_applyTabRailPointerWidth(t){const e=document.querySelector(".main");if(!e)return this._getCurrentTabRailWidth();const i=this._getCurrentTabRailWidth(),a=this._setTabRailWidth(t-e.getBoundingClientRect().left);let n=null;try{n=this.fitAddon?.proposeDimensions?.()}catch{}return n&&n.cols<40?this._setTabRailWidth(i):a},_queueTabRailPointerWidth(t){this._tabRailPendingClientX=t,!this._tabRailPointerRaf&&(this._tabRailPointerRaf=requestAnimationFrame(()=>{this._tabRailPointerRaf=null,this._tabRailDragWidth=this._applyTabRailPointerWidth(this._tabRailPendingClientX)}))},_finishTabRailDrag(t,e){if(!document.body.classList.contains("tab-rail-resizing"))return;this._tabRailPointerRaf&&(cancelAnimationFrame(this._tabRailPointerRaf),this._tabRailPointerRaf=null,this._tabRailDragWidth=this._applyTabRailPointerWidth(this._tabRailPendingClientX)),document.body.classList.remove("tab-rail-resizing");const i=document.getElementById("tabRailResizeShield");i&&(i.hidden=!0);try{t.hasPointerCapture?.(e)&&t.releasePointerCapture(e)}catch{}const a=window.CodemanTabRail?.resolveWidth({width:this._tabRailDragWidth})??this._tabRailDragWidth;this._scheduleTabRailSettle(this._tabRailDragWidth||this._getCurrentTabRailWidth(),a)},_onTabRailKeyDown(t){const e=window.CodemanTabRail?.resolveKeyboardWidth({key:t.key,shiftKey:t.shiftKey,currentWidth:this._getCurrentTabRailWidth(),defaultWidth:this._defaultTabRailWidth?.(),...this._getTabRailBounds()});if(e==null)return;t.preventDefault(),this._claimTabRailResize();const i=this._setTabRailWidth(e);this._scheduleTabRailSettle(i,window.CodemanTabRail.resolveWidth({width:e}))},initTabRailResize(){const t=document.getElementById("tabRailResizeHandle");if(!t||t.dataset.ready==="1")return;t.dataset.ready="1",this.applyTabRailWidth(),t.addEventListener("pointerdown",i=>{if(i.button!==0)return;i.preventDefault(),this.closeTabRailActionMenu(),this._claimTabRailResize(),this._tabRailDragWidth=this._getCurrentTabRailWidth(),this._tabRailPendingClientX=i.clientX,document.body.classList.add("tab-rail-resizing");const a=document.getElementById("tabRailResizeShield");a&&(a.hidden=!1);try{t.setPointerCapture(i.pointerId)}catch{document.body.classList.remove("tab-rail-resizing"),a&&(a.hidden=!0),this._releaseTabRailResize()}}),t.addEventListener("pointermove",i=>{t.hasPointerCapture?.(i.pointerId)&&this._queueTabRailPointerWidth(i.clientX)}),t.addEventListener("pointerup",i=>this._finishTabRailDrag(t,i.pointerId)),t.addEventListener("pointercancel",i=>this._finishTabRailDrag(t,i.pointerId)),t.addEventListener("lostpointercapture",i=>this._finishTabRailDrag(t,i.pointerId)),t.addEventListener("keydown",i=>this._onTabRailKeyDown(i)),t.addEventListener("dblclick",i=>{i.preventDefault(),this._claimTabRailResize();const a=this._defaultTabRailWidth?.()??(window.CodemanTabRail?.DEFAULT_WIDTH||256),n=this._setTabRailWidth(a);this._scheduleTabRailSettle(n,a)});let e=null;window.addEventListener("resize",()=>{clearTimeout(e),e=setTimeout(()=>{this.applyTabOrientation?.(),this.applyTabRailWidth({persist:!1})},100)})},closeTabRailActionMenu(t={}){const e=document.querySelector(".tab-rail-action-menu:not(.tab-layout-group-action-menu)"),i=this._tabRailActionMenuTrigger;e?.remove(),this._tabRailActionMenuOutside&&(document.removeEventListener("pointerdown",this._tabRailActionMenuOutside,!0),this._tabRailActionMenuOutside=null),this._tabRailActionMenuViewport&&(window.removeEventListener("resize",this._tabRailActionMenuViewport),this._tabRailActionMenuViewport=null),this._tabRailActionMenuTrigger=null,t.restoreFocus&&i?.focus?.()},openTabRailActionMenu(t,e){t.preventDefault(),t.stopPropagation(),this.closeTabRailActionMenu();const i=t.currentTarget,a=document.createElement("div");a.className="tab-rail-action-menu",a.setAttribute("role","menu"),a.setAttribute("aria-label","Session actions");const n=this.loadAppSettingsFromStorage(),h=[{label:"Session options",run:()=>this.openSessionOptions(e)},...this._tabRefMoveActions?.({kind:"session",id:e})||[],...(this.tabDetachButtonEnabled?.(n)??n.showTabDetachButton)||this.detachedSessions?.has(e)?[{label:"Open in a new window",run:()=>this.detachSession(e)}]:[],{label:"Close session",className:"danger",run:()=>this.requestCloseSession(e)}];for(const s of h){const l=document.createElement("button");l.type="button",l.setAttribute("role","menuitem"),l.textContent=s.label,s.className&&(l.className=s.className),l.addEventListener("click",()=>{this.closeTabRailActionMenu(),s.run()}),a.appendChild(l)}document.body.appendChild(a);const r=i.getBoundingClientRect(),o=a.getBoundingClientRect();a.style.left=`${Math.max(8,Math.min(r.right-o.width,window.innerWidth-o.width-8))}px`,a.style.top=`${Math.max(8,Math.min(r.bottom+4,window.innerHeight-o.height-8))}px`,this._tabRailActionMenuTrigger=i,this._tabRailActionMenuOutside=s=>{!a.contains(s.target)&&s.target!==i&&this.closeTabRailActionMenu()},document.addEventListener("pointerdown",this._tabRailActionMenuOutside,!0),this._tabRailActionMenuViewport=()=>this.closeTabRailActionMenu(),window.addEventListener("resize",this._tabRailActionMenuViewport,{once:!0}),a.addEventListener("keydown",s=>{const l=[...a.querySelectorAll("button")],d=l.indexOf(document.activeElement);if(s.key==="Escape")s.preventDefault(),this.closeTabRailActionMenu({restoreFocus:!0});else if(s.key==="ArrowDown"||s.key==="ArrowUp"){s.preventDefault();const c=s.key==="ArrowDown"?1:-1;l[(d+c+l.length)%l.length]?.focus()}}),a.querySelector("button")?.focus()}});
|
|
1
|
+
"use strict";Object.assign(CodemanApp.prototype,{_getTabRailMinimumTerminalWidth(){const t=this.terminal?._core?._renderService?.dimensions?.css?.cell?.width;return Number.isFinite(t)&&t>0?Math.ceil(t*40+24):420},_getTabRailBounds(){const t=document.querySelector(".main");return{viewportWidth:window.innerWidth,mainWidth:t?.clientWidth||window.innerWidth,minTerminalWidth:this._getTabRailMinimumTerminalWidth()}},_getCurrentTabRailWidth(){const t=Number.parseFloat(document.documentElement.style.getPropertyValue("--tab-rail-width"));if(Number.isFinite(t))return t;const e=document.getElementById("tabRail")?.getBoundingClientRect?.().width;return Number.isFinite(e)&&e>0?e:window.CodemanTabRail?.DEFAULT_WIDTH||256},readTabRailWidthSetting(){const t=document.getElementById("appSettingsTabRailWidth");return t?t.value==="custom"?Number(t.dataset.currentWidth)||this._getCurrentTabRailWidth():Number(t.value)||window.CodemanTabRail?.DEFAULT_WIDTH||256:this._getCurrentTabRailWidth()},syncTabRailWidthSetting(t){const e=document.getElementById("appSettingsTabRailWidth");if(!e)return;const i=Math.round(t);if(e.dataset.currentWidth=String(i),e.querySelector(`option[value="${i}"]`)){e.value=String(i);return}const n=e.querySelector('option[value="custom"]');n&&(n.textContent=`Custom (${i}px)`),e.value="custom"},_setTabRailWidth(t){const e=window.CodemanTabRail;if(!e)return 256;const i=e.resolveWidth({width:t}),a=this._getTabRailBounds(),n=e.resolveWidth({width:i,...a}),h=e.resolveWidth({width:e.MAX_WIDTH,...a}),o=document.documentElement;o.style.setProperty("--tab-rail-width",`${n}px`);const d=o.classList.contains("tab-rail-compact"),s=n<240;if(o.classList.toggle("tab-rail-compact",s),o.classList.toggle("tab-rail-tight",n<288),d!==s){const r=this._tallTabsEnabled;this.applyTabWrapSettings?.(),r!==void 0&&this._tallTabsEnabled!==r||this._fullRenderSessionTabs?.()}const l=document.getElementById("tabRailResizeHandle");return l&&(l.setAttribute("aria-valuemax",String(h)),l.setAttribute("aria-valuenow",String(n))),this.syncTabRailWidthSetting(i),n},_persistTabRailWidth(t){const e=this.loadAppSettingsFromStorage();e.tabRailWidth!==t&&(e.tabRailWidth=t,this.saveAppSettingsToStorage(e))},_claimTabRailResize(){this._tabRailResizeOwnsObserver=!0,clearTimeout(this._tabRailResizeWatchdog),clearTimeout(this._tabRailReleaseTimer),this._tabRailReleaseRaf&&cancelAnimationFrame(this._tabRailReleaseRaf),this._armTabRailResizeWatchdog(),this._resizeRaf&&cancelAnimationFrame(this._resizeRaf),this._resizeTimeout&&clearTimeout(this._resizeTimeout),this._resizeRaf=null,this._resizeTimeout=null},_armTabRailResizeWatchdog(){this._tabRailResizeWatchdog=setTimeout(()=>{if(this._tabRailResizeWatchdog=null,document.body.classList.contains("tab-rail-resizing")){this._armTabRailResizeWatchdog();return}this._tabRailResizeOwnsObserver=!1},1e3)},_releaseTabRailResize(){clearTimeout(this._tabRailResizeWatchdog),this._tabRailResizeWatchdog=null;const t=()=>{clearTimeout(this._tabRailReleaseTimer),this._tabRailReleaseTimer=null,this._tabRailReleaseRaf=null,this._tabRailResizeOwnsObserver=!1};typeof requestAnimationFrame=="function"?(this._tabRailReleaseRaf=requestAnimationFrame(()=>{this._tabRailReleaseRaf=requestAnimationFrame(t)}),this._tabRailReleaseTimer=setTimeout(t,250)):t()},_scheduleTabRailSettle(t,e=t){clearTimeout(this._tabRailSettleTimer),this._tabRailSettleTimer=setTimeout(async()=>{this._tabRailSettleTimer=null,this._persistTabRailWidth(e);try{this.activeSessionId&&this.sendResize?await this.sendResize(this.activeSessionId):this.syncTerminalGeometry?.(),this._updateConnectionLinesImmediate?.()}catch(i){console.warn("Failed to resize terminal after rail resize:",i)}finally{this._releaseTabRailResize()}},150)},_defaultTabRailWidth(){return document.documentElement.dataset.tabRailDetail!=="simple"?window.CodemanTabRail?.RICH_DEFAULT_WIDTH??320:window.CodemanTabRail?.DEFAULT_WIDTH??256},applyTabRailWidth(t={}){const i=this.loadAppSettingsFromStorage().tabRailWidth??this._defaultTabRailWidth(),a=window.CodemanTabRail?.resolveWidth({width:i})??256;t.settle&&this._claimTabRailResize();const n=this._setTabRailWidth(a);return t.persist!==!1&&i!==a&&this._persistTabRailWidth(a),t.settle&&this._scheduleTabRailSettle(n,a),n},_applyTabRailPointerWidth(t){const e=document.querySelector(".main");if(!e)return this._getCurrentTabRailWidth();const i=this._getCurrentTabRailWidth(),a=this._setTabRailWidth(t-e.getBoundingClientRect().left);let n=null;try{n=this.fitAddon?.proposeDimensions?.()}catch{}return n&&n.cols<40?this._setTabRailWidth(i):a},_queueTabRailPointerWidth(t){this._tabRailPendingClientX=t,!this._tabRailPointerRaf&&(this._tabRailPointerRaf=requestAnimationFrame(()=>{this._tabRailPointerRaf=null,this._tabRailDragWidth=this._applyTabRailPointerWidth(this._tabRailPendingClientX)}))},_finishTabRailDrag(t,e){if(!document.body.classList.contains("tab-rail-resizing"))return;this._tabRailPointerRaf&&(cancelAnimationFrame(this._tabRailPointerRaf),this._tabRailPointerRaf=null,this._tabRailDragWidth=this._applyTabRailPointerWidth(this._tabRailPendingClientX)),document.body.classList.remove("tab-rail-resizing");const i=document.getElementById("tabRailResizeShield");i&&(i.hidden=!0);try{t.hasPointerCapture?.(e)&&t.releasePointerCapture(e)}catch{}const a=window.CodemanTabRail?.resolveWidth({width:this._tabRailDragWidth})??this._tabRailDragWidth;this._scheduleTabRailSettle(this._tabRailDragWidth||this._getCurrentTabRailWidth(),a)},_onTabRailKeyDown(t){const e=window.CodemanTabRail?.resolveKeyboardWidth({key:t.key,shiftKey:t.shiftKey,currentWidth:this._getCurrentTabRailWidth(),defaultWidth:this._defaultTabRailWidth?.(),...this._getTabRailBounds()});if(e==null)return;t.preventDefault(),this._claimTabRailResize();const i=this._setTabRailWidth(e);this._scheduleTabRailSettle(i,window.CodemanTabRail.resolveWidth({width:e}))},initTabRailResize(){const t=document.getElementById("tabRailResizeHandle");if(!t||t.dataset.ready==="1")return;t.dataset.ready="1",this.applyTabRailWidth(),t.addEventListener("pointerdown",i=>{if(i.button!==0)return;i.preventDefault(),this.closeTabRailActionMenu(),this._claimTabRailResize(),this._tabRailDragWidth=this._getCurrentTabRailWidth(),this._tabRailPendingClientX=i.clientX,document.body.classList.add("tab-rail-resizing");const a=document.getElementById("tabRailResizeShield");a&&(a.hidden=!1);try{t.setPointerCapture(i.pointerId)}catch{document.body.classList.remove("tab-rail-resizing"),a&&(a.hidden=!0),this._releaseTabRailResize()}}),t.addEventListener("pointermove",i=>{t.hasPointerCapture?.(i.pointerId)&&this._queueTabRailPointerWidth(i.clientX)}),t.addEventListener("pointerup",i=>this._finishTabRailDrag(t,i.pointerId)),t.addEventListener("pointercancel",i=>this._finishTabRailDrag(t,i.pointerId)),t.addEventListener("lostpointercapture",i=>this._finishTabRailDrag(t,i.pointerId)),t.addEventListener("keydown",i=>this._onTabRailKeyDown(i)),t.addEventListener("dblclick",i=>{i.preventDefault(),this._claimTabRailResize();const a=this._defaultTabRailWidth?.()??(window.CodemanTabRail?.DEFAULT_WIDTH||256),n=this._setTabRailWidth(a);this._scheduleTabRailSettle(n,a)});let e=null;window.addEventListener("resize",()=>{clearTimeout(e),e=setTimeout(()=>{this.applyTabOrientation?.(),this.applyTabRailWidth({persist:!1})},100)})},closeTabRailActionMenu(t={}){const e=document.querySelector(".tab-rail-action-menu:not(.tab-layout-group-action-menu)"),i=this._tabRailActionMenuTrigger;e?.remove(),this._tabRailActionMenuOutside&&(document.removeEventListener("pointerdown",this._tabRailActionMenuOutside,!0),this._tabRailActionMenuOutside=null),this._tabRailActionMenuViewport&&(window.removeEventListener("resize",this._tabRailActionMenuViewport),this._tabRailActionMenuViewport=null),this._tabRailActionMenuTrigger=null,t.restoreFocus&&i?.focus?.()},openTabRailActionMenu(t,e){t.preventDefault(),t.stopPropagation(),this.closeTabRailActionMenu();const i=t.currentTarget,a=document.createElement("div");a.className="tab-rail-action-menu",a.setAttribute("role","menu"),a.setAttribute("aria-label","Session actions");const n=this.loadAppSettingsFromStorage(),h=[{label:"Session options",run:()=>this.openSessionOptions(e)},...this._tabRefFocusActions?.({kind:"session",id:e})||[],...this._tabRefMoveActions?.({kind:"session",id:e})||[],...this._tileGrid?.has?.(e)&&this._tileDetachAllowed?.()?[{label:"Open in a new window",run:()=>this.detachTile(e)}]:(this.tabDetachButtonEnabled?.(n)??n.showTabDetachButton)||this.detachedSessions?.has(e)?[{label:"Open in a new window",run:()=>this.detachSession(e)}]:[],{label:"Close session",className:"danger",run:()=>this.requestCloseSession(e)}];for(const s of h){if(s.note){const r=document.createElement("div");r.className="tab-rail-action-menu-note",r.setAttribute("role","none"),r.id="tabRailActionMenuNote",r.textContent=s.label,a.setAttribute("aria-describedby",r.id),a.appendChild(r);continue}const l=document.createElement("button");l.type="button",l.setAttribute("role","menuitem"),l.textContent=s.label,s.className&&(l.className=s.className),l.addEventListener("click",()=>{this.closeTabRailActionMenu(),s.run()}),a.appendChild(l)}document.body.appendChild(a);const o=i.getBoundingClientRect(),d=a.getBoundingClientRect();a.style.left=`${Math.max(8,Math.min(o.right-d.width,window.innerWidth-d.width-8))}px`,a.style.top=`${Math.max(8,Math.min(o.bottom+4,window.innerHeight-d.height-8))}px`,this._tabRailActionMenuTrigger=i,this._tabRailActionMenuOutside=s=>{!a.contains(s.target)&&s.target!==i&&this.closeTabRailActionMenu()},document.addEventListener("pointerdown",this._tabRailActionMenuOutside,!0),this._tabRailActionMenuViewport=()=>this.closeTabRailActionMenu(),window.addEventListener("resize",this._tabRailActionMenuViewport,{once:!0}),a.addEventListener("keydown",s=>{const l=[...a.querySelectorAll("button")],r=l.indexOf(document.activeElement);if(s.key==="Escape")s.preventDefault(),this.closeTabRailActionMenu({restoreFocus:!0});else if(s.key==="ArrowDown"||s.key==="ArrowUp"){s.preventDefault();const c=s.key==="ArrowDown"?1:-1;l[(r+c+l.length)%l.length]?.focus()}}),a.querySelector("button")?.focus()}});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -11,21 +11,29 @@
|
|
|
11
11
|
*
|
|
12
12
|
* Deliberately plainer than the primary pane (this.terminal/this._ws in
|
|
13
13
|
* terminal-ui.js): no local-echo overlay, no CJK IME textarea, no touch/mobile
|
|
14
|
-
* handlers (a swipe on a touch screen pages nothing), no keyboard
|
|
15
|
-
* bar
|
|
16
|
-
*
|
|
17
|
-
* docs/split-pane-sessions-plan.md and docs/tile-grid-plan.md.
|
|
14
|
+
* handlers (a swipe on a touch screen pages nothing), and no keyboard
|
|
15
|
+
* accessory bar. Built for wide screens; see docs/split-pane-sessions-plan.md
|
|
16
|
+
* and docs/tile-grid-plan.md.
|
|
18
17
|
*
|
|
19
18
|
* What it does carry over from the primary pane, through the primary pane's
|
|
20
19
|
* own code aimed at THIS pane (its terminal, its session, never the active
|
|
21
20
|
* one):
|
|
22
|
-
* -
|
|
23
|
-
*
|
|
24
|
-
* so the wheel
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
21
|
+
* - SGR wheel forwarding (_maybeForwardWheelToCli): Claude's fullscreen
|
|
22
|
+
* renderer scrolls its own transcript on SGR wheel reports, while this
|
|
23
|
+
* xterm holds only replayed repaint frames, so the wheel goes to the CLI
|
|
24
|
+
* as reports at the pointer's cell in this pane, through the primary
|
|
25
|
+
* pane's forwarding gate and its encoding (sgrWheelReports). Shift+wheel
|
|
26
|
+
* scrolls the local scrollback itself (_maybeScrollLocalOnShift), as the
|
|
27
|
+
* primary pane does, since xterm turns it into a horizontal no-op.
|
|
28
|
+
* - Hollow-buffer paging (#555): a CLI that draws in place (opencode and codex
|
|
29
|
+
* on the alternate screen, Claude's repaint mode) leaves the xterm no
|
|
30
|
+
* scrollback, so the wheel pages the CLI's own transcript with
|
|
31
|
+
* PageUp/PageDown (_maybePageCliTranscript) through the primary pane's gates
|
|
32
|
+
* and its pure gesture rules (CodemanTerminalInput.pageKeysForGesture), plus
|
|
33
|
+
* an overflow-row discount for this pane's capture-before-resize load
|
|
34
|
+
* (_localRows), only while the viewport is on the live screen (a wheel-down
|
|
35
|
+
* from those overflow rows is xterm's, and brings it home), and never while
|
|
36
|
+
* THIS pane's session has a dialog open.
|
|
29
37
|
* - The desktop click report: a plain left-click hand-encoded as SGR while
|
|
30
38
|
* the session's CLI has mouse tracking on (cliMouseTracking), for the modes
|
|
31
39
|
* whose mouse DECSETs the server strips (_installClickListener), sent
|
|
@@ -42,8 +50,8 @@
|
|
|
42
50
|
* Android tablet, or a large foldable unfolded in landscape, reaches.
|
|
43
51
|
*
|
|
44
52
|
* @dependency vendor/xterm.js, vendor/xterm-addon-fit.js
|
|
45
|
-
* @dependency constants.js (window.CodemanTerminalFont, window.CodemanFetchDeadline, DEFAULT_SCROLLBACK, TERMINAL_TAIL_SIZE, TERMINAL_CHUNK_SIZE)
|
|
46
|
-
* @dependency terminal-ui.js (codemanCurrentXtermTheme, codemanCurrentSkinIsLight, CodemanTerminalInput.shouldSuppressTerminalQueryResponse/isTerminalFocusOrMouseReport/wheelDeltaLines/
|
|
53
|
+
* @dependency constants.js (window.CodemanTerminalFont, window.CodemanFetchDeadline, DEFAULT_SCROLLBACK, TERMINAL_TAIL_SIZE, SHELL_LOAD_BASE_QUERY, SHELL_LOAD_QUERY, TERMINAL_CHUNK_SIZE)
|
|
54
|
+
* @dependency terminal-ui.js (codemanCurrentXtermTheme, codemanCurrentSkinIsLight, CodemanTerminalInput.shouldSuppressTerminalQueryResponse/isTerminalFocusOrMouseReport/wheelDeltaLines/wheelDeltaWholeLines/sgrWheelReports/pageKeysForGesture, app._shouldForwardWheelToApp/_localScrollbackIsHollow/_terminalViewportAtBottom/_clientPointToCell/_handleDesktopTerminalClick, app.tabAlerts)
|
|
47
55
|
* @dependency terminal-keycode229-recovery.js (window.CodemanKeyCode229Recovery, optional: absent, xterm's own textarea handling stands)
|
|
48
56
|
* @loadorder 7.4 of 16, loaded after terminal-ui.js and before terminal-split.js
|
|
49
57
|
*/
|
|
@@ -198,9 +206,13 @@
|
|
|
198
206
|
// flag, app._linkHovered, belongs to its terminal alone).
|
|
199
207
|
this._linkHovered = false;
|
|
200
208
|
this._onFocusIn = null;
|
|
201
|
-
// Hollow-buffer paging (_maybePageCliTranscript):
|
|
202
|
-
// whole page,
|
|
203
|
-
|
|
209
|
+
// Hollow-buffer paging (_maybePageCliTranscript): the gesture in progress
|
|
210
|
+
// (travel short of a whole page, its direction and last event time), the
|
|
211
|
+
// state CodemanTerminalInput.pageKeysForGesture hands back.
|
|
212
|
+
this._pageKeyGesture = null;
|
|
213
|
+
// Shift+wheel travel short of a whole line, carried to the next wheel
|
|
214
|
+
// event (_maybeScrollLocalOnShift).
|
|
215
|
+
this._shiftScrollPending = 0;
|
|
204
216
|
// Page keys waiting for the 40 ms flush, and its timer (_queueScrollBytes).
|
|
205
217
|
this._scrollBytes = '';
|
|
206
218
|
this._scrollFlushTimer = null;
|
|
@@ -234,6 +246,9 @@
|
|
|
234
246
|
|
|
235
247
|
this.fitAddon = new FitAddon.FitAddon();
|
|
236
248
|
this.terminal.loadAddon(this.fitAddon);
|
|
249
|
+
// OSC 52 clipboard writes from this pane's PTY, gated on THIS pane's
|
|
250
|
+
// buffer load so a replay never re-copies (terminal-ui.js).
|
|
251
|
+
global.app?._installOsc52Clipboard?.(this.terminal, () => this._bufferLoading);
|
|
237
252
|
this.terminal.open(this.mountEl);
|
|
238
253
|
this.fitAddon.fit();
|
|
239
254
|
|
|
@@ -761,8 +776,15 @@
|
|
|
761
776
|
try {
|
|
762
777
|
if (this._destroyed) return;
|
|
763
778
|
const shell = this.sessionMode === 'shell';
|
|
764
|
-
|
|
765
|
-
|
|
779
|
+
// A shell loads tmux's rendered history, bounded (SHELL_LOAD_QUERY,
|
|
780
|
+
// constants.js), never the raw byte recording; a grid tile bounds it
|
|
781
|
+
// by its own scrollback instead.
|
|
782
|
+
let query = shell ? SHELL_LOAD_QUERY : 'full=1';
|
|
783
|
+
if (this.boundedLoad) {
|
|
784
|
+
query = shell
|
|
785
|
+
? `${SHELL_LOAD_BASE_QUERY}${this._historyLinesQuery()}`
|
|
786
|
+
: `full=1&tail=${TERMINAL_TAIL_SIZE}${this._historyLinesQuery()}`;
|
|
787
|
+
}
|
|
766
788
|
this._loadAbort = controller;
|
|
767
789
|
armDeadline(global.CodemanFetchDeadline?.terminalFetchDeadlineMs?.({ full: !shell }) ?? 45000);
|
|
768
790
|
let payload;
|
|
@@ -1027,16 +1049,18 @@
|
|
|
1027
1049
|
|
|
1028
1050
|
// Capture phase, because xterm's own wheel handler stopPropagation()s every
|
|
1029
1051
|
// event it consumes, so a bubbling listener here would never see the wheel
|
|
1030
|
-
// while the pane still has scrollback to scroll. Not passive: the
|
|
1031
|
-
// this pane takes over,
|
|
1032
|
-
// (
|
|
1052
|
+
// while the pane still has scrollback to scroll. Not passive: the three
|
|
1053
|
+
// routes this pane takes over, forwarding the wheel to Claude's fullscreen
|
|
1054
|
+
// renderer (_maybeForwardWheelToCli), paging a hollow buffer's CLI
|
|
1055
|
+
// transcript (_maybePageCliTranscript) and Shift+wheel's local scrollback
|
|
1056
|
+
// (_maybeScrollLocalOnShift), are consumed right here (preventDefault plus
|
|
1033
1057
|
// stopPropagation in the capture phase, the primary pane's technique), so
|
|
1034
|
-
// xterm's viewport, a descendant, never sees
|
|
1058
|
+
// xterm's viewport, a descendant, never sees them. Every other wheel is left
|
|
1035
1059
|
// to xterm, which keeps doing the scrolling, and only observed for the
|
|
1036
1060
|
// shell history pull.
|
|
1037
1061
|
_installWheelListener() {
|
|
1038
1062
|
this._onWheel = (ev) => {
|
|
1039
|
-
if (this._maybePageCliTranscript(ev)) {
|
|
1063
|
+
if (this._maybeForwardWheelToCli(ev) || this._maybePageCliTranscript(ev) || this._maybeScrollLocalOnShift(ev)) {
|
|
1040
1064
|
ev.preventDefault();
|
|
1041
1065
|
ev.stopPropagation();
|
|
1042
1066
|
return;
|
|
@@ -1046,6 +1070,71 @@
|
|
|
1046
1070
|
this.mountEl.addEventListener('wheel', this._onWheel, { capture: true, passive: false });
|
|
1047
1071
|
}
|
|
1048
1072
|
|
|
1073
|
+
// SGR wheel forwarding, the twin of the primary pane's capture-phase wheel
|
|
1074
|
+
// handler and _forwardScrollToApp (terminal-ui.js; keep them in step).
|
|
1075
|
+
// Claude's fullscreen renderer (claude 2.1.187+ while its mouse tracking is
|
|
1076
|
+
// on, cliMouseTracking) scrolls its own transcript on SGR wheel reports,
|
|
1077
|
+
// while this xterm holds only Codeman's replayed repaint frames (tmux keeps
|
|
1078
|
+
// no history for such a pane). Left to xterm, the wheel dragged those stale
|
|
1079
|
+
// frames, Claude's pinned input box with them, up the tile, or scrolled
|
|
1080
|
+
// nothing at all. The gate is the primary pane's own, asked for THIS pane
|
|
1081
|
+
// (its terminal, its session, never the active one), so the CLI rules stay
|
|
1082
|
+
// in terminal-ui.js and this file names no CLI; the reports go to this
|
|
1083
|
+
// pane's session through its own coalescer. Returns true when the wheel
|
|
1084
|
+
// belongs to the CLI: a gesture with no whole line or no measurable cell is
|
|
1085
|
+
// consumed too, as in the primary pane, so xterm never scrolls the stale
|
|
1086
|
+
// frames under a forwarding session. Shift fails the gate, so Shift+wheel
|
|
1087
|
+
// still scrolls the local scrollback (_maybeScrollLocalOnShift).
|
|
1088
|
+
_maybeForwardWheelToCli(ev) {
|
|
1089
|
+
if (this._destroyed || !this.terminal || !ev) return false;
|
|
1090
|
+
const app = global.app;
|
|
1091
|
+
const input = global.CodemanTerminalInput;
|
|
1092
|
+
if (!app?._shouldForwardWheelToApp || !input?.sgrWheelReports || !input.wheelDeltaWholeLines) return false;
|
|
1093
|
+
// xterm's own encoder forwards the wheel while the CLI's tracking reaches
|
|
1094
|
+
// it, and its alt-scroll owns the alternate buffer, as in the primary pane.
|
|
1095
|
+
const tracking = this.terminal.modes?.mouseTrackingMode;
|
|
1096
|
+
if (tracking && tracking !== 'none') return false;
|
|
1097
|
+
if (this.terminal.buffer?.active?.type === 'alternate') return false;
|
|
1098
|
+
if (!app._shouldForwardWheelToApp(ev, { terminal: this.terminal, sessionId: this.sessionId })) return false;
|
|
1099
|
+
// SGR coordinates address the live screen, so a report from a scrolled-up
|
|
1100
|
+
// viewport would hit-test another row: snap home first (_forwardScrollToApp).
|
|
1101
|
+
if (!app._terminalViewportAtBottom?.(this.terminal)) this.terminal.scrollToBottom?.();
|
|
1102
|
+
const lines = input.wheelDeltaWholeLines(ev, this.terminal.rows);
|
|
1103
|
+
const pos = app._clientPointToCell?.(ev.clientX, ev.clientY, this.terminal);
|
|
1104
|
+
const bytes = input.sgrWheelReports(lines, pos);
|
|
1105
|
+
if (bytes) this._queueScrollBytes(bytes);
|
|
1106
|
+
return true;
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
// Shift+wheel scrolls this xterm's local scrollback, the explicit "local
|
|
1110
|
+
// history" gesture, here as in the primary pane (whose capture-phase wheel
|
|
1111
|
+
// handler scrolls with terminal.scrollLines() for the same reason). Left to
|
|
1112
|
+
// xterm it was dead off macOS: Chrome on Windows sends Shift+wheel as a
|
|
1113
|
+
// HORIZONTAL wheel (deltaX), and xterm's own scroller turns a Shift+vertical
|
|
1114
|
+
// wheel into a horizontal one, so the viewport never moved. Reads the
|
|
1115
|
+
// dominant axis under Shift (wheelDeltaLines), keeps the sub-line remainder
|
|
1116
|
+
// for the next event (a trackpad's small deltas), and on the way up still
|
|
1117
|
+
// asks a shell pane for more history. Returns true when the wheel was
|
|
1118
|
+
// consumed here.
|
|
1119
|
+
_maybeScrollLocalOnShift(ev) {
|
|
1120
|
+
if (this._destroyed || !this.terminal || !ev?.shiftKey) return false;
|
|
1121
|
+
const input = global.CodemanTerminalInput;
|
|
1122
|
+
if (!input?.wheelDeltaLines) return false;
|
|
1123
|
+
// xterm's own encoder forwards the wheel while the CLI's tracking reaches
|
|
1124
|
+
// it, and its alt-scroll owns the alternate buffer, as in the primary pane.
|
|
1125
|
+
const tracking = this.terminal.modes?.mouseTrackingMode;
|
|
1126
|
+
if (tracking && tracking !== 'none') return false;
|
|
1127
|
+
if (this.terminal.buffer?.active?.type === 'alternate') return false;
|
|
1128
|
+
const total = this._shiftScrollPending + input.wheelDeltaLines(ev, this.terminal.rows);
|
|
1129
|
+
const lines = Math.trunc(total);
|
|
1130
|
+
this._shiftScrollPending = total - lines;
|
|
1131
|
+
if (lines) {
|
|
1132
|
+
this.terminal.scrollLines(lines);
|
|
1133
|
+
if (lines < 0) this._maybeLoadMoreHistory();
|
|
1134
|
+
}
|
|
1135
|
+
return true;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1049
1138
|
// A plain left-click reported to the CLI, the primary pane's desktop click
|
|
1050
1139
|
// (terminal-ui.js _handleDesktopTerminalClick) aimed at this pane. The
|
|
1051
1140
|
// server strips the mouse DECSETs of some modes (opencode's since #555, so a
|
|
@@ -1071,25 +1160,28 @@
|
|
|
1071
1160
|
|
|
1072
1161
|
// Hollow-buffer paging, the twin of the primary pane's
|
|
1073
1162
|
// _maybePageCliTranscript (terminal-ui.js; keep the two in step). A CLI that
|
|
1074
|
-
// draws in place (
|
|
1075
|
-
//
|
|
1076
|
-
//
|
|
1077
|
-
//
|
|
1078
|
-
//
|
|
1079
|
-
//
|
|
1163
|
+
// draws in place (on the alternate screen, or Claude's repaint mode) leaves
|
|
1164
|
+
// this xterm no scrollback, so a wheel scrolled nothing; instead the travel
|
|
1165
|
+
// pages the CLI's own transcript with PageUp/PageDown. Every gate is the
|
|
1166
|
+
// primary pane's own, asked for THIS pane (its terminal, its session, never
|
|
1167
|
+
// the active one), so the CLI rules stay in terminal-ui.js and this file
|
|
1168
|
+
// names no CLI. The gesture rules (first-event page, notch accumulation,
|
|
1169
|
+
// pinch and sideways-swipe consume) are the shared pure
|
|
1170
|
+
// CodemanTerminalInput.pageKeysForGesture, run on this tile's own state.
|
|
1171
|
+
// Returns true when the wheel was consumed here.
|
|
1080
1172
|
_maybePageCliTranscript(ev) {
|
|
1081
1173
|
if (this._destroyed || !this.terminal || !ev || ev.shiftKey) return false;
|
|
1082
1174
|
const app = global.app;
|
|
1083
1175
|
const input = global.CodemanTerminalInput;
|
|
1084
|
-
if (!app || !input?.
|
|
1176
|
+
if (!app || !input?.pageKeysForGesture || !input.wheelDeltaLines) return false;
|
|
1085
1177
|
// xterm's own encoder forwards the wheel while the CLI's tracking reaches
|
|
1086
1178
|
// it (a shell running htop), as in the primary pane.
|
|
1087
1179
|
const tracking = this.terminal.modes?.mouseTrackingMode;
|
|
1088
1180
|
if (tracking && tracking !== 'none') return false;
|
|
1089
1181
|
const target = { terminal: this.terminal, sessionId: this.sessionId };
|
|
1090
|
-
//
|
|
1091
|
-
//
|
|
1092
|
-
//
|
|
1182
|
+
// A wheel for Claude's fullscreen renderer was forwarded as SGR reports
|
|
1183
|
+
// before this ran (_maybeForwardWheelToCli); the gate is repeated so a
|
|
1184
|
+
// forwarding session is never paged.
|
|
1093
1185
|
if (app._shouldForwardWheelToApp?.(ev, target)) return false;
|
|
1094
1186
|
if (!app._localScrollbackIsHollow?.({ ...target, localRows: this._localRows() })) return false;
|
|
1095
1187
|
// Only from the live screen. The one gate the primary pane never needs: a
|
|
@@ -1105,14 +1197,19 @@
|
|
|
1105
1197
|
if (!app._terminalViewportAtBottom?.(this.terminal)) return false;
|
|
1106
1198
|
const lines = input.wheelDeltaLines(ev, this.terminal.rows);
|
|
1107
1199
|
if (!lines) return false;
|
|
1108
|
-
|
|
1109
|
-
|
|
1200
|
+
// An open dialog (a pending permission prompt or question) in THIS tile's
|
|
1201
|
+
// session, which is usually not the active one: a page key would move its
|
|
1202
|
+
// selector. Consumed, so xterm does not scroll the rows under it either.
|
|
1203
|
+
if (app.tabAlerts?.get(this.sessionId) === 'action') return true;
|
|
1204
|
+
const step = input.pageKeysForGesture(this._pageKeyGesture, ev, lines, this.terminal.rows, performance.now());
|
|
1205
|
+
this._pageKeyGesture = step.state;
|
|
1110
1206
|
if (step.keys) this._queueScrollBytes(step.keys);
|
|
1111
1207
|
return true;
|
|
1112
1208
|
}
|
|
1113
1209
|
|
|
1114
|
-
// Coalesces the
|
|
1115
|
-
//
|
|
1210
|
+
// Coalesces the scroll bytes (SGR wheel reports and page keys alike) into
|
|
1211
|
+
// one send per 40 ms, bounded at 512 bytes so a fling cannot build a backlog
|
|
1212
|
+
// that keeps scrolling after it stops. A narrow
|
|
1116
1213
|
// twin of the primary pane's _queueScrollBytes / _flushWheelSgrQueue
|
|
1117
1214
|
// (terminal-ui.js; keep the two in step), which flushes to the active
|
|
1118
1215
|
// session only. Sent ephemeral (no seq, never persisted) to THIS pane's
|
|
@@ -1459,7 +1556,7 @@
|
|
|
1459
1556
|
clearTimeout(this._scrollFlushTimer);
|
|
1460
1557
|
this._scrollFlushTimer = null;
|
|
1461
1558
|
this._scrollBytes = '';
|
|
1462
|
-
this.
|
|
1559
|
+
this._pageKeyGesture = null;
|
|
1463
1560
|
this._detachSocket();
|
|
1464
1561
|
if (this._onFocusIn) {
|
|
1465
1562
|
this.terminal?.textarea?.removeEventListener('focus', this._onFocusIn);
|
|
Binary file
|
|
Binary file
|