@pat-lewczuk/cezar 0.1.2 → 0.1.4

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.
Files changed (164) hide show
  1. package/README.md +249 -45
  2. package/dist/config.d.ts +8 -0
  3. package/dist/config.js +6 -0
  4. package/dist/config.js.map +1 -1
  5. package/dist/core/agent-runner.d.ts +44 -2
  6. package/dist/core/agent-runner.js +8 -2
  7. package/dist/core/agent-runner.js.map +1 -1
  8. package/dist/core/backend-detect.d.ts +6 -4
  9. package/dist/core/backend-detect.js +44 -4
  10. package/dist/core/backend-detect.js.map +1 -1
  11. package/dist/core/claude-cli-runner.d.ts +3 -25
  12. package/dist/core/claude-cli-runner.js +2 -19
  13. package/dist/core/claude-cli-runner.js.map +1 -1
  14. package/dist/core/claude-ui-mapper.d.ts +57 -0
  15. package/dist/core/claude-ui-mapper.js +370 -0
  16. package/dist/core/claude-ui-mapper.js.map +1 -0
  17. package/dist/core/codex-app-server-runner.d.ts +29 -0
  18. package/dist/core/codex-app-server-runner.js +452 -0
  19. package/dist/core/codex-app-server-runner.js.map +1 -0
  20. package/dist/core/codex-ui-mapper.d.ts +53 -0
  21. package/dist/core/codex-ui-mapper.js +411 -0
  22. package/dist/core/codex-ui-mapper.js.map +1 -0
  23. package/dist/core/ndjson.d.ts +6 -0
  24. package/dist/core/ndjson.js +23 -0
  25. package/dist/core/ndjson.js.map +1 -0
  26. package/dist/core/opencode-server-runner.d.ts +30 -0
  27. package/dist/core/opencode-server-runner.js +451 -0
  28. package/dist/core/opencode-server-runner.js.map +1 -0
  29. package/dist/core/opencode-ui-mapper.d.ts +105 -0
  30. package/dist/core/opencode-ui-mapper.js +578 -0
  31. package/dist/core/opencode-ui-mapper.js.map +1 -0
  32. package/dist/core/process-usage.d.ts +63 -0
  33. package/dist/core/process-usage.js +181 -0
  34. package/dist/core/process-usage.js.map +1 -0
  35. package/dist/core/runner-factory.d.ts +8 -0
  36. package/dist/core/runner-factory.js +22 -0
  37. package/dist/core/runner-factory.js.map +1 -0
  38. package/dist/core/tool-display.d.ts +27 -0
  39. package/dist/core/tool-display.js +150 -0
  40. package/dist/core/tool-display.js.map +1 -0
  41. package/dist/core/ui-events.d.ts +294 -0
  42. package/dist/core/ui-events.js +25 -0
  43. package/dist/core/ui-events.js.map +1 -0
  44. package/dist/index.js +0 -0
  45. package/dist/pack-check.d.ts +17 -0
  46. package/dist/pack-check.js +27 -0
  47. package/dist/pack-check.js.map +1 -0
  48. package/dist/planner.js +7 -3
  49. package/dist/planner.js.map +1 -1
  50. package/dist/runs/store.d.ts +5 -0
  51. package/dist/runs/store.js +3 -0
  52. package/dist/runs/store.js.map +1 -1
  53. package/dist/runs/title-summary.d.ts +15 -0
  54. package/dist/runs/title-summary.js +84 -0
  55. package/dist/runs/title-summary.js.map +1 -0
  56. package/dist/runs/ui-event-sink.d.ts +81 -0
  57. package/dist/runs/ui-event-sink.js +210 -0
  58. package/dist/runs/ui-event-sink.js.map +1 -0
  59. package/dist/server/capabilities.d.ts +18 -0
  60. package/dist/server/capabilities.js +23 -0
  61. package/dist/server/capabilities.js.map +1 -0
  62. package/dist/server/forge/github.d.ts +39 -0
  63. package/dist/server/forge/github.js +369 -0
  64. package/dist/server/forge/github.js.map +1 -0
  65. package/dist/server/forge/index.d.ts +24 -0
  66. package/dist/server/forge/index.js +45 -0
  67. package/dist/server/forge/index.js.map +1 -0
  68. package/dist/server/forge/types.d.ts +80 -0
  69. package/dist/server/forge/types.js +2 -0
  70. package/dist/server/forge/types.js.map +1 -0
  71. package/dist/server/git-changes.d.ts +182 -0
  72. package/dist/server/git-changes.js +424 -0
  73. package/dist/server/git-changes.js.map +1 -0
  74. package/dist/server/open-in-app.d.ts +19 -0
  75. package/dist/server/open-in-app.js +134 -0
  76. package/dist/server/open-in-app.js.map +1 -0
  77. package/dist/server/server.js +34 -10
  78. package/dist/server/server.js.map +1 -1
  79. package/dist/server/static-ui.d.ts +49 -0
  80. package/dist/server/static-ui.js +92 -0
  81. package/dist/server/static-ui.js.map +1 -0
  82. package/dist/update-check.d.ts +12 -0
  83. package/dist/update-check.js +41 -0
  84. package/dist/update-check.js.map +1 -0
  85. package/dist/workflows/run.d.ts +3 -0
  86. package/dist/workflows/run.js +22 -7
  87. package/dist/workflows/run.js.map +1 -1
  88. package/dist/workflows/types.d.ts +16 -0
  89. package/dist/workflows/types.js +3 -1
  90. package/dist/workflows/types.js.map +1 -1
  91. package/package.json +1 -1
  92. package/web/app/node_modules/.vite/vitest/ca84d1343b96baa8137c943ed1860e522cacb238/results.json +1 -0
  93. package/web/app/src/components/app-shell-container.tsx +76 -0
  94. package/web/app.js +145 -18
  95. package/web/dist/assets/arrow-left-BE957rJs.js +1 -0
  96. package/web/dist/assets/bundle-mjs-DLPpRFyl.js +1 -0
  97. package/web/dist/assets/chunk-BO2N2NFS-f5igTtpB.js +131 -0
  98. package/web/dist/assets/compare-variants-D6fPL9cS.js +1 -0
  99. package/web/dist/assets/core-BuMqAF_1.js +12 -0
  100. package/web/dist/assets/css-BsVw1vtW.js +1 -0
  101. package/web/dist/assets/dialog-BEgEWFDS.js +1 -0
  102. package/web/dist/assets/diff-view-CctnJHWe.js +4 -0
  103. package/web/dist/assets/diff-woXpYk--.js +1 -0
  104. package/web/dist/assets/dist-CW7M_Jhs.js +1 -0
  105. package/web/dist/assets/ellipsis-vertical-DJPAfccS.js +1 -0
  106. package/web/dist/assets/engine-javascript-FQvzRocB.js +141 -0
  107. package/web/dist/assets/folder-RbRLfIX-.js +1 -0
  108. package/web/dist/assets/git-pull-request-DJkAMT0f.js +1 -0
  109. package/web/dist/assets/git-toolbar-D8OPPqBP.js +1 -0
  110. package/web/dist/assets/github-BYIHwIJB.js +1 -0
  111. package/web/dist/assets/go-rLFTqkRN.js +1 -0
  112. package/web/dist/assets/highlighted-body-OFNGDK62-DGHHie_q.js +1 -0
  113. package/web/dist/assets/highlighter-BKVEsACy.js +3 -0
  114. package/web/dist/assets/html-BY76lXLH.js +1 -0
  115. package/web/dist/assets/index-9qG98Orw.js +11 -0
  116. package/web/dist/assets/index-Bz_r8Jt3.css +2 -0
  117. package/web/dist/assets/input-BRsSo4xH.js +1 -0
  118. package/web/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  119. package/web/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  120. package/web/dist/assets/javascript-BgS3c2Ky.js +1 -0
  121. package/web/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
  122. package/web/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
  123. package/web/dist/assets/json-qhed-kSA.js +1 -0
  124. package/web/dist/assets/jsonc-CYpm1nAK.js +1 -0
  125. package/web/dist/assets/jsx-Bz0zcwM4.js +1 -0
  126. package/web/dist/assets/lib-CNGa3Dig.js +1 -0
  127. package/web/dist/assets/loader-circle-BV3DO9mE.js +1 -0
  128. package/web/dist/assets/markdown-BYOwaDjH.js +1 -0
  129. package/web/dist/assets/markdown-CR_HLGTs.js +1 -0
  130. package/web/dist/assets/mermaid-GHXKKRXX-DM2VsGBG.js +1 -0
  131. package/web/dist/assets/open-mercato-toBr6SOa.svg +11 -0
  132. package/web/dist/assets/python-gzcpVVnB.js +1 -0
  133. package/web/dist/assets/react-dom-Ddtik4qM.js +1 -0
  134. package/web/dist/assets/refresh-cw-DCa-Rlwz.js +1 -0
  135. package/web/dist/assets/repo-git-XTqlVOl2.js +1 -0
  136. package/web/dist/assets/run-diff-C7mfxj7f.js +3 -0
  137. package/web/dist/assets/run-header-CfVeY3uM.js +1 -0
  138. package/web/dist/assets/rust-Cfkwpbl8.js +1 -0
  139. package/web/dist/assets/search-x-CoCyl7zT.js +1 -0
  140. package/web/dist/assets/shellscript-CLZ0U2zV.js +1 -0
  141. package/web/dist/assets/skill-detail-C9cniyId.js +1 -0
  142. package/web/dist/assets/skills-DXgY1uXJ.js +1 -0
  143. package/web/dist/assets/skills-ynuO5oCr.js +1 -0
  144. package/web/dist/assets/sql-BsFa4tDR.js +1 -0
  145. package/web/dist/assets/square-terminal-B6PZX4Qp.js +1 -0
  146. package/web/dist/assets/tab-link-phWEqSBy.js +1 -0
  147. package/web/dist/assets/task-changes-DYwnPnTN.js +1 -0
  148. package/web/dist/assets/task-commits-DZzxEzbn.js +1 -0
  149. package/web/dist/assets/task-files-FOAAz2FB.js +2 -0
  150. package/web/dist/assets/task-thread-Bncxe8Os.js +5 -0
  151. package/web/dist/assets/toaster-BS2E1bhz.js +43 -0
  152. package/web/dist/assets/trash-2-CDtxmmc8.js +1 -0
  153. package/web/dist/assets/triangle-alert-6su4Js5O.js +1 -0
  154. package/web/dist/assets/tsx-udAQXfEw.js +1 -0
  155. package/web/dist/assets/typescript-bsJCZSQ-.js +1 -0
  156. package/web/dist/assets/upload-Bp7hQxll.js +1 -0
  157. package/web/dist/assets/use-desktop-eHm2iTXX.js +3 -0
  158. package/web/dist/assets/utils-rQGbOrwc.js +1 -0
  159. package/web/dist/assets/workflows-Dg2wQg6i.js +11 -0
  160. package/web/dist/assets/x-Br_jIDBw.js +1 -0
  161. package/web/dist/assets/yaml-rwi0_p6S.js +1 -0
  162. package/web/dist/index.html +67 -0
  163. package/web/index.html +1 -0
  164. package/web/style.css +28 -8
