@dsh-cc/tui 0.5.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/LICENSE +201 -0
- package/README.md +144 -0
- package/lib/bash-history.d.ts +31 -0
- package/lib/bash-history.d.ts.map +1 -0
- package/lib/bash-history.js +94 -0
- package/lib/bash-history.js.map +1 -0
- package/lib/compact-fold.d.ts +35 -0
- package/lib/compact-fold.d.ts.map +1 -0
- package/lib/compact-fold.js +60 -0
- package/lib/compact-fold.js.map +1 -0
- package/lib/components/arg-completers.d.ts +22 -0
- package/lib/components/arg-completers.d.ts.map +1 -0
- package/lib/components/arg-completers.js +75 -0
- package/lib/components/arg-completers.js.map +1 -0
- package/lib/components/code-theme.d.ts +25 -0
- package/lib/components/code-theme.d.ts.map +1 -0
- package/lib/components/code-theme.js +137 -0
- package/lib/components/code-theme.js.map +1 -0
- package/lib/components/completion.d.ts +50 -0
- package/lib/components/completion.d.ts.map +1 -0
- package/lib/components/completion.js +279 -0
- package/lib/components/completion.js.map +1 -0
- package/lib/components/diff-card.d.ts +29 -0
- package/lib/components/diff-card.d.ts.map +1 -0
- package/lib/components/diff-card.js +175 -0
- package/lib/components/diff-card.js.map +1 -0
- package/lib/components/diff-hunks.d.ts +44 -0
- package/lib/components/diff-hunks.d.ts.map +1 -0
- package/lib/components/diff-hunks.js +188 -0
- package/lib/components/diff-hunks.js.map +1 -0
- package/lib/components/editor-history.d.ts +23 -0
- package/lib/components/editor-history.d.ts.map +1 -0
- package/lib/components/editor-history.js +29 -0
- package/lib/components/editor-history.js.map +1 -0
- package/lib/components/markdown-theme.d.ts +11 -0
- package/lib/components/markdown-theme.d.ts.map +1 -0
- package/lib/components/markdown-theme.js +29 -0
- package/lib/components/markdown-theme.js.map +1 -0
- package/lib/components/masked-input.d.ts +24 -0
- package/lib/components/masked-input.d.ts.map +1 -0
- package/lib/components/masked-input.js +168 -0
- package/lib/components/masked-input.js.map +1 -0
- package/lib/components/overlay-host.d.ts +31 -0
- package/lib/components/overlay-host.d.ts.map +1 -0
- package/lib/components/overlay-host.js +128 -0
- package/lib/components/overlay-host.js.map +1 -0
- package/lib/components/overlays.d.ts +94 -0
- package/lib/components/overlays.d.ts.map +1 -0
- package/lib/components/overlays.js +450 -0
- package/lib/components/overlays.js.map +1 -0
- package/lib/components/provider-box.d.ts +23 -0
- package/lib/components/provider-box.d.ts.map +1 -0
- package/lib/components/provider-box.js +164 -0
- package/lib/components/provider-box.js.map +1 -0
- package/lib/components/read-group.d.ts +51 -0
- package/lib/components/read-group.d.ts.map +1 -0
- package/lib/components/read-group.js +105 -0
- package/lib/components/read-group.js.map +1 -0
- package/lib/components/root-bash.d.ts +36 -0
- package/lib/components/root-bash.d.ts.map +1 -0
- package/lib/components/root-bash.js +112 -0
- package/lib/components/root-bash.js.map +1 -0
- package/lib/components/root-types.d.ts +42 -0
- package/lib/components/root-types.d.ts.map +1 -0
- package/lib/components/root-types.js +8 -0
- package/lib/components/root-types.js.map +1 -0
- package/lib/components/root-utils.d.ts +22 -0
- package/lib/components/root-utils.d.ts.map +1 -0
- package/lib/components/root-utils.js +45 -0
- package/lib/components/root-utils.js.map +1 -0
- package/lib/components/root.d.ts +25 -0
- package/lib/components/root.d.ts.map +1 -0
- package/lib/components/root.js +357 -0
- package/lib/components/root.js.map +1 -0
- package/lib/components/theme.d.ts +61 -0
- package/lib/components/theme.d.ts.map +1 -0
- package/lib/components/theme.js +99 -0
- package/lib/components/theme.js.map +1 -0
- package/lib/components/transcript.d.ts +43 -0
- package/lib/components/transcript.d.ts.map +1 -0
- package/lib/components/transcript.js +203 -0
- package/lib/components/transcript.js.map +1 -0
- package/lib/components/working-line.d.ts +35 -0
- package/lib/components/working-line.d.ts.map +1 -0
- package/lib/components/working-line.js +66 -0
- package/lib/components/working-line.js.map +1 -0
- package/lib/effort-catalog.d.ts +27 -0
- package/lib/effort-catalog.d.ts.map +1 -0
- package/lib/effort-catalog.js +36 -0
- package/lib/effort-catalog.js.map +1 -0
- package/lib/export-markdown.d.ts +18 -0
- package/lib/export-markdown.d.ts.map +1 -0
- package/lib/export-markdown.js +124 -0
- package/lib/export-markdown.js.map +1 -0
- package/lib/harness/approval-preview.d.ts +33 -0
- package/lib/harness/approval-preview.d.ts.map +1 -0
- package/lib/harness/approval-preview.js +179 -0
- package/lib/harness/approval-preview.js.map +1 -0
- package/lib/harness/boot-banner.d.ts +14 -0
- package/lib/harness/boot-banner.d.ts.map +1 -0
- package/lib/harness/boot-banner.js +89 -0
- package/lib/harness/boot-banner.js.map +1 -0
- package/lib/harness/driver-agent.d.ts +78 -0
- package/lib/harness/driver-agent.d.ts.map +1 -0
- package/lib/harness/driver-agent.js +314 -0
- package/lib/harness/driver-agent.js.map +1 -0
- package/lib/harness/driver-agents.d.ts +20 -0
- package/lib/harness/driver-agents.d.ts.map +1 -0
- package/lib/harness/driver-agents.js +123 -0
- package/lib/harness/driver-agents.js.map +1 -0
- package/lib/harness/driver-approvals.d.ts +38 -0
- package/lib/harness/driver-approvals.d.ts.map +1 -0
- package/lib/harness/driver-approvals.js +277 -0
- package/lib/harness/driver-approvals.js.map +1 -0
- package/lib/harness/driver-bash.d.ts +15 -0
- package/lib/harness/driver-bash.d.ts.map +1 -0
- package/lib/harness/driver-bash.js +73 -0
- package/lib/harness/driver-bash.js.map +1 -0
- package/lib/harness/driver-catalog.d.ts +84 -0
- package/lib/harness/driver-catalog.d.ts.map +1 -0
- package/lib/harness/driver-catalog.js +256 -0
- package/lib/harness/driver-catalog.js.map +1 -0
- package/lib/harness/driver-ctx.d.ts +462 -0
- package/lib/harness/driver-ctx.d.ts.map +1 -0
- package/lib/harness/driver-ctx.js +11 -0
- package/lib/harness/driver-ctx.js.map +1 -0
- package/lib/harness/driver-hud.d.ts +31 -0
- package/lib/harness/driver-hud.d.ts.map +1 -0
- package/lib/harness/driver-hud.js +204 -0
- package/lib/harness/driver-hud.js.map +1 -0
- package/lib/harness/driver-live.d.ts +36 -0
- package/lib/harness/driver-live.d.ts.map +1 -0
- package/lib/harness/driver-live.js +44 -0
- package/lib/harness/driver-live.js.map +1 -0
- package/lib/harness/driver-modal.d.ts +52 -0
- package/lib/harness/driver-modal.d.ts.map +1 -0
- package/lib/harness/driver-modal.js +78 -0
- package/lib/harness/driver-modal.js.map +1 -0
- package/lib/harness/driver-mode.d.ts +35 -0
- package/lib/harness/driver-mode.d.ts.map +1 -0
- package/lib/harness/driver-mode.js +84 -0
- package/lib/harness/driver-mode.js.map +1 -0
- package/lib/harness/driver-pickers.d.ts +48 -0
- package/lib/harness/driver-pickers.d.ts.map +1 -0
- package/lib/harness/driver-pickers.js +249 -0
- package/lib/harness/driver-pickers.js.map +1 -0
- package/lib/harness/driver-promote.d.ts +29 -0
- package/lib/harness/driver-promote.d.ts.map +1 -0
- package/lib/harness/driver-promote.js +36 -0
- package/lib/harness/driver-promote.js.map +1 -0
- package/lib/harness/driver-queue.d.ts +19 -0
- package/lib/harness/driver-queue.d.ts.map +1 -0
- package/lib/harness/driver-queue.js +281 -0
- package/lib/harness/driver-queue.js.map +1 -0
- package/lib/harness/driver-run-local.d.ts +32 -0
- package/lib/harness/driver-run-local.d.ts.map +1 -0
- package/lib/harness/driver-run-local.js +366 -0
- package/lib/harness/driver-run-local.js.map +1 -0
- package/lib/harness/driver-sessions.d.ts +28 -0
- package/lib/harness/driver-sessions.d.ts.map +1 -0
- package/lib/harness/driver-sessions.js +386 -0
- package/lib/harness/driver-sessions.js.map +1 -0
- package/lib/harness/driver.d.ts +22 -0
- package/lib/harness/driver.d.ts.map +1 -0
- package/lib/harness/driver.js +459 -0
- package/lib/harness/driver.js.map +1 -0
- package/lib/harness/preset.d.ts +32 -0
- package/lib/harness/preset.d.ts.map +1 -0
- package/lib/harness/preset.js +34 -0
- package/lib/harness/preset.js.map +1 -0
- package/lib/harness/session-list.d.ts +65 -0
- package/lib/harness/session-list.d.ts.map +1 -0
- package/lib/harness/session-list.js +91 -0
- package/lib/harness/session-list.js.map +1 -0
- package/lib/harness/shell-output.d.ts +44 -0
- package/lib/harness/shell-output.d.ts.map +1 -0
- package/lib/harness/shell-output.js +90 -0
- package/lib/harness/shell-output.js.map +1 -0
- package/lib/harness/statusline-cc-transcript.d.ts +51 -0
- package/lib/harness/statusline-cc-transcript.d.ts.map +1 -0
- package/lib/harness/statusline-cc-transcript.js +191 -0
- package/lib/harness/statusline-cc-transcript.js.map +1 -0
- package/lib/harness/statusline-command.d.ts +54 -0
- package/lib/harness/statusline-command.d.ts.map +1 -0
- package/lib/harness/statusline-command.js +161 -0
- package/lib/harness/statusline-command.js.map +1 -0
- package/lib/harness/statusline-payload.d.ts +79 -0
- package/lib/harness/statusline-payload.d.ts.map +1 -0
- package/lib/harness/statusline-payload.js +93 -0
- package/lib/harness/statusline-payload.js.map +1 -0
- package/lib/harness/statusline-settings.d.ts +47 -0
- package/lib/harness/statusline-settings.d.ts.map +1 -0
- package/lib/harness/statusline-settings.js +57 -0
- package/lib/harness/statusline-settings.js.map +1 -0
- package/lib/harness/statusline-wiring.d.ts +45 -0
- package/lib/harness/statusline-wiring.d.ts.map +1 -0
- package/lib/harness/statusline-wiring.js +247 -0
- package/lib/harness/statusline-wiring.js.map +1 -0
- package/lib/harness/usage-view.d.ts +84 -0
- package/lib/harness/usage-view.d.ts.map +1 -0
- package/lib/harness/usage-view.js +199 -0
- package/lib/harness/usage-view.js.map +1 -0
- package/lib/harness/worktree-exit.d.ts +105 -0
- package/lib/harness/worktree-exit.d.ts.map +1 -0
- package/lib/harness/worktree-exit.js +168 -0
- package/lib/harness/worktree-exit.js.map +1 -0
- package/lib/history.d.ts +50 -0
- package/lib/history.d.ts.map +1 -0
- package/lib/history.js +139 -0
- package/lib/history.js.map +1 -0
- package/lib/index.d.ts +63 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +54 -0
- package/lib/index.js.map +1 -0
- package/lib/input.d.ts +158 -0
- package/lib/input.d.ts.map +1 -0
- package/lib/input.js +400 -0
- package/lib/input.js.map +1 -0
- package/lib/invariant.d.ts +14 -0
- package/lib/invariant.d.ts.map +1 -0
- package/lib/invariant.js +20 -0
- package/lib/invariant.js.map +1 -0
- package/lib/mode-cycle.d.ts +22 -0
- package/lib/mode-cycle.d.ts.map +1 -0
- package/lib/mode-cycle.js +32 -0
- package/lib/mode-cycle.js.map +1 -0
- package/lib/model-catalog.d.ts +22 -0
- package/lib/model-catalog.d.ts.map +1 -0
- package/lib/model-catalog.js +45 -0
- package/lib/model-catalog.js.map +1 -0
- package/lib/packaged-preset.d.ts +32 -0
- package/lib/packaged-preset.d.ts.map +1 -0
- package/lib/packaged-preset.js +94 -0
- package/lib/packaged-preset.js.map +1 -0
- package/lib/plugin.d.ts +11 -0
- package/lib/plugin.d.ts.map +1 -0
- package/lib/plugin.js +88 -0
- package/lib/plugin.js.map +1 -0
- package/lib/profile.d.ts +4 -0
- package/lib/profile.d.ts.map +1 -0
- package/lib/profile.js +7 -0
- package/lib/profile.js.map +1 -0
- package/lib/project-sessions.d.ts +29 -0
- package/lib/project-sessions.d.ts.map +1 -0
- package/lib/project-sessions.js +60 -0
- package/lib/project-sessions.js.map +1 -0
- package/lib/project.d.ts +75 -0
- package/lib/project.d.ts.map +1 -0
- package/lib/project.js +196 -0
- package/lib/project.js.map +1 -0
- package/lib/provider-actions.d.ts +37 -0
- package/lib/provider-actions.d.ts.map +1 -0
- package/lib/provider-actions.js +417 -0
- package/lib/provider-actions.js.map +1 -0
- package/lib/provider-command.d.ts +109 -0
- package/lib/provider-command.d.ts.map +1 -0
- package/lib/provider-command.js +220 -0
- package/lib/provider-command.js.map +1 -0
- package/lib/provider-detail.d.ts +15 -0
- package/lib/provider-detail.d.ts.map +1 -0
- package/lib/provider-detail.js +201 -0
- package/lib/provider-detail.js.map +1 -0
- package/lib/provider-flow.d.ts +191 -0
- package/lib/provider-flow.d.ts.map +1 -0
- package/lib/provider-flow.js +192 -0
- package/lib/provider-flow.js.map +1 -0
- package/lib/provider-presets.d.ts +32 -0
- package/lib/provider-presets.d.ts.map +1 -0
- package/lib/provider-presets.js +105 -0
- package/lib/provider-presets.js.map +1 -0
- package/lib/provider-read.d.ts +63 -0
- package/lib/provider-read.d.ts.map +1 -0
- package/lib/provider-read.js +115 -0
- package/lib/provider-read.js.map +1 -0
- package/lib/provider-settings.d.ts +30 -0
- package/lib/provider-settings.d.ts.map +1 -0
- package/lib/provider-settings.js +65 -0
- package/lib/provider-settings.js.map +1 -0
- package/lib/resume-target.d.ts +59 -0
- package/lib/resume-target.d.ts.map +1 -0
- package/lib/resume-target.js +143 -0
- package/lib/resume-target.js.map +1 -0
- package/lib/slash.d.ts +44 -0
- package/lib/slash.d.ts.map +1 -0
- package/lib/slash.js +81 -0
- package/lib/slash.js.map +1 -0
- package/lib/state/driver-types.d.ts +505 -0
- package/lib/state/driver-types.d.ts.map +1 -0
- package/lib/state/driver-types.js +8 -0
- package/lib/state/driver-types.js.map +1 -0
- package/lib/state/driver-usage-types.d.ts +59 -0
- package/lib/state/driver-usage-types.d.ts.map +1 -0
- package/lib/state/driver-usage-types.js +8 -0
- package/lib/state/driver-usage-types.js.map +1 -0
- package/lib/statusline.d.ts +63 -0
- package/lib/statusline.d.ts.map +1 -0
- package/lib/statusline.js +97 -0
- package/lib/statusline.js.map +1 -0
- package/lib/store/pickers.d.ts +34 -0
- package/lib/store/pickers.d.ts.map +1 -0
- package/lib/store/pickers.js +111 -0
- package/lib/store/pickers.js.map +1 -0
- package/lib/store/provider-panel.d.ts +107 -0
- package/lib/store/provider-panel.d.ts.map +1 -0
- package/lib/store/provider-panel.js +151 -0
- package/lib/store/provider-panel.js.map +1 -0
- package/lib/store/question.d.ts +21 -0
- package/lib/store/question.d.ts.map +1 -0
- package/lib/store/question.js +59 -0
- package/lib/store/question.js.map +1 -0
- package/lib/store/queue.d.ts +27 -0
- package/lib/store/queue.d.ts.map +1 -0
- package/lib/store/queue.js +34 -0
- package/lib/store/queue.js.map +1 -0
- package/lib/store/session.d.ts +73 -0
- package/lib/store/session.d.ts.map +1 -0
- package/lib/store/session.js +172 -0
- package/lib/store/session.js.map +1 -0
- package/lib/store/subagents.d.ts +16 -0
- package/lib/store/subagents.d.ts.map +1 -0
- package/lib/store/subagents.js +44 -0
- package/lib/store/subagents.js.map +1 -0
- package/lib/store/todos.d.ts +35 -0
- package/lib/store/todos.d.ts.map +1 -0
- package/lib/store/todos.js +68 -0
- package/lib/store/todos.js.map +1 -0
- package/lib/store/usage.d.ts +15 -0
- package/lib/store/usage.d.ts.map +1 -0
- package/lib/store/usage.js +27 -0
- package/lib/store/usage.js.map +1 -0
- package/lib/store/views.d.ts +419 -0
- package/lib/store/views.d.ts.map +1 -0
- package/lib/store/views.js +3 -0
- package/lib/store/views.js.map +1 -0
- package/lib/store.d.ts +19 -0
- package/lib/store.d.ts.map +1 -0
- package/lib/store.js +10 -0
- package/lib/store.js.map +1 -0
- package/lib/terminal/lease.d.ts +33 -0
- package/lib/terminal/lease.d.ts.map +1 -0
- package/lib/terminal/lease.js +99 -0
- package/lib/terminal/lease.js.map +1 -0
- package/lib/tool-card.d.ts +75 -0
- package/lib/tool-card.d.ts.map +1 -0
- package/lib/tool-card.js +109 -0
- package/lib/tool-card.js.map +1 -0
- package/lib/tool-verbs.d.ts +12 -0
- package/lib/tool-verbs.d.ts.map +1 -0
- package/lib/tool-verbs.js +29 -0
- package/lib/tool-verbs.js.map +1 -0
- package/lib/transcript.d.ts +40 -0
- package/lib/transcript.d.ts.map +1 -0
- package/lib/transcript.js +413 -0
- package/lib/transcript.js.map +1 -0
- package/lib/working-line.d.ts +44 -0
- package/lib/working-line.d.ts.map +1 -0
- package/lib/working-line.js +56 -0
- package/lib/working-line.js.map +1 -0
- package/package.json +72 -0
- package/presets/cc/.dsh-cc-managed.json +5 -0
- package/presets/cc/agent.cordis.yml +524 -0
- package/presets/cc/preset.yml +3 -0
- package/scripts/stage-preset.mjs +26 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/quit` worktree cleanup support: detect whether the session cwd is a git
|
|
3
|
+
* worktree this deployment manages, gather removal evidence, and perform the
|
|
4
|
+
* removal. Everything runs through an injectable exec so tests never spawn
|
|
5
|
+
* git.
|
|
6
|
+
*
|
|
7
|
+
* Slug/path/branch conventions mirror
|
|
8
|
+
* `packages/workspace/tool-git-worktree/src/worktree.ts` and the launcher's
|
|
9
|
+
* `packages/launcher/tui/bootstrap.mjs` (`--worktree` flag) — keep all three
|
|
10
|
+
* in sync.
|
|
11
|
+
*
|
|
12
|
+
* @module @dsh-cc/tui/harness/worktree-exit
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Env var the launcher sets when it created the session's worktree via
|
|
16
|
+
* `--worktree`. Mirrors `WORKTREE_ENV` in packages/launcher/tui/bootstrap.mjs.
|
|
17
|
+
*/
|
|
18
|
+
export declare const WORKTREE_ENV = "DSH_CC_WORKTREE";
|
|
19
|
+
/** Branch prefix marking dsh-cc-owned worktree branches. */
|
|
20
|
+
export declare const WORKTREE_BRANCH_PREFIX = "worktree-";
|
|
21
|
+
/** A successful git invocation. */
|
|
22
|
+
export interface WorktreeExecResult {
|
|
23
|
+
stdout: string;
|
|
24
|
+
stderr: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Run one git argv in `cwd`. Rejects on non-zero exit or spawn failure.
|
|
28
|
+
* Injectable so tests script the git conversation.
|
|
29
|
+
*/
|
|
30
|
+
export type WorktreeExec = (argv: readonly string[], cwd: string) => Promise<WorktreeExecResult>;
|
|
31
|
+
/** The default exec: real `git` via execFile (no shell). */
|
|
32
|
+
export declare const gitExec: WorktreeExec;
|
|
33
|
+
/** A session recognized as running inside a worktree. */
|
|
34
|
+
export interface WorktreeExitSession {
|
|
35
|
+
/**
|
|
36
|
+
* `managed`: created by the launcher's `--worktree` (env marker verified
|
|
37
|
+
* against the live cwd; carries `baseHead` and a guaranteed owned branch).
|
|
38
|
+
* `detected`: the session cwd happens to sit under a repo's
|
|
39
|
+
* `.claude/worktrees/` convention directory without a launcher marker.
|
|
40
|
+
*/
|
|
41
|
+
readonly kind: 'managed' | 'detected';
|
|
42
|
+
/** Canonical repository root (where `.claude/worktrees` lives). */
|
|
43
|
+
readonly repoRoot: string;
|
|
44
|
+
/** Absolute worktree path (the session cwd). */
|
|
45
|
+
readonly worktreePath: string;
|
|
46
|
+
/** The branch checked out in the worktree. */
|
|
47
|
+
readonly branch: string;
|
|
48
|
+
/** Managed sessions only: the commit the worktree was created from. */
|
|
49
|
+
readonly baseHead?: string;
|
|
50
|
+
}
|
|
51
|
+
/** Removal evidence shown in the exit overlay before the user confirms. */
|
|
52
|
+
export interface WorktreeExitEvidence {
|
|
53
|
+
/** Uncommitted changes (porcelain line count); undefined when unreadable. */
|
|
54
|
+
readonly dirtyFiles?: number;
|
|
55
|
+
/** Managed sessions only: commits on the worktree branch past baseHead. */
|
|
56
|
+
readonly commitsAhead?: number;
|
|
57
|
+
}
|
|
58
|
+
/** Outcome of a successful removal. */
|
|
59
|
+
export interface WorktreeCleanupOutcome {
|
|
60
|
+
/** Whether the backing branch was deleted (owned branches only). */
|
|
61
|
+
readonly branchDeleted: boolean;
|
|
62
|
+
}
|
|
63
|
+
/** The injectable seam consumed by the driver; production wires gitExec. */
|
|
64
|
+
export interface WorktreeExitHooks {
|
|
65
|
+
probe(cwd: string): Promise<WorktreeExitSession | undefined>;
|
|
66
|
+
evidence(session: WorktreeExitSession): Promise<WorktreeExitEvidence>;
|
|
67
|
+
cleanup(session: WorktreeExitSession): Promise<WorktreeCleanupOutcome>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Recognize a worktree session for `/quit`. Env marker first (it must match
|
|
71
|
+
* the live cwd — an inherited marker in a subprocess running elsewhere is
|
|
72
|
+
* ignored); otherwise probe git: the session top-level must sit under the
|
|
73
|
+
* main checkout's `.claude/worktrees/` directory. Anything else (main
|
|
74
|
+
* checkout, user-managed worktrees outside the convention dir, non-git
|
|
75
|
+
* cwd) returns undefined and `/quit` keeps its plain behavior.
|
|
76
|
+
*/
|
|
77
|
+
export declare function detectWorktreeSession(cwd: string, env?: NodeJS.ProcessEnv, exec?: WorktreeExec): Promise<WorktreeExitSession | undefined>;
|
|
78
|
+
/**
|
|
79
|
+
* Count uncommitted changes and (managed only) commits ahead of the base.
|
|
80
|
+
* Best-effort: an unreadable dimension is reported as undefined rather than
|
|
81
|
+
* failing the prompt — the user's confirmation is the removal grant.
|
|
82
|
+
*/
|
|
83
|
+
export declare function gatherEvidence(session: WorktreeExitSession, exec?: WorktreeExec): Promise<WorktreeExitEvidence>;
|
|
84
|
+
/**
|
|
85
|
+
* Whether the removal may also delete the backing branch. Managed sessions
|
|
86
|
+
* always own theirs; detected sessions only when the branch follows the
|
|
87
|
+
* `worktree-` convention (never a user's own branch).
|
|
88
|
+
*/
|
|
89
|
+
export declare function ownsBranch(session: WorktreeExitSession): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Remove the worktree directory and (when owned) its branch. The branch
|
|
92
|
+
* delete runs only after the worktree remove succeeds — git refuses to
|
|
93
|
+
* delete a branch checked out in a registered worktree, and a failed remove
|
|
94
|
+
* must not escalate into a branch delete. A failed branch delete after a
|
|
95
|
+
* successful remove is lint residue, not a failure: reported, not thrown.
|
|
96
|
+
*
|
|
97
|
+
* The process first chdirs to the repo root (via the injectable `chdir` —
|
|
98
|
+
* tests pass a no-op): the session cwd lives inside the directory being
|
|
99
|
+
* removed, and anything touching cwd between removal and process exit would
|
|
100
|
+
* otherwise fail.
|
|
101
|
+
*/
|
|
102
|
+
export declare function removeWorktree(session: WorktreeExitSession, exec?: WorktreeExec, chdir?: (dir: string) => void): Promise<WorktreeCleanupOutcome>;
|
|
103
|
+
/** The production hook set backed by real git. */
|
|
104
|
+
export declare function createWorktreeExitHooks(env?: NodeJS.ProcessEnv): WorktreeExitHooks;
|
|
105
|
+
//# sourceMappingURL=worktree-exit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree-exit.d.ts","sourceRoot":"","sources":["../../src/harness/worktree-exit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAQH;;;GAGG;AACH,eAAO,MAAM,YAAY,oBAAoB,CAAA;AAE7C,4DAA4D;AAC5D,eAAO,MAAM,sBAAsB,cAAc,CAAA;AAEjD,mCAAmC;AACnC,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAA;AAEhG,4DAA4D;AAC5D,eAAO,MAAM,OAAO,EAAE,YAMrB,CAAA;AAED,yDAAyD;AACzD,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,UAAU,CAAA;IACrC,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,gDAAgD;IAChD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,2EAA2E;AAC3E,MAAM,WAAW,oBAAoB;IACnC,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,2EAA2E;IAC3E,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED,uCAAuC;AACvC,MAAM,WAAW,sBAAsB;IACrC,oEAAoE;IACpE,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;CAChC;AAED,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CAAA;IAC5D,QAAQ,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAA;IACrE,OAAO,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAA;CACvE;AAwBD;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,EACX,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,IAAI,GAAE,YAAsB,GAC3B,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC,CA2B1C;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,mBAAmB,EAC5B,IAAI,GAAE,YAAsB,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CAsB/B;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAEhE;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,mBAAmB,EAC5B,IAAI,GAAE,YAAsB,EAC5B,KAAK,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAgC,GACvD,OAAO,CAAC,sBAAsB,CAAC,CAUjC;AAED,kDAAkD;AAClD,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,iBAAiB,CAM/F"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/quit` worktree cleanup support: detect whether the session cwd is a git
|
|
3
|
+
* worktree this deployment manages, gather removal evidence, and perform the
|
|
4
|
+
* removal. Everything runs through an injectable exec so tests never spawn
|
|
5
|
+
* git.
|
|
6
|
+
*
|
|
7
|
+
* Slug/path/branch conventions mirror
|
|
8
|
+
* `packages/workspace/tool-git-worktree/src/worktree.ts` and the launcher's
|
|
9
|
+
* `packages/launcher/tui/bootstrap.mjs` (`--worktree` flag) — keep all three
|
|
10
|
+
* in sync.
|
|
11
|
+
*
|
|
12
|
+
* @module @dsh-cc/tui/harness/worktree-exit
|
|
13
|
+
*/
|
|
14
|
+
import { execFile } from 'node:child_process';
|
|
15
|
+
import { dirname, join, resolve, sep } from 'node:path';
|
|
16
|
+
import { promisify } from 'node:util';
|
|
17
|
+
const execFileAsync = promisify(execFile);
|
|
18
|
+
/**
|
|
19
|
+
* Env var the launcher sets when it created the session's worktree via
|
|
20
|
+
* `--worktree`. Mirrors `WORKTREE_ENV` in packages/launcher/tui/bootstrap.mjs.
|
|
21
|
+
*/
|
|
22
|
+
export const WORKTREE_ENV = 'DSH_CC_WORKTREE';
|
|
23
|
+
/** Branch prefix marking dsh-cc-owned worktree branches. */
|
|
24
|
+
export const WORKTREE_BRANCH_PREFIX = 'worktree-';
|
|
25
|
+
/** The default exec: real `git` via execFile (no shell). */
|
|
26
|
+
export const gitExec = async (argv, cwd) => {
|
|
27
|
+
const { stdout, stderr } = await execFileAsync('git', [...argv], {
|
|
28
|
+
cwd,
|
|
29
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
30
|
+
});
|
|
31
|
+
return { stdout, stderr };
|
|
32
|
+
};
|
|
33
|
+
/** Parse the launcher's env marker; garbage is treated as absent. */
|
|
34
|
+
function parseMarker(raw) {
|
|
35
|
+
if (raw === undefined || raw.length === 0)
|
|
36
|
+
return undefined;
|
|
37
|
+
try {
|
|
38
|
+
const parsed = JSON.parse(raw);
|
|
39
|
+
if (typeof parsed.repoRoot !== 'string' || typeof parsed.worktreePath !== 'string'
|
|
40
|
+
|| typeof parsed.branch !== 'string') {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
repoRoot: parsed.repoRoot,
|
|
45
|
+
worktreePath: parsed.worktreePath,
|
|
46
|
+
branch: parsed.branch,
|
|
47
|
+
...(typeof parsed.baseHead === 'string' && parsed.baseHead.length > 0
|
|
48
|
+
? { baseHead: parsed.baseHead }
|
|
49
|
+
: {}),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Recognize a worktree session for `/quit`. Env marker first (it must match
|
|
58
|
+
* the live cwd — an inherited marker in a subprocess running elsewhere is
|
|
59
|
+
* ignored); otherwise probe git: the session top-level must sit under the
|
|
60
|
+
* main checkout's `.claude/worktrees/` directory. Anything else (main
|
|
61
|
+
* checkout, user-managed worktrees outside the convention dir, non-git
|
|
62
|
+
* cwd) returns undefined and `/quit` keeps its plain behavior.
|
|
63
|
+
*/
|
|
64
|
+
export async function detectWorktreeSession(cwd, env = process.env, exec = gitExec) {
|
|
65
|
+
const marker = parseMarker(env[WORKTREE_ENV]);
|
|
66
|
+
if (marker !== undefined && resolve(marker.worktreePath) === resolve(cwd)) {
|
|
67
|
+
return { kind: 'managed', ...marker };
|
|
68
|
+
}
|
|
69
|
+
let top;
|
|
70
|
+
let commonDir;
|
|
71
|
+
try {
|
|
72
|
+
top = (await exec(['rev-parse', '--show-toplevel'], cwd)).stdout.trim();
|
|
73
|
+
commonDir = (await exec(['rev-parse', '--path-format=absolute', '--git-common-dir'], cwd)).stdout.trim();
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
// The common dir of a standard layout is `<mainRoot>/.git`; anything else
|
|
79
|
+
// (bare repo, exotic GIT_DIR) is not ours to reason about.
|
|
80
|
+
if (!commonDir.endsWith(`${sep}.git`))
|
|
81
|
+
return undefined;
|
|
82
|
+
const mainRoot = dirname(commonDir);
|
|
83
|
+
if (resolve(top) === resolve(mainRoot))
|
|
84
|
+
return undefined;
|
|
85
|
+
const conventionDir = join(mainRoot, '.claude', 'worktrees');
|
|
86
|
+
if (!resolve(top).startsWith(conventionDir + sep))
|
|
87
|
+
return undefined;
|
|
88
|
+
let branch = '';
|
|
89
|
+
try {
|
|
90
|
+
branch = (await exec(['rev-parse', '--abbrev-ref', 'HEAD'], top)).stdout.trim();
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
return { kind: 'detected', repoRoot: mainRoot, worktreePath: top, branch };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Count uncommitted changes and (managed only) commits ahead of the base.
|
|
99
|
+
* Best-effort: an unreadable dimension is reported as undefined rather than
|
|
100
|
+
* failing the prompt — the user's confirmation is the removal grant.
|
|
101
|
+
*/
|
|
102
|
+
export async function gatherEvidence(session, exec = gitExec) {
|
|
103
|
+
let dirtyFiles;
|
|
104
|
+
try {
|
|
105
|
+
const status = await exec(['status', '--porcelain'], session.worktreePath);
|
|
106
|
+
dirtyFiles = status.stdout.split('\n').filter(line => line.trim().length > 0).length;
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
dirtyFiles = undefined;
|
|
110
|
+
}
|
|
111
|
+
let commitsAhead;
|
|
112
|
+
if (session.baseHead !== undefined) {
|
|
113
|
+
try {
|
|
114
|
+
const revs = await exec(['rev-list', '--count', `${session.baseHead}..HEAD`], session.worktreePath);
|
|
115
|
+
const parsed = Number.parseInt(revs.stdout.trim(), 10);
|
|
116
|
+
commitsAhead = Number.isNaN(parsed) ? undefined : parsed;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
commitsAhead = undefined;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
...(dirtyFiles === undefined ? {} : { dirtyFiles }),
|
|
124
|
+
...(commitsAhead === undefined ? {} : { commitsAhead }),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Whether the removal may also delete the backing branch. Managed sessions
|
|
129
|
+
* always own theirs; detected sessions only when the branch follows the
|
|
130
|
+
* `worktree-` convention (never a user's own branch).
|
|
131
|
+
*/
|
|
132
|
+
export function ownsBranch(session) {
|
|
133
|
+
return session.kind === 'managed' || session.branch.startsWith(WORKTREE_BRANCH_PREFIX);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Remove the worktree directory and (when owned) its branch. The branch
|
|
137
|
+
* delete runs only after the worktree remove succeeds — git refuses to
|
|
138
|
+
* delete a branch checked out in a registered worktree, and a failed remove
|
|
139
|
+
* must not escalate into a branch delete. A failed branch delete after a
|
|
140
|
+
* successful remove is lint residue, not a failure: reported, not thrown.
|
|
141
|
+
*
|
|
142
|
+
* The process first chdirs to the repo root (via the injectable `chdir` —
|
|
143
|
+
* tests pass a no-op): the session cwd lives inside the directory being
|
|
144
|
+
* removed, and anything touching cwd between removal and process exit would
|
|
145
|
+
* otherwise fail.
|
|
146
|
+
*/
|
|
147
|
+
export async function removeWorktree(session, exec = gitExec, chdir = dir => process.chdir(dir)) {
|
|
148
|
+
chdir(session.repoRoot);
|
|
149
|
+
await exec(['worktree', 'remove', '--force', session.worktreePath], session.repoRoot);
|
|
150
|
+
if (!ownsBranch(session))
|
|
151
|
+
return { branchDeleted: false };
|
|
152
|
+
try {
|
|
153
|
+
await exec(['branch', '-D', session.branch], session.repoRoot);
|
|
154
|
+
return { branchDeleted: true };
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return { branchDeleted: false };
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/** The production hook set backed by real git. */
|
|
161
|
+
export function createWorktreeExitHooks(env = process.env) {
|
|
162
|
+
return {
|
|
163
|
+
probe: cwd => detectWorktreeSession(cwd, env, gitExec),
|
|
164
|
+
evidence: session => gatherEvidence(session, gitExec),
|
|
165
|
+
cleanup: session => removeWorktree(session, gitExec),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=worktree-exit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree-exit.js","sourceRoot":"","sources":["../../src/harness/worktree-exit.ts"],"names":[],"mappings":"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"}
|
package/lib/history.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persisted composer prompt history. Prompts (not slash commands) are stored
|
|
3
|
+
* as JSON-lines under the profile data dir so ↑/↓ recall survives restarts.
|
|
4
|
+
* fs access is best-effort: a corrupt or unwritable file degrades silently to
|
|
5
|
+
* an empty history and never breaks a session.
|
|
6
|
+
*
|
|
7
|
+
* One JSON string per physical line — the encoding is unambiguous for
|
|
8
|
+
* multi-line prompts (embedded newlines are escaped by JSON.stringify, so a
|
|
9
|
+
* single entry never spans multiple physical lines). Plain-line storage would
|
|
10
|
+
* split a multi-line prompt across lines and corrupt line-based loading.
|
|
11
|
+
*
|
|
12
|
+
* @module @dsh-cc/tui/history
|
|
13
|
+
*/
|
|
14
|
+
/** Maximum entries retained; the oldest are dropped when exceeded. */
|
|
15
|
+
export declare const HISTORY_CAP = 500;
|
|
16
|
+
/** Absolute path to the history file under the data dir. */
|
|
17
|
+
export declare function historyFilePath(dir?: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* The default `tui` data dir (`$DSH_HOME/tui` or `~/.dsh/tui`) with no
|
|
20
|
+
* override — the parent of the per-project `projects/<key>` buckets and the
|
|
21
|
+
* home of the legacy global files {@link coldCutGlobalHistory} sets aside.
|
|
22
|
+
*/
|
|
23
|
+
export declare function defaultTuiDir(): string;
|
|
24
|
+
/**
|
|
25
|
+
* One-time migration off the pre-project *global* history files. Before
|
|
26
|
+
* history was bucketed per project, prompts and bash commands both lived in
|
|
27
|
+
* single files under `$DSH_HOME/tui` (`history.txt`, `bash-history.txt`),
|
|
28
|
+
* leaking across every directory — the very reason per-project history now
|
|
29
|
+
* exists. Those files carry no provenance, so they cannot be split back onto
|
|
30
|
+
* their projects; they are set aside as `<name>.global.bak` (a previous backup
|
|
31
|
+
* is overwritten) and each project starts its history empty. Best-effort: a
|
|
32
|
+
* missing source or unwritable dir is a silent no-op that never breaks boot.
|
|
33
|
+
*
|
|
34
|
+
* @param tuiDir the `tui` directory holding the legacy global files
|
|
35
|
+
* (`$DSH_HOME/tui`, or `~/.dsh/tui`).
|
|
36
|
+
*/
|
|
37
|
+
export declare function coldCutGlobalHistory(tuiDir: string): void;
|
|
38
|
+
/**
|
|
39
|
+
* Read persisted history (oldest→newest). Missing or corrupt file → `[]`;
|
|
40
|
+
* never throws.
|
|
41
|
+
*/
|
|
42
|
+
export declare function loadHistory(dir?: string): string[];
|
|
43
|
+
/**
|
|
44
|
+
* Write the full list (capped, consecutive-duplicate suppressed) to disk as
|
|
45
|
+
* JSON-lines. Returns the normalised list so callers can keep their in-memory
|
|
46
|
+
* copy in sync with what was actually persisted. Best-effort: fs failures are
|
|
47
|
+
* swallowed (the returned list still reflects the intended state).
|
|
48
|
+
*/
|
|
49
|
+
export declare function saveHistory(entries: readonly string[], dir?: string): string[];
|
|
50
|
+
//# sourceMappingURL=history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAMH,sEAAsE;AACtE,eAAO,MAAM,WAAW,MAAM,CAAA;AAa9B,4DAA4D;AAC5D,wBAAgB,eAAe,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAsBzD;AAiBD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAclD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAY9E"}
|
package/lib/history.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persisted composer prompt history. Prompts (not slash commands) are stored
|
|
3
|
+
* as JSON-lines under the profile data dir so ↑/↓ recall survives restarts.
|
|
4
|
+
* fs access is best-effort: a corrupt or unwritable file degrades silently to
|
|
5
|
+
* an empty history and never breaks a session.
|
|
6
|
+
*
|
|
7
|
+
* One JSON string per physical line — the encoding is unambiguous for
|
|
8
|
+
* multi-line prompts (embedded newlines are escaped by JSON.stringify, so a
|
|
9
|
+
* single entry never spans multiple physical lines). Plain-line storage would
|
|
10
|
+
* split a multi-line prompt across lines and corrupt line-based loading.
|
|
11
|
+
*
|
|
12
|
+
* @module @dsh-cc/tui/history
|
|
13
|
+
*/
|
|
14
|
+
import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
15
|
+
import { homedir } from 'node:os';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
/** Maximum entries retained; the oldest are dropped when exceeded. */
|
|
18
|
+
export const HISTORY_CAP = 500;
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the data directory (the `tui` dir). An injected `dir` overrides;
|
|
21
|
+
* otherwise mirrors {@link resume-target} resolution: `$DSH_HOME/tui` or
|
|
22
|
+
* `~/.dsh/tui`.
|
|
23
|
+
*/
|
|
24
|
+
function dataDir(dir) {
|
|
25
|
+
if (dir !== undefined)
|
|
26
|
+
return dir;
|
|
27
|
+
const dshHome = process.env.DSH_HOME ?? join(homedir(), '.dsh');
|
|
28
|
+
return join(dshHome, 'tui');
|
|
29
|
+
}
|
|
30
|
+
/** Absolute path to the history file under the data dir. */
|
|
31
|
+
export function historyFilePath(dir) {
|
|
32
|
+
return join(dataDir(dir), 'history.txt');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The default `tui` data dir (`$DSH_HOME/tui` or `~/.dsh/tui`) with no
|
|
36
|
+
* override — the parent of the per-project `projects/<key>` buckets and the
|
|
37
|
+
* home of the legacy global files {@link coldCutGlobalHistory} sets aside.
|
|
38
|
+
*/
|
|
39
|
+
export function defaultTuiDir() {
|
|
40
|
+
return dataDir();
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* One-time migration off the pre-project *global* history files. Before
|
|
44
|
+
* history was bucketed per project, prompts and bash commands both lived in
|
|
45
|
+
* single files under `$DSH_HOME/tui` (`history.txt`, `bash-history.txt`),
|
|
46
|
+
* leaking across every directory — the very reason per-project history now
|
|
47
|
+
* exists. Those files carry no provenance, so they cannot be split back onto
|
|
48
|
+
* their projects; they are set aside as `<name>.global.bak` (a previous backup
|
|
49
|
+
* is overwritten) and each project starts its history empty. Best-effort: a
|
|
50
|
+
* missing source or unwritable dir is a silent no-op that never breaks boot.
|
|
51
|
+
*
|
|
52
|
+
* @param tuiDir the `tui` directory holding the legacy global files
|
|
53
|
+
* (`$DSH_HOME/tui`, or `~/.dsh/tui`).
|
|
54
|
+
*/
|
|
55
|
+
export function coldCutGlobalHistory(tuiDir) {
|
|
56
|
+
const moves = {
|
|
57
|
+
'history.txt': 'history.global.bak',
|
|
58
|
+
'bash-history.txt': 'bash-history.global.bak',
|
|
59
|
+
};
|
|
60
|
+
for (const [from, to] of Object.entries(moves)) {
|
|
61
|
+
const src = join(tuiDir, from);
|
|
62
|
+
const dst = join(tuiDir, to);
|
|
63
|
+
// Drop any prior backup (POSIX rename would overwrite it, Windows refuses
|
|
64
|
+
// to — clearing first makes both platforms behave the same), then move the
|
|
65
|
+
// legacy global file aside. Missing source is the common no-op.
|
|
66
|
+
try {
|
|
67
|
+
rmSync(dst, { force: true });
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// Unwritable — best-effort.
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
renameSync(src, dst);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Missing source (or unwritable dir) — best-effort, never break boot.
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Normalise an entry list: drop empty/whitespace-only entries, suppress
|
|
82
|
+
* consecutive duplicates, and cap to {@link HISTORY_CAP} (keeping the newest).
|
|
83
|
+
*/
|
|
84
|
+
function normalize(entries) {
|
|
85
|
+
const out = [];
|
|
86
|
+
for (const entry of entries) {
|
|
87
|
+
if (typeof entry !== 'string')
|
|
88
|
+
continue;
|
|
89
|
+
if (entry.length === 0 || entry.trim().length === 0)
|
|
90
|
+
continue;
|
|
91
|
+
if (out.length > 0 && out[out.length - 1] === entry)
|
|
92
|
+
continue;
|
|
93
|
+
out.push(entry);
|
|
94
|
+
}
|
|
95
|
+
return out.slice(-HISTORY_CAP);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Read persisted history (oldest→newest). Missing or corrupt file → `[]`;
|
|
99
|
+
* never throws.
|
|
100
|
+
*/
|
|
101
|
+
export function loadHistory(dir) {
|
|
102
|
+
try {
|
|
103
|
+
const content = readFileSync(historyFilePath(dir), 'utf8');
|
|
104
|
+
const lines = content.split('\n');
|
|
105
|
+
const entries = [];
|
|
106
|
+
for (const line of lines) {
|
|
107
|
+
if (line.length === 0)
|
|
108
|
+
continue;
|
|
109
|
+
const parsed = JSON.parse(line);
|
|
110
|
+
if (typeof parsed === 'string' && parsed.length > 0)
|
|
111
|
+
entries.push(parsed);
|
|
112
|
+
}
|
|
113
|
+
return entries;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return [];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Write the full list (capped, consecutive-duplicate suppressed) to disk as
|
|
121
|
+
* JSON-lines. Returns the normalised list so callers can keep their in-memory
|
|
122
|
+
* copy in sync with what was actually persisted. Best-effort: fs failures are
|
|
123
|
+
* swallowed (the returned list still reflects the intended state).
|
|
124
|
+
*/
|
|
125
|
+
export function saveHistory(entries, dir) {
|
|
126
|
+
const normalized = normalize(entries);
|
|
127
|
+
try {
|
|
128
|
+
mkdirSync(dataDir(dir), { recursive: true });
|
|
129
|
+
const content = normalized.length === 0
|
|
130
|
+
? ''
|
|
131
|
+
: `${normalized.map(entry => JSON.stringify(entry)).join('\n')}\n`;
|
|
132
|
+
writeFileSync(historyFilePath(dir), content);
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Persistence is best-effort; never break the session over a write.
|
|
136
|
+
}
|
|
137
|
+
return normalized;
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../src/history.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cordis plugin surface for the CC-mode TUI. Heavy wiring lives behind a
|
|
3
|
+
* dynamic import so a boot failure is a plugin error, not a module-load crash.
|
|
4
|
+
* @module @dsh-cc/tui
|
|
5
|
+
*/
|
|
6
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
7
|
+
import Schema from '@deepseek-ai/schemastery';
|
|
8
|
+
import type { ThemeOverrides } from './components/theme.ts';
|
|
9
|
+
export declare const name = "dsh-cc-tui";
|
|
10
|
+
export declare const inject: string[];
|
|
11
|
+
export interface Config {
|
|
12
|
+
cwd?: string;
|
|
13
|
+
agentPreset?: string;
|
|
14
|
+
sessionId?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Allow boot-time resume from the project's resume marker. When true (and
|
|
17
|
+
* `sessionId` is not set), the TUI reads `projects/<projectKey>/resume.txt`
|
|
18
|
+
* on boot and attaches the most recent session of this project. The
|
|
19
|
+
* `dsh-cc` launcher sets this for a bare `dsh-cc` launch; false/undefined
|
|
20
|
+
* default to a fresh session.
|
|
21
|
+
*/
|
|
22
|
+
autoResume?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* `-c`/`--continue` was requested. Only affects the "no previous session
|
|
25
|
+
* to continue" notice when `autoResume` finds no marker — it does not force
|
|
26
|
+
* a resume by itself.
|
|
27
|
+
*/
|
|
28
|
+
continueRequested?: boolean;
|
|
29
|
+
provider?: string;
|
|
30
|
+
model?: string;
|
|
31
|
+
allowNoTty?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Terminal surface mode. 'regular' renders inline into the main screen
|
|
34
|
+
* scrollback; 'fullscreen' takes over the alternate screen on start with a
|
|
35
|
+
* docked layout. Plugin-level default is 'regular' — the
|
|
36
|
+
* cc-tui bundle profile pins 'fullscreen' for fullscreen-on-entry.
|
|
37
|
+
*/
|
|
38
|
+
uiMode?: 'regular' | 'fullscreen';
|
|
39
|
+
/**
|
|
40
|
+
* Fullscreen-only: capture the mouse for viewport scrolling and
|
|
41
|
+
* application-owned text selection (OSC 52 copy). Default true.
|
|
42
|
+
*/
|
|
43
|
+
mouse?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Per-role palette overrides for the terminal theme. Every role accepts a
|
|
46
|
+
* basic ANSI color name ('red', 'brightCyan') or a raw SGR code string
|
|
47
|
+
* ('31', '1;31'); unknown values silently fall back to the built-in
|
|
48
|
+
* default, so omitting a role (or the whole block) keeps the default look.
|
|
49
|
+
*/
|
|
50
|
+
theme?: ThemeOverrides;
|
|
51
|
+
}
|
|
52
|
+
export declare const Config: Schema<Config>;
|
|
53
|
+
/**
|
|
54
|
+
* Effective UI mode. Precedence: the DSH_CCTUI_UI_MODE env beats plugin
|
|
55
|
+
* config, config beats the 'regular' default. The env is the instant escape
|
|
56
|
+
* hatch when a profile pins fullscreen and the terminal cannot cope.
|
|
57
|
+
*/
|
|
58
|
+
export declare function resolveUiMode(config: Config): 'regular' | 'fullscreen';
|
|
59
|
+
/**
|
|
60
|
+
* Mount the terminal surface. Requires a TTY unless `allowNoTty`.
|
|
61
|
+
*/
|
|
62
|
+
export declare function apply(ctx: Context, config: Config): Promise<void>;
|
|
63
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAG3D,eAAO,MAAM,IAAI,eAAe,CAAA;AAChC,eAAO,MAAM,MAAM,UAAa,CAAA;AAEhC,MAAM,WAAW,MAAM;IACrB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,SAAS,GAAG,YAAY,CAAA;IACjC;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;;OAKG;IACH,KAAK,CAAC,EAAE,cAAc,CAAA;CACvB;AAED,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,CAmBhC,CAAA;AAEF;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAItE;AAED;;GAEG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASvE"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cordis plugin surface for the CC-mode TUI. Heavy wiring lives behind a
|
|
3
|
+
* dynamic import so a boot failure is a plugin error, not a module-load crash.
|
|
4
|
+
* @module @dsh-cc/tui
|
|
5
|
+
*/
|
|
6
|
+
import Schema from '@deepseek-ai/schemastery';
|
|
7
|
+
import { resolveDshProfile } from "./profile.js";
|
|
8
|
+
export const name = 'dsh-cc-tui';
|
|
9
|
+
export const inject = ['agents'];
|
|
10
|
+
export const Config = Schema.object({
|
|
11
|
+
cwd: Schema.string(),
|
|
12
|
+
agentPreset: Schema.string(),
|
|
13
|
+
sessionId: Schema.string(),
|
|
14
|
+
autoResume: Schema.boolean(),
|
|
15
|
+
continueRequested: Schema.boolean(),
|
|
16
|
+
provider: Schema.string(),
|
|
17
|
+
model: Schema.string(),
|
|
18
|
+
allowNoTty: Schema.boolean(),
|
|
19
|
+
uiMode: Schema.union([Schema.const('regular'), Schema.const('fullscreen')]),
|
|
20
|
+
mouse: Schema.boolean(),
|
|
21
|
+
theme: Schema.object({
|
|
22
|
+
accent: Schema.string(),
|
|
23
|
+
success: Schema.string(),
|
|
24
|
+
error: Schema.string(),
|
|
25
|
+
warning: Schema.string(),
|
|
26
|
+
muted: Schema.string(),
|
|
27
|
+
highlight: Schema.string(),
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* Effective UI mode. Precedence: the DSH_CCTUI_UI_MODE env beats plugin
|
|
32
|
+
* config, config beats the 'regular' default. The env is the instant escape
|
|
33
|
+
* hatch when a profile pins fullscreen and the terminal cannot cope.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveUiMode(config) {
|
|
36
|
+
const env = process.env.DSH_CCTUI_UI_MODE;
|
|
37
|
+
if (env === 'fullscreen' || env === 'regular')
|
|
38
|
+
return env;
|
|
39
|
+
return config.uiMode === 'fullscreen' ? 'fullscreen' : 'regular';
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Mount the terminal surface. Requires a TTY unless `allowNoTty`.
|
|
43
|
+
*/
|
|
44
|
+
export async function apply(ctx, config) {
|
|
45
|
+
const allowNoTty = config.allowNoTty === true || process.env.DSH_CCTUI_ALLOW_NO_TTY === '1';
|
|
46
|
+
if (!allowNoTty && !process.stdout.isTTY) {
|
|
47
|
+
throw new Error('dsh-cc-tui requires an interactive terminal (stdout must be a TTY).');
|
|
48
|
+
}
|
|
49
|
+
ctx.provide('dshProfile', resolveDshProfile());
|
|
50
|
+
process.env.NODE_ENV ??= 'production';
|
|
51
|
+
const { mountTui } = await import("./plugin.js");
|
|
52
|
+
await mountTui(ctx, { ...config, uiMode: resolveUiMode(config) });
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,MAAM,MAAM,0BAA0B,CAAA;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAEhD,MAAM,CAAC,MAAM,IAAI,GAAG,YAAY,CAAA;AAChC,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAA;AA4ChC,MAAM,CAAC,MAAM,MAAM,GAAmB,MAAM,CAAC,MAAM,CAAC;IAClD,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;IAC5B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE;IAC1B,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE;IAC5B,iBAAiB,EAAE,MAAM,CAAC,OAAO,EAAE;IACnC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;IACzB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;IACtB,UAAU,EAAE,MAAM,CAAC,OAAO,EAAE;IAC5B,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;IAC3E,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE;IACvB,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE;QACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QACxB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;QACtB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE;QACxB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE;QACtB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE;KAC3B,CAAC;CACH,CAAC,CAAA;AAEF;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAA;IACzC,IAAI,GAAG,KAAK,YAAY,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,GAAG,CAAA;IACzD,OAAO,MAAM,CAAC,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAA;AAClE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,GAAY,EAAE,MAAc;IACtD,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,KAAK,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAsB,KAAK,GAAG,CAAA;IAC3F,IAAI,CAAC,UAAU,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACzC,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAA;IACxF,CAAC;IACD,GAAG,CAAC,OAAO,CAAC,YAAY,EAAE,iBAAiB,EAAE,CAAC,CAAA;IAC9C,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAA;IACrC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;IAChD,MAAM,QAAQ,CAAC,GAAG,EAAE,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;AACnE,CAAC"}
|