aicodeman 1.35.0 → 1.41.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 +33 -7
- package/dist/attachment-registry.d.ts +6 -0
- package/dist/attachment-registry.d.ts.map +1 -1
- package/dist/attachment-registry.js +9 -3
- package/dist/attachment-registry.js.map +1 -1
- package/dist/cli-agent.d.ts +225 -0
- package/dist/cli-agent.d.ts.map +1 -0
- package/dist/cli-agent.js +767 -0
- package/dist/cli-agent.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +8 -32
- 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/cli-registry/patterns.d.ts +6 -0
- package/dist/config/cli-registry/patterns.d.ts.map +1 -1
- package/dist/config/cli-registry/patterns.js +13 -0
- package/dist/config/cli-registry/patterns.js.map +1 -1
- package/dist/config/cli-registry/schema.d.ts +15 -0
- package/dist/config/cli-registry/schema.d.ts.map +1 -1
- package/dist/config/cli-registry/schema.js +63 -2
- 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 +180 -7
- package/dist/config/cli-registry/stock.js.map +1 -1
- package/dist/config/cli-registry/types.d.ts +105 -7
- package/dist/config/cli-registry/types.d.ts.map +1 -1
- package/dist/deepseek-route-config.d.ts +110 -0
- package/dist/deepseek-route-config.d.ts.map +1 -0
- package/dist/deepseek-route-config.js +477 -0
- package/dist/deepseek-route-config.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/git-workspace-status.d.ts +31 -5
- package/dist/git-workspace-status.d.ts.map +1 -1
- package/dist/git-workspace-status.js +49 -29
- package/dist/git-workspace-status.js.map +1 -1
- 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-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 +2 -1
- package/dist/mcp-sync.d.ts.map +1 -1
- package/dist/mcp-sync.js +62 -1
- package/dist/mcp-sync.js.map +1 -1
- package/dist/model-config-resolvers.d.ts +29 -0
- package/dist/model-config-resolvers.d.ts.map +1 -0
- package/dist/model-config-resolvers.js +34 -0
- package/dist/model-config-resolvers.js.map +1 -0
- package/dist/session-display-model.d.ts +110 -0
- package/dist/session-display-model.d.ts.map +1 -0
- package/dist/session-display-model.js +154 -0
- package/dist/session-display-model.js.map +1 -0
- package/dist/session.d.ts +145 -8
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +290 -39
- 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/templates/case-template.md +2 -0
- package/dist/tmux-manager.d.ts +5 -0
- package/dist/tmux-manager.d.ts.map +1 -1
- package/dist/tmux-manager.js +47 -22
- 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 +28 -1
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js.map +1 -1
- package/dist/types/tools.d.ts +1 -1
- package/dist/types/tools.d.ts.map +1 -1
- package/dist/utils/deepseek-cli-resolver.d.ts +8 -0
- package/dist/utils/deepseek-cli-resolver.d.ts.map +1 -1
- package/dist/utils/deepseek-cli-resolver.js +18 -2
- package/dist/utils/deepseek-cli-resolver.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/launch-defaults.d.ts +22 -0
- package/dist/web/launch-defaults.d.ts.map +1 -0
- package/dist/web/launch-defaults.js +46 -0
- package/dist/web/launch-defaults.js.map +1 -0
- 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/public/admin-ui.js.gz +0 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/app.6f8552e1.js +43 -0
- package/dist/web/public/app.6f8552e1.js.br +0 -0
- package/dist/web/public/app.6f8552e1.js.gz +0 -0
- package/dist/web/public/approvals-ui.js.gz +0 -0
- package/dist/web/public/{constants.d95fade9.js → constants.bc9c1f63.js} +1276 -127
- package/dist/web/public/constants.bc9c1f63.js.br +0 -0
- package/dist/web/public/constants.bc9c1f63.js.gz +0 -0
- package/dist/web/public/cron-ui.js.gz +0 -0
- package/dist/web/public/entrance-animations.js +491 -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/git-status-ui.js +55 -9
- package/dist/web/public/git-status-ui.js.br +0 -0
- package/dist/web/public/git-status-ui.js.gz +0 -0
- package/dist/web/public/home-sessions.js +13 -9
- 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.a9840ea2.js +2 -0
- package/dist/web/public/i18n.a9840ea2.js.br +0 -0
- package/dist/web/public/i18n.a9840ea2.js.gz +0 -0
- package/dist/web/public/{image-input.a216cf9e.js → image-input.e00471c6.js} +21 -9
- package/dist/web/public/image-input.e00471c6.js.br +0 -0
- package/dist/web/public/image-input.e00471c6.js.gz +0 -0
- package/dist/web/public/index.html +250 -59
- 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.gz +0 -0
- package/dist/web/public/{mobile-handlers.23a85db1.js → mobile-handlers.0ef9c311.js} +20 -0
- package/dist/web/public/mobile-handlers.0ef9c311.js.br +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.gz +0 -0
- package/dist/web/public/mobile.111b187d.css +1 -0
- 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 → 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.6a5898d9.js → panels-ui.71846fcb.js} +4 -4
- package/dist/web/public/panels-ui.71846fcb.js.br +0 -0
- package/dist/web/public/panels-ui.71846fcb.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 +229 -86
- package/dist/web/public/session-lineage.js.br +0 -0
- package/dist/web/public/session-lineage.js.gz +0 -0
- package/dist/web/public/session-ui.f731602c.js +100 -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.4e33390f.js +97 -0
- package/dist/web/public/settings-ui.4e33390f.js.br +0 -0
- package/dist/web/public/settings-ui.4e33390f.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview-worker.js +290 -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 +555 -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/spreadsheet-xlsx-core.js +1006 -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.81a72906.css +1 -0
- package/dist/web/public/styles.81a72906.css.br +0 -0
- package/dist/web/public/styles.81a72906.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 +2 -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.065fcba4.js.gz +0 -0
- package/dist/web/public/{tab-rail-resize.94cd59f0.js → tab-rail-resize.a5867793.js} +1 -1
- package/dist/web/public/tab-rail-resize.a5867793.js.br +0 -0
- package/dist/web/public/{tab-rail-resize.94cd59f0.js.gz → tab-rail-resize.a5867793.js.gz} +0 -0
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js +1 -0
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.br +0 -0
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js.gz +0 -0
- package/dist/web/public/terminal-split.js +146 -649
- package/dist/web/public/terminal-split.js.br +0 -0
- package/dist/web/public/terminal-split.js.gz +0 -0
- package/dist/web/public/terminal-tile.js +1688 -0
- 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.b7267005.js +2 -0
- package/dist/web/public/terminal-ui.b7267005.js.br +0 -0
- package/dist/web/public/terminal-ui.b7267005.js.gz +0 -0
- package/dist/web/public/tile-grid.js +2895 -0
- 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 +44 -0
- package/dist/web/public/vendor/exceljs.min.js.br +0 -0
- package/dist/web/public/vendor/exceljs.min.js.gz +0 -0
- package/dist/web/public/vendor/fflate.min.js +1 -0
- package/dist/web/public/vendor/fflate.min.js.br +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.c4b51eb6.js → voice-input.2342c37b.js} +64 -10
- package/dist/web/public/voice-input.2342c37b.js.br +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 +9 -1
- package/dist/web/public/webview-tabs.js.br +0 -0
- package/dist/web/public/webview-tabs.js.gz +0 -0
- 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 +95 -8
- package/dist/web/routes/cli-registry-routes.js.map +1 -1
- package/dist/web/routes/file-routes.d.ts +7 -0
- package/dist/web/routes/file-routes.d.ts.map +1 -1
- package/dist/web/routes/file-routes.js +34 -4
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/routes/git-status-routes.d.ts.map +1 -1
- package/dist/web/routes/git-status-routes.js +33 -6
- package/dist/web/routes/git-status-routes.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 +1 -1
- package/dist/web/routes/reboot-restore-routes.js.map +1 -1
- package/dist/web/routes/session-routes.d.ts +18 -0
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +154 -69
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/routes/status-telemetry-routes.d.ts +3 -0
- package/dist/web/routes/status-telemetry-routes.d.ts.map +1 -1
- package/dist/web/routes/status-telemetry-routes.js +12 -0
- package/dist/web/routes/status-telemetry-routes.js.map +1 -1
- package/dist/web/routes/system-routes.d.ts.map +1 -1
- package/dist/web/routes/system-routes.js +13 -0
- package/dist/web/routes/system-routes.js.map +1 -1
- package/dist/web/schemas.d.ts +30 -0
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +43 -0
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/server.d.ts +6 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +47 -21
- package/dist/web/server.js.map +1 -1
- package/dist/web/session-listener-wiring.d.ts +1 -0
- package/dist/web/session-listener-wiring.d.ts.map +1 -1
- package/dist/web/session-listener-wiring.js +11 -0
- package/dist/web/session-listener-wiring.js.map +1 -1
- package/package.json +6 -4
- package/scripts/postinstall.js +16 -0
- package/skills/codeman/SKILL.md +6 -0
- package/README.zh-CN.md +0 -1139
- package/dist/web/public/app.b9516c7b.js +0 -43
- package/dist/web/public/app.b9516c7b.js.br +0 -0
- package/dist/web/public/app.b9516c7b.js.gz +0 -0
- package/dist/web/public/constants.d95fade9.js.br +0 -0
- package/dist/web/public/constants.d95fade9.js.gz +0 -0
- package/dist/web/public/i18n.52f5b7cc.js +0 -1
- package/dist/web/public/i18n.52f5b7cc.js.br +0 -0
- package/dist/web/public/i18n.52f5b7cc.js.gz +0 -0
- package/dist/web/public/image-input.a216cf9e.js.br +0 -0
- package/dist/web/public/image-input.a216cf9e.js.gz +0 -0
- package/dist/web/public/mobile-handlers.23a85db1.js.br +0 -0
- package/dist/web/public/mobile-handlers.23a85db1.js.gz +0 -0
- package/dist/web/public/mobile.1aa4952d.css +0 -1
- package/dist/web/public/mobile.1aa4952d.css.br +0 -0
- package/dist/web/public/mobile.1aa4952d.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.6a5898d9.js.br +0 -0
- package/dist/web/public/panels-ui.6a5898d9.js.gz +0 -0
- package/dist/web/public/session-ui.6bddf916.js +0 -89
- package/dist/web/public/session-ui.6bddf916.js.br +0 -0
- package/dist/web/public/session-ui.6bddf916.js.gz +0 -0
- package/dist/web/public/settings-ui.6e798b7b.js +0 -97
- package/dist/web/public/settings-ui.6e798b7b.js.br +0 -0
- package/dist/web/public/settings-ui.6e798b7b.js.gz +0 -0
- package/dist/web/public/styles.2d175c60.css +0 -1
- package/dist/web/public/styles.2d175c60.css.br +0 -0
- package/dist/web/public/styles.2d175c60.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-rail-resize.94cd59f0.js.br +0 -0
- package/dist/web/public/terminal-keycode229-recovery.fb91b25b.js +0 -1
- package/dist/web/public/terminal-keycode229-recovery.fb91b25b.js.br +0 -0
- package/dist/web/public/terminal-keycode229-recovery.fb91b25b.js.gz +0 -0
- package/dist/web/public/terminal-ui.a4535311.js +0 -2
- package/dist/web/public/terminal-ui.a4535311.js.br +0 -0
- package/dist/web/public/terminal-ui.a4535311.js.gz +0 -0
- package/dist/web/public/upload.html +0 -155
- package/dist/web/public/upload.html.br +0 -0
- package/dist/web/public/upload.html.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
- package/dist/web/public/voice-input.c4b51eb6.js.br +0 -0
- package/dist/web/public/voice-input.c4b51eb6.js.gz +0 -0
|
@@ -1,29 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview Session lineage lines
|
|
2
|
+
* @fileoverview Session lineage lines: the tree joining a tab to the tabs it spawned.
|
|
3
3
|
*
|
|
4
4
|
* A session that starts another session (the `codeman` agent skill spawning a worker,
|
|
5
5
|
* which passes its own `$CODEMAN_SESSION_ID`) gets `parentSessionId` stamped on its
|
|
6
|
-
* state server-side. This module turns that field into
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* state server-side. This module turns that field into a quiet orthogonal tree, one per
|
|
7
|
+
* spawning tab, routed through the gaps between tab rows so it never crosses a label or
|
|
8
|
+
* the terminal (geometry: `CodemanLineage.computeTree` in constants.js).
|
|
9
|
+
*
|
|
10
|
+
* EVERY FAMILY IS ALWAYS DRAWN, AND THE SELECTED TAB'S IS EMPHASIZED: the family the
|
|
11
|
+
* active tab spawned, and the family it belongs to as a child, get the
|
|
12
|
+
* `lineage-family--focus` group (thicker, full opacity, drawn last so nothing covers
|
|
13
|
+
* it). Drawing ONLY the selected family was tried first and rejected by the owner
|
|
14
|
+
* (2026-10-07: "I wanna see all the connections always"). Selection still has to
|
|
15
|
+
* redraw to move the emphasis, which `_updateActiveTabImmediate()` does whenever any
|
|
16
|
+
* lineage exists (`_lineageTotalEdges`).
|
|
9
17
|
*
|
|
10
18
|
* It is an ADDITIONAL LAYER on the existing SVG pass, not a second pass: the core
|
|
11
19
|
* `_updateConnectionLinesImmediate()` (subagent-windows.js) calls
|
|
12
20
|
* `_appendLineageConnectionLines(svg, rects)` at its tail, exactly like ultracode does,
|
|
13
21
|
* so every layer shares ONE batched read → write reflow and one tab-rect cache.
|
|
14
22
|
*
|
|
15
|
-
*
|
|
16
|
-
* - DESKTOP ONLY. The overlay is `z-index: 999`; the desktop header is 100 (
|
|
23
|
+
* Constraints that are not obvious from the code:
|
|
24
|
+
* - DESKTOP ONLY. The overlay is `z-index: 999`; the desktop header is 100 (lines paint
|
|
17
25
|
* over it, which is what lets them touch tab bottoms), but under 1024px mobile.css
|
|
18
26
|
* makes the header `position: fixed; z-index: 1200` and would bury them. The phone
|
|
19
27
|
* strip is also a scroller where both endpoints are rarely on screen at once.
|
|
28
|
+
* - The routing room is RESERVED in CSS (`.session-tabs.lineage-tree`), toggled by
|
|
29
|
+
* `_syncLineageGutter()` from `updateTabOverflowMode()`. It keys on whether ANY
|
|
30
|
+
* family exists, never on the selection, so switching tabs never resizes the header
|
|
31
|
+
* (and with it the terminal and the PTY).
|
|
20
32
|
* - Paths carry `data-agent-id="lineage:<childId>"` because that is the attribute
|
|
21
33
|
* `_applyLineEntrances()` queries, so the draw-in animation and its
|
|
22
34
|
* negative-`animation-delay` resume across `svg.innerHTML = ''` come for free.
|
|
23
35
|
*
|
|
24
36
|
* @mixin Extends CodemanApp.prototype via Object.assign
|
|
25
37
|
* @dependency subagent-windows.js (_updateConnectionLinesImmediate, #connectionLines)
|
|
26
|
-
* @dependency constants.js (window.CodemanLineage.
|
|
38
|
+
* @dependency constants.js (window.CodemanLineage.computeTree + .COLORS)
|
|
27
39
|
* @dependency settings-ui.js (loadAppSettingsFromStorage, getDefaultSettings)
|
|
28
40
|
* @loadorder 15.6 (after ultracode-windows.js — appended to the same SVG pass)
|
|
29
41
|
*/
|
|
@@ -62,49 +74,99 @@ Object.assign(CodemanApp.prototype, {
|
|
|
62
74
|
applyLineageLineSettings() {
|
|
63
75
|
const prev = this._lineageLinesOn;
|
|
64
76
|
const next = this._syncLineageLinesEnabled();
|
|
65
|
-
if (prev !== next)
|
|
77
|
+
if (prev !== next) {
|
|
78
|
+
// The reserved routing room follows the setting; updateTabOverflowMode()
|
|
79
|
+
// re-syncs it and re-measures the wrap with the new padding.
|
|
80
|
+
this.updateTabOverflowMode?.();
|
|
81
|
+
this.updateConnectionLines();
|
|
82
|
+
}
|
|
66
83
|
},
|
|
67
84
|
|
|
68
85
|
/**
|
|
69
|
-
*
|
|
70
|
-
*
|
|
86
|
+
* Reserve (or release) the strip's routing room: `.lineage-tree` on #sessionTabs
|
|
87
|
+
* widens the row gap, pads the bottom for the last row's gap, and opens the spine
|
|
88
|
+
* channel on the left of a wrapped strip (styles.css). Called at the top of
|
|
89
|
+
* `updateTabOverflowMode()`, so it runs on every tab render, BEFORE the wrap is
|
|
90
|
+
* measured.
|
|
91
|
+
*
|
|
92
|
+
* Keyed on whether any family exists at all, never on which one is selected: a
|
|
93
|
+
* class that followed the selection would grow and shrink the header on every tab
|
|
94
|
+
* switch, and the header's height is the terminal's height.
|
|
71
95
|
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
96
|
+
* Only the header strip routes through reserved gaps. The vertical rail keeps its
|
|
97
|
+
* own `--lineage-vertical-gutter`, and the sidebar draws no lineage.
|
|
98
|
+
*/
|
|
99
|
+
_syncLineageGutter() {
|
|
100
|
+
const edges = this._lineageLinesEnabled() ? this._collectLineageEdges() : [];
|
|
101
|
+
this._lineageTotalEdges = edges.length;
|
|
102
|
+
const strip = document.getElementById('sessionTabs');
|
|
103
|
+
if (!strip) return;
|
|
104
|
+
const want = edges.length > 0 && !this._isVerticalTabList?.();
|
|
105
|
+
if (strip.classList.contains('lineage-tree') !== want) strip.classList.toggle('lineage-tree', want);
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Every parent → child pair, in strip order. Walks `sessionOrder` rather than the
|
|
110
|
+
* sessions Map so sibling order follows the strip's own left-to-right order, which
|
|
111
|
+
* is what the user sees.
|
|
74
112
|
*/
|
|
75
113
|
_collectLineageEdges() {
|
|
76
114
|
const edges = [];
|
|
77
115
|
if (!this.sessions || this.sessions.size < 2) return edges;
|
|
78
116
|
const order = this.sessionOrder && this.sessionOrder.length ? this.sessionOrder : [...this.sessions.keys()];
|
|
79
|
-
const seenPerParent = new Map();
|
|
80
117
|
for (const id of order) {
|
|
81
118
|
const session = this.sessions.get(id);
|
|
82
119
|
const parentId = session && session.parentSessionId;
|
|
83
120
|
// A parent that is gone (closed, or never came back after a restart) draws
|
|
84
121
|
// nothing: the field is decoration, so a dangling one is simply not rendered.
|
|
85
122
|
if (!parentId || parentId === id || !this.sessions.has(parentId)) continue;
|
|
86
|
-
|
|
87
|
-
seenPerParent.set(parentId, depth + 1);
|
|
88
|
-
edges.push({ parentId, childId: id, depth, status: session.status || 'idle' });
|
|
123
|
+
edges.push({ parentId, childId: id, status: session.status || 'idle' });
|
|
89
124
|
}
|
|
90
125
|
return edges;
|
|
91
126
|
},
|
|
92
127
|
|
|
128
|
+
/** Every family as `{ parentId, edges }`, in strip order of first appearance. */
|
|
129
|
+
_lineageFamilies(edges) {
|
|
130
|
+
const families = new Map();
|
|
131
|
+
for (const edge of edges) {
|
|
132
|
+
if (!families.has(edge.parentId)) families.set(edge.parentId, []);
|
|
133
|
+
families.get(edge.parentId).push(edge);
|
|
134
|
+
}
|
|
135
|
+
return [...families].map(([parentId, familyEdges]) => ({ parentId, edges: familyEdges }));
|
|
136
|
+
},
|
|
137
|
+
|
|
93
138
|
/**
|
|
94
|
-
*
|
|
139
|
+
* Parent ids of the families the selection emphasizes: the family the selected tab
|
|
140
|
+
* spawned, and the family it was spawned into (its parent plus its siblings). Empty
|
|
141
|
+
* when a web tab holds the stage, or the selected tab has no lineage at all.
|
|
142
|
+
*/
|
|
143
|
+
_lineageFocusParents(edges) {
|
|
144
|
+
const parents = new Set();
|
|
145
|
+
const focus = this.activeWebviewId ? null : this.activeSessionId;
|
|
146
|
+
if (!focus) return parents;
|
|
147
|
+
for (const edge of edges) {
|
|
148
|
+
if (edge.parentId === focus || edge.childId === focus) parents.add(edge.parentId);
|
|
149
|
+
}
|
|
150
|
+
return parents;
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Colour for one family, from CodemanLineage.COLORS, keyed on the SPAWNING tab.
|
|
95
155
|
*
|
|
96
|
-
*
|
|
156
|
+
* ⚠ Per PARENT, not per child: every line leaving one tab is the same colour, no
|
|
97
157
|
* matter how many workers it spawns, so the strip reads as "these five came from
|
|
98
158
|
* w1, those two came from w2". Keying it per child instead gave one tab's own
|
|
99
159
|
* children a different colour each, which is the thing the colours exist to tell
|
|
100
160
|
* apart. A child that goes on to spawn its own workers is a parent in its turn and
|
|
101
|
-
* gets its own colour for the
|
|
161
|
+
* gets its own colour for the lines BELOW it, so a chain changes colour at each
|
|
102
162
|
* generation while each generation's fan-out stays uniform.
|
|
103
163
|
*
|
|
104
164
|
* Assigned in FIRST-SEEN order and remembered per parent id. First-seen rather than
|
|
105
165
|
* draw-index keeps a colour stable across re-renders, tab reorders and sibling
|
|
106
166
|
* closes (the SVG is wiped and rebuilt constantly, so an index-based colour would
|
|
107
|
-
* flicker).
|
|
167
|
+
* flicker). The draw pass claims a colour for EVERY family in strip order before it
|
|
168
|
+
* draws anything, so neither the draw order (the selected family goes last) nor
|
|
169
|
+
* which family was selected first ever decides who gets which colour. An empty string means "no override": the CSS falls back to
|
|
108
170
|
* --session-blue, so the first spawning tab keeps the skin-aware blue.
|
|
109
171
|
*/
|
|
110
172
|
_lineageColorFor(parentId) {
|
|
@@ -140,19 +202,20 @@ Object.assign(CodemanApp.prototype, {
|
|
|
140
202
|
_appendLineageConnectionLines(svg, rects) {
|
|
141
203
|
this._lineageEdgeCount = 0;
|
|
142
204
|
if (!svg || !this._lineageLinesEnabled()) return;
|
|
143
|
-
// Sidebar layout:
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
// sidebar, so every arc would draw a giant loop to the foot of the list.
|
|
147
|
-
// Parent/child adjacency reads fine in a vertical list without arcs; a
|
|
148
|
-
// sideways lineage shape is a follow-up with its own visual tuning, not a
|
|
149
|
-
// by-product of a layout port.
|
|
205
|
+
// Sidebar layout: the tree is routed for a horizontal strip or the vertical
|
|
206
|
+
// rail. The sidebar is a vertical list with its own scroller and no reserved
|
|
207
|
+
// channel; parent/child adjacency reads fine there without lines.
|
|
150
208
|
if (this.isSessionSidebarActive?.()) return;
|
|
151
|
-
const
|
|
152
|
-
if (!
|
|
209
|
+
const computeTree = window.CodemanLineage && window.CodemanLineage.computeTree;
|
|
210
|
+
if (!computeTree) return;
|
|
153
211
|
|
|
154
212
|
const edges = this._collectLineageEdges();
|
|
213
|
+
this._lineageTotalEdges = edges.length;
|
|
155
214
|
if (edges.length === 0) return;
|
|
215
|
+
// Claim colours in strip order for every family before drawing (_lineageColorFor).
|
|
216
|
+
for (const edge of edges) this._lineageColorFor(edge.parentId);
|
|
217
|
+
const families = this._lineageFamilies(edges);
|
|
218
|
+
const focusParents = this._lineageFocusParents(edges);
|
|
156
219
|
if (!rects) rects = new Map();
|
|
157
220
|
|
|
158
221
|
// PHASE 1 — reads.
|
|
@@ -162,9 +225,9 @@ Object.assign(CodemanApp.prototype, {
|
|
|
162
225
|
const orientation =
|
|
163
226
|
document.documentElement.getAttribute('data-tab-orientation') === 'vertical' ? 'vertical' : 'horizontal';
|
|
164
227
|
// A session hidden inside a collapsed group of the grouped rail has no row
|
|
165
|
-
// to anchor to, so its end of the
|
|
166
|
-
// "proxied" endpoint, drawn quieter).
|
|
167
|
-
//
|
|
228
|
+
// to anchor to, so its end of the line moves to that group's header (a
|
|
229
|
+
// "proxied" endpoint, drawn quieter). A child proxied to the same header as
|
|
230
|
+
// its parent would be a line from a row to itself: skipped.
|
|
168
231
|
const resolveEndpoint = (id) => {
|
|
169
232
|
const tab = strip.querySelector(`.session-tab[data-id="${CSS.escape(id)}"]`);
|
|
170
233
|
if (tab) return { key: 'tab:' + id, element: tab, proxied: false };
|
|
@@ -173,71 +236,138 @@ Object.assign(CodemanApp.prototype, {
|
|
|
173
236
|
const header = strip.querySelector(`[data-tab-group-header="${CSS.escape(groupId)}"]`);
|
|
174
237
|
return { key: 'group:' + groupId, element: header, proxied: !!header };
|
|
175
238
|
};
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
const parentEndpoint = resolveEndpoint(edge.parentId);
|
|
179
|
-
const childEndpoint = resolveEndpoint(edge.childId);
|
|
180
|
-
if (parentEndpoint.key === childEndpoint.key) continue;
|
|
181
|
-
resolvedEdges.push({ edge, parentEndpoint, childEndpoint });
|
|
182
|
-
for (const endpoint of [parentEndpoint, childEndpoint]) {
|
|
183
|
-
if (rects.has(endpoint.key)) continue;
|
|
239
|
+
const measure = (endpoint) => {
|
|
240
|
+
if (!rects.has(endpoint.key)) {
|
|
184
241
|
rects.set(endpoint.key, endpoint.element ? endpoint.element.getBoundingClientRect() : null);
|
|
185
242
|
}
|
|
243
|
+
return rects.get(endpoint.key);
|
|
244
|
+
};
|
|
245
|
+
const resolvedFamilies = [];
|
|
246
|
+
for (const family of families) {
|
|
247
|
+
const parentEndpoint = resolveEndpoint(family.parentId);
|
|
248
|
+
const parentRect = measure(parentEndpoint);
|
|
249
|
+
if (!parentRect) continue;
|
|
250
|
+
const children = [];
|
|
251
|
+
for (const edge of family.edges) {
|
|
252
|
+
const childEndpoint = resolveEndpoint(edge.childId);
|
|
253
|
+
if (childEndpoint.key === parentEndpoint.key) continue;
|
|
254
|
+
const rect = measure(childEndpoint);
|
|
255
|
+
if (rect) children.push({ edge, endpoint: childEndpoint, rect });
|
|
256
|
+
}
|
|
257
|
+
if (children.length > 0) resolvedFamilies.push({ family, parentEndpoint, parentRect, children });
|
|
258
|
+
}
|
|
259
|
+
if (resolvedFamilies.length === 0) return;
|
|
260
|
+
// The header strip's rows come from EVERY tab in it (computeTree hangs a row's
|
|
261
|
+
// gap under its tallest tab), web tabs included. The rail needs none.
|
|
262
|
+
const tabRects = [];
|
|
263
|
+
let spineLeft;
|
|
264
|
+
if (orientation === 'horizontal') {
|
|
265
|
+
// Where the spine channel is: the reserved --lineage-spine-channel just left
|
|
266
|
+
// of the strip's content edge. Usually that is the strip's own left edge,
|
|
267
|
+
// but grouped by state the label column comes first (styles.css), and a
|
|
268
|
+
// spine at the edge ran through every label. Read back from the padding
|
|
269
|
+
// the CSS laid out, so geometry and stylesheet cannot disagree.
|
|
270
|
+
const style = typeof getComputedStyle === 'function' ? getComputedStyle(strip) : null;
|
|
271
|
+
const channel = style ? parseFloat(style.getPropertyValue('--lineage-spine-channel')) : NaN;
|
|
272
|
+
if (Number.isFinite(channel)) {
|
|
273
|
+
const inset = (parseFloat(style.borderLeftWidth) || 0) + (parseFloat(style.paddingLeft) || 0);
|
|
274
|
+
spineLeft = stripRect.left + inset - channel;
|
|
275
|
+
}
|
|
276
|
+
for (const tab of strip.querySelectorAll('.session-tab')) {
|
|
277
|
+
const id = tab.getAttribute('data-id');
|
|
278
|
+
const key = id ? 'tab:' + id : null;
|
|
279
|
+
if (key && rects.has(key)) tabRects.push(rects.get(key));
|
|
280
|
+
else {
|
|
281
|
+
const rect = tab.getBoundingClientRect();
|
|
282
|
+
if (key) rects.set(key, rect);
|
|
283
|
+
tabRects.push(rect);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
186
286
|
}
|
|
187
|
-
this._lineageEdgeCount = resolvedEdges.length;
|
|
188
287
|
|
|
189
288
|
// PHASE 2 — writes, from the cache only.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
289
|
+
// Lanes follow STRIP order, so a family keeps its lane when the selection moves;
|
|
290
|
+
// only the DRAW order changes (the emphasized families last, on top). A row gap
|
|
291
|
+
// fits a few lanes, so they cycle: families that share one are told apart by colour.
|
|
292
|
+
const laneLimit = Math.max(1, (window.CodemanLineage && window.CodemanLineage.MAX_LANES) || 3);
|
|
293
|
+
const laneCount = Math.min(laneLimit, resolvedFamilies.length);
|
|
294
|
+
const drawOrder = resolvedFamilies
|
|
295
|
+
.map((resolved, index) => ({
|
|
296
|
+
...resolved,
|
|
297
|
+
lane: index % laneCount,
|
|
298
|
+
focus: focusParents.has(resolved.family.parentId),
|
|
299
|
+
}))
|
|
300
|
+
.sort((a, b) => a.focus - b.focus);
|
|
301
|
+
for (const { family, parentEndpoint, parentRect, children, lane, focus } of drawOrder) {
|
|
302
|
+
const geom = computeTree({
|
|
196
303
|
parent: parentRect,
|
|
197
|
-
|
|
304
|
+
children: children.map((c) => ({ id: c.edge.childId, rect: c.rect })),
|
|
198
305
|
strip: stripRect,
|
|
199
|
-
|
|
306
|
+
tabs: tabRects,
|
|
307
|
+
spineLeft,
|
|
200
308
|
orientation,
|
|
309
|
+
lane,
|
|
310
|
+
laneCount,
|
|
201
311
|
});
|
|
202
|
-
if (!geom
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
//
|
|
207
|
-
// the
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
//
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
312
|
+
if (!geom || geom.routes.length === 0) continue;
|
|
313
|
+
const byId = new Map(children.map((c) => [c.edge.childId, c]));
|
|
314
|
+
const color = this._lineageColorFor(family.parentId);
|
|
315
|
+
// One group per family: it carries the translucency, so the stretches its
|
|
316
|
+
// routes share (the trunk) do not stack into a brighter line than the branches,
|
|
317
|
+
// and the emphasis for the selected tab's families (styles.css).
|
|
318
|
+
const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
|
319
|
+
group.setAttribute('class', 'lineage-family' + (focus ? ' lineage-family--focus' : ''));
|
|
320
|
+
group.setAttribute('data-parent-tab', family.parentId);
|
|
321
|
+
// Working routes go in FIRST, so an idle sibling's solid stroke covers the
|
|
322
|
+
// shared trunk and only the working child's own branch shows its dashes.
|
|
323
|
+
const routes = geom.routes
|
|
324
|
+
.map((route) => ({ route, child: byId.get(route.id) }))
|
|
325
|
+
.filter((r) => r.child)
|
|
326
|
+
.sort((a, b) => (b.child.edge.status === 'working') - (a.child.edge.status === 'working'));
|
|
327
|
+
for (const { route, child } of routes) {
|
|
328
|
+
const line = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
329
|
+
line.setAttribute('d', route.d);
|
|
330
|
+
// `status` is the CHILD's, which is the interesting end: a working child's
|
|
331
|
+
// route is dashed (and marches, motion permitting).
|
|
332
|
+
const working = child.edge.status === 'working' ? ' lineage-line--working' : '';
|
|
333
|
+
const proxied = parentEndpoint.proxied || child.endpoint.proxied;
|
|
334
|
+
line.setAttribute(
|
|
335
|
+
'class',
|
|
336
|
+
'connection-line lineage-line' + working + (proxied ? ' lineage-line--proxied' : '')
|
|
337
|
+
);
|
|
338
|
+
// The PARENT's colour rides a CSS custom property so the stylesheet keeps
|
|
339
|
+
// owning weight and dash; an empty colour leaves the --session-blue fallback.
|
|
340
|
+
if (color) line.style.setProperty('--lineage-color', color);
|
|
341
|
+
// `data-agent-id` is what _applyLineEntrances() queries — see the file header.
|
|
342
|
+
line.setAttribute('data-agent-id', 'lineage:' + child.edge.childId);
|
|
343
|
+
line.setAttribute('data-parent-tab', family.parentId);
|
|
344
|
+
line.setAttribute('data-child-tab', child.edge.childId);
|
|
345
|
+
group.appendChild(line);
|
|
346
|
+
}
|
|
347
|
+
// Direction marker at each CHILD end, after every path so no stroke covers it.
|
|
348
|
+
for (const { route, child } of routes) {
|
|
349
|
+
const working = child.edge.status === 'working' ? ' lineage-line--working' : '';
|
|
350
|
+
const proxied = parentEndpoint.proxied || child.endpoint.proxied;
|
|
351
|
+
const dot = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
|
|
352
|
+
dot.setAttribute('cx', String(route.endX));
|
|
353
|
+
dot.setAttribute('cy', String(route.endY));
|
|
354
|
+
// Fallback radius only: styles.css sizes the dot through `--lineage-dot-r`
|
|
355
|
+
// (larger in an emphasized family), and `lineage-dot-pulse` breathes from it.
|
|
356
|
+
dot.setAttribute('r', '2.5');
|
|
357
|
+
dot.setAttribute('class', 'lineage-line-dot' + working + (proxied ? ' lineage-line-dot--proxied' : ''));
|
|
358
|
+
dot.setAttribute('data-child-tab', child.edge.childId);
|
|
359
|
+
if (color) dot.style.setProperty('--lineage-color', color);
|
|
360
|
+
group.appendChild(dot);
|
|
361
|
+
}
|
|
362
|
+
svg.appendChild(group);
|
|
363
|
+
this._lineageEdgeCount += routes.length;
|
|
234
364
|
}
|
|
235
365
|
},
|
|
236
366
|
|
|
237
367
|
/**
|
|
238
368
|
* The strip scrolls (desktop `overflow-x: auto` and every wrapped layout), and a
|
|
239
|
-
* scroll moves both endpoints without firing any render, so the
|
|
240
|
-
* their tabs. Passive listener, and the redraw is the normal coalesced one.
|
|
369
|
+
* scroll moves both endpoints without firing any render, so the lines would slide
|
|
370
|
+
* off their tabs. Passive listener, and the redraw is the normal coalesced one.
|
|
241
371
|
*
|
|
242
372
|
* Installed once; the guard also keeps a re-init from stacking listeners.
|
|
243
373
|
*/
|
|
@@ -248,11 +378,24 @@ Object.assign(CodemanApp.prototype, {
|
|
|
248
378
|
this._lineageScrollHandler = () => {
|
|
249
379
|
// Sidebar layout and the vertical rail scroll the SAME element
|
|
250
380
|
// vertically, and there the subagent/ultracode connectors anchor to tab
|
|
251
|
-
// rects too (the sidebar skips lineage
|
|
252
|
-
//
|
|
253
|
-
//
|
|
381
|
+
// rects too (the sidebar skips lineage entirely, and the rail can show
|
|
382
|
+
// connectors with zero lineage edges, so _lineageEdgeCount alone would
|
|
383
|
+
// never redraw them).
|
|
254
384
|
if (this._lineageEdgeCount > 0 || this._isVerticalTabList?.()) this.updateConnectionLines();
|
|
255
385
|
};
|
|
256
386
|
strip.addEventListener('scroll', this._lineageScrollHandler, { passive: true });
|
|
387
|
+
|
|
388
|
+
// ⚠ A SELECTION RESIZES TABS AFTER THE REDRAW. The active tab reveals its gear
|
|
389
|
+
// and close icons by transitioning their padding (styles.css), so it keeps
|
|
390
|
+
// widening for ~150ms after `_updateActiveTabImmediate()` has already redrawn,
|
|
391
|
+
// and the tab it was selected from shrinks. That can move tabs or re-wrap a row,
|
|
392
|
+
// which left a family's trunk hanging under the tab's OLD position. Redraw once
|
|
393
|
+
// a size transition inside the strip ends (coalesced, like every other redraw).
|
|
394
|
+
this._lineageTransitionHandler = (event) => {
|
|
395
|
+
const prop = event.propertyName || '';
|
|
396
|
+
if (!(prop === 'width' || prop === 'max-width' || prop.startsWith('padding'))) return;
|
|
397
|
+
if (this._lineageTotalEdges > 0) this.updateConnectionLines();
|
|
398
|
+
};
|
|
399
|
+
strip.addEventListener('transitionend', this._lineageTransitionHandler);
|
|
257
400
|
},
|
|
258
401
|
});
|
|
Binary file
|
|
Binary file
|