@letrquan/book 0.3.0 → 0.4.0-beta.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/CHANGELOG.md +1024 -0
- package/README.md +6 -3
- package/dist/{additional-roots-H7UNAEHS.js → additional-roots-VAWRQ625.js} +8 -7
- package/dist/{app-GE4OHJOC.js → app-J7BVPSUH.js} +5397 -2953
- package/dist/app-J7BVPSUH.js.map +1 -0
- package/dist/chunk-32WBCUAN.js +660 -0
- package/dist/chunk-32WBCUAN.js.map +1 -0
- package/dist/{chunk-525CAZPY.js → chunk-4DKHLZRI.js} +6 -6
- package/dist/{chunk-4AS7LKKQ.js → chunk-62EEAUID.js} +2 -2
- package/dist/{chunk-AQEQX4FF.js → chunk-AHC7OU75.js} +385 -55
- package/dist/chunk-AHC7OU75.js.map +1 -0
- package/dist/{chunk-EFJ2NH6E.js → chunk-AJZWLKLQ.js} +63 -14
- package/dist/chunk-AJZWLKLQ.js.map +1 -0
- package/dist/chunk-B5FC3MYZ.js +395 -0
- package/dist/chunk-B5FC3MYZ.js.map +1 -0
- package/dist/{chunk-67UZEWWF.js → chunk-DNFQTSMJ.js} +53 -11
- package/dist/chunk-DNFQTSMJ.js.map +1 -0
- package/dist/{chunk-TLX3H2CL.js → chunk-E5WLQSKA.js} +231 -40
- package/dist/chunk-E5WLQSKA.js.map +1 -0
- package/dist/chunk-ECLC4CIJ.js +1181 -0
- package/dist/chunk-ECLC4CIJ.js.map +1 -0
- package/dist/chunk-EEX6QNXV.js +127 -0
- package/dist/chunk-EEX6QNXV.js.map +1 -0
- package/dist/chunk-EFXVSQ5J.js +931 -0
- package/dist/chunk-EFXVSQ5J.js.map +1 -0
- package/dist/{chunk-RFJ6Q6LE.js → chunk-ENLB7NYV.js} +577 -164
- package/dist/chunk-ENLB7NYV.js.map +1 -0
- package/dist/{chunk-IME7R2UI.js → chunk-FPR7SKIE.js} +1268 -883
- package/dist/chunk-FPR7SKIE.js.map +1 -0
- package/dist/{chunk-VPNLCMVR.js → chunk-HFB74CLM.js} +13 -5
- package/dist/chunk-HFB74CLM.js.map +1 -0
- package/dist/{chunk-5RDRAO4B.js → chunk-HOZXKOE3.js} +37 -1
- package/dist/chunk-HOZXKOE3.js.map +1 -0
- package/dist/chunk-IDYWN37T.js +36 -0
- package/dist/chunk-IDYWN37T.js.map +1 -0
- package/dist/{chunk-YC6W4EJH.js → chunk-JGF5HLSI.js} +193 -75
- package/dist/chunk-JGF5HLSI.js.map +1 -0
- package/dist/{chunk-5YHTKWJN.js → chunk-KDNWMKXV.js} +2447 -907
- package/dist/chunk-KDNWMKXV.js.map +1 -0
- package/dist/{chunk-Y2VHN7TC.js → chunk-MEOB2DZA.js} +11 -1
- package/dist/chunk-MEOB2DZA.js.map +1 -0
- package/dist/{chunk-KBQS35OV.js → chunk-MV5PQNIA.js} +2 -2
- package/dist/chunk-N2G4Q7ME.js +2672 -0
- package/dist/chunk-N2G4Q7ME.js.map +1 -0
- package/dist/{chunk-62QL5QUP.js → chunk-OJBMDM5H.js} +17 -1
- package/dist/chunk-OJBMDM5H.js.map +1 -0
- package/dist/{chunk-56SIEMDX.js → chunk-PTDC7ZUP.js} +2 -2
- package/dist/{chunk-X4NJT436.js → chunk-REASC2QG.js} +67 -28
- package/dist/chunk-REASC2QG.js.map +1 -0
- package/dist/chunk-SBTU5BEC.js +114 -0
- package/dist/chunk-SBTU5BEC.js.map +1 -0
- package/dist/{chunk-HQI7NYGX.js → chunk-SWPDKLNM.js} +2 -2
- package/dist/{chunk-W3XFHEF4.js → chunk-UCFJ43OS.js} +140 -28
- package/dist/chunk-UCFJ43OS.js.map +1 -0
- package/dist/{chunk-QYBD22H5.js → chunk-W7SLYS3M.js} +80 -16
- package/dist/chunk-W7SLYS3M.js.map +1 -0
- package/dist/{chunk-SOW4WRQP.js → chunk-WV3O5PGX.js} +3 -3
- package/dist/{chunk-JTPOI3KU.js → chunk-XJRJVXJR.js} +262 -38
- package/dist/chunk-XJRJVXJR.js.map +1 -0
- package/dist/{chunk-224FJZLH.js → chunk-YIL6HTJX.js} +228 -5
- package/dist/chunk-YIL6HTJX.js.map +1 -0
- package/dist/{command-approvals-VBIU6BLM.js → command-approvals-ZRY66LCW.js} +5 -4
- package/dist/context-C3RAP6K5.js +41 -0
- package/dist/{hook-approvals-ZVT4V7IM.js → hook-approvals-DPQD5H65.js} +5 -4
- package/dist/index.js +657 -754
- package/dist/index.js.map +1 -1
- package/dist/{interactive-assets-T4I4SEHU.js → interactive-assets-73AQO5WP.js} +11 -6
- package/dist/{interactive-assets-T4I4SEHU.js.map → interactive-assets-73AQO5WP.js.map} +1 -1
- package/dist/job-runner.js +10 -3
- package/dist/job-runner.js.map +1 -1
- package/dist/job-supervisor.js +13 -4
- package/dist/job-supervisor.js.map +1 -1
- package/dist/loader-DQNPDKOX.js +27 -0
- package/dist/{mcp-approvals-HJ2VDYMC.js → mcp-approvals-27LJYADQ.js} +5 -4
- package/dist/{mcp-config-RNB5LEVE.js → mcp-config-GXSODNCM.js} +3 -2
- package/dist/memory-store-I6Z54VUN.js +51 -0
- package/dist/{model-window-store-MTSQ5JDJ.js → model-window-store-6VKXXTPJ.js} +4 -3
- package/dist/{openai-compatible-2OB54YST.js → openai-compatible-IPUNBJ53.js} +5 -3
- package/dist/{permission-approvals-YLV6UC5W.js → permission-approvals-Q5IMFEZI.js} +5 -4
- package/dist/{permissions-DHOKF3W2.js → permissions-7Y35X6HZ.js} +26 -9
- package/dist/provider-approvals-5AGH3RVT.js +76 -0
- package/dist/{sandbox-WRYTZH3D.js → sandbox-N2RY72GN.js} +6 -5
- package/dist/{scrollback-35ME2GFX.js → scrollback-GD76GNM4.js} +36 -28
- package/dist/scrollback-GD76GNM4.js.map +1 -0
- package/dist/sdk.d.ts +876 -64
- package/dist/sdk.js +57 -37
- package/dist/sdk.js.map +1 -1
- package/dist/settings-loader-KDBH45AQ.js +43 -0
- package/dist/{settings-removed-JWWPT4WA.js → settings-removed-3ATWJEF3.js} +2 -2
- package/dist/shell-selection-Z5WORZU4.js +31 -0
- package/dist/shell-selection-Z5WORZU4.js.map +1 -0
- package/package.json +5 -5
- package/dist/app-GE4OHJOC.js.map +0 -1
- package/dist/chunk-224FJZLH.js.map +0 -1
- package/dist/chunk-5RDRAO4B.js.map +0 -1
- package/dist/chunk-5YHTKWJN.js.map +0 -1
- package/dist/chunk-62QL5QUP.js.map +0 -1
- package/dist/chunk-67UZEWWF.js.map +0 -1
- package/dist/chunk-6OQQOMZR.js +0 -785
- package/dist/chunk-6OQQOMZR.js.map +0 -1
- package/dist/chunk-AQEQX4FF.js.map +0 -1
- package/dist/chunk-C7ADUNPR.js +0 -273
- package/dist/chunk-C7ADUNPR.js.map +0 -1
- package/dist/chunk-EFJ2NH6E.js.map +0 -1
- package/dist/chunk-IME7R2UI.js.map +0 -1
- package/dist/chunk-J62VZYOB.js +0 -1339
- package/dist/chunk-J62VZYOB.js.map +0 -1
- package/dist/chunk-JTPOI3KU.js.map +0 -1
- package/dist/chunk-QYBD22H5.js.map +0 -1
- package/dist/chunk-RFJ6Q6LE.js.map +0 -1
- package/dist/chunk-S4JMID4G.js +0 -259
- package/dist/chunk-S4JMID4G.js.map +0 -1
- package/dist/chunk-TLX3H2CL.js.map +0 -1
- package/dist/chunk-VPNLCMVR.js.map +0 -1
- package/dist/chunk-W3XFHEF4.js.map +0 -1
- package/dist/chunk-X4NJT436.js.map +0 -1
- package/dist/chunk-X66I2NQO.js +0 -137
- package/dist/chunk-X66I2NQO.js.map +0 -1
- package/dist/chunk-Y2VHN7TC.js.map +0 -1
- package/dist/chunk-YC6W4EJH.js.map +0 -1
- package/dist/context-CBOBDY5Q.js +0 -38
- package/dist/loader-S77OVTHH.js +0 -18
- package/dist/memory-store-DZUT5HUH.js +0 -75
- package/dist/scrollback-35ME2GFX.js.map +0 -1
- package/dist/settings-loader-JUNPGAAM.js +0 -35
- package/dist/shell-selection-CDHGJ4GC.js +0 -17
- /package/dist/{additional-roots-H7UNAEHS.js.map → additional-roots-VAWRQ625.js.map} +0 -0
- /package/dist/{chunk-525CAZPY.js.map → chunk-4DKHLZRI.js.map} +0 -0
- /package/dist/{chunk-4AS7LKKQ.js.map → chunk-62EEAUID.js.map} +0 -0
- /package/dist/{chunk-KBQS35OV.js.map → chunk-MV5PQNIA.js.map} +0 -0
- /package/dist/{chunk-56SIEMDX.js.map → chunk-PTDC7ZUP.js.map} +0 -0
- /package/dist/{chunk-HQI7NYGX.js.map → chunk-SWPDKLNM.js.map} +0 -0
- /package/dist/{chunk-SOW4WRQP.js.map → chunk-WV3O5PGX.js.map} +0 -0
- /package/dist/{command-approvals-VBIU6BLM.js.map → command-approvals-ZRY66LCW.js.map} +0 -0
- /package/dist/{context-CBOBDY5Q.js.map → context-C3RAP6K5.js.map} +0 -0
- /package/dist/{hook-approvals-ZVT4V7IM.js.map → hook-approvals-DPQD5H65.js.map} +0 -0
- /package/dist/{loader-S77OVTHH.js.map → loader-DQNPDKOX.js.map} +0 -0
- /package/dist/{mcp-approvals-HJ2VDYMC.js.map → mcp-approvals-27LJYADQ.js.map} +0 -0
- /package/dist/{mcp-config-RNB5LEVE.js.map → mcp-config-GXSODNCM.js.map} +0 -0
- /package/dist/{memory-store-DZUT5HUH.js.map → memory-store-I6Z54VUN.js.map} +0 -0
- /package/dist/{model-window-store-MTSQ5JDJ.js.map → model-window-store-6VKXXTPJ.js.map} +0 -0
- /package/dist/{openai-compatible-2OB54YST.js.map → openai-compatible-IPUNBJ53.js.map} +0 -0
- /package/dist/{permission-approvals-YLV6UC5W.js.map → permission-approvals-Q5IMFEZI.js.map} +0 -0
- /package/dist/{permissions-DHOKF3W2.js.map → permissions-7Y35X6HZ.js.map} +0 -0
- /package/dist/{sandbox-WRYTZH3D.js.map → provider-approvals-5AGH3RVT.js.map} +0 -0
- /package/dist/{settings-loader-JUNPGAAM.js.map → sandbox-N2RY72GN.js.map} +0 -0
- /package/dist/{settings-removed-JWWPT4WA.js.map → settings-loader-KDBH45AQ.js.map} +0 -0
- /package/dist/{shell-selection-CDHGJ4GC.js.map → settings-removed-3ATWJEF3.js.map} +0 -0
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
2
|
HARDENED_DIFF_ARGS,
|
|
3
3
|
hardenedGitArgs,
|
|
4
|
-
hardenedGitEnv
|
|
5
|
-
|
|
4
|
+
hardenedGitEnv,
|
|
5
|
+
noFetchGitEnv,
|
|
6
|
+
parseGitConfig,
|
|
7
|
+
readRepositoryProgramPins
|
|
8
|
+
} from "./chunk-32WBCUAN.js";
|
|
6
9
|
import {
|
|
7
10
|
systemClock
|
|
8
11
|
} from "./chunk-RT5SATF7.js";
|
|
9
12
|
import {
|
|
10
13
|
buildChildEnv
|
|
11
14
|
} from "./chunk-XHAO3K7I.js";
|
|
15
|
+
import {
|
|
16
|
+
ignoresHomeRepository
|
|
17
|
+
} from "./chunk-SBTU5BEC.js";
|
|
18
|
+
import {
|
|
19
|
+
canonicalizePath,
|
|
20
|
+
isOutside
|
|
21
|
+
} from "./chunk-YIL6HTJX.js";
|
|
12
22
|
import {
|
|
13
23
|
resolveBookHome
|
|
14
24
|
} from "./chunk-ZPSZZUWF.js";
|
|
@@ -31,7 +41,7 @@ import { createHash, randomUUID } from "crypto";
|
|
|
31
41
|
import { execFile, spawn } from "child_process";
|
|
32
42
|
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from "fs";
|
|
33
43
|
import { tmpdir } from "os";
|
|
34
|
-
import { dirname, join, resolve } from "path";
|
|
44
|
+
import { dirname, join, relative, resolve, sep } from "path";
|
|
35
45
|
|
|
36
46
|
// src/agents/git-signing.ts
|
|
37
47
|
var SIGNING_KEY_PATTERN = "^(commit\\.gpgsign|gpg\\..*|user\\.signingkey)$";
|
|
@@ -56,51 +66,29 @@ var PIN_UNITS = [
|
|
|
56
66
|
{ keys: ["gpg.ssh.allowedsignersfile"], fallback: "" },
|
|
57
67
|
{ keys: ["gpg.ssh.revocationfile"], fallback: "" }
|
|
58
68
|
];
|
|
59
|
-
async function readSigningConfig(repoRoot, run2) {
|
|
69
|
+
async function readSigningConfig(repoRoot, run2, signal) {
|
|
60
70
|
const result = await run2(
|
|
61
71
|
"git",
|
|
62
72
|
["config", "--show-scope", "-z", "--get-regexp", SIGNING_KEY_PATTERN],
|
|
63
|
-
{ cwd: repoRoot, allowExitCodes: [1, 129], timeoutMs: READ_TIMEOUT_MS }
|
|
73
|
+
{ cwd: repoRoot, allowExitCodes: [1, 129], timeoutMs: READ_TIMEOUT_MS, signal }
|
|
64
74
|
);
|
|
65
75
|
if (result.code === 129 || /unknown option/i.test(result.stderr)) {
|
|
66
76
|
throw new Error(
|
|
67
|
-
`Applying an agent's result needs git ${MINIMUM_GIT} or later (for \`git config --show-scope\`); this git is ${await gitVersion(run2, repoRoot)}`
|
|
77
|
+
`Applying an agent's result needs git ${MINIMUM_GIT} or later (for \`git config --show-scope\`); this git is ${await gitVersion(run2, repoRoot, signal)}`
|
|
68
78
|
);
|
|
69
79
|
}
|
|
70
80
|
return parseSigningConfig(result.stdout);
|
|
71
81
|
}
|
|
72
|
-
async function gitVersion(run2, repoRoot) {
|
|
82
|
+
async function gitVersion(run2, repoRoot, signal) {
|
|
73
83
|
try {
|
|
74
|
-
return (await run2("git", ["--version"], { cwd: repoRoot, timeoutMs: READ_TIMEOUT_MS })).stdout.trim();
|
|
75
|
-
} catch {
|
|
84
|
+
return (await run2("git", ["--version"], { cwd: repoRoot, timeoutMs: READ_TIMEOUT_MS, signal })).stdout.trim();
|
|
85
|
+
} catch (error) {
|
|
86
|
+
if (signal?.aborted) throw error;
|
|
76
87
|
return "of an unknown version";
|
|
77
88
|
}
|
|
78
89
|
}
|
|
79
90
|
function parseSigningConfig(stdout) {
|
|
80
|
-
|
|
81
|
-
const entries = [];
|
|
82
|
-
for (let index = 0; index + 1 < fields.length; index += 2) {
|
|
83
|
-
const separator = fields[index + 1].indexOf("\n");
|
|
84
|
-
entries.push({
|
|
85
|
-
scope: fields[index].toLowerCase(),
|
|
86
|
-
key: canonicalConfigKey(
|
|
87
|
-
separator === -1 ? fields[index + 1] : fields[index + 1].slice(0, separator)
|
|
88
|
-
),
|
|
89
|
-
// Git's own reading of a key with no value: a boolean true.
|
|
90
|
-
value: separator === -1 ? "true" : fields[index + 1].slice(separator + 1)
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
return entries;
|
|
94
|
-
}
|
|
95
|
-
function canonicalConfigKey(raw) {
|
|
96
|
-
const nameStart = raw.lastIndexOf(".");
|
|
97
|
-
if (nameStart === -1) return raw.toLowerCase();
|
|
98
|
-
const head = raw.slice(0, nameStart);
|
|
99
|
-
const name = raw.slice(nameStart + 1).toLowerCase();
|
|
100
|
-
const subsectionStart = head.indexOf(".");
|
|
101
|
-
if (subsectionStart === -1) return `${head.toLowerCase()}.${name}`;
|
|
102
|
-
const section = head.slice(0, subsectionStart).toLowerCase();
|
|
103
|
-
return `${section}.${head.slice(subsectionStart + 1)}.${name}`;
|
|
91
|
+
return parseGitConfig(stdout);
|
|
104
92
|
}
|
|
105
93
|
function signingFacts(entries) {
|
|
106
94
|
const operatorEntries = [];
|
|
@@ -180,36 +168,42 @@ function derivedSigningKey(facts, inputs) {
|
|
|
180
168
|
function committerSigningIdentity(ident) {
|
|
181
169
|
return ident.trim().replace(/\s+\d+\s+[+-]\d{4}$/, "");
|
|
182
170
|
}
|
|
183
|
-
async function signingPinArgs(repoRoot, run2) {
|
|
184
|
-
const entries = await readSigningConfig(repoRoot, run2);
|
|
171
|
+
async function signingPinArgs(repoRoot, run2, signal) {
|
|
172
|
+
const entries = await readSigningConfig(repoRoot, run2, signal);
|
|
185
173
|
const facts = signingFacts(entries);
|
|
186
174
|
const inputs = { committerIdent: "", sshDefaultKey: "" };
|
|
187
175
|
const source = signingKeySource(facts);
|
|
188
176
|
if (source === "committer") {
|
|
189
177
|
inputs.committerIdent = (await run2("git", ["var", "GIT_COMMITTER_IDENT"], {
|
|
190
178
|
cwd: repoRoot,
|
|
191
|
-
timeoutMs: READ_TIMEOUT_MS
|
|
179
|
+
timeoutMs: READ_TIMEOUT_MS,
|
|
180
|
+
signal
|
|
192
181
|
})).stdout;
|
|
193
182
|
} else if (source === "ssh-default-key-command") {
|
|
194
|
-
inputs.sshDefaultKey = await sshDefaultSigningKey(facts, repoRoot, run2);
|
|
183
|
+
inputs.sshDefaultKey = await sshDefaultSigningKey(facts, repoRoot, run2, signal);
|
|
195
184
|
}
|
|
196
185
|
return pinsFor(facts, inputs);
|
|
197
186
|
}
|
|
198
|
-
async function sshDefaultSigningKey(facts, repoRoot, run2) {
|
|
187
|
+
async function sshDefaultSigningKey(facts, repoRoot, run2, signal) {
|
|
199
188
|
const command = lastOperatorValue(facts, ["gpg.ssh.defaultkeycommand"])?.trim();
|
|
200
189
|
if (!command) return "";
|
|
201
190
|
const [program, ...args] = command.split(/\s+/);
|
|
202
191
|
try {
|
|
203
|
-
const result = await run2(program, args, {
|
|
192
|
+
const result = await run2(program, args, {
|
|
193
|
+
cwd: repoRoot,
|
|
194
|
+
timeoutMs: READ_TIMEOUT_MS,
|
|
195
|
+
signal
|
|
196
|
+
});
|
|
204
197
|
const first = result.stdout.split(/\r?\n/)[0]?.trim() ?? "";
|
|
205
198
|
return first.startsWith("key::") ? first : "";
|
|
206
|
-
} catch {
|
|
199
|
+
} catch (error) {
|
|
200
|
+
if (signal?.aborted) throw error;
|
|
207
201
|
return "";
|
|
208
202
|
}
|
|
209
203
|
}
|
|
210
204
|
|
|
211
205
|
// src/agents/git-isolation.ts
|
|
212
|
-
function run(command, args, options) {
|
|
206
|
+
function run(command, args, options, maxBuffer = DEFAULT_MAX_BUFFER_BYTES) {
|
|
213
207
|
const env = internalGitEnv(options.env);
|
|
214
208
|
const timeoutMs = options.timeoutMs ?? DEFAULT_GIT_TIMEOUT_MS;
|
|
215
209
|
const signal = options.signal;
|
|
@@ -280,7 +274,15 @@ function run(command, args, options) {
|
|
|
280
274
|
}
|
|
281
275
|
reject(
|
|
282
276
|
new Error(
|
|
283
|
-
|
|
277
|
+
failureDescription(
|
|
278
|
+
null,
|
|
279
|
+
stderr.trim() || stdout.trim() || stdinError?.message || outputError?.message || "",
|
|
280
|
+
command,
|
|
281
|
+
args,
|
|
282
|
+
timeoutMs,
|
|
283
|
+
stoppedBy === "aborted",
|
|
284
|
+
code
|
|
285
|
+
)
|
|
284
286
|
)
|
|
285
287
|
);
|
|
286
288
|
});
|
|
@@ -332,10 +334,10 @@ function run(command, args, options) {
|
|
|
332
334
|
cwd: options.cwd,
|
|
333
335
|
env,
|
|
334
336
|
encoding: "utf8",
|
|
335
|
-
//
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
maxBuffer
|
|
337
|
+
// Each of stdout and stderr is capped here, and a call that overruns the cap fails rather
|
|
338
|
+
// than resolving on what had arrived. Only this branch is capped: the `input` branch above
|
|
339
|
+
// collects its output without a limit. See {@link DEFAULT_MAX_BUFFER_BYTES}.
|
|
340
|
+
maxBuffer
|
|
339
341
|
// No `timeout` and no `signal` option here. `execFile`'s own timeout kills the child but
|
|
340
342
|
// still waits for its output to close, and a grandchild holding that pipe — a shell script,
|
|
341
343
|
// a `credential.helper` that started something of its own — means it never does, so the
|
|
@@ -350,7 +352,7 @@ function run(command, args, options) {
|
|
|
350
352
|
new Error(
|
|
351
353
|
failureDescription(
|
|
352
354
|
error,
|
|
353
|
-
stderr || stdout,
|
|
355
|
+
stderr.trim() || stdout.trim(),
|
|
354
356
|
command,
|
|
355
357
|
args,
|
|
356
358
|
timeoutMs,
|
|
@@ -368,11 +370,15 @@ function run(command, args, options) {
|
|
|
368
370
|
settle(
|
|
369
371
|
() => reject(
|
|
370
372
|
new Error(
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
373
|
+
failureDescription(
|
|
374
|
+
error,
|
|
375
|
+
stderr.trim() || stdout.trim(),
|
|
376
|
+
command,
|
|
377
|
+
args,
|
|
378
|
+
timeoutMs,
|
|
379
|
+
stoppedBy === "aborted",
|
|
380
|
+
code
|
|
381
|
+
)
|
|
376
382
|
)
|
|
377
383
|
)
|
|
378
384
|
);
|
|
@@ -385,6 +391,7 @@ function run(command, args, options) {
|
|
|
385
391
|
});
|
|
386
392
|
}
|
|
387
393
|
var DEFAULT_GIT_TIMEOUT_MS = 12e4;
|
|
394
|
+
var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
388
395
|
var KILL_GRACE_MS = 2e3;
|
|
389
396
|
function stopEscalating(child, settled) {
|
|
390
397
|
child.kill("SIGTERM");
|
|
@@ -429,13 +436,20 @@ function exitCodeOf(error) {
|
|
|
429
436
|
function isAbortError(error) {
|
|
430
437
|
return error?.name === "AbortError" || error?.code === "ABORT_ERR";
|
|
431
438
|
}
|
|
432
|
-
function failureDescription(error, output, command, args, timeoutMs, aborted) {
|
|
439
|
+
function failureDescription(error, output, command, args, timeoutMs, aborted, code) {
|
|
433
440
|
const invocation = `${command} ${subcommandOf(args)}`;
|
|
434
441
|
if (aborted || isAbortError(error)) return `${invocation} was cancelled`;
|
|
435
442
|
if (error?.killed) return `${invocation} timed out after ${timeoutMs}ms and was killed`;
|
|
436
443
|
if (error?.signal) return `${invocation} was killed with ${error.signal}`;
|
|
437
444
|
if (typeof error?.code === "string") return `${invocation} failed: ${error.code}`;
|
|
438
|
-
|
|
445
|
+
const trimmed = output.trim();
|
|
446
|
+
if (/promisor remote|lazy fetching disabled/i.test(trimmed)) {
|
|
447
|
+
return "this repository is a partial clone; Book's agent isolation does not fetch missing objects, because the fetch would run the transport this checkout configures (`core.sshCommand`, `credential.helper`) with no prompt; fetch the missing objects yourself (for example `git fetch --refetch <remote>` after unsetting `remote.<remote>.partialclonefilter`), then retry.\n" + trimmed;
|
|
448
|
+
}
|
|
449
|
+
if (trimmed) return trimmed;
|
|
450
|
+
if (code !== void 0) return `${invocation} failed (${code})`;
|
|
451
|
+
if (error?.message) return error.message;
|
|
452
|
+
return `${invocation} failed`;
|
|
439
453
|
}
|
|
440
454
|
var GIT_REPOSITORY_SELECTION_VARIABLES = /* @__PURE__ */ new Set([
|
|
441
455
|
"GIT_DIR",
|
|
@@ -455,12 +469,31 @@ var GIT_REPOSITORY_SELECTION_VARIABLES = /* @__PURE__ */ new Set([
|
|
|
455
469
|
function internalGitEnv(overrides) {
|
|
456
470
|
const ambient = buildChildEnv(process.env);
|
|
457
471
|
for (const name of GIT_REPOSITORY_SELECTION_VARIABLES) delete ambient[name];
|
|
458
|
-
return {
|
|
472
|
+
return {
|
|
473
|
+
...ambient,
|
|
474
|
+
...overrides,
|
|
475
|
+
...hardenedGitEnv(),
|
|
476
|
+
...noFetchGitEnv()
|
|
477
|
+
};
|
|
459
478
|
}
|
|
460
|
-
function git(cwd, args, options = {}) {
|
|
461
|
-
|
|
479
|
+
async function git(cwd, args, options = {}) {
|
|
480
|
+
const pins = await readRepositoryProgramPins(
|
|
481
|
+
cwd,
|
|
482
|
+
(pinArgs, pinOpts) => run("git", pinArgs, {
|
|
483
|
+
signal: options.signal,
|
|
484
|
+
timeoutMs: options.timeoutMs,
|
|
485
|
+
env: options.env,
|
|
486
|
+
...pinOpts
|
|
487
|
+
}),
|
|
488
|
+
{
|
|
489
|
+
signal: options.signal,
|
|
490
|
+
timeoutMs: options.timeoutMs,
|
|
491
|
+
env: options.env,
|
|
492
|
+
allowFsmonitor: false
|
|
493
|
+
}
|
|
494
|
+
);
|
|
495
|
+
return run("git", hardenedGitArgs([...pins, ...args]), { ...options, cwd });
|
|
462
496
|
}
|
|
463
|
-
var hardenedRunner = run;
|
|
464
497
|
function cherryPickFailureResult(facts) {
|
|
465
498
|
const conflicted = facts.unmergedPaths.length > 0;
|
|
466
499
|
if (facts.abortError) {
|
|
@@ -491,28 +524,81 @@ function tempIndex() {
|
|
|
491
524
|
return { dir, path: join(dir, "index") };
|
|
492
525
|
}
|
|
493
526
|
async function findGitRoot(workspace, signal) {
|
|
494
|
-
|
|
495
|
-
return (await git(workspace, ["rev-parse", "--show-toplevel"], { signal })).stdout.trim();
|
|
496
|
-
} catch {
|
|
527
|
+
if (!existsSync(workspace)) {
|
|
497
528
|
return void 0;
|
|
498
529
|
}
|
|
530
|
+
try {
|
|
531
|
+
const top = (await git(workspace, ["rev-parse", "--show-toplevel"], { signal })).stdout.trim();
|
|
532
|
+
return ignoresHomeRepository(top, workspace) ? void 0 : top;
|
|
533
|
+
} catch (error) {
|
|
534
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
535
|
+
const code = error?.code;
|
|
536
|
+
if (/not a git repository/i.test(message) || code === "ENOENT" || /no such file or directory/i.test(message)) {
|
|
537
|
+
return void 0;
|
|
538
|
+
}
|
|
539
|
+
throw error;
|
|
540
|
+
}
|
|
499
541
|
}
|
|
500
542
|
function repositoryHash(repoRoot) {
|
|
501
543
|
return createHash("sha256").update(resolve(repoRoot).toLowerCase()).digest("hex").slice(0, 20);
|
|
502
544
|
}
|
|
545
|
+
function bookHomeInRepository(repoRoot) {
|
|
546
|
+
const rootReal = canonicalizePath(repoRoot);
|
|
547
|
+
const bookHomeReal = canonicalizePath(resolveBookHome());
|
|
548
|
+
if (isOutside(rootReal, bookHomeReal)) return void 0;
|
|
549
|
+
const inside = relative(rootReal, bookHomeReal);
|
|
550
|
+
return inside === "" ? void 0 : inside.split(sep).join("/");
|
|
551
|
+
}
|
|
503
552
|
async function writeWorkspaceTree(repoRoot, includeUntracked, signal) {
|
|
504
553
|
const index = tempIndex();
|
|
505
554
|
try {
|
|
506
555
|
const env = { GIT_INDEX_FILE: index.path };
|
|
556
|
+
const bookHome = bookHomeInRepository(repoRoot);
|
|
557
|
+
const magic = bookHome === void 0 ? [] : ["--no-literal-pathspecs"];
|
|
558
|
+
const exclusion = bookHome === void 0 ? [] : [`:(top,literal,exclude)${bookHome}`];
|
|
507
559
|
const head = (await git(repoRoot, ["rev-parse", "HEAD"], { signal })).stdout.trim();
|
|
508
560
|
await git(repoRoot, ["read-tree", head], { env, signal });
|
|
509
|
-
await git(
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
561
|
+
await git(
|
|
562
|
+
repoRoot,
|
|
563
|
+
[...magic, "add", includeUntracked ? "-A" : "-u", "--", ".", ...exclusion],
|
|
564
|
+
{
|
|
565
|
+
env,
|
|
566
|
+
signal
|
|
567
|
+
}
|
|
568
|
+
);
|
|
513
569
|
const tree = (await git(repoRoot, ["write-tree"], { env, signal })).stdout.trim();
|
|
514
|
-
const status =
|
|
515
|
-
|
|
570
|
+
const status = [
|
|
571
|
+
(await git(
|
|
572
|
+
repoRoot,
|
|
573
|
+
[
|
|
574
|
+
...magic,
|
|
575
|
+
"status",
|
|
576
|
+
"--porcelain=v1",
|
|
577
|
+
"--untracked-files=all",
|
|
578
|
+
"--ignore-submodules=dirty",
|
|
579
|
+
...bookHome === void 0 ? [] : ["--", ".", ...exclusion]
|
|
580
|
+
],
|
|
581
|
+
{ signal }
|
|
582
|
+
)).stdout
|
|
583
|
+
];
|
|
584
|
+
if (bookHome !== void 0) {
|
|
585
|
+
status.push(
|
|
586
|
+
(await git(
|
|
587
|
+
repoRoot,
|
|
588
|
+
[
|
|
589
|
+
...magic,
|
|
590
|
+
"status",
|
|
591
|
+
"--porcelain=v1",
|
|
592
|
+
"--untracked-files=no",
|
|
593
|
+
"--ignore-submodules=dirty",
|
|
594
|
+
"--",
|
|
595
|
+
`:(top,literal)${bookHome}`
|
|
596
|
+
],
|
|
597
|
+
{ signal }
|
|
598
|
+
)).stdout
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
return { head, tree, status: status.join("") };
|
|
516
602
|
} finally {
|
|
517
603
|
rmSync(index.dir, { recursive: true, force: true });
|
|
518
604
|
}
|
|
@@ -744,14 +830,22 @@ async function unmergedPathsAfterFailure(repoRoot) {
|
|
|
744
830
|
return [];
|
|
745
831
|
}
|
|
746
832
|
}
|
|
747
|
-
async function applyVerifiedCandidate(snapshot, candidate, signal) {
|
|
833
|
+
async function applyVerifiedCandidate(snapshot, candidate, signal, options) {
|
|
834
|
+
return applyCandidate(snapshot, candidate, signal, DEFAULT_MAX_BUFFER_BYTES, options);
|
|
835
|
+
}
|
|
836
|
+
function stoppedApplyError(signal, step, outcome) {
|
|
837
|
+
const reason = typeof signal?.reason === "string" ? ` (${signal.reason})` : "";
|
|
838
|
+
return new Error(`The apply was stopped${reason} during ${step}. ${outcome}`);
|
|
839
|
+
}
|
|
840
|
+
async function applyCandidate(snapshot, candidate, signal, signingBuffer, options) {
|
|
841
|
+
const mutationSignal = options?.mutationSignal ?? signal;
|
|
748
842
|
if (candidate.baseCommit !== snapshot.commit) {
|
|
749
843
|
return {
|
|
750
844
|
status: "conflicted",
|
|
751
845
|
error: "Patch candidate base does not match the task snapshot."
|
|
752
846
|
};
|
|
753
847
|
}
|
|
754
|
-
const actualHead = (await git(snapshot.repoRoot, ["rev-parse", candidate.headCommit])).stdout.trim();
|
|
848
|
+
const actualHead = (await git(snapshot.repoRoot, ["rev-parse", candidate.headCommit], { signal })).stdout.trim();
|
|
755
849
|
if (actualHead !== candidate.headCommit) {
|
|
756
850
|
return { status: "conflicted", error: "Patch candidate commit no longer resolves exactly." };
|
|
757
851
|
}
|
|
@@ -776,16 +870,22 @@ async function applyVerifiedCandidate(snapshot, candidate, signal) {
|
|
|
776
870
|
try {
|
|
777
871
|
await precheckDelta(snapshot, patch, signal);
|
|
778
872
|
} catch (error) {
|
|
873
|
+
const stopped = signal?.aborted === true;
|
|
874
|
+
if (stopped) {
|
|
875
|
+
throw stoppedApplyError(signal, "the patch pre-check", "No changes were applied.");
|
|
876
|
+
}
|
|
779
877
|
return {
|
|
780
878
|
status: "conflicted",
|
|
781
879
|
error: `Patch pre-check failed; no changes were applied: ${error instanceof Error ? error.message : String(error)}`
|
|
782
880
|
};
|
|
783
881
|
}
|
|
882
|
+
const signingRunner = (command, args, options2) => run(command, args, options2, signingBuffer);
|
|
784
883
|
if (!snapshot.dirty) {
|
|
785
884
|
let signingPins;
|
|
786
885
|
try {
|
|
787
|
-
signingPins = await signingPinArgs(snapshot.repoRoot,
|
|
886
|
+
signingPins = await signingPinArgs(snapshot.repoRoot, signingRunner, signal);
|
|
788
887
|
} catch (error) {
|
|
888
|
+
if (signal?.aborted) throw error;
|
|
789
889
|
return {
|
|
790
890
|
status: "conflicted",
|
|
791
891
|
error: `Could not read the signing configuration for the cherry-pick: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -794,11 +894,10 @@ async function applyVerifiedCandidate(snapshot, candidate, signal) {
|
|
|
794
894
|
try {
|
|
795
895
|
await git(snapshot.repoRoot, [...signingPins, "cherry-pick", candidate.headCommit], {
|
|
796
896
|
timeoutMs: CHERRY_PICK_TIMEOUT_MS,
|
|
797
|
-
signal
|
|
897
|
+
signal: mutationSignal
|
|
798
898
|
});
|
|
799
|
-
const appliedCommit = (await git(snapshot.repoRoot, ["rev-parse", "HEAD"], { signal })).stdout.trim();
|
|
800
|
-
return { status: "applied", commit: appliedCommit };
|
|
801
899
|
} catch (error) {
|
|
900
|
+
const stopped = mutationSignal?.aborted === true;
|
|
802
901
|
const unmergedPaths = await unmergedPathsAfterFailure(snapshot.repoRoot);
|
|
803
902
|
let abortError;
|
|
804
903
|
try {
|
|
@@ -806,17 +905,36 @@ async function applyVerifiedCandidate(snapshot, candidate, signal) {
|
|
|
806
905
|
} catch (abortFailure) {
|
|
807
906
|
abortError = abortFailure instanceof Error ? abortFailure.message : String(abortFailure);
|
|
808
907
|
}
|
|
908
|
+
if (stopped) {
|
|
909
|
+
throw stoppedApplyError(
|
|
910
|
+
mutationSignal,
|
|
911
|
+
"the cherry-pick",
|
|
912
|
+
[
|
|
913
|
+
abortError ? `The rollback did not complete (${abortError}), so this repository may be left mid-cherry-pick: finish it with git cherry-pick --continue or undo it with git cherry-pick --abort.` : "The cherry-pick was rolled back.",
|
|
914
|
+
unmergedPaths.length > 0 ? `Unmerged paths: ${unmergedPaths.join(", ")}.` : void 0
|
|
915
|
+
].filter(Boolean).join(" ")
|
|
916
|
+
);
|
|
917
|
+
}
|
|
809
918
|
return cherryPickFailureResult({
|
|
810
919
|
pickError: error instanceof Error ? error.message : String(error),
|
|
811
920
|
abortError,
|
|
812
921
|
unmergedPaths
|
|
813
922
|
});
|
|
814
923
|
}
|
|
924
|
+
const appliedCommit = (await git(snapshot.repoRoot, ["rev-parse", "HEAD"])).stdout.trim();
|
|
925
|
+
return { status: "applied", commit: appliedCommit };
|
|
815
926
|
}
|
|
816
927
|
try {
|
|
817
|
-
await git(snapshot.repoRoot, ["apply", "-"], { input: patch, signal });
|
|
928
|
+
await git(snapshot.repoRoot, ["apply", "-"], { input: patch, signal: mutationSignal });
|
|
818
929
|
return { status: "applied", commit: candidate.headCommit };
|
|
819
930
|
} catch (error) {
|
|
931
|
+
if (mutationSignal?.aborted) {
|
|
932
|
+
throw stoppedApplyError(
|
|
933
|
+
mutationSignal,
|
|
934
|
+
"git apply",
|
|
935
|
+
"git apply was cut short, so check git status before applying again: the working tree may be partly changed."
|
|
936
|
+
);
|
|
937
|
+
}
|
|
820
938
|
return {
|
|
821
939
|
status: "conflicted",
|
|
822
940
|
error: `Patch application failed: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -944,4 +1062,4 @@ export {
|
|
|
944
1062
|
removePersistentJobFiles,
|
|
945
1063
|
removePersistentRunnerFiles
|
|
946
1064
|
};
|
|
947
|
-
//# sourceMappingURL=chunk-
|
|
1065
|
+
//# sourceMappingURL=chunk-JGF5HLSI.js.map
|