@rallycry/conveyor-agent 11.0.45 → 11.0.47
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/{boot-T5HQVF3W.js → boot-ZPXDDZDF.js} +2 -2
- package/dist/{chunk-IIYEASRQ.js → chunk-4A6GCJGG.js} +2 -2
- package/dist/{chunk-NHKEFOCV.js → chunk-7Y3IY5QQ.js} +154 -44
- package/dist/{chunk-IBLFLCFK.js → chunk-KXB55NJP.js} +10 -242
- package/dist/{chunk-37J5MMQT.js → chunk-V5WR2F2P.js} +4 -1
- package/dist/{chunk-Q4FQOJ7D.js → chunk-VIUZS7V4.js} +1 -12
- package/dist/cli.js +11 -58
- package/dist/index.d.ts +1 -7
- package/dist/index.js +4 -4
- package/dist/{serve-boot-G4LZGJ6W.js → serve-boot-TPZ6CPCQ.js} +4 -7
- package/package.json +2 -3
- package/skills/conveyor-prune/SKILL.md +1 -1
|
@@ -11,14 +11,14 @@ import {
|
|
|
11
11
|
readAgentVersion,
|
|
12
12
|
refreshSkillsAfterCheckout,
|
|
13
13
|
runPreReadyBinds
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-V5WR2F2P.js";
|
|
15
15
|
import "./chunk-EKTPDG3G.js";
|
|
16
16
|
import {
|
|
17
17
|
GitPrepJob,
|
|
18
18
|
defaultGit,
|
|
19
19
|
ensureDir,
|
|
20
20
|
reportBootMilestone
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-VIUZS7V4.js";
|
|
22
22
|
import "./chunk-W4LZ7R6Z.js";
|
|
23
23
|
import "./chunk-372R6E4C.js";
|
|
24
24
|
import "./chunk-SQM2BQ7H.js";
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
readWorkspaceBytes,
|
|
9
9
|
statWorkspacePath,
|
|
10
10
|
workspacePathExists
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-KXB55NJP.js";
|
|
12
12
|
import {
|
|
13
13
|
reportBootMilestone
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-VIUZS7V4.js";
|
|
15
15
|
import {
|
|
16
16
|
runSetupCommand,
|
|
17
17
|
runStartCommand,
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
mapChatHistory,
|
|
3
3
|
readAgentVersion,
|
|
4
4
|
refreshSkillsAfterCheckout
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-V5WR2F2P.js";
|
|
6
6
|
import {
|
|
7
7
|
MAX_BETWEEN_TURN_BUFFER,
|
|
8
8
|
MAX_DIAGNOSTIC_OUTPUT,
|
|
@@ -37,7 +37,6 @@ import {
|
|
|
37
37
|
CARD_DESCRIPTION_FIELD_HINT,
|
|
38
38
|
CONTEXT_LINK_LOCATOR_MAX,
|
|
39
39
|
CRITICAL_AUTOMATED_SOURCES,
|
|
40
|
-
CodespacePortVisibility,
|
|
41
40
|
DEFAULT_CI_WAIT_TIMEOUT_MINUTES,
|
|
42
41
|
DEFAULT_CODEX_CODING_MODEL,
|
|
43
42
|
DEFAULT_LIFECYCLE_CONFIG,
|
|
@@ -98,11 +97,10 @@ import {
|
|
|
98
97
|
statWorkspacePath,
|
|
99
98
|
updateRemoteToken,
|
|
100
99
|
verifyGitCredential
|
|
101
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-KXB55NJP.js";
|
|
102
101
|
import {
|
|
103
|
-
registerBootMilestoneSocketFallback,
|
|
104
102
|
reportBootMilestone
|
|
105
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-VIUZS7V4.js";
|
|
106
104
|
import {
|
|
107
105
|
describeTokenFile,
|
|
108
106
|
ghHostsExternallyOwned,
|
|
@@ -2746,7 +2744,7 @@ function claudeCredentialsPath() {
|
|
|
2746
2744
|
return join7(claudeConfigHome(), ".credentials.json");
|
|
2747
2745
|
}
|
|
2748
2746
|
function isConveyorCloudEnv(env = process.env) {
|
|
2749
|
-
return Boolean(env.CLAUDESPACE_NAME
|
|
2747
|
+
return Boolean(env.CLAUDESPACE_NAME);
|
|
2750
2748
|
}
|
|
2751
2749
|
async function readRaw(path) {
|
|
2752
2750
|
try {
|
|
@@ -5862,7 +5860,7 @@ function composerOverrides(runMode, env = process.env) {
|
|
|
5862
5860
|
}
|
|
5863
5861
|
|
|
5864
5862
|
// src/execution/query-executor.ts
|
|
5865
|
-
import { createHash as
|
|
5863
|
+
import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
|
|
5866
5864
|
import {
|
|
5867
5865
|
closeSync,
|
|
5868
5866
|
existsSync,
|
|
@@ -5906,7 +5904,7 @@ Respond to them with post_to_chat (your turn output is NOT shown in chat).`
|
|
|
5906
5904
|
// src/execution/relaunch-hold.ts
|
|
5907
5905
|
function findLastAgentMessageIndex(history) {
|
|
5908
5906
|
for (let i = history.length - 1; i >= 0; i--) {
|
|
5909
|
-
if (history[i].role === "assistant") return i;
|
|
5907
|
+
if (history[i].role === "assistant" && history[i].kind !== "lifecycle") return i;
|
|
5910
5908
|
}
|
|
5911
5909
|
return -1;
|
|
5912
5910
|
}
|
|
@@ -5970,6 +5968,11 @@ function formatFileSize(bytes) {
|
|
|
5970
5968
|
if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)}KB`;
|
|
5971
5969
|
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
5972
5970
|
}
|
|
5971
|
+
function notInlinedRef(file) {
|
|
5972
|
+
const link = file.downloadUrl && isCapabilityServableMime(file.mimeType) ? file.downloadUrl : void 0;
|
|
5973
|
+
if (!file.fileId) return link ?? "read it with get_attachment (see list_task_files)";
|
|
5974
|
+
return `read it with get_attachment("${file.fileId}")${link ? ` or download: ${link}` : ""}`;
|
|
5975
|
+
}
|
|
5973
5976
|
function formatChatFile(file) {
|
|
5974
5977
|
const sizeStr = file.fileSize ? `, ${formatFileSize(file.fileSize)}` : "";
|
|
5975
5978
|
if (file.content && file.contentEncoding === "utf-8") {
|
|
@@ -5981,7 +5984,7 @@ function formatChatFile(file) {
|
|
|
5981
5984
|
];
|
|
5982
5985
|
}
|
|
5983
5986
|
if (!file.content) {
|
|
5984
|
-
return [`[Attached: ${file.fileName} (${file.mimeType}${sizeStr})]: ${file
|
|
5987
|
+
return [`[Attached: ${file.fileName} (${file.mimeType}${sizeStr})]: ${notInlinedRef(file)}`];
|
|
5985
5988
|
}
|
|
5986
5989
|
if (file.content && file.contentEncoding === "base64") {
|
|
5987
5990
|
const link = file.downloadUrl ? ` or download: ${file.downloadUrl}` : "";
|
|
@@ -6018,7 +6021,7 @@ function formatTaskFile(file) {
|
|
|
6018
6021
|
];
|
|
6019
6022
|
}
|
|
6020
6023
|
if (!file.content) {
|
|
6021
|
-
return [`- **${file.fileName}** (${file.mimeType}): ${file
|
|
6024
|
+
return [`- **${file.fileName}** (${file.mimeType}): ${notInlinedRef(file)}`];
|
|
6022
6025
|
}
|
|
6023
6026
|
return [];
|
|
6024
6027
|
}
|
|
@@ -6367,8 +6370,8 @@ var PACK_RUNNER_FOOTER = [
|
|
|
6367
6370
|
function resolveSinglePodPackBranch(context) {
|
|
6368
6371
|
return context.githubBranch || context.baseBranch;
|
|
6369
6372
|
}
|
|
6370
|
-
function isPackRunnerSession(mode
|
|
6371
|
-
return mode === "pack"
|
|
6373
|
+
function isPackRunnerSession(mode) {
|
|
6374
|
+
return mode === "pack";
|
|
6372
6375
|
}
|
|
6373
6376
|
function buildSinglePodPackPrompt(context, setupLog) {
|
|
6374
6377
|
const packBranch = resolveSinglePodPackBranch(context);
|
|
@@ -6937,7 +6940,7 @@ Git:`,
|
|
|
6937
6940
|
function buildSystemPrompt(mode, context, config, setupLog, agentMode) {
|
|
6938
6941
|
const isPm = mode === "pm";
|
|
6939
6942
|
const isPmActive = isPm && agentMode === "building";
|
|
6940
|
-
if (isPackRunnerSession(mode
|
|
6943
|
+
if (isPackRunnerSession(mode)) {
|
|
6941
6944
|
return buildSinglePodPackPrompt(context, setupLog);
|
|
6942
6945
|
}
|
|
6943
6946
|
const parts = isPmActive ? buildActivePreamble(context, config.workspaceDir) : isPm ? buildPmPreamble(context) : buildTaskAgentPreamble(context, config.workspaceDir, config.runtimeTui, agentMode);
|
|
@@ -7236,7 +7239,7 @@ function buildInstructions(mode, context, scenario, agentMode, isAuto) {
|
|
|
7236
7239
|
return parts;
|
|
7237
7240
|
}
|
|
7238
7241
|
async function buildInitialPrompt(mode, context, isAuto, agentMode) {
|
|
7239
|
-
const isPackRunner = isPackRunnerSession(mode
|
|
7242
|
+
const isPackRunner = isPackRunnerSession(mode);
|
|
7240
7243
|
if (!isPackRunner) {
|
|
7241
7244
|
const sessionRelaunch = buildRelaunchWithSession(mode, context, agentMode, isAuto);
|
|
7242
7245
|
if (sessionRelaunch) {
|
|
@@ -8091,7 +8094,7 @@ var listTaskFilesContract = defineToolContract({
|
|
|
8091
8094
|
var getAttachmentContract = defineToolContract({
|
|
8092
8095
|
name: "get_attachment",
|
|
8093
8096
|
agent: {
|
|
8094
|
-
description: "Fetch one task file
|
|
8097
|
+
description: "Fetch one task file by ID. Text and images under the inline size caps come back inline. Any other file (PDF, Word, Excel, zip, large logs) is saved into this pod, and the result names the local path: open it with the Read tool or Bash. A document downloadUrl answers 404 without a signed-in project member's session, so do not curl or WebFetch it. Call list_task_files first to discover IDs and sizes. Pass task_id when the file is attached to another card in this project, such as the pack parent.",
|
|
8095
8098
|
fields: {
|
|
8096
8099
|
fileId: f.string({ desc: "The file ID to retrieve" }),
|
|
8097
8100
|
task_id: agentTaskIdOrSlug
|
|
@@ -9511,6 +9514,97 @@ function formatCliEvent(e) {
|
|
|
9511
9514
|
return formatter ? formatter(e) : JSON.stringify(e);
|
|
9512
9515
|
}
|
|
9513
9516
|
|
|
9517
|
+
// src/tools/attachment-download.ts
|
|
9518
|
+
import { createHash as createHash4, randomUUID as randomUUID2 } from "crypto";
|
|
9519
|
+
import { createWriteStream } from "fs";
|
|
9520
|
+
import { mkdir as mkdir6, rename, rm as rm4 } from "fs/promises";
|
|
9521
|
+
import { basename as basename2, join as join17 } from "path";
|
|
9522
|
+
import { Readable, Transform } from "stream";
|
|
9523
|
+
import { pipeline } from "stream/promises";
|
|
9524
|
+
var DOWNLOAD_TIMEOUT_MS = 12e4;
|
|
9525
|
+
var AttachmentSaveError = class extends Error {
|
|
9526
|
+
constructor(code) {
|
|
9527
|
+
super(`Attachment save failed: ${code}`);
|
|
9528
|
+
this.code = code;
|
|
9529
|
+
this.name = "AttachmentSaveError";
|
|
9530
|
+
}
|
|
9531
|
+
code;
|
|
9532
|
+
};
|
|
9533
|
+
function attachmentsRoot() {
|
|
9534
|
+
return join17(sessionTempBase(), "conveyor-attachments");
|
|
9535
|
+
}
|
|
9536
|
+
function safeAttachmentId(fileId) {
|
|
9537
|
+
if (/^[A-Za-z0-9_-]{1,64}$/.test(fileId)) return fileId;
|
|
9538
|
+
return createHash4("sha256").update(fileId).digest("hex").slice(0, 32);
|
|
9539
|
+
}
|
|
9540
|
+
function safeAttachmentName(fileName) {
|
|
9541
|
+
const cleaned = basename2(fileName).replace(/[^A-Za-z0-9._-]/g, "_").replace(/^[.-]+/, "").slice(-120);
|
|
9542
|
+
return cleaned || "attachment";
|
|
9543
|
+
}
|
|
9544
|
+
function byteCap(limit) {
|
|
9545
|
+
let seen = 0;
|
|
9546
|
+
const stream = new Transform({
|
|
9547
|
+
transform(chunk, _enc, callback) {
|
|
9548
|
+
seen += chunk.length;
|
|
9549
|
+
if (seen > limit) callback(new AttachmentSaveError("too_large"));
|
|
9550
|
+
else callback(null, chunk);
|
|
9551
|
+
}
|
|
9552
|
+
});
|
|
9553
|
+
return Object.assign(stream, { bytes: () => seen });
|
|
9554
|
+
}
|
|
9555
|
+
function classify(err) {
|
|
9556
|
+
if (err instanceof AttachmentSaveError) return err;
|
|
9557
|
+
if (err instanceof Error) {
|
|
9558
|
+
if (err.name === "TimeoutError" || err.name === "AbortError") {
|
|
9559
|
+
return new AttachmentSaveError("timeout");
|
|
9560
|
+
}
|
|
9561
|
+
if ("syscall" in err && typeof err.syscall === "string" && "path" in err) {
|
|
9562
|
+
return new AttachmentSaveError("write_failed");
|
|
9563
|
+
}
|
|
9564
|
+
}
|
|
9565
|
+
return new AttachmentSaveError("network");
|
|
9566
|
+
}
|
|
9567
|
+
async function fetchAttachment(url) {
|
|
9568
|
+
let res;
|
|
9569
|
+
try {
|
|
9570
|
+
res = await fetch(url, { signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS) });
|
|
9571
|
+
} catch (err) {
|
|
9572
|
+
throw classify(err);
|
|
9573
|
+
}
|
|
9574
|
+
if (!res.ok) throw new AttachmentSaveError(`http_${res.status}`);
|
|
9575
|
+
const declared = Number(res.headers.get("content-length"));
|
|
9576
|
+
if (Number.isFinite(declared) && declared > MAX_FILE_SIZE_BYTES) {
|
|
9577
|
+
throw new AttachmentSaveError("too_large");
|
|
9578
|
+
}
|
|
9579
|
+
if (!res.body) throw new AttachmentSaveError("network");
|
|
9580
|
+
return res;
|
|
9581
|
+
}
|
|
9582
|
+
async function saveAttachmentToDisk(input) {
|
|
9583
|
+
const res = await fetchAttachment(input.url);
|
|
9584
|
+
const dir = join17(attachmentsRoot(), safeAttachmentId(input.fileId));
|
|
9585
|
+
const dest = join17(dir, safeAttachmentName(input.fileName));
|
|
9586
|
+
const part = `${dest}.${randomUUID2()}.part`;
|
|
9587
|
+
try {
|
|
9588
|
+
await mkdir6(dir, { recursive: true, mode: 448 });
|
|
9589
|
+
} catch {
|
|
9590
|
+
throw new AttachmentSaveError("write_failed");
|
|
9591
|
+
}
|
|
9592
|
+
const cap = byteCap(MAX_FILE_SIZE_BYTES);
|
|
9593
|
+
try {
|
|
9594
|
+
await pipeline(
|
|
9595
|
+
Readable.fromWeb(res.body),
|
|
9596
|
+
cap,
|
|
9597
|
+
createWriteStream(part, { mode: 384 })
|
|
9598
|
+
);
|
|
9599
|
+
await rename(part, dest);
|
|
9600
|
+
} catch (err) {
|
|
9601
|
+
await rm4(part, { force: true }).catch(() => {
|
|
9602
|
+
});
|
|
9603
|
+
throw classify(err);
|
|
9604
|
+
}
|
|
9605
|
+
return { path: dest, bytes: cap.bytes() };
|
|
9606
|
+
}
|
|
9607
|
+
|
|
9514
9608
|
// src/tools/task-context-tools.ts
|
|
9515
9609
|
function buildReadTaskChatTool(connection) {
|
|
9516
9610
|
return defineContractTool(
|
|
@@ -9699,18 +9793,23 @@ function buildGetAttachmentTool(connection) {
|
|
|
9699
9793
|
const file = await connection.call("getTaskFile", {
|
|
9700
9794
|
sessionId: connection.sessionId,
|
|
9701
9795
|
fileId,
|
|
9702
|
-
...task_id ? { taskId: task_id } : {}
|
|
9796
|
+
...task_id ? { taskId: task_id } : {},
|
|
9797
|
+
agentDownload: true
|
|
9703
9798
|
});
|
|
9704
|
-
const { content: rawContent, ...metadata } = file;
|
|
9705
|
-
const content = [
|
|
9706
|
-
{ type: "text", text: JSON.stringify(metadata, null, 2) }
|
|
9707
|
-
];
|
|
9799
|
+
const { content: rawContent, agentDownloadUrl, ...metadata } = file;
|
|
9708
9800
|
if (rawContent && file.contentEncoding === "base64" && isImageMimeType(file.mimeType)) {
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9801
|
+
return {
|
|
9802
|
+
content: [
|
|
9803
|
+
{ type: "text", text: JSON.stringify(metadata, null, 2) },
|
|
9804
|
+
imageBlock(rawContent, file.mimeType)
|
|
9805
|
+
]
|
|
9806
|
+
};
|
|
9712
9807
|
}
|
|
9713
|
-
|
|
9808
|
+
if (rawContent) {
|
|
9809
|
+
return textResult(JSON.stringify({ ...metadata, content: rawContent }, null, 2));
|
|
9810
|
+
}
|
|
9811
|
+
if (!agentDownloadUrl) return textResult(JSON.stringify(metadata, null, 2));
|
|
9812
|
+
return textResult(await saveForAgent(metadata, agentDownloadUrl));
|
|
9714
9813
|
} catch (error) {
|
|
9715
9814
|
return textResult(
|
|
9716
9815
|
`Failed to get task file: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -9720,6 +9819,26 @@ function buildGetAttachmentTool(connection) {
|
|
|
9720
9819
|
{ annotations: { readOnlyHint: true } }
|
|
9721
9820
|
);
|
|
9722
9821
|
}
|
|
9822
|
+
async function saveForAgent(metadata, url) {
|
|
9823
|
+
const { downloadUrl: _documentLink, ...rest } = metadata;
|
|
9824
|
+
const shown = isCapabilityServableMime(metadata.mimeType) ? metadata : rest;
|
|
9825
|
+
const header = JSON.stringify(shown, null, 2);
|
|
9826
|
+
try {
|
|
9827
|
+
const saved = await saveAttachmentToDisk({
|
|
9828
|
+
url,
|
|
9829
|
+
fileId: metadata.id,
|
|
9830
|
+
fileName: metadata.fileName
|
|
9831
|
+
});
|
|
9832
|
+
return `${header}
|
|
9833
|
+
|
|
9834
|
+
Saved to ${saved.path} (${saved.bytes} bytes). Open it with the Read tool (a PDF over 10 pages needs the pages parameter) or process it with Bash.`;
|
|
9835
|
+
} catch (error) {
|
|
9836
|
+
const code = error instanceof AttachmentSaveError ? error.code : "network";
|
|
9837
|
+
return `${header}
|
|
9838
|
+
|
|
9839
|
+
Could not save the file (${code}). Call get_attachment again; each call mints a fresh 5-minute link.`;
|
|
9840
|
+
}
|
|
9841
|
+
}
|
|
9723
9842
|
function buildTaskContextTools(connection) {
|
|
9724
9843
|
return [
|
|
9725
9844
|
buildReadTaskChatTool(connection),
|
|
@@ -10264,7 +10383,7 @@ function buildMutationTools(connection, config) {
|
|
|
10264
10383
|
}
|
|
10265
10384
|
|
|
10266
10385
|
// src/tools/attachment-tools.ts
|
|
10267
|
-
import { basename as
|
|
10386
|
+
import { basename as basename3, extname, isAbsolute, join as join18 } from "path";
|
|
10268
10387
|
var MIME_BY_EXT = {
|
|
10269
10388
|
".png": "image/png",
|
|
10270
10389
|
".jpg": "image/jpeg",
|
|
@@ -10343,7 +10462,7 @@ function buildUploadAttachmentTool(connection, config) {
|
|
|
10343
10462
|
async ({ path, title, comment, tags, showcase, supersedes }) => {
|
|
10344
10463
|
const caption = title ?? comment;
|
|
10345
10464
|
try {
|
|
10346
|
-
const filePath = isAbsolute(path) ? path :
|
|
10465
|
+
const filePath = isAbsolute(path) ? path : join18(config.workspaceDir, path);
|
|
10347
10466
|
const mimeType = inferMimeType(filePath);
|
|
10348
10467
|
const info = await statWorkspacePath(filePath);
|
|
10349
10468
|
if (!info.isFile) {
|
|
@@ -10354,7 +10473,7 @@ function buildUploadAttachmentTool(connection, config) {
|
|
|
10354
10473
|
`File is ${info.size} bytes \u2014 exceeds the ${MAX_FILE_SIZE_BYTES} byte (25MB) upload limit.`
|
|
10355
10474
|
);
|
|
10356
10475
|
}
|
|
10357
|
-
const fileName =
|
|
10476
|
+
const fileName = basename3(filePath);
|
|
10358
10477
|
const { fileId, uploadUrl } = await connection.call("requestFileUpload", {
|
|
10359
10478
|
sessionId: connection.sessionId,
|
|
10360
10479
|
fileName,
|
|
@@ -11003,7 +11122,7 @@ import { z as z9 } from "zod";
|
|
|
11003
11122
|
|
|
11004
11123
|
// src/execution/context-path-verifier.ts
|
|
11005
11124
|
import { readFile as readFile4 } from "fs/promises";
|
|
11006
|
-
import { isAbsolute as isAbsolute2, join as
|
|
11125
|
+
import { isAbsolute as isAbsolute2, join as join19, normalize } from "path";
|
|
11007
11126
|
var PROBLEM_TEXT = {
|
|
11008
11127
|
not_found: "does not exist in the repo",
|
|
11009
11128
|
expected_folder: "is a file, not a folder \u2014 use type 'file', 'rule', or 'doc'",
|
|
@@ -11048,7 +11167,7 @@ async function verifyContextPaths(links, workspaceDir) {
|
|
|
11048
11167
|
problems.push({ type: link.type, path: link.path, reason: shape });
|
|
11049
11168
|
continue;
|
|
11050
11169
|
}
|
|
11051
|
-
const absolutePath =
|
|
11170
|
+
const absolutePath = join19(workspaceDir, toRelativePath(link.path));
|
|
11052
11171
|
const stat = await statWorkspacePath(absolutePath);
|
|
11053
11172
|
const wantsDirectory = expectsDirectory(link.type);
|
|
11054
11173
|
if (!stat.exists) {
|
|
@@ -11999,7 +12118,7 @@ function buildEvaluateTools(connection, projectId) {
|
|
|
11999
12118
|
|
|
12000
12119
|
// src/tools/site-asset-tools.ts
|
|
12001
12120
|
import crypto from "crypto";
|
|
12002
|
-
import { extname as extname2, isAbsolute as isAbsolute3, join as
|
|
12121
|
+
import { extname as extname2, isAbsolute as isAbsolute3, join as join20 } from "path";
|
|
12003
12122
|
var MAX_SITE_ASSET_BYTES = 25 * 1024 * 1024;
|
|
12004
12123
|
function buildSiteAssetTools(connection, config, projectId) {
|
|
12005
12124
|
const list = defineContractTool(listSiteAssetTargetsContract, async () => {
|
|
@@ -12016,7 +12135,7 @@ function buildSiteAssetTools(connection, config, projectId) {
|
|
|
12016
12135
|
const upload = defineContractTool(uploadSiteAssetsContract, async ({ siteId, paths }) => {
|
|
12017
12136
|
const results = [];
|
|
12018
12137
|
for (const requestedPath of [...paths].sort()) {
|
|
12019
|
-
const path = isAbsolute3(requestedPath) ? requestedPath :
|
|
12138
|
+
const path = isAbsolute3(requestedPath) ? requestedPath : join20(config.workspaceDir, requestedPath);
|
|
12020
12139
|
try {
|
|
12021
12140
|
const info = await statWorkspacePath(path);
|
|
12022
12141
|
if (!info.isFile) throw new Error("not a file");
|
|
@@ -13343,7 +13462,7 @@ function buildHooks(host) {
|
|
|
13343
13462
|
};
|
|
13344
13463
|
}
|
|
13345
13464
|
function taskIdToSessionUuid(lineageKey) {
|
|
13346
|
-
const hash =
|
|
13465
|
+
const hash = createHash5("sha256").update(lineageKey).digest("hex");
|
|
13347
13466
|
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-8${hash.slice(13, 16)}-a${hash.slice(17, 20)}-${hash.slice(20, 32)}`;
|
|
13348
13467
|
}
|
|
13349
13468
|
function sessionLineageKey(taskId, agentMode, runnerMode) {
|
|
@@ -13480,12 +13599,6 @@ function buildQueryOptions(host, context) {
|
|
|
13480
13599
|
context,
|
|
13481
13600
|
{
|
|
13482
13601
|
...host.config,
|
|
13483
|
-
// ModeController's live value, NOT the boot-frozen `config.isAuto` the
|
|
13484
|
-
// spread carries: the pack gate reads this, and the turn prompt below
|
|
13485
|
-
// gates on `host.isAuto`. Letting the two read different sources is how
|
|
13486
|
-
// a codespace parent card got "you cannot write or edit files" beside
|
|
13487
|
-
// "run /conveyor-build".
|
|
13488
|
-
isAuto: host.isAuto,
|
|
13489
13602
|
runtimeTui: process.env.CONVEYOR_TUI
|
|
13490
13603
|
},
|
|
13491
13604
|
host.setupLog,
|
|
@@ -13957,7 +14070,7 @@ function freshSessionOptions(host, context, options) {
|
|
|
13957
14070
|
markSpawnedTranscript(host.config.workspaceDir, lineageUuid);
|
|
13958
14071
|
return { ...options, sessionId: lineageUuid };
|
|
13959
14072
|
}
|
|
13960
|
-
return { ...options, sessionId:
|
|
14073
|
+
return { ...options, sessionId: randomUUID3() };
|
|
13961
14074
|
}
|
|
13962
14075
|
async function buildRetryQuery(host, context, options, lastErrorWasImage) {
|
|
13963
14076
|
if (lastErrorWasImage) {
|
|
@@ -15224,11 +15337,9 @@ var SessionRunner = class _SessionRunner {
|
|
|
15224
15337
|
this.config = config;
|
|
15225
15338
|
this.callbacks = callbacks;
|
|
15226
15339
|
this.connection = new AgentConnection(config.connection);
|
|
15227
|
-
const portVisibility = new CodespacePortVisibility();
|
|
15228
15340
|
this.portDiscovery = deps.portDiscovery ?? new PortDiscovery({
|
|
15229
15341
|
report: (ports) => this.connection.reportDiscoveredPorts(ports),
|
|
15230
|
-
annotate: (ports) => loadAndAnnotateDiscoveredPorts(config.workspaceDir, ports)
|
|
15231
|
-
onReported: (ports) => portVisibility.ensureVisible(ports.map(({ port }) => port))
|
|
15342
|
+
annotate: (ports) => loadAndAnnotateDiscoveredPorts(config.workspaceDir, ports)
|
|
15232
15343
|
});
|
|
15233
15344
|
const initialMode = config.agentMode ?? (config.runnerMode === "pm" ? config.isAuto ? "auto" : "discovery" : "building");
|
|
15234
15345
|
this.mode = new ModeController(initialMode, config.runnerMode, config.isAuto);
|
|
@@ -15561,7 +15672,6 @@ var SessionRunner = class _SessionRunner {
|
|
|
15561
15672
|
await this.setState("connected");
|
|
15562
15673
|
this.connection.sendEvent({ type: "connected", sessionId: this.sessionId });
|
|
15563
15674
|
this.wireConnectionCallbacks();
|
|
15564
|
-
registerBootMilestoneSocketFallback((key) => this.connection.reportBootMilestone(key));
|
|
15565
15675
|
this.lifecycle.startHeartbeat();
|
|
15566
15676
|
this.loopLag.start();
|
|
15567
15677
|
this.connection.startHeartbeatWorker(this.loopLag.sharedBuffer);
|
|
@@ -16743,7 +16853,7 @@ ${outcome.failures.join("\n")}
|
|
|
16743
16853
|
}
|
|
16744
16854
|
};
|
|
16745
16855
|
|
|
16746
|
-
// src/setup/
|
|
16856
|
+
// src/setup/unshallow.ts
|
|
16747
16857
|
import { execSync } from "child_process";
|
|
16748
16858
|
function unshallowRepo(workspaceDir) {
|
|
16749
16859
|
try {
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
DEFAULT_RETRY_DELAY_MS,
|
|
4
4
|
FETCH_TIMEOUT_MS,
|
|
5
5
|
GIT_PREP_MAX_RETRIES
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-VIUZS7V4.js";
|
|
7
7
|
import {
|
|
8
8
|
gitCredentialHelper,
|
|
9
9
|
sleep,
|
|
@@ -25,117 +25,6 @@ import {
|
|
|
25
25
|
workbenchEnabled
|
|
26
26
|
} from "./chunk-KMB3BU4S.js";
|
|
27
27
|
|
|
28
|
-
// src/setup/bootstrap.ts
|
|
29
|
-
var BOOTSTRAP_TIMEOUT_MS = 3e4;
|
|
30
|
-
var RETRY_DELAYS_MS = [5e3, 1e4, 2e4];
|
|
31
|
-
function emitFailureEvent(payload) {
|
|
32
|
-
process.stderr.write(JSON.stringify(payload) + "\n");
|
|
33
|
-
}
|
|
34
|
-
async function singleBootstrapAttempt(apiUrl, instanceName, bootstrapToken, timeoutMs) {
|
|
35
|
-
const controller = new AbortController();
|
|
36
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
37
|
-
try {
|
|
38
|
-
const headers = {};
|
|
39
|
-
if (bootstrapToken) headers["x-codespace-token"] = bootstrapToken;
|
|
40
|
-
const response = await fetch(`${apiUrl}/api/codespace/bootstrap/${instanceName}`, {
|
|
41
|
-
headers,
|
|
42
|
-
signal: controller.signal
|
|
43
|
-
});
|
|
44
|
-
if (!response.ok) {
|
|
45
|
-
const errorText = await response.text().catch(() => "");
|
|
46
|
-
return {
|
|
47
|
-
ok: false,
|
|
48
|
-
status: response.status,
|
|
49
|
-
errorText: errorText.slice(0, 500),
|
|
50
|
-
reason: response.status === 401 || response.status === 403 ? "auth_rejected" : "http_error"
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
const body = await response.json();
|
|
54
|
-
return { ok: true, body };
|
|
55
|
-
} catch (err) {
|
|
56
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
57
|
-
const reason = controller.signal.aborted ? "timeout" : "network_error";
|
|
58
|
-
return { ok: false, errorText: message.slice(0, 500), reason };
|
|
59
|
-
} finally {
|
|
60
|
-
clearTimeout(timer);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
function buildFailure(reason, attempts, status, detail) {
|
|
64
|
-
const out = { ok: false, reason, attempts };
|
|
65
|
-
if (status === void 0) {
|
|
66
|
-
} else {
|
|
67
|
-
out.status = status;
|
|
68
|
-
}
|
|
69
|
-
if (detail) out.detail = detail;
|
|
70
|
-
return out;
|
|
71
|
-
}
|
|
72
|
-
function isRetryable(reason, retryOnHttpError) {
|
|
73
|
-
if (reason === "timeout" || reason === "network_error") return true;
|
|
74
|
-
return retryOnHttpError === true && reason === "http_error";
|
|
75
|
-
}
|
|
76
|
-
async function fetchBootstrap(opts) {
|
|
77
|
-
const timeoutMs = opts.timeoutMs ?? BOOTSTRAP_TIMEOUT_MS;
|
|
78
|
-
const delays = opts.retryDelaysMs ?? RETRY_DELAYS_MS;
|
|
79
|
-
const maxAttempts = delays.length + 1;
|
|
80
|
-
const hasBootstrapToken = Boolean(opts.bootstrapToken);
|
|
81
|
-
const hasTaskToken = Boolean(process.env.CONVEYOR_TASK_TOKEN);
|
|
82
|
-
let lastReason = "unknown";
|
|
83
|
-
let lastStatus;
|
|
84
|
-
let lastDetail;
|
|
85
|
-
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
86
|
-
const result = await singleBootstrapAttempt(
|
|
87
|
-
opts.apiUrl,
|
|
88
|
-
opts.instanceName,
|
|
89
|
-
opts.bootstrapToken,
|
|
90
|
-
timeoutMs
|
|
91
|
-
);
|
|
92
|
-
if (result.ok && result.body) {
|
|
93
|
-
return { ok: true, config: result.body, attempts: attempt };
|
|
94
|
-
}
|
|
95
|
-
lastReason = result.reason ?? "unknown";
|
|
96
|
-
lastStatus = result.status;
|
|
97
|
-
lastDetail = result.errorText;
|
|
98
|
-
const failurePayload = {
|
|
99
|
-
event: "bootstrap_failed",
|
|
100
|
-
reason: lastReason,
|
|
101
|
-
apiUrl: opts.apiUrl,
|
|
102
|
-
instanceName: opts.instanceName,
|
|
103
|
-
hasBootstrapToken,
|
|
104
|
-
hasTaskToken,
|
|
105
|
-
attempt
|
|
106
|
-
};
|
|
107
|
-
if (lastStatus === void 0) {
|
|
108
|
-
} else {
|
|
109
|
-
failurePayload.status = lastStatus;
|
|
110
|
-
}
|
|
111
|
-
if (lastDetail) failurePayload.detail = lastDetail;
|
|
112
|
-
emitFailureEvent(failurePayload);
|
|
113
|
-
if (!isRetryable(lastReason, opts.retryOnHttpError) || attempt >= maxAttempts) {
|
|
114
|
-
return buildFailure(lastReason, attempt, lastStatus, lastDetail);
|
|
115
|
-
}
|
|
116
|
-
await sleep(delays[attempt - 1]);
|
|
117
|
-
}
|
|
118
|
-
return buildFailure(lastReason, maxAttempts, lastStatus, lastDetail);
|
|
119
|
-
}
|
|
120
|
-
function applyBootstrapToEnv(config) {
|
|
121
|
-
for (const [key, value] of Object.entries(config.envVars ?? {})) {
|
|
122
|
-
process.env[key] = value;
|
|
123
|
-
}
|
|
124
|
-
if (config.mode === "project") {
|
|
125
|
-
if (config.projectToken) process.env.CONVEYOR_PROJECT_TOKEN = config.projectToken;
|
|
126
|
-
if (config.projectId) process.env.CONVEYOR_PROJECT_ID = config.projectId;
|
|
127
|
-
if (config.workspaceBranch) process.env.CONVEYOR_WORKSPACE_BRANCH = config.workspaceBranch;
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
if (config.taskId) process.env.CONVEYOR_TASK_ID = config.taskId;
|
|
131
|
-
if (config.sessionId) process.env.CONVEYOR_SESSION_ID = config.sessionId;
|
|
132
|
-
if (config.taskToken) process.env.CONVEYOR_TASK_TOKEN = config.taskToken;
|
|
133
|
-
if (config.agentMode !== void 0) process.env.CONVEYOR_AGENT_MODE = config.agentMode;
|
|
134
|
-
if (config.isAuto !== void 0) process.env.CONVEYOR_IS_AUTO = config.isAuto;
|
|
135
|
-
if (config.runnerMode) process.env.CONVEYOR_MODE = config.runnerMode;
|
|
136
|
-
if (config.taskBranch) process.env.CONVEYOR_TASK_BRANCH = config.taskBranch;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
28
|
// src/utils/logger.ts
|
|
140
29
|
function createServiceLogger(service) {
|
|
141
30
|
const prefix = `[conveyor-agent:${service}]`;
|
|
@@ -236,9 +125,6 @@ function applyBundleGithubToken(bundle, self) {
|
|
|
236
125
|
syncGithubTokenFiles(bundle.githubToken);
|
|
237
126
|
return { written: true };
|
|
238
127
|
}
|
|
239
|
-
function syncBundleGithubToken(token) {
|
|
240
|
-
syncGithubTokenFiles(token);
|
|
241
|
-
}
|
|
242
128
|
|
|
243
129
|
// src/connection/event-batch.ts
|
|
244
130
|
var MAX_EVENT_BATCH_BYTES = 256 * 1024;
|
|
@@ -1239,15 +1125,6 @@ var AgentConnection = class _AgentConnection {
|
|
|
1239
1125
|
async reportDiscoveredPorts(ports) {
|
|
1240
1126
|
await this.call("reportDiscoveredPorts", { sessionId: this.config.sessionId, ports });
|
|
1241
1127
|
}
|
|
1242
|
-
/** Boot-milestone report over the socket — the codespace-parity fallback
|
|
1243
|
-
* for the GKE pod bootstrap-token route. Fire-and-forget: a failed report
|
|
1244
|
-
* must never delay or fail the boot path. */
|
|
1245
|
-
reportBootMilestone(key) {
|
|
1246
|
-
void this.call("reportBootMilestone", { sessionId: this.config.sessionId, key }).catch(
|
|
1247
|
-
() => {
|
|
1248
|
-
}
|
|
1249
|
-
);
|
|
1250
|
-
}
|
|
1251
1128
|
// ── Typing indicators ───────────────────────────────────────────────
|
|
1252
1129
|
sendTypingStart() {
|
|
1253
1130
|
this.sendEvent({ type: "agent_typing_start" });
|
|
@@ -1336,9 +1213,8 @@ ${q.question}${q.options.length ? "\n" + q.options.map((o) => `- ${o.label}: ${o
|
|
|
1336
1213
|
refreshFromBootstrap() {
|
|
1337
1214
|
const none = Promise.resolve({ refreshedClaude: false, refreshedTaskToken: false });
|
|
1338
1215
|
const podBootstrapToken = process.env.POD_BOOTSTRAP_TOKEN;
|
|
1339
|
-
const codespaceName = process.env.CODESPACE_NAME;
|
|
1340
1216
|
const apiUrl = this.config.apiUrl;
|
|
1341
|
-
if (!apiUrl || !podBootstrapToken
|
|
1217
|
+
if (!apiUrl || !podBootstrapToken) {
|
|
1342
1218
|
return none;
|
|
1343
1219
|
}
|
|
1344
1220
|
const now = Date.now();
|
|
@@ -1346,50 +1222,7 @@ ${q.question}${q.options.length ? "\n" + q.options.map((o) => `- ${o.label}: ${o
|
|
|
1346
1222
|
return none;
|
|
1347
1223
|
}
|
|
1348
1224
|
this.lastTaskTokenRefreshAt = now;
|
|
1349
|
-
|
|
1350
|
-
return this.refreshFromV3Bootstrap(apiUrl, podBootstrapToken);
|
|
1351
|
-
}
|
|
1352
|
-
if (!codespaceName) return none;
|
|
1353
|
-
return this.refreshFromCodespaceBootstrap(apiUrl, codespaceName);
|
|
1354
|
-
}
|
|
1355
|
-
/** Legacy GitHub Codespaces refresh path — keys on instance name. */
|
|
1356
|
-
async refreshFromCodespaceBootstrap(apiUrl, codespaceName) {
|
|
1357
|
-
const bootstrapToken = process.env.CONVEYOR_BOOTSTRAP_TOKEN;
|
|
1358
|
-
const result = await fetchBootstrap({
|
|
1359
|
-
apiUrl,
|
|
1360
|
-
instanceName: codespaceName,
|
|
1361
|
-
bootstrapToken
|
|
1362
|
-
// Do not retry on http errors during a runtime refresh — a 401/403
|
|
1363
|
-
// means the token is consumed / session terminal and retrying won't
|
|
1364
|
-
// help. Network/timeout still retry inside fetchBootstrap.
|
|
1365
|
-
});
|
|
1366
|
-
if (!result.ok) {
|
|
1367
|
-
logger.warn("bootstrap refresh abandoned \u2014 pod credentials will go stale", {
|
|
1368
|
-
path: "codespace",
|
|
1369
|
-
reason: result.reason,
|
|
1370
|
-
status: result.status,
|
|
1371
|
-
attempts: result.attempts,
|
|
1372
|
-
detail: result.detail
|
|
1373
|
-
});
|
|
1374
|
-
return { refreshedClaude: false, refreshedTaskToken: false };
|
|
1375
|
-
}
|
|
1376
|
-
const previousTaskToken = process.env.CONVEYOR_TASK_TOKEN;
|
|
1377
|
-
applyBootstrapToEnv(result.config);
|
|
1378
|
-
const env = result.config.envVars ?? {};
|
|
1379
|
-
syncBundleGithubToken(env.CONVEYOR_GITHUB_TOKEN ?? env.GH_TOKEN ?? env.GITHUB_TOKEN);
|
|
1380
|
-
const refreshedTaskToken = result.config.mode !== "project" && Boolean(result.config.taskToken) && result.config.taskToken !== previousTaskToken;
|
|
1381
|
-
if (refreshedTaskToken && result.config.taskToken) {
|
|
1382
|
-
this.config.taskToken = result.config.taskToken;
|
|
1383
|
-
if (this.socket) {
|
|
1384
|
-
const auth = this.socket.auth;
|
|
1385
|
-
if (auth && typeof auth === "object") {
|
|
1386
|
-
auth.taskToken = result.config.taskToken;
|
|
1387
|
-
}
|
|
1388
|
-
}
|
|
1389
|
-
this.heartbeatWorker?.postMessage({ taskToken: result.config.taskToken });
|
|
1390
|
-
}
|
|
1391
|
-
const refreshedClaude = Boolean(result.config.envVars?.CLAUDE_CODE_OAUTH_TOKEN);
|
|
1392
|
-
return { refreshedClaude, refreshedTaskToken };
|
|
1225
|
+
return this.refreshFromV3Bootstrap(apiUrl, podBootstrapToken);
|
|
1393
1226
|
}
|
|
1394
1227
|
/**
|
|
1395
1228
|
* v3 refresh: re-fetch the full bootstrap bundle from the pod's bound v3
|
|
@@ -1538,7 +1371,7 @@ ${q.question}${q.options.length ? "\n" + q.options.map((o) => `- ${o.label}: ${o
|
|
|
1538
1371
|
}
|
|
1539
1372
|
};
|
|
1540
1373
|
|
|
1541
|
-
// ../shared/dist/chunk-
|
|
1374
|
+
// ../shared/dist/chunk-DXAS5XD4.js
|
|
1542
1375
|
import { z } from "zod";
|
|
1543
1376
|
import { z as z2 } from "zod";
|
|
1544
1377
|
var DEFAULT_SONNET_MODEL = "claude-sonnet-5-5";
|
|
@@ -2289,7 +2122,9 @@ var GetTaskFilesRequestSchema = z5.object({
|
|
|
2289
2122
|
var GetTaskFileRequestSchema = z5.object({
|
|
2290
2123
|
sessionId: z5.string(),
|
|
2291
2124
|
fileId: z5.string(),
|
|
2292
|
-
taskId: z5.string().optional()
|
|
2125
|
+
taskId: z5.string().optional(),
|
|
2126
|
+
/** Ask for a short-lived `agentDownloadUrl` when the bytes are not inlined. */
|
|
2127
|
+
agentDownload: z5.boolean().optional()
|
|
2293
2128
|
});
|
|
2294
2129
|
var DeleteTaskFileRequestSchema = z5.object({
|
|
2295
2130
|
sessionId: z5.string(),
|
|
@@ -2429,10 +2264,6 @@ var ReportDiscoveredPortsRequestSchema = z5.object({
|
|
|
2429
2264
|
sessionId: z5.string(),
|
|
2430
2265
|
ports: z5.array(DiscoveredPortSchema).max(64)
|
|
2431
2266
|
});
|
|
2432
|
-
var ReportBootMilestoneRequestSchema = z5.object({
|
|
2433
|
-
sessionId: z5.string(),
|
|
2434
|
-
key: z5.string().max(64)
|
|
2435
|
-
});
|
|
2436
2267
|
var CreateSubtaskRequestSchema = z5.object({
|
|
2437
2268
|
sessionId: z5.string(),
|
|
2438
2269
|
title: z5.string().min(1),
|
|
@@ -3985,6 +3816,8 @@ When you write prose a person will read \u2014 chat messages, plan updates, PR t
|
|
|
3985
3816
|
- Define a technical term on first use when a non-engineer will read the message.
|
|
3986
3817
|
- Never drop a condition, number, or scope qualifier to shorten a sentence. Precision beats brevity.
|
|
3987
3818
|
These rules do NOT apply to code, code comments, commit messages, or quoted output.`;
|
|
3819
|
+
var PROJECT_ARCHIVE_RETENTION_DAYS = 30;
|
|
3820
|
+
var RETENTION_MS = PROJECT_ARCHIVE_RETENTION_DAYS * 24 * 60 * 60 * 1e3;
|
|
3988
3821
|
var CLAUDESPACE_WORKLOAD_LABEL = "rc-workload";
|
|
3989
3822
|
var CLAUDESPACE_WORKLOAD_VALUE = "claudespace";
|
|
3990
3823
|
var CONVEYOR_POD_SELECTOR = `${CLAUDESPACE_WORKLOAD_LABEL}=${CLAUDESPACE_WORKLOAD_VALUE}`;
|
|
@@ -5481,71 +5314,7 @@ var PortDiscovery = class {
|
|
|
5481
5314
|
}
|
|
5482
5315
|
};
|
|
5483
5316
|
|
|
5484
|
-
// src/runner/codespace-port-visibility.ts
|
|
5485
|
-
import { execFile as execFile3 } from "child_process";
|
|
5486
|
-
var GH_TIMEOUT_MS = 15e3;
|
|
5487
|
-
var VISIBILITIES = ["org", "public"];
|
|
5488
|
-
function runGh(args) {
|
|
5489
|
-
return new Promise((resolve) => {
|
|
5490
|
-
execFile3("gh", [...args], { timeout: GH_TIMEOUT_MS }, (error, _stdout, stderr) => {
|
|
5491
|
-
resolve({ ok: !error, stderr: (stderr || (error ? String(error.message) : "")).trim() });
|
|
5492
|
-
});
|
|
5493
|
-
});
|
|
5494
|
-
}
|
|
5495
|
-
function isCodespaceEnvironment(env = process.env) {
|
|
5496
|
-
return env.CODESPACES === "true" && !!env.CODESPACE_NAME;
|
|
5497
|
-
}
|
|
5498
|
-
var CodespacePortVisibility = class {
|
|
5499
|
-
env;
|
|
5500
|
-
run;
|
|
5501
|
-
log;
|
|
5502
|
-
/** Ports already attempted (success or failure) — one try per process. */
|
|
5503
|
-
attempted = /* @__PURE__ */ new Set();
|
|
5504
|
-
constructor(options = {}) {
|
|
5505
|
-
this.env = options.env ?? process.env;
|
|
5506
|
-
this.run = options.run ?? runGh;
|
|
5507
|
-
this.log = options.log ?? ((m) => process.stderr.write(`[conveyor-agent] ${m}
|
|
5508
|
-
`));
|
|
5509
|
-
}
|
|
5510
|
-
/** Flip every not-yet-attempted port. Resolves even when everything fails. */
|
|
5511
|
-
async ensureVisible(ports) {
|
|
5512
|
-
if (!isCodespaceEnvironment(this.env)) return;
|
|
5513
|
-
const codespaceName = this.env.CODESPACE_NAME;
|
|
5514
|
-
for (const port of ports) {
|
|
5515
|
-
if (this.attempted.has(port)) continue;
|
|
5516
|
-
this.attempted.add(port);
|
|
5517
|
-
await this.flip(port, codespaceName);
|
|
5518
|
-
}
|
|
5519
|
-
}
|
|
5520
|
-
async flip(port, codespaceName) {
|
|
5521
|
-
let lastError = "";
|
|
5522
|
-
for (const visibility of VISIBILITIES) {
|
|
5523
|
-
const result = await this.run([
|
|
5524
|
-
"codespace",
|
|
5525
|
-
"ports",
|
|
5526
|
-
"visibility",
|
|
5527
|
-
`${port}:${visibility}`,
|
|
5528
|
-
"-c",
|
|
5529
|
-
codespaceName
|
|
5530
|
-
]).catch((error) => ({
|
|
5531
|
-
ok: false,
|
|
5532
|
-
stderr: error instanceof Error ? error.message : String(error)
|
|
5533
|
-
}));
|
|
5534
|
-
if (result.ok) {
|
|
5535
|
-
this.log(`Forwarded port ${port} set to ${visibility} visibility`);
|
|
5536
|
-
return;
|
|
5537
|
-
}
|
|
5538
|
-
lastError = result.stderr;
|
|
5539
|
-
}
|
|
5540
|
-
this.log(
|
|
5541
|
-
`Could not change visibility of forwarded port ${port} \u2014 the preview URL may 404 for other users${lastError ? `: ${lastError}` : ""}`
|
|
5542
|
-
);
|
|
5543
|
-
}
|
|
5544
|
-
};
|
|
5545
|
-
|
|
5546
5317
|
export {
|
|
5547
|
-
fetchBootstrap,
|
|
5548
|
-
applyBootstrapToEnv,
|
|
5549
5318
|
createServiceLogger,
|
|
5550
5319
|
AgentConnection,
|
|
5551
5320
|
DEFAULT_SONNET_MODEL,
|
|
@@ -5619,6 +5388,5 @@ export {
|
|
|
5619
5388
|
buildSessionPreviewPorts,
|
|
5620
5389
|
loadAndAnnotateDiscoveredPorts,
|
|
5621
5390
|
loadConveyorConfig,
|
|
5622
|
-
PortDiscovery
|
|
5623
|
-
CodespacePortVisibility
|
|
5391
|
+
PortDiscovery
|
|
5624
5392
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
redactToken
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-VIUZS7V4.js";
|
|
4
4
|
|
|
5
5
|
// src/boot/graphify.ts
|
|
6
6
|
var USER_HOME_MOUNT = "/mnt/conveyor-users";
|
|
@@ -42,6 +42,9 @@ function mapChatHistory(messages) {
|
|
|
42
42
|
userName: m.user?.name ?? void 0,
|
|
43
43
|
createdAt: m.createdAt,
|
|
44
44
|
...m.source ? { source: m.source } : {},
|
|
45
|
+
// The relaunch batch reads `kind` to skip server bookkeeping rows; dropping
|
|
46
|
+
// it here made that check dead in every pod (relaunch-hold.ts).
|
|
47
|
+
...m.kind ? { kind: m.kind } : {},
|
|
45
48
|
...m.files && m.files.length > 0 ? {
|
|
46
49
|
files: m.files.map((f) => ({
|
|
47
50
|
fileId: f.id,
|
|
@@ -371,21 +371,11 @@ var GitPrepJob = class {
|
|
|
371
371
|
|
|
372
372
|
// src/setup/boot-milestone.ts
|
|
373
373
|
var REPORT_TIMEOUT_MS = 5e3;
|
|
374
|
-
var socketFallback = null;
|
|
375
|
-
function registerBootMilestoneSocketFallback(fn) {
|
|
376
|
-
socketFallback = fn;
|
|
377
|
-
}
|
|
378
374
|
async function reportBootMilestone(opts) {
|
|
379
375
|
const env = opts.env ?? process.env;
|
|
380
376
|
const apiUrl = env.CONVEYOR_API_URL;
|
|
381
377
|
const token = env.POD_BOOTSTRAP_TOKEN;
|
|
382
|
-
if (!apiUrl || !token)
|
|
383
|
-
try {
|
|
384
|
-
socketFallback?.(opts.key);
|
|
385
|
-
} catch {
|
|
386
|
-
}
|
|
387
|
-
return false;
|
|
388
|
-
}
|
|
378
|
+
if (!apiUrl || !token) return false;
|
|
389
379
|
const fetchFn = opts.fetchFn ?? fetch;
|
|
390
380
|
const controller = new AbortController();
|
|
391
381
|
const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? REPORT_TIMEOUT_MS);
|
|
@@ -416,6 +406,5 @@ export {
|
|
|
416
406
|
GIT_PREP_MAX_RETRIES,
|
|
417
407
|
DEFAULT_RETRY_DELAY_MS,
|
|
418
408
|
GitPrepJob,
|
|
419
|
-
registerBootMilestoneSocketFallback,
|
|
420
409
|
reportBootMilestone
|
|
421
410
|
};
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
WorkspaceCommandSupervisor,
|
|
8
8
|
startWorkspaceCommandsAfterConnect,
|
|
9
9
|
stopWorkspaceCommands
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-4A6GCJGG.js";
|
|
11
11
|
import {
|
|
12
12
|
PtyHarness,
|
|
13
13
|
SessionRunner,
|
|
@@ -27,8 +27,8 @@ import {
|
|
|
27
27
|
runUsageProbe,
|
|
28
28
|
sampleKeyUsage,
|
|
29
29
|
usesNativeUsageReporting
|
|
30
|
-
} from "./chunk-
|
|
31
|
-
import "./chunk-
|
|
30
|
+
} from "./chunk-7Y3IY5QQ.js";
|
|
31
|
+
import "./chunk-V5WR2F2P.js";
|
|
32
32
|
import {
|
|
33
33
|
inheritedEnv,
|
|
34
34
|
resolvePtySpawn,
|
|
@@ -36,19 +36,16 @@ import {
|
|
|
36
36
|
} from "./chunk-EKTPDG3G.js";
|
|
37
37
|
import {
|
|
38
38
|
AgentConnection,
|
|
39
|
-
CodespacePortVisibility,
|
|
40
39
|
DEFAULT_LIFECYCLE_CONFIG,
|
|
41
40
|
DEFAULT_SONNET_MODEL,
|
|
42
41
|
Lifecycle,
|
|
43
42
|
PortDiscovery,
|
|
44
43
|
RUNNER_MODES,
|
|
45
|
-
applyBootstrapToEnv,
|
|
46
44
|
createServiceLogger,
|
|
47
|
-
fetchBootstrap,
|
|
48
45
|
loadAndAnnotateDiscoveredPorts,
|
|
49
46
|
loadConveyorConfig
|
|
50
|
-
} from "./chunk-
|
|
51
|
-
import "./chunk-
|
|
47
|
+
} from "./chunk-KXB55NJP.js";
|
|
48
|
+
import "./chunk-VIUZS7V4.js";
|
|
52
49
|
import "./chunk-W4LZ7R6Z.js";
|
|
53
50
|
import "./chunk-372R6E4C.js";
|
|
54
51
|
import "./chunk-IA45XHOA.js";
|
|
@@ -415,11 +412,9 @@ var AdhocSessionRunner = class {
|
|
|
415
412
|
buildAdhocPtyBridge(this.connection, () => this.lifecycle.startIdleTimer()),
|
|
416
413
|
resolveTuiAdapter(resolveAdhocTui(process.env))
|
|
417
414
|
);
|
|
418
|
-
const portVisibility = new CodespacePortVisibility();
|
|
419
415
|
this.portDiscovery = deps?.portDiscovery ?? new PortDiscovery({
|
|
420
416
|
report: (ports) => this.connection.reportDiscoveredPorts(ports),
|
|
421
|
-
annotate: (ports) => loadAndAnnotateDiscoveredPorts(config.workspaceDir, ports)
|
|
422
|
-
onReported: (ports) => portVisibility.ensureVisible(ports.map(({ port }) => port))
|
|
417
|
+
annotate: (ports) => loadAndAnnotateDiscoveredPorts(config.workspaceDir, ports)
|
|
423
418
|
});
|
|
424
419
|
this.commandSupervisor = deps?.commandSupervisor ?? new WorkspaceCommandSupervisor({
|
|
425
420
|
config: loadConveyorConfig(),
|
|
@@ -1217,7 +1212,7 @@ function wireSpawnChildren(mode, connection, supervisors, logger7) {
|
|
|
1217
1212
|
|
|
1218
1213
|
// src/cli.ts
|
|
1219
1214
|
if (process.argv[2] === "boot") {
|
|
1220
|
-
const { runBoot } = await import("./boot-
|
|
1215
|
+
const { runBoot } = await import("./boot-ZPXDDZDF.js");
|
|
1221
1216
|
process.exit(await runBoot(process.argv.slice(3)));
|
|
1222
1217
|
}
|
|
1223
1218
|
if (isLegacyEntrypointLaunch(process.env)) {
|
|
@@ -1249,39 +1244,6 @@ function logAgentExit(reason, opts) {
|
|
|
1249
1244
|
});
|
|
1250
1245
|
logger6[exitLogLevel(reason)]("agent_exit", payload);
|
|
1251
1246
|
}
|
|
1252
|
-
async function bootstrapFromCodespace(apiUrl, instanceName) {
|
|
1253
|
-
const bootstrapToken = process.env.CONVEYOR_BOOTSTRAP_TOKEN;
|
|
1254
|
-
const apiUrlFromEnv = Boolean(process.env.CONVEYOR_API_URL);
|
|
1255
|
-
logger6.info("Bootstrapping from codespace", {
|
|
1256
|
-
codespace: instanceName,
|
|
1257
|
-
apiUrl,
|
|
1258
|
-
apiUrlFromEnv,
|
|
1259
|
-
bootstrapTokenPresent: Boolean(bootstrapToken)
|
|
1260
|
-
});
|
|
1261
|
-
const result = await fetchBootstrap({
|
|
1262
|
-
apiUrl,
|
|
1263
|
-
instanceName,
|
|
1264
|
-
bootstrapToken
|
|
1265
|
-
});
|
|
1266
|
-
if (!result.ok) {
|
|
1267
|
-
logger6.error("Bootstrap failed after retries", {
|
|
1268
|
-
reason: result.reason,
|
|
1269
|
-
attempts: result.attempts,
|
|
1270
|
-
status: result.status,
|
|
1271
|
-
detail: result.detail,
|
|
1272
|
-
apiUrl,
|
|
1273
|
-
apiUrlFromEnv,
|
|
1274
|
-
bootstrapTokenPresent: Boolean(bootstrapToken),
|
|
1275
|
-
hint: apiUrlFromEnv ? "Verify the codespace was created by this Conveyor deployment and that the bootstrap token is current." : "CONVEYOR_API_URL was not set as a codespace secret \u2014 agent fell back to the built-in default. Re-create the codespace, or push CONVEYOR_API_URL via project settings."
|
|
1276
|
-
});
|
|
1277
|
-
process.exit(1);
|
|
1278
|
-
}
|
|
1279
|
-
applyBootstrapToEnv(result.config);
|
|
1280
|
-
logger6.info("Bootstrap complete", {
|
|
1281
|
-
taskId: result.config.taskId,
|
|
1282
|
-
attempts: result.attempts
|
|
1283
|
-
});
|
|
1284
|
-
}
|
|
1285
1247
|
function isExpectedAbortError(error) {
|
|
1286
1248
|
const message2 = error.message || "";
|
|
1287
1249
|
const hasAbortMessage = /operation aborted/i.test(message2) || /abort/i.test(message2);
|
|
@@ -1347,15 +1309,6 @@ if (process.env.CONVEYOR_MODE === "workbench") {
|
|
|
1347
1309
|
}
|
|
1348
1310
|
var DEFAULT_CONVEYOR_API_URL = "https://api.conveyor.rallycryapp.com";
|
|
1349
1311
|
var conveyorApiUrl = process.env.CONVEYOR_API_URL || DEFAULT_CONVEYOR_API_URL;
|
|
1350
|
-
var INSTANCE_NAME = process.env.CODESPACE_NAME || process.env.CLAUDESPACE_NAME;
|
|
1351
|
-
if (INSTANCE_NAME && !process.env.CONVEYOR_TASK_TOKEN) {
|
|
1352
|
-
if (!conveyorApiUrl) {
|
|
1353
|
-
logger6.error("Could not resolve CONVEYOR_API_URL for codespace bootstrap");
|
|
1354
|
-
process.exit(1);
|
|
1355
|
-
}
|
|
1356
|
-
await bootstrapFromCodespace(conveyorApiUrl, INSTANCE_NAME);
|
|
1357
|
-
conveyorApiUrl = process.env.CONVEYOR_API_URL ?? conveyorApiUrl;
|
|
1358
|
-
}
|
|
1359
1312
|
var CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;
|
|
1360
1313
|
var CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;
|
|
1361
1314
|
var CONVEYOR_WORKSPACE = process.env.CONVEYOR_WORKSPACE ?? process.cwd();
|
|
@@ -1455,7 +1408,7 @@ if (!CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {
|
|
|
1455
1408
|
logger6.error(" CONVEYOR_TASK_TOKEN - JWT token for task authentication");
|
|
1456
1409
|
logger6.error(" CONVEYOR_TASK_ID - ID of the task to execute");
|
|
1457
1410
|
logger6.error("");
|
|
1458
|
-
logger6.error("CONVEYOR_API_URL
|
|
1411
|
+
logger6.error("CONVEYOR_API_URL defaults to the hosted API when unset.");
|
|
1459
1412
|
logger6.error("");
|
|
1460
1413
|
logger6.error("Optional:");
|
|
1461
1414
|
logger6.error(" CONVEYOR_MODE - Runner mode: 'task' (default), 'pack', or 'pm'");
|
|
@@ -1470,7 +1423,7 @@ if (!RUNNER_MODES.includes(CONVEYOR_MODE)) {
|
|
|
1470
1423
|
process.exit(1);
|
|
1471
1424
|
}
|
|
1472
1425
|
if (CONVEYOR_MODE === "serving") {
|
|
1473
|
-
const { runServingSession } = await import("./serve-boot-
|
|
1426
|
+
const { runServingSession } = await import("./serve-boot-TPZ6CPCQ.js");
|
|
1474
1427
|
exitContext.runnerMode = "serving";
|
|
1475
1428
|
exitContext.sessionId = process.env.CONVEYOR_SESSION_ID ?? exitContext.sessionId;
|
|
1476
1429
|
const outcome = await runServingSession({
|
|
@@ -1530,8 +1483,8 @@ var runner = new SessionRunner(
|
|
|
1530
1483
|
connection: {
|
|
1531
1484
|
apiUrl: conveyorApiUrl ?? "",
|
|
1532
1485
|
taskToken: CONVEYOR_TASK_TOKEN,
|
|
1533
|
-
// CONVEYOR_SESSION_ID is the
|
|
1534
|
-
// Falls back to CONVEYOR_TASK_ID for backward compat
|
|
1486
|
+
// CONVEYOR_SESSION_ID is the WorkspaceSession ID for BaseService ACL.
|
|
1487
|
+
// Falls back to CONVEYOR_TASK_ID for backward compat.
|
|
1535
1488
|
sessionId: process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID,
|
|
1536
1489
|
runnerMode: CONVEYOR_MODE
|
|
1537
1490
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -361,10 +361,6 @@ declare class AgentConnection {
|
|
|
361
361
|
* Throws on failure so the PortDiscovery poller can retry on its next
|
|
362
362
|
* tick (a swallowed error here would silently drop the delta). */
|
|
363
363
|
reportDiscoveredPorts(ports: WorkspaceDiscoveredPort[]): Promise<void>;
|
|
364
|
-
/** Boot-milestone report over the socket — the codespace-parity fallback
|
|
365
|
-
* for the GKE pod bootstrap-token route. Fire-and-forget: a failed report
|
|
366
|
-
* must never delay or fail the boot path. */
|
|
367
|
-
reportBootMilestone(key: string): void;
|
|
368
364
|
sendTypingStart(): void;
|
|
369
365
|
sendTypingStop(): void;
|
|
370
366
|
emitRateLimitPause(resetsAt: string): void;
|
|
@@ -418,8 +414,6 @@ declare class AgentConnection {
|
|
|
418
414
|
private lastTaskTokenRefreshAt;
|
|
419
415
|
refreshTaskTokenFromBootstrap(): Promise<boolean>;
|
|
420
416
|
private refreshFromBootstrap;
|
|
421
|
-
/** Legacy GitHub Codespaces refresh path — keys on instance name. */
|
|
422
|
-
private refreshFromCodespaceBootstrap;
|
|
423
417
|
/**
|
|
424
418
|
* v3 refresh: re-fetch the full bootstrap bundle from the pod's bound v3
|
|
425
419
|
* route and swap the credentials in place. The GitHub installation token
|
|
@@ -594,7 +588,7 @@ interface LifecycleConfig {
|
|
|
594
588
|
/** Periodic WIP git flush interval (default: 2 min). Covers ungraceful
|
|
595
589
|
* pod termination (OOMKilled, node eviction) where preStop doesn't run.
|
|
596
590
|
* Set to `0` to disable the timer entirely — used for environments with
|
|
597
|
-
* persistent state (local, workspace
|
|
591
|
+
* persistent state (local, workspace) that don't lose
|
|
598
592
|
* in-flight work on a crash. */
|
|
599
593
|
gitFlushIntervalMs: number;
|
|
600
594
|
/** Claude key usage sample interval (default: 5 min). Polls the Anthropic
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
SessionRunner,
|
|
3
3
|
unshallowRepo
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-7Y3IY5QQ.js";
|
|
5
|
+
import "./chunk-V5WR2F2P.js";
|
|
6
6
|
import "./chunk-EKTPDG3G.js";
|
|
7
7
|
import {
|
|
8
8
|
AgentConnection,
|
|
@@ -17,8 +17,8 @@ import {
|
|
|
17
17
|
stageAndCommit,
|
|
18
18
|
updateRemoteToken,
|
|
19
19
|
workspacePathExists
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-KXB55NJP.js";
|
|
21
|
+
import "./chunk-VIUZS7V4.js";
|
|
22
22
|
import {
|
|
23
23
|
runAuthTokenCommand,
|
|
24
24
|
runSetupCommand,
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
WorkspaceCommandSupervisor
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4A6GCJGG.js";
|
|
4
4
|
import {
|
|
5
5
|
AgentConnection,
|
|
6
|
-
CodespacePortVisibility,
|
|
7
6
|
DEFAULT_LIFECYCLE_CONFIG,
|
|
8
7
|
Lifecycle,
|
|
9
8
|
PortDiscovery,
|
|
@@ -12,8 +11,8 @@ import {
|
|
|
12
11
|
ensureOnTaskBranch,
|
|
13
12
|
loadAndAnnotateDiscoveredPorts,
|
|
14
13
|
loadConveyorConfig
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-KXB55NJP.js";
|
|
15
|
+
import "./chunk-VIUZS7V4.js";
|
|
17
16
|
import "./chunk-W4LZ7R6Z.js";
|
|
18
17
|
import "./chunk-IA45XHOA.js";
|
|
19
18
|
import "./chunk-SQM2BQ7H.js";
|
|
@@ -36,11 +35,9 @@ var ServeSessionRunner = class {
|
|
|
36
35
|
this.config = config;
|
|
37
36
|
this.callbacks = callbacks;
|
|
38
37
|
this.connection = deps?.connection ?? new AgentConnection(config.connection);
|
|
39
|
-
const portVisibility = new CodespacePortVisibility();
|
|
40
38
|
this.portDiscovery = deps?.portDiscovery ?? new PortDiscovery({
|
|
41
39
|
report: (ports) => this.connection.reportDiscoveredPorts(ports),
|
|
42
|
-
annotate: (ports) => loadAndAnnotateDiscoveredPorts(config.workspaceDir, ports)
|
|
43
|
-
onReported: (ports) => portVisibility.ensureVisible(ports.map(({ port }) => port))
|
|
40
|
+
annotate: (ports) => loadAndAnnotateDiscoveredPorts(config.workspaceDir, ports)
|
|
44
41
|
});
|
|
45
42
|
this.commandSupervisor = deps?.commandSupervisor ?? new WorkspaceCommandSupervisor({
|
|
46
43
|
config: loadConveyorConfig(),
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rallycry/conveyor-agent",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.47",
|
|
4
4
|
"description": "Conveyor Agent Runner v10 - PTY harness for the task chat (SDK harness for audit/project-chat). Agent-as-User architecture with BaseService patterns. Works locally too.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
7
7
|
"claude",
|
|
8
|
-
"codespace",
|
|
9
8
|
"conveyor",
|
|
10
9
|
"v10"
|
|
11
10
|
],
|
|
@@ -39,7 +38,7 @@
|
|
|
39
38
|
},
|
|
40
39
|
"dependencies": {
|
|
41
40
|
"@anthropic-ai/claude-agent-sdk": "^0.3.284",
|
|
42
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
41
|
+
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
43
42
|
"node-pty": "^1.1.0",
|
|
44
43
|
"socket.io-client": "^4.8.4",
|
|
45
44
|
"tar": "^7.5.22",
|
|
@@ -71,7 +71,7 @@ mutation applied before the reply — is a stalled run, not a paused one.
|
|
|
71
71
|
4. Skip, and list under "deliberately not touched":
|
|
72
72
|
- rows with `parentTaskId` set — prune the pack parent; its children follow
|
|
73
73
|
the parent's disposition;
|
|
74
|
-
- rows with a non-null `codespaceStatus` — something is running on it;
|
|
74
|
+
- rows with a non-null `workspaceStatus` (`codespaceStatus` on older servers) — something is running on it;
|
|
75
75
|
- rows with a `githubPRUrl` — work exists; that is a review question, not
|
|
76
76
|
a prune question.
|
|
77
77
|
5. `mcp__conveyor__list_tags` once — the project's vocabulary, and whether a
|