aicodeman 1.46.0 → 1.48.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 +3 -0
- package/dist/cli-notify.d.ts +34 -0
- package/dist/cli-notify.d.ts.map +1 -0
- package/dist/cli-notify.js +100 -0
- package/dist/cli-notify.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +16 -0
- package/dist/cli.js.map +1 -1
- package/dist/config/cli-registry/patterns.d.ts +1 -1
- package/dist/config/cli-registry/patterns.d.ts.map +1 -1
- package/dist/config/cli-registry/patterns.js +4 -0
- package/dist/config/cli-registry/patterns.js.map +1 -1
- package/dist/config/cli-registry/schema.d.ts +6 -0
- package/dist/config/cli-registry/schema.d.ts.map +1 -1
- package/dist/config/cli-registry/schema.js +62 -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 +43 -26
- package/dist/config/cli-registry/stock.js.map +1 -1
- package/dist/config/cli-registry/types.d.ts +47 -17
- package/dist/config/cli-registry/types.d.ts.map +1 -1
- package/dist/config/path-probe.d.ts +6 -0
- package/dist/config/path-probe.d.ts.map +1 -1
- package/dist/config/path-probe.js +6 -0
- package/dist/config/path-probe.js.map +1 -1
- package/dist/config-backup.d.ts +1 -1
- package/dist/config-backup.d.ts.map +1 -1
- package/dist/config-backup.js +2 -0
- package/dist/config-backup.js.map +1 -1
- package/dist/custom-model-hosts.d.ts +32 -8
- package/dist/custom-model-hosts.d.ts.map +1 -1
- package/dist/custom-model-hosts.js +10 -0
- package/dist/custom-model-hosts.js.map +1 -1
- package/dist/custom-model-injection-apply.d.ts +19 -5
- package/dist/custom-model-injection-apply.d.ts.map +1 -1
- package/dist/custom-model-injection-apply.js +88 -8
- package/dist/custom-model-injection-apply.js.map +1 -1
- package/dist/custom-model-injection.d.ts +6 -0
- package/dist/custom-model-injection.d.ts.map +1 -1
- package/dist/custom-model-injection.js +92 -10
- package/dist/custom-model-injection.js.map +1 -1
- package/dist/discord-bridge.d.ts +338 -0
- package/dist/discord-bridge.d.ts.map +1 -0
- package/dist/discord-bridge.js +1256 -0
- package/dist/discord-bridge.js.map +1 -0
- package/dist/edit-history-local-source.d.ts +83 -0
- package/dist/edit-history-local-source.d.ts.map +1 -0
- package/dist/edit-history-local-source.js +198 -0
- package/dist/edit-history-local-source.js.map +1 -0
- package/dist/edit-history-parse.d.ts +114 -0
- package/dist/edit-history-parse.d.ts.map +1 -0
- package/dist/edit-history-parse.js +312 -0
- package/dist/edit-history-parse.js.map +1 -0
- package/dist/edit-history-store.d.ts +209 -0
- package/dist/edit-history-store.d.ts.map +1 -0
- package/dist/edit-history-store.js +599 -0
- package/dist/edit-history-store.js.map +1 -0
- package/dist/git-clone.d.ts +6 -1
- package/dist/git-clone.d.ts.map +1 -1
- package/dist/git-clone.js +79 -14
- package/dist/git-clone.js.map +1 -1
- package/dist/image-watcher.js +4 -4
- package/dist/image-watcher.js.map +1 -1
- package/dist/mux-interface.d.ts +10 -1
- package/dist/mux-interface.d.ts.map +1 -1
- package/dist/ralph-fix-plan-watcher.d.ts +13 -1
- package/dist/ralph-fix-plan-watcher.d.ts.map +1 -1
- package/dist/ralph-fix-plan-watcher.js +21 -3
- package/dist/ralph-fix-plan-watcher.js.map +1 -1
- package/dist/ralph-tracker.d.ts +6 -0
- package/dist/ralph-tracker.d.ts.map +1 -1
- package/dist/ralph-tracker.js +8 -0
- package/dist/ralph-tracker.js.map +1 -1
- package/dist/session-cli-registry-bridge.d.ts.map +1 -1
- package/dist/session-cli-registry-bridge.js +4 -0
- package/dist/session-cli-registry-bridge.js.map +1 -1
- package/dist/session.d.ts +70 -3
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +147 -4
- package/dist/session.js.map +1 -1
- package/dist/tmux-manager.d.ts +40 -0
- package/dist/tmux-manager.d.ts.map +1 -1
- package/dist/tmux-manager.js +62 -0
- package/dist/tmux-manager.js.map +1 -1
- package/dist/types/discord.d.ts +55 -0
- package/dist/types/discord.d.ts.map +1 -0
- package/dist/types/discord.js +18 -0
- package/dist/types/discord.js.map +1 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/session.d.ts +13 -0
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js.map +1 -1
- package/dist/web/case-path.d.ts +2 -0
- package/dist/web/case-path.d.ts.map +1 -1
- package/dist/web/case-path.js +3 -3
- package/dist/web/case-path.js.map +1 -1
- package/dist/web/edit-history-sync.d.ts +158 -0
- package/dist/web/edit-history-sync.d.ts.map +1 -0
- package/dist/web/edit-history-sync.js +445 -0
- package/dist/web/edit-history-sync.js.map +1 -0
- package/dist/web/paste-image-gc.d.ts +6 -0
- package/dist/web/paste-image-gc.d.ts.map +1 -1
- package/dist/web/paste-image-gc.js +6 -0
- package/dist/web/paste-image-gc.js.map +1 -1
- package/dist/web/ports/session-port.d.ts +13 -0
- 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.3093527f.js → app.963b5ba8.js} +18 -18
- package/dist/web/public/app.963b5ba8.js.br +0 -0
- package/dist/web/public/app.963b5ba8.js.gz +0 -0
- package/dist/web/public/approvals-ui.js.gz +0 -0
- package/dist/web/public/{constants.affcdde6.js → constants.782170e1.js} +114 -25
- package/dist/web/public/constants.782170e1.js.br +0 -0
- package/dist/web/public/constants.782170e1.js.gz +0 -0
- package/dist/web/public/cron-ui.js.gz +0 -0
- package/dist/web/public/edit-history-ui.js +630 -0
- package/dist/web/public/edit-history-ui.js.br +0 -0
- package/dist/web/public/edit-history-ui.js.gz +0 -0
- package/dist/web/public/entrance-animations.js.gz +0 -0
- package/dist/web/public/git-status-ui.js.gz +0 -0
- package/dist/web/public/header-divider.eb2d2463.js.gz +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.33f930d7.js +2 -0
- package/dist/web/public/i18n.33f930d7.js.br +0 -0
- package/dist/web/public/i18n.33f930d7.js.gz +0 -0
- package/dist/web/public/{image-input.941386e7.js → image-input.a5d0f8f3.js} +18 -9
- package/dist/web/public/image-input.a5d0f8f3.js.br +0 -0
- package/dist/web/public/image-input.a5d0f8f3.js.gz +0 -0
- package/dist/web/public/index.html +162 -16
- 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.4e8b20ac.js → keyboard-accessory.d4ec5957.js} +77 -2
- package/dist/web/public/keyboard-accessory.d4ec5957.js.br +0 -0
- package/dist/web/public/keyboard-accessory.d4ec5957.js.gz +0 -0
- package/dist/web/public/mobile-handlers.f7c3f692.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.5ef2ce85.css +1 -0
- package/dist/web/public/mobile.5ef2ce85.css.br +0 -0
- package/dist/web/public/mobile.5ef2ce85.css.gz +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.4a56ee63.js → panels-ui.b100727d.js} +2 -2
- package/dist/web/public/panels-ui.b100727d.js.br +0 -0
- package/dist/web/public/{panels-ui.4a56ee63.js.gz → panels-ui.b100727d.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.d7adcf6a.js → respawn-ui.304ba0d4.js} +1 -1
- package/dist/web/public/respawn-ui.304ba0d4.js.br +0 -0
- package/dist/web/public/respawn-ui.304ba0d4.js.gz +0 -0
- package/dist/web/public/sanitize-html.e7147e76.js.gz +0 -0
- package/dist/web/public/security-notices.json +1 -21
- package/dist/web/public/session-lineage.js.gz +0 -0
- package/dist/web/public/{session-ui.186f9419.js → session-ui.5ac82f2c.js} +30 -30
- package/dist/web/public/session-ui.5ac82f2c.js.br +0 -0
- package/dist/web/public/session-ui.5ac82f2c.js.gz +0 -0
- package/dist/web/public/settings-ui.d1d4fb99.js +106 -0
- package/dist/web/public/settings-ui.d1d4fb99.js.br +0 -0
- package/dist/web/public/settings-ui.d1d4fb99.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview-worker.js.gz +0 -0
- package/dist/web/public/spreadsheet-preview.75c751de.js.gz +0 -0
- package/dist/web/public/spreadsheet-xlsx-core.js.gz +0 -0
- package/dist/web/public/styles.77dc538f.css +1 -0
- package/dist/web/public/styles.77dc538f.css.br +0 -0
- package/dist/web/public/styles.77dc538f.css.gz +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.2d6189f7.js.gz +0 -0
- package/dist/web/public/tab-rail-resize.b5cdceaf.js.gz +0 -0
- package/dist/web/public/terminal-keycode229-recovery.98843069.js +1 -0
- package/dist/web/public/terminal-keycode229-recovery.98843069.js.br +0 -0
- package/dist/web/public/terminal-keycode229-recovery.98843069.js.gz +0 -0
- package/dist/web/public/terminal-split.js.gz +0 -0
- package/dist/web/public/terminal-tile.js +8 -6
- 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.7e787829.js → terminal-ui.d7c75ce8.js} +3 -3
- package/dist/web/public/terminal-ui.d7c75ce8.js.br +0 -0
- package/dist/web/public/terminal-ui.d7c75ce8.js.gz +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.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.276b11d9.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.1be42307.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.gz +0 -0
- package/dist/web/public/whats-new.json +9 -9
- package/dist/web/request-body-parser.d.ts +23 -0
- package/dist/web/request-body-parser.d.ts.map +1 -0
- package/dist/web/request-body-parser.js +57 -0
- package/dist/web/request-body-parser.js.map +1 -0
- package/dist/web/routes/case-routes.d.ts.map +1 -1
- package/dist/web/routes/case-routes.js +104 -8
- package/dist/web/routes/case-routes.js.map +1 -1
- package/dist/web/routes/config-backup-routes.d.ts +5 -1
- package/dist/web/routes/config-backup-routes.d.ts.map +1 -1
- package/dist/web/routes/config-backup-routes.js +4 -1
- package/dist/web/routes/config-backup-routes.js.map +1 -1
- package/dist/web/routes/custom-model-routes.d.ts +7 -2
- package/dist/web/routes/custom-model-routes.d.ts.map +1 -1
- package/dist/web/routes/custom-model-routes.js +51 -6
- package/dist/web/routes/custom-model-routes.js.map +1 -1
- package/dist/web/routes/discord-routes.d.ts +25 -0
- package/dist/web/routes/discord-routes.d.ts.map +1 -0
- package/dist/web/routes/discord-routes.js +206 -0
- package/dist/web/routes/discord-routes.js.map +1 -0
- package/dist/web/routes/edit-history-routes.d.ts +43 -0
- package/dist/web/routes/edit-history-routes.d.ts.map +1 -0
- package/dist/web/routes/edit-history-routes.js +106 -0
- package/dist/web/routes/edit-history-routes.js.map +1 -0
- package/dist/web/routes/file-routes.d.ts +5 -0
- package/dist/web/routes/file-routes.d.ts.map +1 -1
- package/dist/web/routes/file-routes.js +67 -3
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/routes/index.d.ts +2 -0
- package/dist/web/routes/index.d.ts.map +1 -1
- package/dist/web/routes/index.js +2 -0
- package/dist/web/routes/index.js.map +1 -1
- package/dist/web/routes/ralph-routes.d.ts.map +1 -1
- package/dist/web/routes/ralph-routes.js +45 -2
- package/dist/web/routes/ralph-routes.js.map +1 -1
- package/dist/web/routes/session-routes.d.ts +17 -0
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +92 -37
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/routes/system-routes.d.ts.map +1 -1
- package/dist/web/routes/system-routes.js +4 -2
- package/dist/web/routes/system-routes.js.map +1 -1
- package/dist/web/schemas.d.ts +68 -1
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +77 -1
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/sensitive-path.d.ts.map +1 -1
- package/dist/web/sensitive-path.js +15 -0
- package/dist/web/sensitive-path.js.map +1 -1
- package/dist/web/server.d.ts +43 -0
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +237 -15
- package/dist/web/server.js.map +1 -1
- package/package.json +1 -1
- package/dist/web/public/app.3093527f.js.br +0 -0
- package/dist/web/public/app.3093527f.js.gz +0 -0
- package/dist/web/public/constants.affcdde6.js.br +0 -0
- package/dist/web/public/constants.affcdde6.js.gz +0 -0
- package/dist/web/public/i18n.70265257.js +0 -2
- package/dist/web/public/i18n.70265257.js.br +0 -0
- package/dist/web/public/i18n.70265257.js.gz +0 -0
- package/dist/web/public/image-input.941386e7.js.br +0 -0
- package/dist/web/public/image-input.941386e7.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.4e8b20ac.js.br +0 -0
- package/dist/web/public/keyboard-accessory.4e8b20ac.js.gz +0 -0
- package/dist/web/public/mobile.1bbd2d67.css +0 -1
- package/dist/web/public/mobile.1bbd2d67.css.br +0 -0
- package/dist/web/public/mobile.1bbd2d67.css.gz +0 -0
- package/dist/web/public/panels-ui.4a56ee63.js.br +0 -0
- package/dist/web/public/respawn-ui.d7adcf6a.js.br +0 -0
- package/dist/web/public/respawn-ui.d7adcf6a.js.gz +0 -0
- package/dist/web/public/session-ui.186f9419.js.br +0 -0
- package/dist/web/public/session-ui.186f9419.js.gz +0 -0
- package/dist/web/public/settings-ui.a191154e.js +0 -106
- package/dist/web/public/settings-ui.a191154e.js.br +0 -0
- package/dist/web/public/settings-ui.a191154e.js.gz +0 -0
- package/dist/web/public/styles.7238eae8.css +0 -1
- package/dist/web/public/styles.7238eae8.css.br +0 -0
- package/dist/web/public/styles.7238eae8.css.gz +0 -0
- package/dist/web/public/terminal-keycode229-recovery.af09f99a.js +0 -1
- 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-ui.7e787829.js.br +0 -0
- package/dist/web/public/terminal-ui.7e787829.js.gz +0 -0
package/dist/session.js
CHANGED
|
@@ -29,12 +29,15 @@
|
|
|
29
29
|
*/
|
|
30
30
|
import { EventEmitter } from 'node:events';
|
|
31
31
|
import { basename } from 'node:path';
|
|
32
|
+
import { realpath } from 'node:fs/promises';
|
|
32
33
|
import { execSync, execFileSync } from 'node:child_process';
|
|
33
34
|
import { v4 as uuidv4 } from 'uuid';
|
|
34
35
|
import * as pty from 'node-pty';
|
|
35
36
|
import { DEFAULT_NICE_CONFIG, getErrorMessage, isAdvisorModel, isEffortLevel, } from './types.js';
|
|
36
37
|
import { resolveAndClaimOmpSessionId } from './utils/omp-session-resolver.js';
|
|
37
38
|
import { claudeTranscriptExists } from './utils/claude-transcript.js';
|
|
39
|
+
import { probePathKind } from './utils/bounded-path-probe.js';
|
|
40
|
+
import { PATH_PROBE_TIMEOUT_MS, WORKSPACE_REALPATH_RETRY_MS } from './config/path-probe.js';
|
|
38
41
|
import { matchesPattern } from './config/cli-registry/patterns.js';
|
|
39
42
|
import { probeDockerCliVersion } from './docker-hosts.js';
|
|
40
43
|
import { probeRemoteCliVersion } from './remote-hosts.js';
|
|
@@ -268,6 +271,21 @@ const TEST_PTY_SCRIPT = 'if (process.stdin.isTTY) process.stdin.setRawMode(true)
|
|
|
268
271
|
const DOCKER_CLI_VERSION_PROBE_DELAY_MS = 3000;
|
|
269
272
|
/** Delay before the over-ssh Claude CLI version probe (keeps session start off the ssh round-trip). */
|
|
270
273
|
const REMOTE_CLI_VERSION_PROBE_DELAY_MS = 3000;
|
|
274
|
+
/** Whether absolute `path` is `root` or lies under it (a lexical compare). */
|
|
275
|
+
function isSameOrUnder(path, root) {
|
|
276
|
+
return path === root || path.startsWith(root === '/' ? '/' : `${root}/`);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Rewrite `path` from under `from` to the same place under `to`; a path not at or
|
|
280
|
+
* under `from` comes back unchanged. Exported for unit testing.
|
|
281
|
+
*/
|
|
282
|
+
export function rebasePath(path, from, to) {
|
|
283
|
+
if (path === from)
|
|
284
|
+
return to;
|
|
285
|
+
if (path.startsWith(`${from}/`))
|
|
286
|
+
return to + path.slice(from.length);
|
|
287
|
+
return path;
|
|
288
|
+
}
|
|
271
289
|
/**
|
|
272
290
|
* Ask tmux for the current window geometry of `muxName` so a re-attaching PTY
|
|
273
291
|
* client can spawn at the same size and avoid the resize-flicker / scrollback
|
|
@@ -564,6 +582,21 @@ export class Session extends EventEmitter {
|
|
|
564
582
|
* rendered as "alive".
|
|
565
583
|
*/
|
|
566
584
|
_paneExit = null;
|
|
585
|
+
/**
|
|
586
|
+
* The pane's live directory, from the pane-exit watcher's read. Runtime-only:
|
|
587
|
+
* serialized by toState() but never restored by the constructor.
|
|
588
|
+
*/
|
|
589
|
+
_paneCwd;
|
|
590
|
+
/**
|
|
591
|
+
* `workingDir` with symlinks resolved, so a pane reading (tmux reads the
|
|
592
|
+
* process cwd, always the resolved path) can be put back into `workingDir`'s
|
|
593
|
+
* spelling. `undefined` until the first resolution settles; `null` when there
|
|
594
|
+
* is nothing to translate (no symlink in the path) or it could not be resolved.
|
|
595
|
+
*/
|
|
596
|
+
_workspaceRealPath;
|
|
597
|
+
_workspaceRealPathPending = false;
|
|
598
|
+
/** When a resolution that met an unreachable folder may be tried again (0 = never). */
|
|
599
|
+
_workspaceRealPathRetryAt = 0;
|
|
567
600
|
/**
|
|
568
601
|
* How many starts, attaches or relaunches are running for this session's
|
|
569
602
|
* pane. While one is, a dead-pane reading may describe a pane that is being
|
|
@@ -993,6 +1026,16 @@ export class Session extends EventEmitter {
|
|
|
993
1026
|
const value = this._envOverrides?.DSH_HOME;
|
|
994
1027
|
return value && value.trim() ? value.trim() : undefined;
|
|
995
1028
|
}
|
|
1029
|
+
/**
|
|
1030
|
+
* One env var from this session's overrides, for internal path resolution only
|
|
1031
|
+
* (custom-model injection linking an isolated config dir back to a path that must
|
|
1032
|
+
* survive lives in). Single-key lookup by design, like `deepSeekHomeOverride`: the
|
|
1033
|
+
* map can hold provider credentials and stays off the public `SessionState`.
|
|
1034
|
+
*/
|
|
1035
|
+
envOverrideValue(key) {
|
|
1036
|
+
const value = this._envOverrides?.[key];
|
|
1037
|
+
return value && value.trim() ? value.trim() : undefined;
|
|
1038
|
+
}
|
|
996
1039
|
/** Owning username in multi-user mode, else undefined. */
|
|
997
1040
|
get owner() {
|
|
998
1041
|
return this._owner;
|
|
@@ -1144,6 +1187,101 @@ export class Session extends EventEmitter {
|
|
|
1144
1187
|
if (this._muxSession)
|
|
1145
1188
|
this._mux?.clearPaneExit?.(this._muxSession.muxName);
|
|
1146
1189
|
}
|
|
1190
|
+
/** The pane's live working directory, when the pane read has reported one. */
|
|
1191
|
+
get paneCwd() {
|
|
1192
|
+
return this._paneCwd;
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Record the pane's live directory. Returns whether it CHANGED, so the caller
|
|
1196
|
+
* broadcasts only on a real transition.
|
|
1197
|
+
*
|
|
1198
|
+
* Scoped by {@link paneExitApplies}, the same rule as the exit reading: a
|
|
1199
|
+
* remote session's local pane runs the ssh client and a docker case's runs a
|
|
1200
|
+
* `docker exec`, so their pane directory is a host directory the agent was
|
|
1201
|
+
* never in, and a direct-PTY or rediscovered session has no pane Codeman can
|
|
1202
|
+
* vouch for. A relative value is refused rather than stored.
|
|
1203
|
+
*
|
|
1204
|
+
* tmux reads the pane's directory from the process cwd, which is always the
|
|
1205
|
+
* resolved path, while `workingDir` keeps the spelling the case was created
|
|
1206
|
+
* with. A workspace reached through a symlink would otherwise read as outside
|
|
1207
|
+
* itself, and the browser's preview routing (a lexical compare against
|
|
1208
|
+
* `workingDir`) would send every relative link to the attachment route. So a
|
|
1209
|
+
* reading at or under the workspace's resolved path is written back in
|
|
1210
|
+
* `workingDir`'s spelling. Until that resolution has settled, only a reading
|
|
1211
|
+
* lexically inside `workingDir` is accepted.
|
|
1212
|
+
*/
|
|
1213
|
+
setPaneCwd(next) {
|
|
1214
|
+
let resolved = this.paneExitApplies && next?.startsWith('/') ? next : undefined;
|
|
1215
|
+
if (resolved !== undefined) {
|
|
1216
|
+
if (this._workspaceRealPath === undefined ||
|
|
1217
|
+
(this._workspaceRealPathRetryAt !== 0 && Date.now() >= this._workspaceRealPathRetryAt)) {
|
|
1218
|
+
this._resolveWorkspaceRealPath();
|
|
1219
|
+
}
|
|
1220
|
+
if (this._workspaceRealPath === undefined) {
|
|
1221
|
+
// The workspace's resolved path is not known yet. A reading outside
|
|
1222
|
+
// `workingDir` could be the workspace itself seen through its symlink, so
|
|
1223
|
+
// it waits for the next tick rather than mis-route links for one.
|
|
1224
|
+
if (!isSameOrUnder(resolved, this._workspaceSpelling()))
|
|
1225
|
+
return false;
|
|
1226
|
+
}
|
|
1227
|
+
else if (this._workspaceRealPath !== null) {
|
|
1228
|
+
resolved = rebasePath(resolved, this._workspaceRealPath, this._workspaceSpelling());
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
if (resolved === this._paneCwd)
|
|
1232
|
+
return false;
|
|
1233
|
+
this._paneCwd = resolved;
|
|
1234
|
+
return true;
|
|
1235
|
+
}
|
|
1236
|
+
/** `workingDir` without a trailing separator (the root stays `/`). */
|
|
1237
|
+
_workspaceSpelling() {
|
|
1238
|
+
return this.workingDir.length > 1 ? this.workingDir.replace(/\/+$/, '') : this.workingDir;
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Resolve `workingDir`'s symlinks in the background for {@link setPaneCwd}.
|
|
1242
|
+
*
|
|
1243
|
+
* Bounded: the folder can sit on a network mount that stopped answering, so it
|
|
1244
|
+
* is probed with `probePathKind()` first and the `realpath()` is raced against
|
|
1245
|
+
* the same timeout. An `unknown` probe, a failed or slow `realpath()` leave no
|
|
1246
|
+
* translation and allow one more try after `WORKSPACE_REALPATH_RETRY_MS`; a
|
|
1247
|
+
* folder that is absent or not a directory is settled for good.
|
|
1248
|
+
*/
|
|
1249
|
+
_resolveWorkspaceRealPath() {
|
|
1250
|
+
if (this._workspaceRealPathPending)
|
|
1251
|
+
return;
|
|
1252
|
+
this._workspaceRealPathPending = true;
|
|
1253
|
+
const spelling = this._workspaceSpelling();
|
|
1254
|
+
void (async () => {
|
|
1255
|
+
let real = null;
|
|
1256
|
+
let retry = false;
|
|
1257
|
+
try {
|
|
1258
|
+
const kind = await probePathKind(spelling);
|
|
1259
|
+
if (kind === 'unknown') {
|
|
1260
|
+
retry = true;
|
|
1261
|
+
}
|
|
1262
|
+
else if (kind === 'directory') {
|
|
1263
|
+
let timer;
|
|
1264
|
+
const answer = await Promise.race([
|
|
1265
|
+
realpath(spelling).catch(() => undefined),
|
|
1266
|
+
new Promise((resolveTimeout) => {
|
|
1267
|
+
timer = setTimeout(() => resolveTimeout(undefined), PATH_PROBE_TIMEOUT_MS);
|
|
1268
|
+
timer.unref?.();
|
|
1269
|
+
}),
|
|
1270
|
+
]).finally(() => clearTimeout(timer));
|
|
1271
|
+
if (answer === undefined)
|
|
1272
|
+
retry = true;
|
|
1273
|
+
else if (answer !== spelling && answer !== '/')
|
|
1274
|
+
real = answer;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
catch {
|
|
1278
|
+
retry = true;
|
|
1279
|
+
}
|
|
1280
|
+
this._workspaceRealPath = real;
|
|
1281
|
+
this._workspaceRealPathRetryAt = retry ? Date.now() + WORKSPACE_REALPATH_RETRY_MS : 0;
|
|
1282
|
+
this._workspaceRealPathPending = false;
|
|
1283
|
+
})();
|
|
1284
|
+
}
|
|
1147
1285
|
/**
|
|
1148
1286
|
* Record what the mux layer observed of this pane's agent, and say whether
|
|
1149
1287
|
* that changed the answer. The caller persists and broadcasts on a true.
|
|
@@ -1731,6 +1869,7 @@ export class Session extends EventEmitter {
|
|
|
1731
1869
|
pid: this.pid,
|
|
1732
1870
|
status: this._status,
|
|
1733
1871
|
workingDir: this.workingDir,
|
|
1872
|
+
paneCwd: this._paneCwd,
|
|
1734
1873
|
remote: this._remote,
|
|
1735
1874
|
docker: this._docker,
|
|
1736
1875
|
owner: this._owner,
|
|
@@ -2240,7 +2379,7 @@ export class Session extends EventEmitter {
|
|
|
2240
2379
|
if (entry?.launch.chain !== 'fallback')
|
|
2241
2380
|
return options;
|
|
2242
2381
|
const resumeIdPattern = entry.launch.params?.resumeId;
|
|
2243
|
-
const configDir = this.
|
|
2382
|
+
const configDir = this.claudeConfigDir();
|
|
2244
2383
|
const chainTail = this._claudeSessionChain[this._claudeSessionChain.length - 1];
|
|
2245
2384
|
const candidates = [chainTail, options.resumeSessionId, this.id].filter((v) => !!v);
|
|
2246
2385
|
for (const candidate of candidates) {
|
|
@@ -2262,8 +2401,11 @@ export class Session extends EventEmitter {
|
|
|
2262
2401
|
// unpinned options already carry is the correct command.
|
|
2263
2402
|
return options;
|
|
2264
2403
|
}
|
|
2265
|
-
/**
|
|
2266
|
-
|
|
2404
|
+
/**
|
|
2405
|
+
* The session's Claude config dir when it has been relocated (#255), else undefined.
|
|
2406
|
+
* Public for the edit history reader, which looks for the transcript there.
|
|
2407
|
+
*/
|
|
2408
|
+
claudeConfigDir() {
|
|
2267
2409
|
// Trimmed like `claudeProjectsDir()` trims the process-wide override: the
|
|
2268
2410
|
// envOverrides schema validates keys only, and a whitespace-only value would
|
|
2269
2411
|
// otherwise resolve to a relative path and read "no transcript" for everything.
|
|
@@ -2271,7 +2413,8 @@ export class Session extends EventEmitter {
|
|
|
2271
2413
|
}
|
|
2272
2414
|
/**
|
|
2273
2415
|
* Force the custom-model selection's `launchModel` (pi/omp `custom/<id>`, grok's
|
|
2274
|
-
* `[model.<name>]` block name) onto the CLI's `model`
|
|
2416
|
+
* `[model.<name>]` block name, codex's bare selected id) onto the CLI's `model`
|
|
2417
|
+
* launch param. Where that param
|
|
2275
2418
|
* lives is registry DATA — the entry's `legacyConfigField` (`piConfig`, `grokConfig`,
|
|
2276
2419
|
* ...) or the top-level `model` for an entry that declares none — so this stays a
|
|
2277
2420
|
* generic reader rather than a branch per CLI. Applied on the OPTIONS only: the stored
|