@ai-development-environment/control-agent 0.0.137 → 0.0.139
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/control-agent.js +468 -191
- package/package.json +1 -1
package/dist/control-agent.js
CHANGED
|
@@ -7130,25 +7130,38 @@ var AgentGraphQLClient = class {
|
|
|
7130
7130
|
);
|
|
7131
7131
|
}
|
|
7132
7132
|
async uploadBuildArtifact(input) {
|
|
7133
|
+
const timeoutMs = input.timeoutMs ?? this.requestTimeoutMs;
|
|
7134
|
+
if (timeoutMs <= 0)
|
|
7135
|
+
throw new DOMException("Artifact upload timed out", "TimeoutError");
|
|
7136
|
+
const timeout = AbortSignal.timeout(timeoutMs);
|
|
7137
|
+
const signal2 = input.signal ? AbortSignal.any([input.signal, timeout]) : timeout;
|
|
7138
|
+
signal2.throwIfAborted();
|
|
7133
7139
|
const information = await stat(input.path);
|
|
7134
|
-
|
|
7135
|
-
|
|
7136
|
-
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
"
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7140
|
+
signal2.throwIfAborted();
|
|
7141
|
+
const source = createReadStream(input.path);
|
|
7142
|
+
try {
|
|
7143
|
+
const response = await fetch(
|
|
7144
|
+
`${this.server}/api/build-artifact-uploads/${encodeURIComponent(input.uploadId)}`,
|
|
7145
|
+
{
|
|
7146
|
+
method: "POST",
|
|
7147
|
+
headers: mergeHeaders(this.headers, {
|
|
7148
|
+
...this.credential ? { authorization: `Bearer ${this.credential}` } : {},
|
|
7149
|
+
"content-length": String(information.size),
|
|
7150
|
+
"content-type": input.contentType,
|
|
7151
|
+
"x-artifact-filename": encodeURIComponent(input.filename)
|
|
7152
|
+
}),
|
|
7153
|
+
body: Readable.toWeb(source),
|
|
7154
|
+
duplex: "half",
|
|
7155
|
+
signal: signal2
|
|
7156
|
+
}
|
|
7151
7157
|
);
|
|
7158
|
+
if (!response.ok) {
|
|
7159
|
+
throw new Error(
|
|
7160
|
+
`Artifact upload failed: HTTP ${response.status} ${await response.text()}`
|
|
7161
|
+
);
|
|
7162
|
+
}
|
|
7163
|
+
} finally {
|
|
7164
|
+
source.destroy();
|
|
7152
7165
|
}
|
|
7153
7166
|
}
|
|
7154
7167
|
artifactTransferHeaders(values = {}) {
|
|
@@ -7471,12 +7484,12 @@ var AgentGraphQLClient = class {
|
|
|
7471
7484
|
);
|
|
7472
7485
|
return data.beginRunAttempt;
|
|
7473
7486
|
}
|
|
7474
|
-
updateRunAttemptNativeId(attemptId, nativeId, providerVersion) {
|
|
7487
|
+
updateRunAttemptNativeId(attemptId, nativeId, providerVersion, sessionInfo) {
|
|
7475
7488
|
return this.request(
|
|
7476
|
-
`mutation UpdateRunAttemptNativeId($attemptId: ID!, $nativeId: String!, $providerVersion: String) {
|
|
7477
|
-
updateRunAttemptNativeId(attemptId: $attemptId, nativeId: $nativeId, providerVersion: $providerVersion) { id nativeId }
|
|
7489
|
+
`mutation UpdateRunAttemptNativeId($attemptId: ID!, $nativeId: String!, $providerVersion: String, $sessionInfo: RunSessionInfoInput) {
|
|
7490
|
+
updateRunAttemptNativeId(attemptId: $attemptId, nativeId: $nativeId, providerVersion: $providerVersion, sessionInfo: $sessionInfo) { id nativeId }
|
|
7478
7491
|
}`,
|
|
7479
|
-
{ attemptId, nativeId, providerVersion }
|
|
7492
|
+
{ attemptId, nativeId, providerVersion, sessionInfo }
|
|
7480
7493
|
);
|
|
7481
7494
|
}
|
|
7482
7495
|
appendRunEvents(runId, attemptId, events) {
|
|
@@ -9301,7 +9314,7 @@ function worktreeGitInspectPayload(value) {
|
|
|
9301
9314
|
`Unexpected worktree Git inspect payload field: ${unexpected}`
|
|
9302
9315
|
);
|
|
9303
9316
|
}
|
|
9304
|
-
if (payload.action !== "STATE" && payload.action !== "STASH_DIFF") {
|
|
9317
|
+
if (payload.action !== "STATE" && payload.action !== "REFRESH" && payload.action !== "STASH_DIFF") {
|
|
9305
9318
|
throw new Error("worktree Git inspect payload.action is invalid");
|
|
9306
9319
|
}
|
|
9307
9320
|
const common = {
|
|
@@ -9319,9 +9332,9 @@ function worktreeGitInspectPayload(value) {
|
|
|
9319
9332
|
"worktree Git inspect payload.expectedOrigin"
|
|
9320
9333
|
)
|
|
9321
9334
|
};
|
|
9322
|
-
if (payload.action === "STATE") {
|
|
9335
|
+
if (payload.action === "STATE" || payload.action === "REFRESH") {
|
|
9323
9336
|
if (payload.stashOid !== void 0) {
|
|
9324
|
-
throw new Error(
|
|
9337
|
+
throw new Error(`${payload.action} inspection cannot include stashOid`);
|
|
9325
9338
|
}
|
|
9326
9339
|
return { action: payload.action, ...common };
|
|
9327
9340
|
}
|
|
@@ -11552,7 +11565,7 @@ function tailscaleServeRemovePayload(value) {
|
|
|
11552
11565
|
// package.json
|
|
11553
11566
|
var package_default = {
|
|
11554
11567
|
name: "@ai-development-environment/control-agent",
|
|
11555
|
-
version: "0.0.
|
|
11568
|
+
version: "0.0.139",
|
|
11556
11569
|
description: "Control agent for the AI Development Environment",
|
|
11557
11570
|
license: "MIT",
|
|
11558
11571
|
repository: {
|
|
@@ -12060,6 +12073,17 @@ function repairToolPath(options = {}) {
|
|
|
12060
12073
|
|
|
12061
12074
|
// src/runs/codex-adapter.ts
|
|
12062
12075
|
var execFileAsync = promisify(execFile);
|
|
12076
|
+
async function codexSessionInfo(thread, cwd) {
|
|
12077
|
+
const path = typeof thread.path === "string" && thread.path ? thread.path : await findCodexSessionFile(
|
|
12078
|
+
String(thread.id),
|
|
12079
|
+
homedir4(),
|
|
12080
|
+
process.env.CODEX_HOME
|
|
12081
|
+
).catch(() => null);
|
|
12082
|
+
return {
|
|
12083
|
+
workingDirectory: typeof thread.cwd === "string" && thread.cwd ? thread.cwd : cwd,
|
|
12084
|
+
...path ? { nativeTranscriptPath: path } : {}
|
|
12085
|
+
};
|
|
12086
|
+
}
|
|
12063
12087
|
function codexAppServerArgs(modelCatalogPath) {
|
|
12064
12088
|
return [
|
|
12065
12089
|
"app-server",
|
|
@@ -12453,7 +12477,8 @@ var CodexAdapter = class {
|
|
|
12453
12477
|
throw new Error("Codex did not return a thread ID");
|
|
12454
12478
|
await callbacks.onNativeId(
|
|
12455
12479
|
nativeId,
|
|
12456
|
-
typeof thread.cliVersion === "string" ? thread.cliVersion : void 0
|
|
12480
|
+
typeof thread.cliVersion === "string" ? thread.cliVersion : void 0,
|
|
12481
|
+
await codexSessionInfo(thread, cwd)
|
|
12457
12482
|
);
|
|
12458
12483
|
let turnId = "";
|
|
12459
12484
|
let stopReason = null;
|
|
@@ -12618,6 +12643,7 @@ var CodexAdapter = class {
|
|
|
12618
12643
|
const thread = asRecord(value);
|
|
12619
12644
|
const updatedAtKey = String(thread.updatedAt ?? "");
|
|
12620
12645
|
const cached = this.hydrationCache.get(String(thread.id));
|
|
12646
|
+
const sessionInfo = await codexSessionInfo(thread, worktree.folder);
|
|
12621
12647
|
let history = {};
|
|
12622
12648
|
const active = asRecord(thread.status).type === "active";
|
|
12623
12649
|
if (active) this.hydrationCache.delete(String(thread.id));
|
|
@@ -12640,11 +12666,7 @@ var CodexAdapter = class {
|
|
|
12640
12666
|
} catch {
|
|
12641
12667
|
}
|
|
12642
12668
|
try {
|
|
12643
|
-
const path =
|
|
12644
|
-
String(thread.id),
|
|
12645
|
-
homedir4(),
|
|
12646
|
-
process.env.CODEX_HOME
|
|
12647
|
-
);
|
|
12669
|
+
const path = sessionInfo.nativeTranscriptPath;
|
|
12648
12670
|
if (path)
|
|
12649
12671
|
Object.assign(
|
|
12650
12672
|
history,
|
|
@@ -12671,7 +12693,8 @@ var CodexAdapter = class {
|
|
|
12671
12693
|
branch: firstString(asRecord(thread.gitInfo).branch) || worktree.branch || void 0,
|
|
12672
12694
|
createdAt: thread.createdAt ? new Date(Number(thread.createdAt) * 1e3).toISOString() : void 0,
|
|
12673
12695
|
updatedAt: thread.updatedAt ? new Date(Number(thread.updatedAt) * 1e3).toISOString() : void 0,
|
|
12674
|
-
rawMetadata: thread
|
|
12696
|
+
rawMetadata: thread,
|
|
12697
|
+
sessionInfo
|
|
12675
12698
|
});
|
|
12676
12699
|
}
|
|
12677
12700
|
cursor = typeof page.nextCursor === "string" ? page.nextCursor : null;
|
|
@@ -42895,7 +42918,15 @@ var ClaudeAdapter = class {
|
|
|
42895
42918
|
if (sessionId && sessionId !== nativeId) {
|
|
42896
42919
|
nativeId = sessionId;
|
|
42897
42920
|
const version = record.subtype === "init" && typeof record.claude_code_version === "string" ? record.claude_code_version : void 0;
|
|
42898
|
-
await
|
|
42921
|
+
const path = await findClaudeSessionFile(
|
|
42922
|
+
sessionId,
|
|
42923
|
+
homedir5(),
|
|
42924
|
+
process.env.CLAUDE_CONFIG_DIR
|
|
42925
|
+
).catch(() => null);
|
|
42926
|
+
await callbacks.onNativeId(sessionId, version, {
|
|
42927
|
+
workingDirectory: typeof record.cwd === "string" && record.cwd ? record.cwd : input.run.worktree.folder,
|
|
42928
|
+
...path ? { nativeTranscriptPath: path } : {}
|
|
42929
|
+
});
|
|
42899
42930
|
}
|
|
42900
42931
|
const messageText = firstString(
|
|
42901
42932
|
record.message ?? record.result ?? record.summary
|
|
@@ -42976,16 +43007,20 @@ var ClaudeAdapter = class {
|
|
|
42976
43007
|
const lastModifiedKey = `${session.lastModified ?? ""}:${session.fileSize ?? ""}`;
|
|
42977
43008
|
const cached = this.hydrationCache.get(session.sessionId);
|
|
42978
43009
|
let history = {};
|
|
43010
|
+
const path = await findClaudeSessionFile(
|
|
43011
|
+
session.sessionId,
|
|
43012
|
+
homedir5(),
|
|
43013
|
+
process.env.CLAUDE_CONFIG_DIR
|
|
43014
|
+
).catch(() => null);
|
|
43015
|
+
const sessionInfo = {
|
|
43016
|
+
workingDirectory: session.cwd || worktree.folder,
|
|
43017
|
+
...path ? { nativeTranscriptPath: path } : {}
|
|
43018
|
+
};
|
|
42979
43019
|
if (cached && cached.lastModified === lastModifiedKey) {
|
|
42980
43020
|
history = cached.history;
|
|
42981
43021
|
} else {
|
|
42982
43022
|
let transcript = [];
|
|
42983
43023
|
try {
|
|
42984
|
-
const path = await findClaudeSessionFile(
|
|
42985
|
-
session.sessionId,
|
|
42986
|
-
homedir5(),
|
|
42987
|
-
process.env.CLAUDE_CONFIG_DIR
|
|
42988
|
-
);
|
|
42989
43024
|
if (path) transcript = await readClaudeTranscript(path);
|
|
42990
43025
|
history = claudeTranscriptMetadata(transcript);
|
|
42991
43026
|
} catch {
|
|
@@ -43016,7 +43051,8 @@ var ClaudeAdapter = class {
|
|
|
43016
43051
|
branch: session.gitBranch || worktree.branch || void 0,
|
|
43017
43052
|
createdAt: session.createdAt ? new Date(session.createdAt).toISOString() : void 0,
|
|
43018
43053
|
updatedAt: new Date(session.lastModified).toISOString(),
|
|
43019
|
-
rawMetadata: session
|
|
43054
|
+
rawMetadata: session,
|
|
43055
|
+
sessionInfo
|
|
43020
43056
|
});
|
|
43021
43057
|
}
|
|
43022
43058
|
}
|
|
@@ -43788,6 +43824,7 @@ function captureCommand(options) {
|
|
|
43788
43824
|
let timedOut = false;
|
|
43789
43825
|
let cancelled = false;
|
|
43790
43826
|
let settled = false;
|
|
43827
|
+
let terminating = false;
|
|
43791
43828
|
let killTimer = null;
|
|
43792
43829
|
const detached = process.platform !== "win32";
|
|
43793
43830
|
const child = spawn3(options.command, options.args, {
|
|
@@ -43842,10 +43879,11 @@ function captureCommand(options) {
|
|
|
43842
43879
|
}
|
|
43843
43880
|
};
|
|
43844
43881
|
const terminate2 = () => {
|
|
43845
|
-
if (
|
|
43882
|
+
if (settled || terminating) return;
|
|
43883
|
+
terminating = true;
|
|
43846
43884
|
sendSignal("SIGTERM");
|
|
43847
43885
|
killTimer = setTimeout(() => {
|
|
43848
|
-
if (
|
|
43886
|
+
if (!settled) sendSignal("SIGKILL");
|
|
43849
43887
|
}, 5e3);
|
|
43850
43888
|
killTimer.unref();
|
|
43851
43889
|
};
|
|
@@ -45298,21 +45336,148 @@ import {
|
|
|
45298
45336
|
|
|
45299
45337
|
// src/repository-coordinator.ts
|
|
45300
45338
|
var RepositoryCoordinator = class {
|
|
45301
|
-
|
|
45302
|
-
|
|
45303
|
-
|
|
45304
|
-
|
|
45305
|
-
|
|
45306
|
-
|
|
45339
|
+
queues = /* @__PURE__ */ new Map();
|
|
45340
|
+
run(key, task, signal2) {
|
|
45341
|
+
return this.enqueue(key, "exclusive", () => task(), signal2);
|
|
45342
|
+
}
|
|
45343
|
+
/** Keep source files stable during builds while allowing live inspections. */
|
|
45344
|
+
runBuild(key, task, signal2) {
|
|
45345
|
+
return this.enqueue(key, "build", () => task(), signal2);
|
|
45346
|
+
}
|
|
45347
|
+
/** Read-only worktree inspections may overlap builds and reconciliation. */
|
|
45348
|
+
runInspection(key, task, signal2) {
|
|
45349
|
+
return this.enqueue(key, "inspection", () => task(), signal2);
|
|
45350
|
+
}
|
|
45351
|
+
/** Keep reconciliation and its reports ordered with all user mutations. */
|
|
45352
|
+
runReconciliation(key, task, signal2) {
|
|
45353
|
+
return this.enqueue(
|
|
45354
|
+
key,
|
|
45355
|
+
"reconciliation",
|
|
45356
|
+
(queue) => task({
|
|
45357
|
+
runExclusive: (exclusiveTask) => this.runReconciliationExclusive(key, queue, exclusiveTask)
|
|
45358
|
+
}),
|
|
45359
|
+
signal2
|
|
45360
|
+
);
|
|
45361
|
+
}
|
|
45362
|
+
runReconciliationExclusive(key, queue, task) {
|
|
45363
|
+
if (!queue.reconciliation || queue.exclusiveReconciliationPhase) {
|
|
45364
|
+
return Promise.reject(new Error("Invalid reconciliation phase"));
|
|
45365
|
+
}
|
|
45366
|
+
return new Promise((resolve11, reject) => {
|
|
45367
|
+
const complete = () => {
|
|
45368
|
+
queue.exclusiveReconciliationPhase = null;
|
|
45369
|
+
queue.exclusive = false;
|
|
45370
|
+
this.drain(key, queue);
|
|
45371
|
+
};
|
|
45372
|
+
queue.exclusiveReconciliationPhase = () => {
|
|
45373
|
+
void Promise.resolve().then(task).then(
|
|
45374
|
+
(result) => {
|
|
45375
|
+
complete();
|
|
45376
|
+
resolve11(result);
|
|
45377
|
+
},
|
|
45378
|
+
(error) => {
|
|
45379
|
+
complete();
|
|
45380
|
+
reject(error);
|
|
45381
|
+
}
|
|
45382
|
+
);
|
|
45383
|
+
};
|
|
45384
|
+
this.drain(key, queue);
|
|
45307
45385
|
});
|
|
45308
|
-
|
|
45309
|
-
|
|
45310
|
-
|
|
45311
|
-
|
|
45312
|
-
|
|
45313
|
-
|
|
45314
|
-
|
|
45315
|
-
|
|
45386
|
+
}
|
|
45387
|
+
enqueue(key, kind, task, signal2) {
|
|
45388
|
+
if (signal2?.aborted) return Promise.reject(signal2.reason);
|
|
45389
|
+
let queue = this.queues.get(key);
|
|
45390
|
+
if (!queue) {
|
|
45391
|
+
queue = {
|
|
45392
|
+
inspections: 0,
|
|
45393
|
+
reconciliation: false,
|
|
45394
|
+
exclusive: false,
|
|
45395
|
+
build: false,
|
|
45396
|
+
exclusiveReconciliationPhase: null,
|
|
45397
|
+
pending: []
|
|
45398
|
+
};
|
|
45399
|
+
this.queues.set(key, queue);
|
|
45400
|
+
}
|
|
45401
|
+
const repositoryQueue = queue;
|
|
45402
|
+
return new Promise((resolve11, reject) => {
|
|
45403
|
+
let pending = true;
|
|
45404
|
+
const complete = () => {
|
|
45405
|
+
if (kind === "inspection") repositoryQueue.inspections -= 1;
|
|
45406
|
+
else if (kind === "reconciliation")
|
|
45407
|
+
repositoryQueue.reconciliation = false;
|
|
45408
|
+
else if (kind === "build") repositoryQueue.build = false;
|
|
45409
|
+
else repositoryQueue.exclusive = false;
|
|
45410
|
+
this.drain(key, repositoryQueue);
|
|
45411
|
+
};
|
|
45412
|
+
const abort = () => {
|
|
45413
|
+
if (!pending) return;
|
|
45414
|
+
pending = false;
|
|
45415
|
+
const index = repositoryQueue.pending.indexOf(operation);
|
|
45416
|
+
if (index !== -1) repositoryQueue.pending.splice(index, 1);
|
|
45417
|
+
signal2?.removeEventListener("abort", abort);
|
|
45418
|
+
reject(signal2?.reason);
|
|
45419
|
+
this.drain(key, repositoryQueue);
|
|
45420
|
+
};
|
|
45421
|
+
const operation = {
|
|
45422
|
+
kind,
|
|
45423
|
+
start: () => {
|
|
45424
|
+
pending = false;
|
|
45425
|
+
signal2?.removeEventListener("abort", abort);
|
|
45426
|
+
void Promise.resolve().then(() => {
|
|
45427
|
+
signal2?.throwIfAborted();
|
|
45428
|
+
return task(repositoryQueue);
|
|
45429
|
+
}).then(
|
|
45430
|
+
(result) => {
|
|
45431
|
+
complete();
|
|
45432
|
+
resolve11(result);
|
|
45433
|
+
},
|
|
45434
|
+
(error) => {
|
|
45435
|
+
complete();
|
|
45436
|
+
reject(error);
|
|
45437
|
+
}
|
|
45438
|
+
);
|
|
45439
|
+
}
|
|
45440
|
+
};
|
|
45441
|
+
repositoryQueue.pending.push(operation);
|
|
45442
|
+
signal2?.addEventListener("abort", abort, { once: true });
|
|
45443
|
+
if (signal2?.aborted) abort();
|
|
45444
|
+
else this.drain(key, repositoryQueue);
|
|
45445
|
+
});
|
|
45446
|
+
}
|
|
45447
|
+
drain(key, queue) {
|
|
45448
|
+
if (queue.exclusiveReconciliationPhase) {
|
|
45449
|
+
if (!queue.exclusive && queue.inspections === 0) {
|
|
45450
|
+
queue.exclusive = true;
|
|
45451
|
+
queue.exclusiveReconciliationPhase();
|
|
45452
|
+
}
|
|
45453
|
+
return;
|
|
45454
|
+
}
|
|
45455
|
+
while (!queue.exclusive && !queue.build && queue.pending.length) {
|
|
45456
|
+
const next = queue.pending[0];
|
|
45457
|
+
if (next.kind === "exclusive" && (queue.inspections > 0 || queue.reconciliation) || next.kind === "build" && queue.reconciliation || next.kind === "reconciliation" && queue.reconciliation) {
|
|
45458
|
+
return;
|
|
45459
|
+
}
|
|
45460
|
+
queue.pending.shift();
|
|
45461
|
+
if (next.kind === "inspection") queue.inspections += 1;
|
|
45462
|
+
else if (next.kind === "reconciliation") queue.reconciliation = true;
|
|
45463
|
+
else if (next.kind === "build") queue.build = true;
|
|
45464
|
+
else queue.exclusive = true;
|
|
45465
|
+
next.start();
|
|
45466
|
+
}
|
|
45467
|
+
if (queue.build) {
|
|
45468
|
+
const inspections = queue.pending.filter(
|
|
45469
|
+
(operation) => operation.kind === "inspection"
|
|
45470
|
+
);
|
|
45471
|
+
queue.pending = queue.pending.filter(
|
|
45472
|
+
(operation) => operation.kind !== "inspection"
|
|
45473
|
+
);
|
|
45474
|
+
for (const inspection of inspections) {
|
|
45475
|
+
queue.inspections += 1;
|
|
45476
|
+
inspection.start();
|
|
45477
|
+
}
|
|
45478
|
+
}
|
|
45479
|
+
if (!queue.exclusive && !queue.build && !queue.reconciliation && queue.inspections === 0 && queue.pending.length === 0) {
|
|
45480
|
+
this.queues.delete(key);
|
|
45316
45481
|
}
|
|
45317
45482
|
}
|
|
45318
45483
|
};
|
|
@@ -48322,7 +48487,9 @@ var downloadIosBuildArtifact = async (payload, timeoutMs, signal2, onLog, contex
|
|
|
48322
48487
|
uploadId: input.uploadId,
|
|
48323
48488
|
path: uploadPath,
|
|
48324
48489
|
filename,
|
|
48325
|
-
contentType
|
|
48490
|
+
contentType,
|
|
48491
|
+
signal: signal2,
|
|
48492
|
+
timeoutMs
|
|
48326
48493
|
});
|
|
48327
48494
|
return successfulProcess3;
|
|
48328
48495
|
} finally {
|
|
@@ -51028,6 +51195,17 @@ async function compareGitCheckpoint(cwd, target2, current) {
|
|
|
51028
51195
|
],
|
|
51029
51196
|
PATCH_LIMIT
|
|
51030
51197
|
);
|
|
51198
|
+
const worktreeSummary = await cappedGit(
|
|
51199
|
+
cwd,
|
|
51200
|
+
[
|
|
51201
|
+
"diff",
|
|
51202
|
+
"--stat",
|
|
51203
|
+
"--find-renames",
|
|
51204
|
+
target2.worktreeTree,
|
|
51205
|
+
current.worktreeTree
|
|
51206
|
+
],
|
|
51207
|
+
SUMMARY_LIMIT
|
|
51208
|
+
);
|
|
51031
51209
|
const indexPatch = target2.indexTree && current.indexTree ? await cappedGit(
|
|
51032
51210
|
cwd,
|
|
51033
51211
|
[
|
|
@@ -51048,6 +51226,8 @@ async function compareGitCheckpoint(cwd, target2, current) {
|
|
|
51048
51226
|
])
|
|
51049
51227
|
) : 0;
|
|
51050
51228
|
return {
|
|
51229
|
+
worktreePatch,
|
|
51230
|
+
worktreeSummary,
|
|
51051
51231
|
rollbackPatch: [
|
|
51052
51232
|
worktreePatch && `Worktree changes that will be undone:
|
|
51053
51233
|
|
|
@@ -51844,6 +52024,62 @@ async function rebaseInProgress(folder, timeoutMs, signal2) {
|
|
|
51844
52024
|
}
|
|
51845
52025
|
return false;
|
|
51846
52026
|
}
|
|
52027
|
+
async function gitStatePathExists(folder, name, timeoutMs, signal2) {
|
|
52028
|
+
const result = requireSuccess4(
|
|
52029
|
+
await git4(
|
|
52030
|
+
folder,
|
|
52031
|
+
["rev-parse", "--path-format=absolute", "--git-path", name],
|
|
52032
|
+
timeoutMs,
|
|
52033
|
+
signal2
|
|
52034
|
+
),
|
|
52035
|
+
`Could not resolve Git state path ${name}`
|
|
52036
|
+
);
|
|
52037
|
+
const candidate = result.stdout.trim();
|
|
52038
|
+
if (!candidate || result.outputTruncated) {
|
|
52039
|
+
throw new Error(`Could not resolve Git state path ${name}`);
|
|
52040
|
+
}
|
|
52041
|
+
try {
|
|
52042
|
+
await stat11(candidate);
|
|
52043
|
+
return true;
|
|
52044
|
+
} catch (error) {
|
|
52045
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
52046
|
+
return false;
|
|
52047
|
+
}
|
|
52048
|
+
throw error;
|
|
52049
|
+
}
|
|
52050
|
+
}
|
|
52051
|
+
async function inspectWorktreeRefreshState(folder, timeoutMs, signal2) {
|
|
52052
|
+
const [status2, rebaseMerge, rebaseApply, mergeInProgress] = await Promise.all(
|
|
52053
|
+
[
|
|
52054
|
+
git4(
|
|
52055
|
+
folder,
|
|
52056
|
+
[
|
|
52057
|
+
"--no-optional-locks",
|
|
52058
|
+
"status",
|
|
52059
|
+
"--porcelain=v1",
|
|
52060
|
+
"-z",
|
|
52061
|
+
"--untracked-files=all",
|
|
52062
|
+
"--ignore-submodules=none"
|
|
52063
|
+
],
|
|
52064
|
+
timeoutMs,
|
|
52065
|
+
signal2
|
|
52066
|
+
),
|
|
52067
|
+
gitStatePathExists(folder, "rebase-merge", timeoutMs, signal2),
|
|
52068
|
+
gitStatePathExists(folder, "rebase-apply", timeoutMs, signal2),
|
|
52069
|
+
gitStatePathExists(folder, "MERGE_HEAD", timeoutMs, signal2)
|
|
52070
|
+
]
|
|
52071
|
+
);
|
|
52072
|
+
requireSuccess4(status2, "Could not refresh worktree Git status");
|
|
52073
|
+
if (status2.outputTruncated) {
|
|
52074
|
+
throw new Error("Worktree Git status exceeded the output limit");
|
|
52075
|
+
}
|
|
52076
|
+
return {
|
|
52077
|
+
dirty: Boolean(status2.stdout),
|
|
52078
|
+
hasConflicts: statusChangeState(status2.stdout).hasConflicts,
|
|
52079
|
+
rebaseInProgress: rebaseMerge || rebaseApply,
|
|
52080
|
+
mergeInProgress
|
|
52081
|
+
};
|
|
52082
|
+
}
|
|
51847
52083
|
async function rebaseBranch(folder, timeoutMs, signal2) {
|
|
51848
52084
|
for (const name of ["rebase-merge/head-name", "rebase-apply/head-name"]) {
|
|
51849
52085
|
const pathResult = await git4(
|
|
@@ -52900,7 +53136,9 @@ var downloadWorktreeDiffAsset = async (payload, timeoutMs, signal2, _onLog, cont
|
|
|
52900
53136
|
uploadId: input.uploadId,
|
|
52901
53137
|
path: uploadPath,
|
|
52902
53138
|
filename: basename5(input.path),
|
|
52903
|
-
contentType: imageContentType(input.path)
|
|
53139
|
+
contentType: imageContentType(input.path),
|
|
53140
|
+
signal: signal2,
|
|
53141
|
+
timeoutMs
|
|
52904
53142
|
});
|
|
52905
53143
|
return successfulProcess9;
|
|
52906
53144
|
} finally {
|
|
@@ -52982,10 +53220,10 @@ var inspectWorktree = async (payload, timeoutMs, signal2) => {
|
|
|
52982
53220
|
var inspectWorktreeGit = async (payload, timeoutMs, signal2) => {
|
|
52983
53221
|
const input = worktreeGitInspectPayload(payload);
|
|
52984
53222
|
const folder = await validateWorktree2(input, timeoutMs, signal2);
|
|
52985
|
-
if (input.action
|
|
53223
|
+
if (input.action !== "STASH_DIFF") {
|
|
52986
53224
|
return {
|
|
52987
53225
|
...successfulProcess9,
|
|
52988
|
-
state: await inspectCodebaseGitState(folder, timeoutMs, signal2)
|
|
53226
|
+
state: input.action === "REFRESH" ? await inspectWorktreeRefreshState(folder, timeoutMs, signal2) : await inspectCodebaseGitState(folder, timeoutMs, signal2)
|
|
52989
53227
|
};
|
|
52990
53228
|
}
|
|
52991
53229
|
return {
|
|
@@ -55146,39 +55384,61 @@ var JobExecutor = class {
|
|
|
55146
55384
|
const handler = handlers[claimed.kind];
|
|
55147
55385
|
if (!handler)
|
|
55148
55386
|
throw new Error(`No local handler is registered for ${claimed.kind}`);
|
|
55149
|
-
const runHandler = () =>
|
|
55150
|
-
|
|
55151
|
-
|
|
55152
|
-
|
|
55153
|
-
|
|
55154
|
-
|
|
55155
|
-
|
|
55156
|
-
|
|
55157
|
-
|
|
55158
|
-
|
|
55159
|
-
this.client,
|
|
55160
|
-
input
|
|
55161
|
-
|
|
55162
|
-
|
|
55163
|
-
|
|
55164
|
-
|
|
55165
|
-
|
|
55166
|
-
|
|
55167
|
-
deploymentId,
|
|
55168
|
-
|
|
55169
|
-
|
|
55170
|
-
|
|
55171
|
-
|
|
55172
|
-
|
|
55173
|
-
|
|
55174
|
-
|
|
55175
|
-
|
|
55176
|
-
|
|
55177
|
-
|
|
55178
|
-
|
|
55179
|
-
|
|
55387
|
+
const runHandler = () => {
|
|
55388
|
+
controller.signal.throwIfAborted();
|
|
55389
|
+
return handler(
|
|
55390
|
+
claimed.payload,
|
|
55391
|
+
claimed.timeoutSeconds * 1e3,
|
|
55392
|
+
controller.signal,
|
|
55393
|
+
(log2) => this.client.appendLog(claimed.id, log2).then(() => void 0),
|
|
55394
|
+
{
|
|
55395
|
+
agentId: claimed.agentId,
|
|
55396
|
+
reportBranchDeletionResult: (result2) => this.client.reportBranchDeletionResult(claimed.id, result2),
|
|
55397
|
+
reportWorktreeActivity: (input) => this.client.reportWorktreeActivity(input),
|
|
55398
|
+
refreshFetchedCodebase: (input) => refreshFetchedCodebase(
|
|
55399
|
+
this.client,
|
|
55400
|
+
input,
|
|
55401
|
+
claimed.timeoutSeconds * 1e3,
|
|
55402
|
+
controller.signal
|
|
55403
|
+
),
|
|
55404
|
+
reportBuildProgress: (input) => this.client.reportBuildProgress(input),
|
|
55405
|
+
reportBuildDeploymentLaunched: (deploymentId, launchedAt) => this.client.reportBuildDeploymentLaunched(
|
|
55406
|
+
claimed.id,
|
|
55407
|
+
deploymentId,
|
|
55408
|
+
launchedAt
|
|
55409
|
+
),
|
|
55410
|
+
appendBuildLogChunks: (buildId, chunks) => this.client.appendBuildLogChunks(buildId, chunks),
|
|
55411
|
+
uploadBuildArtifact: (input) => this.client.uploadBuildArtifact(input),
|
|
55412
|
+
uploadBuildArtifactTransfer: (input) => this.client.uploadBuildArtifactTransfer(input),
|
|
55413
|
+
downloadBuildArtifactTransfer: (input) => this.client.downloadBuildArtifactTransfer(input),
|
|
55414
|
+
downloadDsymDwarf: (input) => this.client.downloadDsymDwarf(input),
|
|
55415
|
+
claimSigningSecretTransfer: (transferId) => this.client.claimSigningSecretTransfer(transferId),
|
|
55416
|
+
claimWorkflowJobSecrets: () => this.client.claimWorkflowJobSecrets(claimed.id),
|
|
55417
|
+
appendCommandOutput: (attemptId, chunks) => this.client.appendCommandOutput(claimed.id, attemptId, chunks)
|
|
55418
|
+
}
|
|
55419
|
+
);
|
|
55420
|
+
};
|
|
55180
55421
|
const codebaseId = claimed.payload && typeof claimed.payload === "object" && !Array.isArray(claimed.payload) && typeof claimed.payload.codebaseId === "string" ? String(claimed.payload.codebaseId) : null;
|
|
55181
|
-
|
|
55422
|
+
if (!codebaseId) result = await runHandler();
|
|
55423
|
+
else if (claimed.kind === IOS_BUILD_JOB_KIND) {
|
|
55424
|
+
result = await this.repositoryCoordinator.runBuild(
|
|
55425
|
+
codebaseId,
|
|
55426
|
+
runHandler,
|
|
55427
|
+
controller.signal
|
|
55428
|
+
);
|
|
55429
|
+
} else if (claimed.kind === WORKTREE_INSPECT_JOB_KIND || claimed.kind === WORKTREE_DIFF_JOB_KIND || claimed.kind === WORKTREE_DIFF_ASSET_JOB_KIND || claimed.kind === WORKTREE_GIT_INSPECT_JOB_KIND || claimed.kind === CODEBASE_GIT_INSPECT_JOB_KIND) {
|
|
55430
|
+
result = await this.repositoryCoordinator.runInspection(
|
|
55431
|
+
codebaseId,
|
|
55432
|
+
runHandler,
|
|
55433
|
+
controller.signal
|
|
55434
|
+
);
|
|
55435
|
+
} else {
|
|
55436
|
+
result = await this.repositoryCoordinator.run(
|
|
55437
|
+
codebaseId,
|
|
55438
|
+
runHandler,
|
|
55439
|
+
controller.signal
|
|
55440
|
+
);
|
|
55441
|
+
}
|
|
55182
55442
|
status2 = result.cancelled ? "CANCELLED" : result.timedOut ? "TIMED_OUT" : result.exitCode === 0 ? "SUCCEEDED" : "FAILED";
|
|
55183
55443
|
completionError = status2 === "FAILED" ? `Process exited with code ${result.exitCode}` : void 0;
|
|
55184
55444
|
} catch (error) {
|
|
@@ -55244,110 +55504,118 @@ var CodebaseMonitor = class {
|
|
|
55244
55504
|
const batch = codebases.slice(index, index + CONCURRENCY2);
|
|
55245
55505
|
await Promise.all(
|
|
55246
55506
|
batch.map(
|
|
55247
|
-
(codebase) => this.repositoryCoordinator.
|
|
55248
|
-
|
|
55249
|
-
|
|
55250
|
-
|
|
55251
|
-
|
|
55252
|
-
|
|
55253
|
-
|
|
55254
|
-
|
|
55255
|
-
|
|
55256
|
-
|
|
55257
|
-
|
|
55258
|
-
|
|
55259
|
-
|
|
55260
|
-
|
|
55261
|
-
|
|
55262
|
-
|
|
55263
|
-
|
|
55264
|
-
|
|
55265
|
-
|
|
55266
|
-
|
|
55267
|
-
|
|
55268
|
-
|
|
55269
|
-
|
|
55270
|
-
|
|
55271
|
-
|
|
55272
|
-
|
|
55273
|
-
|
|
55274
|
-
|
|
55275
|
-
|
|
55276
|
-
|
|
55507
|
+
(codebase) => this.repositoryCoordinator.runReconciliation(
|
|
55508
|
+
codebase.id,
|
|
55509
|
+
async ({ runExclusive }) => {
|
|
55510
|
+
let snapshot = await inspectCodebase(
|
|
55511
|
+
codebase.folder,
|
|
55512
|
+
INSPECTION_TIMEOUT_MS,
|
|
55513
|
+
signal2,
|
|
55514
|
+
codebase.canonicalOrigin
|
|
55515
|
+
);
|
|
55516
|
+
let fetchAttemptedAt = null;
|
|
55517
|
+
let fetchError = null;
|
|
55518
|
+
const fetchedAt2 = Math.max(
|
|
55519
|
+
snapshot.fetchedAt ? new Date(snapshot.fetchedAt).getTime() : 0,
|
|
55520
|
+
codebase.lastFetchAttemptAt ? new Date(codebase.lastFetchAttemptAt).getTime() : 0
|
|
55521
|
+
);
|
|
55522
|
+
const fetchDue = snapshot.availability === "AVAILABLE" && Date.now() - fetchedAt2 >= configuration.fetchIntervalSeconds * 1e3;
|
|
55523
|
+
if (fetchDue && !signal2.aborted) {
|
|
55524
|
+
fetchAttemptedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
55525
|
+
const fetchResult = await captureCommand({
|
|
55526
|
+
command: "git",
|
|
55527
|
+
args: ["-C", codebase.folder, "fetch", "origin"],
|
|
55528
|
+
timeoutMs: 3e5,
|
|
55529
|
+
signal: signal2,
|
|
55530
|
+
env: {
|
|
55531
|
+
...process.env,
|
|
55532
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
55533
|
+
GIT_OPTIONAL_LOCKS: "0"
|
|
55534
|
+
}
|
|
55535
|
+
});
|
|
55536
|
+
if (fetchResult.exitCode === 0) {
|
|
55537
|
+
if (codebase.keepBaseBranchUpToDate && codebase.defaultBranch) {
|
|
55538
|
+
const baseBranch = codebase.defaultBranch;
|
|
55539
|
+
await runExclusive(
|
|
55540
|
+
() => updateBaseBranchAfterFetch(
|
|
55541
|
+
codebase.folder,
|
|
55542
|
+
baseBranch,
|
|
55543
|
+
INSPECTION_TIMEOUT_MS,
|
|
55544
|
+
signal2
|
|
55545
|
+
)
|
|
55546
|
+
);
|
|
55547
|
+
}
|
|
55548
|
+
snapshot = await inspectCodebase(
|
|
55277
55549
|
codebase.folder,
|
|
55278
|
-
codebase.defaultBranch,
|
|
55279
55550
|
INSPECTION_TIMEOUT_MS,
|
|
55280
|
-
signal2
|
|
55551
|
+
signal2,
|
|
55552
|
+
codebase.canonicalOrigin
|
|
55281
55553
|
);
|
|
55554
|
+
} else {
|
|
55555
|
+
fetchError = (fetchResult.stderr || "Git fetch failed").replace(/([a-z][a-z0-9+.-]*:\/\/)[^\s/@]+@/gi, "$1").slice(0, 2e3);
|
|
55282
55556
|
}
|
|
55283
|
-
|
|
55557
|
+
}
|
|
55558
|
+
let inventory;
|
|
55559
|
+
try {
|
|
55560
|
+
inventory = await discoverWorktrees(
|
|
55284
55561
|
codebase.folder,
|
|
55562
|
+
new Map(
|
|
55563
|
+
codebase.worktrees.map((worktree) => [
|
|
55564
|
+
worktree.gitDirectory,
|
|
55565
|
+
worktree.baseBranchOverride
|
|
55566
|
+
])
|
|
55567
|
+
),
|
|
55568
|
+
codebase.defaultBranch,
|
|
55285
55569
|
INSPECTION_TIMEOUT_MS,
|
|
55286
|
-
signal2
|
|
55287
|
-
codebase.canonicalOrigin
|
|
55570
|
+
signal2
|
|
55288
55571
|
);
|
|
55289
|
-
}
|
|
55290
|
-
|
|
55572
|
+
} catch (error) {
|
|
55573
|
+
inventory = {
|
|
55574
|
+
complete: false,
|
|
55575
|
+
defaultBranch: null,
|
|
55576
|
+
localBranches: [],
|
|
55577
|
+
remoteBranches: [],
|
|
55578
|
+
worktrees: []
|
|
55579
|
+
};
|
|
55580
|
+
fetchError ??= error instanceof Error ? error.message.slice(0, 2e3) : String(error);
|
|
55291
55581
|
}
|
|
55292
|
-
|
|
55293
|
-
|
|
55294
|
-
|
|
55295
|
-
|
|
55296
|
-
|
|
55297
|
-
|
|
55298
|
-
|
|
55299
|
-
|
|
55300
|
-
|
|
55301
|
-
|
|
55302
|
-
|
|
55303
|
-
|
|
55304
|
-
|
|
55305
|
-
|
|
55306
|
-
|
|
55307
|
-
} catch (error) {
|
|
55308
|
-
inventory = {
|
|
55309
|
-
complete: false,
|
|
55310
|
-
defaultBranch: null,
|
|
55311
|
-
localBranches: [],
|
|
55312
|
-
remoteBranches: [],
|
|
55313
|
-
worktrees: []
|
|
55314
|
-
};
|
|
55315
|
-
fetchError ??= error instanceof Error ? error.message.slice(0, 2e3) : String(error);
|
|
55316
|
-
}
|
|
55317
|
-
const localBranchInventoryAttemptedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
55318
|
-
let localBranchInventory = null;
|
|
55319
|
-
let localBranchInventoryError = null;
|
|
55320
|
-
try {
|
|
55321
|
-
if (snapshot.availability !== "AVAILABLE")
|
|
55322
|
-
throw new Error(snapshot.error || "Codebase is unavailable");
|
|
55323
|
-
localBranchInventory = await scanLocalBranches(
|
|
55324
|
-
codebase.folder,
|
|
55325
|
-
INSPECTION_TIMEOUT_MS,
|
|
55326
|
-
signal2
|
|
55327
|
-
);
|
|
55328
|
-
} catch (error) {
|
|
55329
|
-
localBranchInventoryError = error instanceof Error ? error.message.slice(0, 2e3) : String(error).slice(0, 2e3);
|
|
55330
|
-
}
|
|
55331
|
-
if (signal2.aborted) return;
|
|
55332
|
-
await this.client.reportCodebaseStatuses([
|
|
55333
|
-
{
|
|
55334
|
-
codebaseId: codebase.id,
|
|
55335
|
-
snapshot,
|
|
55336
|
-
localBranchInventory,
|
|
55337
|
-
localBranchInventoryError,
|
|
55338
|
-
localBranchInventoryAttemptedAt
|
|
55339
|
-
}
|
|
55340
|
-
]);
|
|
55341
|
-
await this.client.reportWorktrees([
|
|
55342
|
-
{
|
|
55343
|
-
codebaseId: codebase.id,
|
|
55344
|
-
...inventory,
|
|
55345
|
-
fetchedAt: snapshot.fetchedAt,
|
|
55346
|
-
fetchAttemptedAt,
|
|
55347
|
-
fetchError
|
|
55582
|
+
const localBranchInventoryAttemptedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
55583
|
+
let localBranchInventory = null;
|
|
55584
|
+
let localBranchInventoryError = null;
|
|
55585
|
+
try {
|
|
55586
|
+
if (snapshot.availability !== "AVAILABLE")
|
|
55587
|
+
throw new Error(
|
|
55588
|
+
snapshot.error || "Codebase is unavailable"
|
|
55589
|
+
);
|
|
55590
|
+
localBranchInventory = await scanLocalBranches(
|
|
55591
|
+
codebase.folder,
|
|
55592
|
+
INSPECTION_TIMEOUT_MS,
|
|
55593
|
+
signal2
|
|
55594
|
+
);
|
|
55595
|
+
} catch (error) {
|
|
55596
|
+
localBranchInventoryError = error instanceof Error ? error.message.slice(0, 2e3) : String(error).slice(0, 2e3);
|
|
55348
55597
|
}
|
|
55349
|
-
|
|
55350
|
-
|
|
55598
|
+
if (signal2.aborted) return;
|
|
55599
|
+
await this.client.reportCodebaseStatuses([
|
|
55600
|
+
{
|
|
55601
|
+
codebaseId: codebase.id,
|
|
55602
|
+
snapshot,
|
|
55603
|
+
localBranchInventory,
|
|
55604
|
+
localBranchInventoryError,
|
|
55605
|
+
localBranchInventoryAttemptedAt
|
|
55606
|
+
}
|
|
55607
|
+
]);
|
|
55608
|
+
await this.client.reportWorktrees([
|
|
55609
|
+
{
|
|
55610
|
+
codebaseId: codebase.id,
|
|
55611
|
+
...inventory,
|
|
55612
|
+
fetchedAt: snapshot.fetchedAt,
|
|
55613
|
+
fetchAttemptedAt,
|
|
55614
|
+
fetchError
|
|
55615
|
+
}
|
|
55616
|
+
]);
|
|
55617
|
+
}
|
|
55618
|
+
)
|
|
55351
55619
|
)
|
|
55352
55620
|
);
|
|
55353
55621
|
}
|
|
@@ -56200,7 +56468,9 @@ var OpenCodeAdapter = class {
|
|
|
56200
56468
|
initial = new Set(
|
|
56201
56469
|
(await openCodeMessages(client, nativeId)).map((entry) => entry.id)
|
|
56202
56470
|
);
|
|
56203
|
-
await callbacks.onNativeId(nativeId, runtime.version
|
|
56471
|
+
await callbacks.onNativeId(nativeId, runtime.version, {
|
|
56472
|
+
workingDirectory: cwd
|
|
56473
|
+
});
|
|
56204
56474
|
} catch (error) {
|
|
56205
56475
|
await cleanup();
|
|
56206
56476
|
throw error;
|
|
@@ -56645,7 +56915,8 @@ var OpenCodeAdapter = class {
|
|
|
56645
56915
|
pricingSource: "opencode-history",
|
|
56646
56916
|
createdAt: opencodeTimestamp(session.time.created),
|
|
56647
56917
|
updatedAt: opencodeTimestamp(session.time.updated),
|
|
56648
|
-
rawMetadata: session
|
|
56918
|
+
rawMetadata: session,
|
|
56919
|
+
sessionInfo: { workingDirectory: session.location.directory }
|
|
56649
56920
|
});
|
|
56650
56921
|
}
|
|
56651
56922
|
}
|
|
@@ -56945,12 +57216,17 @@ var RunManager = class {
|
|
|
56945
57216
|
return;
|
|
56946
57217
|
}
|
|
56947
57218
|
const callbacks = {
|
|
56948
|
-
onNativeId: async (nativeId, providerVersion) => {
|
|
57219
|
+
onNativeId: async (nativeId, providerVersion, sessionInfo) => {
|
|
56949
57220
|
await this.retry(
|
|
56950
57221
|
() => this.client.updateRunAttemptNativeId(
|
|
56951
57222
|
attempt.id,
|
|
56952
57223
|
nativeId,
|
|
56953
|
-
providerVersion
|
|
57224
|
+
providerVersion,
|
|
57225
|
+
{
|
|
57226
|
+
workingDirectory: run.worktree.folder,
|
|
57227
|
+
...sessionInfo,
|
|
57228
|
+
activityLogPath: journal.eventsPath
|
|
57229
|
+
}
|
|
56954
57230
|
)
|
|
56955
57231
|
);
|
|
56956
57232
|
},
|
|
@@ -57091,7 +57367,8 @@ var RunManager = class {
|
|
|
57091
57367
|
await this.retryFinalization(
|
|
57092
57368
|
() => this.client.reportRunCheckpoint(run.id, attemptId, {
|
|
57093
57369
|
...finalCheckpoint,
|
|
57094
|
-
diffPatch: comparison.
|
|
57370
|
+
diffPatch: comparison.worktreePatch || null,
|
|
57371
|
+
diffSummary: comparison.worktreeSummary || null
|
|
57095
57372
|
})
|
|
57096
57373
|
);
|
|
57097
57374
|
}
|