pi-webdesk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -0
- package/dist/apps/daemon/src/appearance-preferences.js +218 -0
- package/dist/apps/daemon/src/auth.js +88 -0
- package/dist/apps/daemon/src/bin.js +123 -0
- package/dist/apps/daemon/src/cli.js +48 -0
- package/dist/apps/daemon/src/event-hub.js +155 -0
- package/dist/apps/daemon/src/index.js +102 -0
- package/dist/apps/daemon/src/launcher-control.js +114 -0
- package/dist/apps/daemon/src/launcher.js +73 -0
- package/dist/apps/daemon/src/pi-auth.js +290 -0
- package/dist/apps/daemon/src/pi-resources.js +182 -0
- package/dist/apps/daemon/src/pi-runtime-factory.js +19 -0
- package/dist/apps/daemon/src/pi-sessions.js +265 -0
- package/dist/apps/daemon/src/runtime-process.js +241 -0
- package/dist/apps/daemon/src/secret.js +71 -0
- package/dist/apps/daemon/src/server.js +1662 -0
- package/dist/apps/daemon/src/session-projection.js +117 -0
- package/dist/apps/daemon/src/state-lock.js +31 -0
- package/dist/apps/daemon/src/static-web.js +53 -0
- package/dist/apps/daemon/src/task-archive.js +152 -0
- package/dist/apps/daemon/src/task-commit.js +503 -0
- package/dist/apps/daemon/src/task-merge.js +912 -0
- package/dist/apps/daemon/src/task-review.js +204 -0
- package/dist/apps/daemon/src/task-runtime.js +1124 -0
- package/dist/apps/daemon/src/task-validation.js +352 -0
- package/dist/apps/daemon/src/workspace-store.js +140 -0
- package/dist/apps/daemon/src/workspace.js +795 -0
- package/dist/extensions/webdesk.js +34 -0
- package/dist/packages/git/src/commit.js +675 -0
- package/dist/packages/git/src/errors.js +55 -0
- package/dist/packages/git/src/fingerprint.js +286 -0
- package/dist/packages/git/src/index.js +123 -0
- package/dist/packages/git/src/merge.js +1008 -0
- package/dist/packages/git/src/paths.js +58 -0
- package/dist/packages/git/src/repository.js +77 -0
- package/dist/packages/git/src/review.js +396 -0
- package/dist/packages/git/src/runner.js +110 -0
- package/dist/packages/git/src/validation.js +263 -0
- package/dist/packages/git/src/worktree.js +233 -0
- package/dist/packages/pi-bridge/extensions/pita-policy.js +117 -0
- package/dist/packages/pi-bridge/src/auth.js +80 -0
- package/dist/packages/pi-bridge/src/errors.js +19 -0
- package/dist/packages/pi-bridge/src/handshake.js +43 -0
- package/dist/packages/pi-bridge/src/index.js +76 -0
- package/dist/packages/pi-bridge/src/jsonl.js +105 -0
- package/dist/packages/pi-bridge/src/policy-approval.js +62 -0
- package/dist/packages/pi-bridge/src/resolve.js +59 -0
- package/dist/packages/pi-bridge/src/resources-child.mjs +23 -0
- package/dist/packages/pi-bridge/src/resources.js +481 -0
- package/dist/packages/pi-bridge/src/rpc/client.js +480 -0
- package/dist/packages/pi-bridge/src/rpc/runtime.js +496 -0
- package/dist/packages/pi-bridge/src/rpc/supervisor.mjs +129 -0
- package/dist/packages/pi-bridge/src/rpc/tool-events.js +78 -0
- package/dist/packages/pi-bridge/src/rpc/wire.js +263 -0
- package/dist/packages/pi-bridge/src/runtime.js +0 -0
- package/dist/packages/pi-bridge/src/sessions-child.mjs +38 -0
- package/dist/packages/pi-bridge/src/sessions.js +314 -0
- package/dist/packages/pi-bridge/src/tool-activity.js +56 -0
- package/dist/packages/protocol/src/index.js +1863 -0
- package/dist/web/assets/index-BOw_fhvO.css +2 -0
- package/dist/web/assets/index-oXs7yAAo.js +119 -0
- package/dist/web/index.html +14 -0
- package/package.json +69 -0
- package/scripts/prepare.mjs +7 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// packages/git/src/errors.ts
|
|
2
|
+
var GitServiceError = class extends Error {
|
|
3
|
+
code;
|
|
4
|
+
details;
|
|
5
|
+
constructor(code, message, options) {
|
|
6
|
+
super(message, options?.cause === void 0 ? void 0 : { cause: options.cause });
|
|
7
|
+
this.name = "GitServiceError";
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.details = options?.details ?? {};
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
function isGitServiceError(value, code) {
|
|
13
|
+
if (!(value instanceof GitServiceError)) return false;
|
|
14
|
+
return code === void 0 || value.code === code;
|
|
15
|
+
}
|
|
16
|
+
var GitWorktreeIncompleteError = class extends GitServiceError {
|
|
17
|
+
facts;
|
|
18
|
+
constructor(message, facts, options) {
|
|
19
|
+
super("GIT_WORKTREE_CREATE_INCOMPLETE", message, {
|
|
20
|
+
cause: options?.cause,
|
|
21
|
+
details: { ...facts }
|
|
22
|
+
});
|
|
23
|
+
this.name = "GitWorktreeIncompleteError";
|
|
24
|
+
this.facts = facts;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var GitMergeConflictError = class extends GitServiceError {
|
|
28
|
+
/** Raw conflicted paths, bounded in count; presentation must escape them. */
|
|
29
|
+
conflictPaths;
|
|
30
|
+
/** Conflicted paths beyond the retained bound (reported, never silent). */
|
|
31
|
+
omittedConflictPaths;
|
|
32
|
+
constructor(message, conflictPaths, omittedConflictPaths, options) {
|
|
33
|
+
super("GIT_MERGE_CONFLICTED", message, {
|
|
34
|
+
...options?.cause === void 0 ? {} : { cause: options.cause },
|
|
35
|
+
details: {
|
|
36
|
+
conflictedPaths: conflictPaths.length + omittedConflictPaths
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
this.name = "GitMergeConflictError";
|
|
40
|
+
this.conflictPaths = conflictPaths;
|
|
41
|
+
this.omittedConflictPaths = omittedConflictPaths;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
function boundedDetailText(text, maxLength = 400) {
|
|
45
|
+
const trimmed = text.trim();
|
|
46
|
+
if (trimmed.length <= maxLength) return trimmed;
|
|
47
|
+
return `${trimmed.slice(0, maxLength)}\u2026 [truncated]`;
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
GitMergeConflictError,
|
|
51
|
+
GitServiceError,
|
|
52
|
+
GitWorktreeIncompleteError,
|
|
53
|
+
boundedDetailText,
|
|
54
|
+
isGitServiceError
|
|
55
|
+
};
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
// packages/git/src/fingerprint.ts
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { constants } from "node:fs";
|
|
4
|
+
import { lstat, open, readlink } from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { GitServiceError, isGitServiceError } from "./errors.js";
|
|
7
|
+
import { inspectRepository } from "./repository.js";
|
|
8
|
+
import {
|
|
9
|
+
READ_ONLY_GIT_FLAGS,
|
|
10
|
+
parseStatusOutput,
|
|
11
|
+
sameRepositoryIdentity
|
|
12
|
+
} from "./review.js";
|
|
13
|
+
import {
|
|
14
|
+
defaultGitRunner,
|
|
15
|
+
runGitExpectingSuccess
|
|
16
|
+
} from "./runner.js";
|
|
17
|
+
var DEFAULT_STATE_MAX_ENTRIES = 2e3;
|
|
18
|
+
var DEFAULT_STATE_MAX_DURATION_MS = 1e4;
|
|
19
|
+
var DEFAULT_STATE_MAX_CONTENT_BYTES = 64 * 1024 * 1024;
|
|
20
|
+
function positiveBound(value, label) {
|
|
21
|
+
if (!Number.isSafeInteger(value) || value < 1) {
|
|
22
|
+
throw new GitServiceError(
|
|
23
|
+
"GIT_STATE_TOO_LARGE",
|
|
24
|
+
`${label} must be a positive safe integer`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
function withCaptureDeadline(runner, deadlineMs, now) {
|
|
30
|
+
return async (args, options = {}) => {
|
|
31
|
+
const remainingMs = Math.floor(deadlineMs - now());
|
|
32
|
+
if (remainingMs < 1) {
|
|
33
|
+
throw new GitServiceError(
|
|
34
|
+
"GIT_STATE_DEADLINE_EXCEEDED",
|
|
35
|
+
"The worktree-state capture exceeded its overall time budget"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
const callerLimitMs = options.timeoutMs ?? Number.POSITIVE_INFINITY;
|
|
39
|
+
try {
|
|
40
|
+
return await runner(args, {
|
|
41
|
+
...options,
|
|
42
|
+
timeoutMs: Math.min(remainingMs, callerLimitMs)
|
|
43
|
+
});
|
|
44
|
+
} catch (error) {
|
|
45
|
+
if (remainingMs <= callerLimitMs && isGitServiceError(error, "GIT_COMMAND_TERMINATED")) {
|
|
46
|
+
throw new GitServiceError(
|
|
47
|
+
"GIT_STATE_DEADLINE_EXCEEDED",
|
|
48
|
+
"The worktree-state capture exceeded its overall time budget",
|
|
49
|
+
{ cause: error }
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function needsContentHash(entry) {
|
|
57
|
+
if (entry.record === "untracked" || entry.record === "unmerged") return true;
|
|
58
|
+
return entry.y !== "." && entry.y !== "D";
|
|
59
|
+
}
|
|
60
|
+
async function hashWorktreeContent(root, paths, maxContentBytes, deadlineMs, now) {
|
|
61
|
+
const hashes = /* @__PURE__ */ new Map();
|
|
62
|
+
let consumedBytes = 0;
|
|
63
|
+
function ensureBudget() {
|
|
64
|
+
if (now() >= deadlineMs) {
|
|
65
|
+
throw new GitServiceError(
|
|
66
|
+
"GIT_STATE_DEADLINE_EXCEEDED",
|
|
67
|
+
"The worktree-state capture exceeded its overall time budget"
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function consume(bytes) {
|
|
72
|
+
consumedBytes += bytes;
|
|
73
|
+
if (consumedBytes > maxContentBytes) {
|
|
74
|
+
throw new GitServiceError(
|
|
75
|
+
"GIT_STATE_TOO_LARGE",
|
|
76
|
+
`Changed worktree content exceeds the ${maxContentBytes}-byte fingerprint bound`,
|
|
77
|
+
{ details: { maxContentBytes } }
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function sameFileIdentity(before, after) {
|
|
82
|
+
return before.dev === after.dev && before.ino === after.ino && before.size === after.size && before.mtimeNs === after.mtimeNs && before.ctimeNs === after.ctimeNs && before.mode === after.mode;
|
|
83
|
+
}
|
|
84
|
+
for (const entryPath of paths) {
|
|
85
|
+
ensureBudget();
|
|
86
|
+
const absolutePath = path.join(root, ...entryPath.split("/"));
|
|
87
|
+
let before;
|
|
88
|
+
try {
|
|
89
|
+
before = await lstat(absolutePath, { bigint: true });
|
|
90
|
+
} catch (error) {
|
|
91
|
+
throw new GitServiceError(
|
|
92
|
+
"GIT_STATE_CHANGED_DURING_CAPTURE",
|
|
93
|
+
"A changed worktree path disappeared while its state was being captured",
|
|
94
|
+
{ cause: error }
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
if (before.isSymbolicLink()) {
|
|
98
|
+
let target;
|
|
99
|
+
let after;
|
|
100
|
+
try {
|
|
101
|
+
target = await readlink(absolutePath, { encoding: "buffer" });
|
|
102
|
+
after = await lstat(absolutePath, { bigint: true });
|
|
103
|
+
} catch (error) {
|
|
104
|
+
throw new GitServiceError(
|
|
105
|
+
"GIT_STATE_CHANGED_DURING_CAPTURE",
|
|
106
|
+
"A symlink changed while its state was being captured",
|
|
107
|
+
{ cause: error }
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
if (!sameFileIdentity(before, after)) {
|
|
111
|
+
throw new GitServiceError(
|
|
112
|
+
"GIT_STATE_CHANGED_DURING_CAPTURE",
|
|
113
|
+
"A symlink changed while its state was being captured"
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
consume(target.byteLength);
|
|
117
|
+
hashes.set(
|
|
118
|
+
entryPath,
|
|
119
|
+
`symlink-sha256:${createHash("sha256").update(target).digest("hex")}`
|
|
120
|
+
);
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (!before.isFile()) {
|
|
124
|
+
throw new GitServiceError(
|
|
125
|
+
"GIT_STATE_UNFINGERPRINTABLE",
|
|
126
|
+
"A changed worktree path is a directory or special file that Webdesk cannot fingerprint safely"
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
if (before.size > BigInt(maxContentBytes - consumedBytes)) {
|
|
130
|
+
throw new GitServiceError(
|
|
131
|
+
"GIT_STATE_TOO_LARGE",
|
|
132
|
+
`Changed worktree content exceeds the ${maxContentBytes}-byte fingerprint bound`,
|
|
133
|
+
{ details: { maxContentBytes } }
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
consume(Number(before.size));
|
|
137
|
+
let handle = null;
|
|
138
|
+
try {
|
|
139
|
+
handle = await open(absolutePath, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
140
|
+
const opened = await handle.stat({ bigint: true });
|
|
141
|
+
if (!opened.isFile() || !sameFileIdentity(before, opened)) {
|
|
142
|
+
throw new GitServiceError(
|
|
143
|
+
"GIT_STATE_CHANGED_DURING_CAPTURE",
|
|
144
|
+
"A worktree file changed before its content could be captured"
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
const digest = createHash("sha256");
|
|
148
|
+
const buffer = Buffer.allocUnsafe(64 * 1024);
|
|
149
|
+
let bytesReadTotal = 0;
|
|
150
|
+
while (true) {
|
|
151
|
+
ensureBudget();
|
|
152
|
+
const { bytesRead } = await handle.read(buffer, 0, buffer.length, null);
|
|
153
|
+
if (bytesRead === 0) break;
|
|
154
|
+
bytesReadTotal += bytesRead;
|
|
155
|
+
digest.update(buffer.subarray(0, bytesRead));
|
|
156
|
+
}
|
|
157
|
+
const after = await handle.stat({ bigint: true });
|
|
158
|
+
if (BigInt(bytesReadTotal) !== before.size || !sameFileIdentity(before, after)) {
|
|
159
|
+
throw new GitServiceError(
|
|
160
|
+
"GIT_STATE_CHANGED_DURING_CAPTURE",
|
|
161
|
+
"A worktree file changed while its content was being captured"
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
hashes.set(entryPath, `file-sha256:${digest.digest("hex")}`);
|
|
165
|
+
} catch (error) {
|
|
166
|
+
if (isGitServiceError(error)) throw error;
|
|
167
|
+
throw new GitServiceError(
|
|
168
|
+
"GIT_STATE_CHANGED_DURING_CAPTURE",
|
|
169
|
+
"A worktree file changed or could not be opened safely while its state was being captured",
|
|
170
|
+
{ cause: error }
|
|
171
|
+
);
|
|
172
|
+
} finally {
|
|
173
|
+
await handle?.close().catch(() => void 0);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return hashes;
|
|
177
|
+
}
|
|
178
|
+
async function captureWorktreeState(options) {
|
|
179
|
+
const maxEntries = positiveBound(
|
|
180
|
+
options.maxEntries ?? DEFAULT_STATE_MAX_ENTRIES,
|
|
181
|
+
"State entry limit"
|
|
182
|
+
);
|
|
183
|
+
const maxDurationMs = positiveBound(
|
|
184
|
+
options.maxDurationMs ?? DEFAULT_STATE_MAX_DURATION_MS,
|
|
185
|
+
"State duration limit"
|
|
186
|
+
);
|
|
187
|
+
const maxContentBytes = positiveBound(
|
|
188
|
+
options.maxContentBytes ?? DEFAULT_STATE_MAX_CONTENT_BYTES,
|
|
189
|
+
"State content-byte limit"
|
|
190
|
+
);
|
|
191
|
+
const now = options.now ?? Date.now;
|
|
192
|
+
const deadlineMs = now() + maxDurationMs;
|
|
193
|
+
const runner = withCaptureDeadline(
|
|
194
|
+
options.runner ?? defaultGitRunner,
|
|
195
|
+
deadlineMs,
|
|
196
|
+
now
|
|
197
|
+
);
|
|
198
|
+
const worktree = await inspectRepository(options.worktreePath, { runner });
|
|
199
|
+
const status = await runGitExpectingSuccess(
|
|
200
|
+
runner,
|
|
201
|
+
[
|
|
202
|
+
...READ_ONLY_GIT_FLAGS,
|
|
203
|
+
"status",
|
|
204
|
+
"--porcelain=v2",
|
|
205
|
+
"-z",
|
|
206
|
+
"--untracked-files=all"
|
|
207
|
+
],
|
|
208
|
+
{ cwd: worktree.root }
|
|
209
|
+
);
|
|
210
|
+
const entries = parseStatusOutput(status.stdout);
|
|
211
|
+
if (entries.length > maxEntries) {
|
|
212
|
+
throw new GitServiceError(
|
|
213
|
+
"GIT_STATE_TOO_LARGE",
|
|
214
|
+
`The worktree has ${entries.length} changed or untracked entries, more than the ${maxEntries}-entry fingerprint bound`,
|
|
215
|
+
{ details: { entries: entries.length, maxEntries } }
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
entries.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
219
|
+
if (entries.some((entry) => entry.sub.startsWith("S"))) {
|
|
220
|
+
throw new GitServiceError(
|
|
221
|
+
"GIT_STATE_UNFINGERPRINTABLE",
|
|
222
|
+
"Dirty or moved submodules cannot be fingerprinted safely yet"
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
const contentPaths = entries.filter(needsContentHash).map((entry) => entry.path);
|
|
226
|
+
const contentHashes = await hashWorktreeContent(
|
|
227
|
+
worktree.root,
|
|
228
|
+
contentPaths,
|
|
229
|
+
maxContentBytes,
|
|
230
|
+
deadlineMs,
|
|
231
|
+
now
|
|
232
|
+
);
|
|
233
|
+
const digest = createHash("sha256");
|
|
234
|
+
digest.update("pita-worktree-state-v1");
|
|
235
|
+
digest.update("\0");
|
|
236
|
+
digest.update(worktree.root);
|
|
237
|
+
digest.update("\0");
|
|
238
|
+
digest.update(worktree.commonDir);
|
|
239
|
+
digest.update("\0");
|
|
240
|
+
digest.update(worktree.branch ?? "detached");
|
|
241
|
+
digest.update("\0");
|
|
242
|
+
digest.update(worktree.headCommit);
|
|
243
|
+
digest.update("\0\0");
|
|
244
|
+
digest.update(status.stdout);
|
|
245
|
+
digest.update("\0\0");
|
|
246
|
+
for (const entryPath of contentPaths) {
|
|
247
|
+
const contentHash = contentHashes.get(entryPath);
|
|
248
|
+
if (contentHash === void 0) {
|
|
249
|
+
throw new GitServiceError(
|
|
250
|
+
"GIT_STATE_CHANGED_DURING_CAPTURE",
|
|
251
|
+
"A changed worktree path was not captured consistently"
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
digest.update(entryPath);
|
|
255
|
+
digest.update("\0");
|
|
256
|
+
digest.update(contentHash);
|
|
257
|
+
digest.update("\0");
|
|
258
|
+
}
|
|
259
|
+
const stateFingerprint = digest.digest("hex");
|
|
260
|
+
const verified = await inspectRepository(worktree.root, { runner });
|
|
261
|
+
if (!sameRepositoryIdentity(worktree, verified)) {
|
|
262
|
+
throw new GitServiceError(
|
|
263
|
+
"GIT_REPOSITORY_CHANGED_DURING_CAPTURE",
|
|
264
|
+
"The worktree branch or HEAD changed while its state was being captured; retry to observe the new state",
|
|
265
|
+
{
|
|
266
|
+
details: {
|
|
267
|
+
beforeHead: worktree.headCommit,
|
|
268
|
+
afterHead: verified.headCommit,
|
|
269
|
+
beforeBranch: worktree.branch,
|
|
270
|
+
afterBranch: verified.branch
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
worktree,
|
|
277
|
+
stateFingerprint,
|
|
278
|
+
statusEntryCount: entries.length
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
export {
|
|
282
|
+
DEFAULT_STATE_MAX_CONTENT_BYTES,
|
|
283
|
+
DEFAULT_STATE_MAX_DURATION_MS,
|
|
284
|
+
DEFAULT_STATE_MAX_ENTRIES,
|
|
285
|
+
captureWorktreeState
|
|
286
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// packages/git/src/index.ts
|
|
2
|
+
import {
|
|
3
|
+
GitMergeConflictError,
|
|
4
|
+
GitServiceError,
|
|
5
|
+
GitWorktreeIncompleteError,
|
|
6
|
+
isGitServiceError
|
|
7
|
+
} from "./errors.js";
|
|
8
|
+
import {
|
|
9
|
+
createDefaultGitRunner
|
|
10
|
+
} from "./runner.js";
|
|
11
|
+
import {
|
|
12
|
+
inspectRepository
|
|
13
|
+
} from "./repository.js";
|
|
14
|
+
import {
|
|
15
|
+
DEFAULT_REVIEW_MAX_DIFF_CHARS_PER_FILE,
|
|
16
|
+
DEFAULT_REVIEW_MAX_DURATION_MS,
|
|
17
|
+
DEFAULT_REVIEW_MAX_FILES,
|
|
18
|
+
DEFAULT_REVIEW_MAX_TOTAL_DIFF_CHARS,
|
|
19
|
+
reviewWorktree
|
|
20
|
+
} from "./review.js";
|
|
21
|
+
import {
|
|
22
|
+
DEFAULT_STATE_MAX_DURATION_MS,
|
|
23
|
+
DEFAULT_STATE_MAX_CONTENT_BYTES,
|
|
24
|
+
DEFAULT_STATE_MAX_ENTRIES,
|
|
25
|
+
captureWorktreeState
|
|
26
|
+
} from "./fingerprint.js";
|
|
27
|
+
import {
|
|
28
|
+
DEFAULT_VALIDATION_MAX_OUTPUT_CHARS,
|
|
29
|
+
DEFAULT_VALIDATION_TIMEOUT_MS,
|
|
30
|
+
MAX_VALIDATION_COMMAND_CHARS,
|
|
31
|
+
MAX_VALIDATION_TIMEOUT_MS,
|
|
32
|
+
ValidationRunnerError,
|
|
33
|
+
isValidationRunnerError,
|
|
34
|
+
startValidationRun
|
|
35
|
+
} from "./validation.js";
|
|
36
|
+
import {
|
|
37
|
+
createTaskWorktree,
|
|
38
|
+
preflightTaskWorktree
|
|
39
|
+
} from "./worktree.js";
|
|
40
|
+
import {
|
|
41
|
+
DEFAULT_COMMIT_MAX_DIFF_CHARS_PER_FILE,
|
|
42
|
+
DEFAULT_COMMIT_MAX_DURATION_MS,
|
|
43
|
+
DEFAULT_COMMIT_MAX_ENTRIES,
|
|
44
|
+
DEFAULT_COMMIT_MAX_FILES,
|
|
45
|
+
DEFAULT_COMMIT_MAX_TOTAL_DIFF_CHARS,
|
|
46
|
+
DEFAULT_COMMIT_SIGNING_TIMEOUT_MS,
|
|
47
|
+
MAX_COMMIT_MESSAGE_CHARS,
|
|
48
|
+
commitPreparedTree,
|
|
49
|
+
prepareCommitTree
|
|
50
|
+
} from "./commit.js";
|
|
51
|
+
import {
|
|
52
|
+
DEFAULT_MERGE_MAX_COMMIT_SUBJECTS,
|
|
53
|
+
DEFAULT_MERGE_MAX_DIFF_CHARS_PER_FILE,
|
|
54
|
+
DEFAULT_MERGE_MAX_DURATION_MS,
|
|
55
|
+
DEFAULT_MERGE_MAX_ENTRIES,
|
|
56
|
+
DEFAULT_MERGE_MAX_FILES,
|
|
57
|
+
DEFAULT_MERGE_MAX_GUARD_PATH_CHARS,
|
|
58
|
+
DEFAULT_MERGE_MAX_TOTAL_DIFF_CHARS,
|
|
59
|
+
DEFAULT_MERGE_GUARD_TIMEOUT_MS,
|
|
60
|
+
DEFAULT_MERGE_SIGNING_TIMEOUT_MS,
|
|
61
|
+
MAX_MERGE_CONFLICT_PATHS,
|
|
62
|
+
MAX_MERGE_MESSAGE_CHARS,
|
|
63
|
+
MIN_MERGE_GIT_VERSION,
|
|
64
|
+
assertMergeTargetPathsUnoccupied,
|
|
65
|
+
ensureMergeCapableGit,
|
|
66
|
+
isMergeCommitAncestor,
|
|
67
|
+
prepareMergeTree,
|
|
68
|
+
publishMerge,
|
|
69
|
+
syncTargetCheckout
|
|
70
|
+
} from "./merge.js";
|
|
71
|
+
export {
|
|
72
|
+
DEFAULT_COMMIT_MAX_DIFF_CHARS_PER_FILE,
|
|
73
|
+
DEFAULT_COMMIT_MAX_DURATION_MS,
|
|
74
|
+
DEFAULT_COMMIT_MAX_ENTRIES,
|
|
75
|
+
DEFAULT_COMMIT_MAX_FILES,
|
|
76
|
+
DEFAULT_COMMIT_MAX_TOTAL_DIFF_CHARS,
|
|
77
|
+
DEFAULT_COMMIT_SIGNING_TIMEOUT_MS,
|
|
78
|
+
DEFAULT_MERGE_GUARD_TIMEOUT_MS,
|
|
79
|
+
DEFAULT_MERGE_MAX_COMMIT_SUBJECTS,
|
|
80
|
+
DEFAULT_MERGE_MAX_DIFF_CHARS_PER_FILE,
|
|
81
|
+
DEFAULT_MERGE_MAX_DURATION_MS,
|
|
82
|
+
DEFAULT_MERGE_MAX_ENTRIES,
|
|
83
|
+
DEFAULT_MERGE_MAX_FILES,
|
|
84
|
+
DEFAULT_MERGE_MAX_GUARD_PATH_CHARS,
|
|
85
|
+
DEFAULT_MERGE_MAX_TOTAL_DIFF_CHARS,
|
|
86
|
+
DEFAULT_MERGE_SIGNING_TIMEOUT_MS,
|
|
87
|
+
DEFAULT_REVIEW_MAX_DIFF_CHARS_PER_FILE,
|
|
88
|
+
DEFAULT_REVIEW_MAX_DURATION_MS,
|
|
89
|
+
DEFAULT_REVIEW_MAX_FILES,
|
|
90
|
+
DEFAULT_REVIEW_MAX_TOTAL_DIFF_CHARS,
|
|
91
|
+
DEFAULT_STATE_MAX_CONTENT_BYTES,
|
|
92
|
+
DEFAULT_STATE_MAX_DURATION_MS,
|
|
93
|
+
DEFAULT_STATE_MAX_ENTRIES,
|
|
94
|
+
DEFAULT_VALIDATION_MAX_OUTPUT_CHARS,
|
|
95
|
+
DEFAULT_VALIDATION_TIMEOUT_MS,
|
|
96
|
+
GitMergeConflictError,
|
|
97
|
+
GitServiceError,
|
|
98
|
+
GitWorktreeIncompleteError,
|
|
99
|
+
MAX_COMMIT_MESSAGE_CHARS,
|
|
100
|
+
MAX_MERGE_CONFLICT_PATHS,
|
|
101
|
+
MAX_MERGE_MESSAGE_CHARS,
|
|
102
|
+
MAX_VALIDATION_COMMAND_CHARS,
|
|
103
|
+
MAX_VALIDATION_TIMEOUT_MS,
|
|
104
|
+
MIN_MERGE_GIT_VERSION,
|
|
105
|
+
ValidationRunnerError,
|
|
106
|
+
assertMergeTargetPathsUnoccupied,
|
|
107
|
+
captureWorktreeState,
|
|
108
|
+
commitPreparedTree,
|
|
109
|
+
createDefaultGitRunner,
|
|
110
|
+
createTaskWorktree,
|
|
111
|
+
ensureMergeCapableGit,
|
|
112
|
+
inspectRepository,
|
|
113
|
+
isGitServiceError,
|
|
114
|
+
isMergeCommitAncestor,
|
|
115
|
+
isValidationRunnerError,
|
|
116
|
+
preflightTaskWorktree,
|
|
117
|
+
prepareCommitTree,
|
|
118
|
+
prepareMergeTree,
|
|
119
|
+
publishMerge,
|
|
120
|
+
reviewWorktree,
|
|
121
|
+
startValidationRun,
|
|
122
|
+
syncTargetCheckout
|
|
123
|
+
};
|