@@ -0,0 +1,182 @@
1
+ export interface ChangedFile {
2
+ path: string;
3
+ /** Rename/copy source — present only when `status` is renamed/copied. */
4
+ oldPath?: string;
5
+ status: 'added' | 'modified' | 'deleted' | 'renamed' | 'copied';
6
+ adds: number;
7
+ dels: number;
8
+ binary: boolean;
9
+ patch: string;
10
+ }
11
+ export interface ChangesPayload {
12
+ files: ChangedFile[];
13
+ stat: {
14
+ adds: number;
15
+ dels: number;
16
+ files: number;
17
+ };
18
+ }
19
+ export type ChangesResult = {
20
+ ok: true;
21
+ changes: ChangesPayload;
22
+ } | {
23
+ ok: false;
24
+ error: string;
25
+ };
26
+ interface NumstatEntry {
27
+ adds: number;
28
+ dels: number;
29
+ binary: boolean;
30
+ path: string;
31
+ oldPath?: string;
32
+ }
33
+ /** Parse `git diff --numstat -z -M`: `adds TAB dels TAB path NUL`, or for a
34
+ * rename/copy `adds TAB dels TAB NUL old NUL new NUL`. Binary files report
35
+ * `-` for both counters. Exported for tests. */
36
+ export declare function parseNumstatZ(out: string): NumstatEntry[];
37
+ interface NameStatusEntry {
38
+ status: string;
39
+ path: string;
40
+ oldPath?: string;
41
+ }
42
+ /** Parse `git diff --name-status -z -M`: `X NUL path NUL`, renames/copies
43
+ * `Rnnn NUL old NUL new NUL`. Exported for tests. */
44
+ export declare function parseNameStatusZ(out: string): NameStatusEntry[];
45
+ /** Split one `git diff --patch` blob into per-file sections, in git's file
46
+ * order (the same order `--numstat`/`--name-status` use). Exported for tests. */
47
+ export declare function splitPatch(patch: string): string[];
48
+ /**
49
+ * Structured "what changed here" for a directory vs its base branch:
50
+ * committed + uncommitted + untracked (via `add -N`), anchored at the
51
+ * merge-base so the diff stays *this task's* changes even after the base
52
+ * moves on — the exact resolution `worktreeDiff` (src/git-worktree.ts) uses
53
+ * for the text-blob `/diff` endpoint, which stays untouched.
54
+ */
55
+ export declare function collectChanges(dir: string, baseBranch: string, opts?: {
56
+ patchCap?: number;
57
+ intentToAdd?: boolean;
58
+ }): Promise<ChangesResult>;
59
+ export interface RunCommit {
60
+ sha: string;
61
+ subject: string;
62
+ author: string;
63
+ /** Relative time ("3 hours ago"), git's `%cr`. */
64
+ when: string;
65
+ }
66
+ export type RunCommitsResult = {
67
+ ok: true;
68
+ commits: RunCommit[];
69
+ } | {
70
+ ok: false;
71
+ error: string;
72
+ };
73
+ /**
74
+ * The commits a run made on its worktree branch: `<merge-base>..HEAD`, newest first — the same
75
+ * range `collectChanges` diffs, so the commit list and the aggregate Changes tab always agree on
76
+ * what "this task's work" means. Empty (not an error) when the branch has no commits past base.
77
+ */
78
+ export declare function collectRunCommits(dir: string, baseBranch: string): Promise<RunCommitsResult>;
79
+ /** `GET /api/repo/commit/:sha?structured=1` — one commit's metadata plus the same
80
+ * structured `{files, stat}` shape the working-tree routes serve (R5 Step 1.7). The
81
+ * legacy text-blob answer of that route is a protected surface and stays untouched. */
82
+ export interface CommitPayload {
83
+ sha: string;
84
+ subject: string;
85
+ author: string;
86
+ /** Relative time ("3 hours ago") — same `%cr` format the /api/repo log uses. */
87
+ when: string;
88
+ files: ChangedFile[];
89
+ stat: {
90
+ adds: number;
91
+ dels: number;
92
+ files: number;
93
+ };
94
+ }
95
+ export type CommitChangesResult = {
96
+ ok: true;
97
+ commit: CommitPayload;
98
+ } | {
99
+ ok: false;
100
+ error: string;
101
+ };
102
+ /**
103
+ * Structured diff of ONE commit vs its first parent (`--root` covers the initial commit).
104
+ * A merge commit honestly answers zero files — `git diff-tree` shows no diff for merges
105
+ * without `-m`/`-c`, and inventing one side's diff would misattribute the changes.
106
+ * Unknown/invalid shas degrade to `{ ok:false, error }` for the route's 409.
107
+ */
108
+ export declare function collectCommitChanges(dir: string, sha: string, patchCap?: number): Promise<CommitChangesResult>;
109
+ /** Max file content served to the Files tab — past this the GUI shows an
110
+ * honest "too large" state instead of the bytes. */
111
+ export declare const FILE_CONTENT_CAP = 512000;
112
+ export interface DirEntry {
113
+ name: string;
114
+ type: 'dir' | 'file';
115
+ size?: number;
116
+ }
117
+ export type FilesResult = {
118
+ kind: 'dir';
119
+ path: string;
120
+ entries: DirEntry[];
121
+ } | {
122
+ kind: 'file';
123
+ path: string;
124
+ size: number;
125
+ binary: boolean;
126
+ tooLarge: boolean;
127
+ content?: string;
128
+ } | {
129
+ kind: 'invalid';
130
+ error: string;
131
+ } | {
132
+ kind: 'missing';
133
+ error: string;
134
+ };
135
+ /** The image MIME type for a path, or null when it is not an image we serve raw. */
136
+ export declare function imageMimeType(path: string): string | null;
137
+ /**
138
+ * Directory listing or file content from inside `root`, traversal-safe:
139
+ * anything resolving outside the root (dot-segments, absolute paths, NUL) is
140
+ * rejected — same "not a file we serve" stance as `isSafeAssetFilename` in
141
+ * src/server/static-ui.ts. `.git` and symlinks are off-limits too.
142
+ */
143
+ export declare function readWorktreePath(root: string, relPath: string, contentCap?: number): Promise<FilesResult>;
144
+ export type BranchResult = {
145
+ ok: true;
146
+ branch: string;
147
+ created: boolean;
148
+ } | {
149
+ ok: false;
150
+ error: string;
151
+ };
152
+ /**
153
+ * Repo-view branch action (`POST /api/repo/branch`): switch to `name` when it
154
+ * already exists locally, otherwise create it from `from` (or HEAD) and switch.
155
+ * Name validation is delegated to `git check-ref-format --branch` — git's own
156
+ * rules, not a reimplementation. Predictable failures (invalid name, unknown
157
+ * `from`, dirty-tree checkout conflict) come back as `{ ok:false, error }`.
158
+ */
159
+ export declare function createOrSwitchBranch(dir: string, name: string, from?: string): Promise<BranchResult>;
160
+ export type CommitResult = {
161
+ ok: true;
162
+ sha: string;
163
+ } | {
164
+ ok: false;
165
+ error: string;
166
+ };
167
+ /** `git add -A && git commit -m <message>` in `dir`. A clean tree, a failing
168
+ * hook or missing identity all come back as `{ ok:false, error }`. */
169
+ export declare function commitAll(dir: string, message: string): Promise<CommitResult>;
170
+ export type PushResult = {
171
+ ok: true;
172
+ branch: string;
173
+ remote: string;
174
+ upstreamSet: boolean;
175
+ } | {
176
+ ok: false;
177
+ error: string;
178
+ };
179
+ /** Push the current branch, setting upstream when it has none. No remote,
180
+ * detached HEAD and rejected pushes all degrade to `{ ok:false, error }`. */
181
+ export declare function pushCurrentBranch(dir: string): Promise<PushResult>;
182
+ export {};
@@ -0,0 +1,424 @@
1
+ import { execFile } from 'node:child_process';
2
+ import { rmSync } from 'node:fs';
3
+ import { lstat, open, readFile, readdir, realpath, stat } from 'node:fs/promises';
4
+ import { tmpdir } from 'node:os';
5
+ import { join, resolve, sep } from 'node:path';
6
+ /** Run git, never throw — degradation is the caller's policy. `env` overrides (e.g. a scratch
7
+ * `GIT_INDEX_FILE`) merge over the process env. */
8
+ function git(cwd, args, env) {
9
+ return new Promise((resolvePromise) => {
10
+ execFile('git', args, {
11
+ cwd,
12
+ maxBuffer: 32 * 1024 * 1024,
13
+ encoding: 'utf8',
14
+ ...(env ? { env: { ...process.env, ...env } } : {}),
15
+ }, (err, stdout, stderr) => resolvePromise({ ok: !err, stdout: stdout ?? '', stderr: stderr ?? '' }));
16
+ });
17
+ }
18
+ /** First line of git's stderr (or stdout) as a one-line human reason. */
19
+ function gitReason(res, fallback) {
20
+ const text = (res.stderr.trim() || res.stdout.trim()).split('\n')[0]?.trim();
21
+ return text || fallback;
22
+ }
23
+ // ---- structured changes -----------------------------------------------------
24
+ /** Per-file patch cap — the GUI shows a "truncated" note past this. */
25
+ const PATCH_CAP = 200_000;
26
+ /** Parse `git diff --numstat -z -M`: `adds TAB dels TAB path NUL`, or for a
27
+ * rename/copy `adds TAB dels TAB NUL old NUL new NUL`. Binary files report
28
+ * `-` for both counters. Exported for tests. */
29
+ export function parseNumstatZ(out) {
30
+ const tokens = out.split('\0');
31
+ const entries = [];
32
+ let i = 0;
33
+ while (i < tokens.length) {
34
+ const head = tokens[i] ?? '';
35
+ if (!head) {
36
+ i += 1;
37
+ continue;
38
+ }
39
+ const m = /^(\d+|-)\t(\d+|-)\t([\s\S]*)$/.exec(head);
40
+ if (!m) {
41
+ i += 1;
42
+ continue;
43
+ }
44
+ const binary = m[1] === '-';
45
+ const adds = binary ? 0 : Number(m[1]);
46
+ const dels = m[2] === '-' ? 0 : Number(m[2]);
47
+ if (m[3]) {
48
+ entries.push({ adds, dels, binary, path: m[3] });
49
+ i += 1;
50
+ }
51
+ else {
52
+ entries.push({ adds, dels, binary, oldPath: tokens[i + 1] ?? '', path: tokens[i + 2] ?? '' });
53
+ i += 3;
54
+ }
55
+ }
56
+ return entries;
57
+ }
58
+ /** Parse `git diff --name-status -z -M`: `X NUL path NUL`, renames/copies
59
+ * `Rnnn NUL old NUL new NUL`. Exported for tests. */
60
+ export function parseNameStatusZ(out) {
61
+ const tokens = out.split('\0');
62
+ const entries = [];
63
+ let i = 0;
64
+ while (i < tokens.length) {
65
+ const status = tokens[i] ?? '';
66
+ if (!status) {
67
+ i += 1;
68
+ continue;
69
+ }
70
+ if (/^[RC]/.test(status)) {
71
+ entries.push({ status, oldPath: tokens[i + 1] ?? '', path: tokens[i + 2] ?? '' });
72
+ i += 3;
73
+ }
74
+ else {
75
+ entries.push({ status, path: tokens[i + 1] ?? '' });
76
+ i += 2;
77
+ }
78
+ }
79
+ return entries;
80
+ }
81
+ /** Split one `git diff --patch` blob into per-file sections, in git's file
82
+ * order (the same order `--numstat`/`--name-status` use). Exported for tests. */
83
+ export function splitPatch(patch) {
84
+ if (!patch.trim())
85
+ return [];
86
+ const starts = [];
87
+ const re = /^diff --git /gm;
88
+ for (let m = re.exec(patch); m; m = re.exec(patch))
89
+ starts.push(m.index);
90
+ return starts.map((start, idx) => patch.slice(start, starts[idx + 1] ?? patch.length));
91
+ }
92
+ function statusWord(letter) {
93
+ switch (letter[0]) {
94
+ case 'A':
95
+ return 'added';
96
+ case 'D':
97
+ return 'deleted';
98
+ case 'R':
99
+ return 'renamed';
100
+ case 'C':
101
+ return 'copied';
102
+ default:
103
+ // M, T (typechange), U — the GUI treats them all as "modified".
104
+ return 'modified';
105
+ }
106
+ }
107
+ /**
108
+ * Structured "what changed here" for a directory vs its base branch:
109
+ * committed + uncommitted + untracked (via `add -N`), anchored at the
110
+ * merge-base so the diff stays *this task's* changes even after the base
111
+ * moves on — the exact resolution `worktreeDiff` (src/git-worktree.ts) uses
112
+ * for the text-blob `/diff` endpoint, which stays untouched.
113
+ */
114
+ export async function collectChanges(dir, baseBranch, opts = {}) {
115
+ const patchCap = opts.patchCap ?? PATCH_CAP;
116
+ // `git add -N .` (intent-to-add) makes untracked files appear in the diff, but it MUTATES the
117
+ // index — fine in a task worktree cezar owns, but forbidden on the user's real main tree (a
118
+ // read-only GET must never stage files, #major-index-mutation). When `intentToAdd` is false we
119
+ // build a SCRATCH index (GIT_INDEX_FILE) seeded from HEAD + intent-to-add, so untracked files
120
+ // still show WITHOUT touching the user's real index.
121
+ let env;
122
+ let scratchIndex;
123
+ try {
124
+ if (opts.intentToAdd === false) {
125
+ scratchIndex = join(tmpdir(), `cez-scratch-index-${process.pid}-${scratchSeq++}`);
126
+ env = { GIT_INDEX_FILE: scratchIndex };
127
+ await git(dir, ['read-tree', 'HEAD'], env); // seed with tracked files; harmless if no HEAD
128
+ await git(dir, ['add', '-N', '.'], env);
129
+ }
130
+ else {
131
+ await git(dir, ['add', '-N', '.']);
132
+ }
133
+ const mergeBase = await git(dir, ['merge-base', baseBranch, 'HEAD']);
134
+ const base = mergeBase.ok && mergeBase.stdout.trim() ? mergeBase.stdout.trim() : baseBranch;
135
+ const nameStatus = await git(dir, ['diff', '--name-status', '-z', '-M', base], env);
136
+ if (!nameStatus.ok)
137
+ return { ok: false, error: gitReason(nameStatus, 'git diff failed') };
138
+ const numstat = await git(dir, ['diff', '--numstat', '-z', '-M', base], env);
139
+ if (!numstat.ok)
140
+ return { ok: false, error: gitReason(numstat, 'git diff failed') };
141
+ const patchOut = await git(dir, ['diff', '--patch', '-M', '--no-color', base], env);
142
+ if (!patchOut.ok)
143
+ return { ok: false, error: gitReason(patchOut, 'git diff failed') };
144
+ return { ok: true, changes: assemblePayload(nameStatus.stdout, numstat.stdout, patchOut.stdout, patchCap) };
145
+ }
146
+ finally {
147
+ if (scratchIndex)
148
+ rmSync(scratchIndex, { force: true });
149
+ }
150
+ }
151
+ /** Monotonic suffix for scratch index files, so concurrent /api/repo/changes calls never share
152
+ * one (each is cleaned up in the finally above). */
153
+ let scratchSeq = 0;
154
+ /** The three raw `git diff` listings (name-status, numstat, patch) → the `{files, stat}`
155
+ * payload. Shared by the working-tree diff above and the commit diff below — the listings
156
+ * come out in git's path order either way, so index-matching the patch sections is safe;
157
+ * a length mismatch degrades to "no patch". */
158
+ function assemblePayload(nameStatusOut, numstatOut, patchOut, patchCap) {
159
+ const statuses = parseNameStatusZ(nameStatusOut);
160
+ const counts = parseNumstatZ(numstatOut);
161
+ const patches = splitPatch(patchOut);
162
+ const countByPath = new Map(counts.map((entry) => [entry.path, entry]));
163
+ const files = statuses.map((entry, idx) => {
164
+ const count = countByPath.get(entry.path);
165
+ let patch = patches.length === statuses.length ? (patches[idx] ?? '') : '';
166
+ if (patch.length > patchCap)
167
+ patch = `${patch.slice(0, patchCap)}\n… (patch truncated)`;
168
+ return {
169
+ path: entry.path,
170
+ ...(entry.oldPath ? { oldPath: entry.oldPath } : {}),
171
+ status: statusWord(entry.status),
172
+ adds: count?.adds ?? 0,
173
+ dels: count?.dels ?? 0,
174
+ binary: count?.binary ?? false,
175
+ patch,
176
+ };
177
+ });
178
+ return {
179
+ files,
180
+ stat: {
181
+ adds: files.reduce((sum, f) => sum + f.adds, 0),
182
+ dels: files.reduce((sum, f) => sum + f.dels, 0),
183
+ files: files.length,
184
+ },
185
+ };
186
+ }
187
+ /**
188
+ * The commits a run made on its worktree branch: `<merge-base>..HEAD`, newest first — the same
189
+ * range `collectChanges` diffs, so the commit list and the aggregate Changes tab always agree on
190
+ * what "this task's work" means. Empty (not an error) when the branch has no commits past base.
191
+ */
192
+ export async function collectRunCommits(dir, baseBranch) {
193
+ const mergeBase = await git(dir, ['merge-base', baseBranch, 'HEAD']);
194
+ const base = mergeBase.ok && mergeBase.stdout.trim() ? mergeBase.stdout.trim() : baseBranch;
195
+ const log = await git(dir, ['log', '--pretty=format:%H%x1f%s%x1f%an%x1f%cr', `${base}..HEAD`]);
196
+ if (!log.ok)
197
+ return { ok: false, error: gitReason(log, 'git log failed') };
198
+ const commits = log.stdout
199
+ .split('\n')
200
+ .filter(Boolean)
201
+ .map((line) => {
202
+ const [sha = '', subject = '', author = '', when = ''] = line.split('\x1f');
203
+ return { sha, subject, author, when };
204
+ });
205
+ return { ok: true, commits };
206
+ }
207
+ /**
208
+ * Structured diff of ONE commit vs its first parent (`--root` covers the initial commit).
209
+ * A merge commit honestly answers zero files — `git diff-tree` shows no diff for merges
210
+ * without `-m`/`-c`, and inventing one side's diff would misattribute the changes.
211
+ * Unknown/invalid shas degrade to `{ ok:false, error }` for the route's 409.
212
+ */
213
+ export async function collectCommitChanges(dir, sha, patchCap = PATCH_CAP) {
214
+ if (!/^[0-9a-f]{4,40}$/i.test(sha))
215
+ return { ok: false, error: `not a commit hash: ${sha}` };
216
+ const meta = await git(dir, ['show', '-s', '--format=%H%x1f%s%x1f%an%x1f%cr', `${sha}^{commit}`]);
217
+ if (!meta.ok)
218
+ return { ok: false, error: gitReason(meta, `unknown commit: ${sha}`) };
219
+ const [fullSha = '', subject = '', author = '', when = ''] = meta.stdout.trim().split('\x1f');
220
+ const common = ['diff-tree', '--no-commit-id', '--root', '-r', '-M'];
221
+ const nameStatus = await git(dir, [...common, '--name-status', '-z', fullSha]);
222
+ if (!nameStatus.ok)
223
+ return { ok: false, error: gitReason(nameStatus, 'git diff-tree failed') };
224
+ const numstat = await git(dir, [...common, '--numstat', '-z', fullSha]);
225
+ if (!numstat.ok)
226
+ return { ok: false, error: gitReason(numstat, 'git diff-tree failed') };
227
+ const patchOut = await git(dir, [...common, '--patch', '--no-color', fullSha]);
228
+ if (!patchOut.ok)
229
+ return { ok: false, error: gitReason(patchOut, 'git diff-tree failed') };
230
+ const payload = assemblePayload(nameStatus.stdout, numstat.stdout, patchOut.stdout, patchCap);
231
+ return { ok: true, commit: { sha: fullSha, subject, author, when, ...payload } };
232
+ }
233
+ // ---- worktree file browsing ---------------------------------------------------
234
+ /** Max file content served to the Files tab — past this the GUI shows an
235
+ * honest "too large" state instead of the bytes. */
236
+ export const FILE_CONTENT_CAP = 512_000;
237
+ /**
238
+ * Extensions the Files tab renders inline as `<img>` — the only kinds the
239
+ * `/files?raw=1` mode will ever serve as bytes (anything else stays JSON, so a
240
+ * worktree HTML file can never become a same-origin document). SVG is included:
241
+ * inert inside `<img>`, and the raw response carries a no-script CSP for the
242
+ * "opened the URL directly" case. Keep in sync with IMAGE_EXTENSIONS in
243
+ * web/app/src/routes/task-git/file-preview.tsx.
244
+ */
245
+ const IMAGE_MIME = {
246
+ png: 'image/png',
247
+ jpg: 'image/jpeg',
248
+ jpeg: 'image/jpeg',
249
+ gif: 'image/gif',
250
+ webp: 'image/webp',
251
+ svg: 'image/svg+xml',
252
+ bmp: 'image/bmp',
253
+ ico: 'image/x-icon',
254
+ avif: 'image/avif',
255
+ };
256
+ /** The image MIME type for a path, or null when it is not an image we serve raw. */
257
+ export function imageMimeType(path) {
258
+ const name = path.slice(path.lastIndexOf('/') + 1);
259
+ const dot = name.lastIndexOf('.');
260
+ if (dot <= 0)
261
+ return null;
262
+ return IMAGE_MIME[name.slice(dot + 1).toLowerCase()] ?? null;
263
+ }
264
+ /** True when the first 8 KB contain a NUL byte — good enough for a viewer flag. */
265
+ async function sniffBinary(path, size) {
266
+ const handle = await open(path, 'r');
267
+ try {
268
+ const len = Math.min(size, 8192);
269
+ if (len === 0)
270
+ return false;
271
+ const buf = Buffer.alloc(len);
272
+ await handle.read(buf, 0, len, 0);
273
+ return buf.includes(0);
274
+ }
275
+ finally {
276
+ await handle.close();
277
+ }
278
+ }
279
+ /**
280
+ * Directory listing or file content from inside `root`, traversal-safe:
281
+ * anything resolving outside the root (dot-segments, absolute paths, NUL) is
282
+ * rejected — same "not a file we serve" stance as `isSafeAssetFilename` in
283
+ * src/server/static-ui.ts. `.git` and symlinks are off-limits too.
284
+ */
285
+ export async function readWorktreePath(root, relPath, contentCap = FILE_CONTENT_CAP) {
286
+ if (relPath.includes('\0'))
287
+ return { kind: 'invalid', error: 'invalid path' };
288
+ const rootAbs = resolve(root);
289
+ const target = resolve(rootAbs, relPath);
290
+ if (target !== rootAbs && !target.startsWith(rootAbs + sep)) {
291
+ return { kind: 'invalid', error: `path escapes the worktree: ${relPath}` };
292
+ }
293
+ const gitDir = join(rootAbs, '.git');
294
+ if (target === gitDir || target.startsWith(gitDir + sep)) {
295
+ return { kind: 'invalid', error: '.git internals are not browsable' };
296
+ }
297
+ const display = target === rootAbs ? '' : target.slice(rootAbs.length + 1).split(sep).join('/');
298
+ let info;
299
+ try {
300
+ info = await lstat(target);
301
+ }
302
+ catch {
303
+ return { kind: 'missing', error: `no such file or directory in the worktree: ${relPath || '/'}` };
304
+ }
305
+ if (info.isSymbolicLink()) {
306
+ return { kind: 'invalid', error: `symlinks are not served: ${display}` };
307
+ }
308
+ // Intermediate symlinked DIRECTORIES: `resolve()` never follows links and the `lstat` above
309
+ // only guards the final component, so a path through a symlinked dir (e.g. `link/secret.txt`
310
+ // where `link -> /etc`) would otherwise be served. Resolve the whole chain and re-check
311
+ // containment against the real root (#blocker-symlink-traversal).
312
+ let realTarget;
313
+ let realRoot;
314
+ try {
315
+ realTarget = await realpath(target);
316
+ realRoot = await realpath(rootAbs);
317
+ }
318
+ catch {
319
+ return { kind: 'missing', error: `no such file or directory in the worktree: ${relPath || '/'}` };
320
+ }
321
+ if (realTarget !== realRoot && !realTarget.startsWith(realRoot + sep)) {
322
+ return { kind: 'invalid', error: `path escapes the worktree: ${relPath}` };
323
+ }
324
+ if (info.isDirectory()) {
325
+ const dirents = await readdir(target, { withFileTypes: true });
326
+ const entries = [];
327
+ for (const d of dirents) {
328
+ if (d.name === '.git')
329
+ continue;
330
+ if (d.isDirectory()) {
331
+ entries.push({ name: d.name, type: 'dir' });
332
+ }
333
+ else if (d.isFile()) {
334
+ const size = await stat(join(target, d.name))
335
+ .then((s) => s.size)
336
+ .catch(() => undefined);
337
+ entries.push({ name: d.name, type: 'file', ...(size !== undefined ? { size } : {}) });
338
+ }
339
+ // Symlinks, sockets, … deliberately omitted from the listing.
340
+ }
341
+ entries.sort((a, b) => (a.type === b.type ? a.name.localeCompare(b.name) : a.type === 'dir' ? -1 : 1));
342
+ return { kind: 'dir', path: display, entries };
343
+ }
344
+ if (!info.isFile())
345
+ return { kind: 'invalid', error: `not a regular file: ${display}` };
346
+ const binary = await sniffBinary(target, info.size).catch(() => true);
347
+ const tooLarge = info.size > contentCap;
348
+ if (binary || tooLarge) {
349
+ return { kind: 'file', path: display, size: info.size, binary, tooLarge };
350
+ }
351
+ const content = await readFile(target, 'utf8');
352
+ return { kind: 'file', path: display, size: info.size, binary: false, tooLarge: false, content };
353
+ }
354
+ /**
355
+ * Repo-view branch action (`POST /api/repo/branch`): switch to `name` when it
356
+ * already exists locally, otherwise create it from `from` (or HEAD) and switch.
357
+ * Name validation is delegated to `git check-ref-format --branch` — git's own
358
+ * rules, not a reimplementation. Predictable failures (invalid name, unknown
359
+ * `from`, dirty-tree checkout conflict) come back as `{ ok:false, error }`.
360
+ */
361
+ export async function createOrSwitchBranch(dir, name, from) {
362
+ const check = await git(dir, ['check-ref-format', '--branch', name]);
363
+ if (!check.ok)
364
+ return { ok: false, error: `invalid branch name: ${name}` };
365
+ const exists = await git(dir, ['rev-parse', '--verify', '--quiet', `refs/heads/${name}`]);
366
+ if (exists.ok) {
367
+ const sw = await git(dir, ['checkout', name]);
368
+ if (!sw.ok)
369
+ return { ok: false, error: gitReason(sw, `git checkout ${name} failed`) };
370
+ return { ok: true, branch: name, created: false };
371
+ }
372
+ if (from) {
373
+ // `--quiet` keeps git silent on failure, so supply our own reason.
374
+ const start = await git(dir, ['rev-parse', '--verify', '--quiet', `${from}^{commit}`]);
375
+ if (!start.ok)
376
+ return { ok: false, error: `unknown start point: ${from}` };
377
+ }
378
+ const create = await git(dir, from ? ['checkout', '-b', name, from] : ['checkout', '-b', name]);
379
+ if (!create.ok)
380
+ return { ok: false, error: gitReason(create, `git checkout -b ${name} failed`) };
381
+ return { ok: true, branch: name, created: true };
382
+ }
383
+ /** `git add -A && git commit -m <message>` in `dir`. A clean tree, a failing
384
+ * hook or missing identity all come back as `{ ok:false, error }`. */
385
+ export async function commitAll(dir, message) {
386
+ const status = await git(dir, ['status', '--porcelain']);
387
+ if (!status.ok)
388
+ return { ok: false, error: gitReason(status, 'git status failed') };
389
+ if (!status.stdout.trim()) {
390
+ return { ok: false, error: 'nothing to commit — the working tree is clean' };
391
+ }
392
+ const add = await git(dir, ['add', '-A']);
393
+ if (!add.ok)
394
+ return { ok: false, error: gitReason(add, 'git add failed') };
395
+ const commit = await git(dir, ['commit', '-m', message]);
396
+ if (!commit.ok)
397
+ return { ok: false, error: gitReason(commit, 'git commit failed') };
398
+ const head = await git(dir, ['rev-parse', 'HEAD']);
399
+ return { ok: true, sha: head.ok ? head.stdout.trim() : '' };
400
+ }
401
+ /** Push the current branch, setting upstream when it has none. No remote,
402
+ * detached HEAD and rejected pushes all degrade to `{ ok:false, error }`. */
403
+ export async function pushCurrentBranch(dir) {
404
+ const branchRes = await git(dir, ['rev-parse', '--abbrev-ref', 'HEAD']);
405
+ if (!branchRes.ok)
406
+ return { ok: false, error: gitReason(branchRes, 'not a git repository') };
407
+ const branch = branchRes.stdout.trim();
408
+ if (!branch || branch === 'HEAD') {
409
+ return { ok: false, error: 'detached HEAD — check out a branch before pushing' };
410
+ }
411
+ const remotesRes = await git(dir, ['remote']);
412
+ const remotes = remotesRes.stdout.split('\n').map((r) => r.trim()).filter(Boolean);
413
+ if (remotes.length === 0) {
414
+ return { ok: false, error: 'no remote configured — add one with `git remote add origin <url>`' };
415
+ }
416
+ const remote = remotes.includes('origin') ? 'origin' : remotes[0];
417
+ const upstream = await git(dir, ['rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}']);
418
+ const args = upstream.ok ? ['push'] : ['push', '-u', remote, branch];
419
+ const push = await git(dir, args);
420
+ if (!push.ok)
421
+ return { ok: false, error: gitReason(push, 'git push failed') };
422
+ return { ok: true, branch, remote, upstreamSet: !upstream.ok };
423
+ }
424
+ //# sourceMappingURL=git-changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-changes.js","sourceRoot":"","sources":["../../src/server/git-changes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * "Open in…" session takeover (#open-in): detect the editors / file managers / terminals on THIS
3
+ * machine, and open a run's worktree in the one the user picks — the desktop-app equivalent of
4
+ * the "cd <path>" hint. Local-only; the server gates these behind `localHandoff` (CEZ_REMOTE).
5
+ *
6
+ * Detection is best-effort and cross-platform: an editor counts as present if its CLI is on PATH
7
+ * or (macOS) its .app bundle is installed. Finder/file-manager and Terminal are always offered.
8
+ */
9
+ export interface OpenTarget {
10
+ id: string;
11
+ label: string;
12
+ }
13
+ /** The runner behind a `cli:<runner>` open target, or null when the id isn't a CLI handoff. */
14
+ export declare function agentCliRunner(targetId: string): 'claude' | 'codex' | 'opencode' | null;
15
+ /** The open targets available on this machine: the file manager, a terminal, every detected
16
+ * editor, and every installed coding-agent CLI. Order is stable so the menu never reshuffles. */
17
+ export declare function detectOpenTargets(): OpenTarget[];
18
+ /** Open `dir` in the given target. Unknown/unavailable target → false (the caller 409s). */
19
+ export declare function openInApp(targetId: string, dir: string): Promise<boolean>;