@pat-lewczuk/cezar 0.1.3 → 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.
- package/dist/core/claude-ui-mapper.d.ts +57 -0
- package/dist/core/claude-ui-mapper.js +370 -0
- package/dist/core/claude-ui-mapper.js.map +1 -0
- package/dist/core/codex-ui-mapper.d.ts +53 -0
- package/dist/core/codex-ui-mapper.js +411 -0
- package/dist/core/codex-ui-mapper.js.map +1 -0
- package/dist/core/opencode-ui-mapper.d.ts +105 -0
- package/dist/core/opencode-ui-mapper.js +578 -0
- package/dist/core/opencode-ui-mapper.js.map +1 -0
- package/dist/core/process-usage.d.ts +63 -0
- package/dist/core/process-usage.js +181 -0
- package/dist/core/process-usage.js.map +1 -0
- package/dist/core/tool-display.d.ts +27 -0
- package/dist/core/tool-display.js +150 -0
- package/dist/core/tool-display.js.map +1 -0
- package/dist/core/ui-events.d.ts +294 -0
- package/dist/core/ui-events.js +25 -0
- package/dist/core/ui-events.js.map +1 -0
- package/dist/index.js +0 -0
- package/dist/pack-check.d.ts +17 -0
- package/dist/pack-check.js +27 -0
- package/dist/pack-check.js.map +1 -0
- package/dist/runs/title-summary.d.ts +15 -0
- package/dist/runs/title-summary.js +84 -0
- package/dist/runs/title-summary.js.map +1 -0
- package/dist/runs/ui-event-sink.d.ts +81 -0
- package/dist/runs/ui-event-sink.js +210 -0
- package/dist/runs/ui-event-sink.js.map +1 -0
- package/dist/server/capabilities.d.ts +18 -0
- package/dist/server/capabilities.js +23 -0
- package/dist/server/capabilities.js.map +1 -0
- package/dist/server/forge/github.d.ts +39 -0
- package/dist/server/forge/github.js +369 -0
- package/dist/server/forge/github.js.map +1 -0
- package/dist/server/forge/index.d.ts +24 -0
- package/dist/server/forge/index.js +45 -0
- package/dist/server/forge/index.js.map +1 -0
- package/dist/server/forge/types.d.ts +80 -0
- package/dist/server/forge/types.js +2 -0
- package/dist/server/forge/types.js.map +1 -0
- package/dist/server/git-changes.d.ts +182 -0
- package/dist/server/git-changes.js +424 -0
- package/dist/server/git-changes.js.map +1 -0
- package/dist/server/open-in-app.d.ts +19 -0
- package/dist/server/open-in-app.js +134 -0
- package/dist/server/open-in-app.js.map +1 -0
- package/dist/server/static-ui.d.ts +49 -0
- package/dist/server/static-ui.js +92 -0
- package/dist/server/static-ui.js.map +1 -0
- package/dist/update-check.d.ts +12 -0
- package/dist/update-check.js +41 -0
- package/dist/update-check.js.map +1 -0
- package/package.json +1 -1
- package/web/app/node_modules/.vite/vitest/ca84d1343b96baa8137c943ed1860e522cacb238/results.json +1 -0
- package/web/app/src/components/app-shell-container.tsx +76 -0
- package/web/dist/assets/arrow-left-BE957rJs.js +1 -0
- package/web/dist/assets/bundle-mjs-DLPpRFyl.js +1 -0
- package/web/dist/assets/chunk-BO2N2NFS-f5igTtpB.js +131 -0
- package/web/dist/assets/compare-variants-D6fPL9cS.js +1 -0
- package/web/dist/assets/core-BuMqAF_1.js +12 -0
- package/web/dist/assets/css-BsVw1vtW.js +1 -0
- package/web/dist/assets/dialog-BEgEWFDS.js +1 -0
- package/web/dist/assets/diff-view-CctnJHWe.js +4 -0
- package/web/dist/assets/diff-woXpYk--.js +1 -0
- package/web/dist/assets/dist-CW7M_Jhs.js +1 -0
- package/web/dist/assets/ellipsis-vertical-DJPAfccS.js +1 -0
- package/web/dist/assets/engine-javascript-FQvzRocB.js +141 -0
- package/web/dist/assets/folder-RbRLfIX-.js +1 -0
- package/web/dist/assets/git-pull-request-DJkAMT0f.js +1 -0
- package/web/dist/assets/git-toolbar-D8OPPqBP.js +1 -0
- package/web/dist/assets/github-BYIHwIJB.js +1 -0
- package/web/dist/assets/go-rLFTqkRN.js +1 -0
- package/web/dist/assets/highlighted-body-OFNGDK62-DGHHie_q.js +1 -0
- package/web/dist/assets/highlighter-BKVEsACy.js +3 -0
- package/web/dist/assets/html-BY76lXLH.js +1 -0
- package/web/dist/assets/index-9qG98Orw.js +11 -0
- package/web/dist/assets/index-Bz_r8Jt3.css +2 -0
- package/web/dist/assets/input-BRsSo4xH.js +1 -0
- package/web/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/web/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/web/dist/assets/javascript-BgS3c2Ky.js +1 -0
- package/web/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/web/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/web/dist/assets/json-qhed-kSA.js +1 -0
- package/web/dist/assets/jsonc-CYpm1nAK.js +1 -0
- package/web/dist/assets/jsx-Bz0zcwM4.js +1 -0
- package/web/dist/assets/lib-CNGa3Dig.js +1 -0
- package/web/dist/assets/loader-circle-BV3DO9mE.js +1 -0
- package/web/dist/assets/markdown-BYOwaDjH.js +1 -0
- package/web/dist/assets/markdown-CR_HLGTs.js +1 -0
- package/web/dist/assets/mermaid-GHXKKRXX-DM2VsGBG.js +1 -0
- package/web/dist/assets/open-mercato-toBr6SOa.svg +11 -0
- package/web/dist/assets/python-gzcpVVnB.js +1 -0
- package/web/dist/assets/react-dom-Ddtik4qM.js +1 -0
- package/web/dist/assets/refresh-cw-DCa-Rlwz.js +1 -0
- package/web/dist/assets/repo-git-XTqlVOl2.js +1 -0
- package/web/dist/assets/run-diff-C7mfxj7f.js +3 -0
- package/web/dist/assets/run-header-CfVeY3uM.js +1 -0
- package/web/dist/assets/rust-Cfkwpbl8.js +1 -0
- package/web/dist/assets/search-x-CoCyl7zT.js +1 -0
- package/web/dist/assets/shellscript-CLZ0U2zV.js +1 -0
- package/web/dist/assets/skill-detail-C9cniyId.js +1 -0
- package/web/dist/assets/skills-DXgY1uXJ.js +1 -0
- package/web/dist/assets/skills-ynuO5oCr.js +1 -0
- package/web/dist/assets/sql-BsFa4tDR.js +1 -0
- package/web/dist/assets/square-terminal-B6PZX4Qp.js +1 -0
- package/web/dist/assets/tab-link-phWEqSBy.js +1 -0
- package/web/dist/assets/task-changes-DYwnPnTN.js +1 -0
- package/web/dist/assets/task-commits-DZzxEzbn.js +1 -0
- package/web/dist/assets/task-files-FOAAz2FB.js +2 -0
- package/web/dist/assets/task-thread-Bncxe8Os.js +5 -0
- package/web/dist/assets/toaster-BS2E1bhz.js +43 -0
- package/web/dist/assets/trash-2-CDtxmmc8.js +1 -0
- package/web/dist/assets/triangle-alert-6su4Js5O.js +1 -0
- package/web/dist/assets/tsx-udAQXfEw.js +1 -0
- package/web/dist/assets/typescript-bsJCZSQ-.js +1 -0
- package/web/dist/assets/upload-Bp7hQxll.js +1 -0
- package/web/dist/assets/use-desktop-eHm2iTXX.js +3 -0
- package/web/dist/assets/utils-rQGbOrwc.js +1 -0
- package/web/dist/assets/workflows-Dg2wQg6i.js +11 -0
- package/web/dist/assets/x-Br_jIDBw.js +1 -0
- package/web/dist/assets/yaml-rwi0_p6S.js +1 -0
- package/web/dist/index.html +67 -0
|
@@ -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>;
|