@rallycry/conveyor-agent 11.0.44 → 11.0.46
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-5AZLXH5M.js} +2 -2
- package/dist/{chunk-42YPRICN.js → chunk-2SIMOUOD.js} +315 -47
- package/dist/{chunk-37J5MMQT.js → chunk-6CKFZ4JG.js} +1 -1
- package/dist/{chunk-4H75HQVM.js → chunk-A43UZ5RC.js} +2 -2
- package/dist/{chunk-KMBMW3J3.js → chunk-SKAFB6DG.js} +1280 -1502
- 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-TZZ45CJR.js → serve-boot-HRMFAX7H.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-6CKFZ4JG.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";
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
mapChatHistory,
|
|
3
3
|
readAgentVersion,
|
|
4
4
|
refreshSkillsAfterCheckout
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-6CKFZ4JG.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-SKAFB6DG.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,
|
|
@@ -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
|
|
@@ -9343,6 +9346,109 @@ var evaluateQuestionsContract = defineToolContract({
|
|
|
9343
9346
|
}
|
|
9344
9347
|
});
|
|
9345
9348
|
var evaluateContracts = [evaluateQuestionsContract];
|
|
9349
|
+
var listSiteAssetTargetsContract = defineToolContract({
|
|
9350
|
+
name: "list_site_asset_targets",
|
|
9351
|
+
agent: {
|
|
9352
|
+
description: "List the registered static-site media targets this card's project may publish to.",
|
|
9353
|
+
fields: {}
|
|
9354
|
+
},
|
|
9355
|
+
mcp: {
|
|
9356
|
+
description: "List registered static-site media targets for a project.",
|
|
9357
|
+
fields: { projectId: mcpProjectId }
|
|
9358
|
+
}
|
|
9359
|
+
});
|
|
9360
|
+
var uploadSiteAssetsContract = defineToolContract({
|
|
9361
|
+
name: "upload_site_assets",
|
|
9362
|
+
agent: {
|
|
9363
|
+
description: "Upload up to 50 workspace image or video files (25 MiB each) to a registered site using Conveyor identity. Call list_site_asset_targets first for the registered siteId. Returns verified immutable keys and public URLs per file.",
|
|
9364
|
+
fields: {
|
|
9365
|
+
siteId: f.string({ min: 1, max: 100 }),
|
|
9366
|
+
paths: f.array(f.string({ min: 1 }), { min: 1, max: 50 })
|
|
9367
|
+
}
|
|
9368
|
+
},
|
|
9369
|
+
mcp: {
|
|
9370
|
+
description: "Upload up to 50 workspace image or video files (25 MiB each) to a registered site using Conveyor identity. Call list_site_asset_targets first for the registered siteId. Returns verified immutable keys and public URLs per file.",
|
|
9371
|
+
fields: {
|
|
9372
|
+
projectId: mcpProjectId,
|
|
9373
|
+
siteId: f.string({ min: 1, max: 100 }),
|
|
9374
|
+
paths: f.array(f.string({ min: 1 }), { min: 1, max: 50 })
|
|
9375
|
+
}
|
|
9376
|
+
}
|
|
9377
|
+
});
|
|
9378
|
+
var siteAssetsContracts = [
|
|
9379
|
+
listSiteAssetTargetsContract,
|
|
9380
|
+
uploadSiteAssetsContract
|
|
9381
|
+
];
|
|
9382
|
+
function validateSiteAssetResult(value, expected) {
|
|
9383
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
9384
|
+
throw new Error("verify returned invalid JSON");
|
|
9385
|
+
const result = value;
|
|
9386
|
+
for (const key of ["key", "publicUrl", "sha256", "sizeBytes", "mimeType"]) {
|
|
9387
|
+
if (result[key] !== expected[key])
|
|
9388
|
+
throw new Error(`verify response ${key} does not match upload capability`);
|
|
9389
|
+
}
|
|
9390
|
+
if (result.status !== "uploaded" && result.status !== "existing")
|
|
9391
|
+
throw new Error("verify response has invalid status");
|
|
9392
|
+
return { ...expected, status: result.status };
|
|
9393
|
+
}
|
|
9394
|
+
async function readReply(response) {
|
|
9395
|
+
if (!response.body) throw new Error("verify returned an empty response");
|
|
9396
|
+
const reader = response.body.getReader();
|
|
9397
|
+
const decoder = new TextDecoder();
|
|
9398
|
+
let text = "";
|
|
9399
|
+
let size = 0;
|
|
9400
|
+
try {
|
|
9401
|
+
while (true) {
|
|
9402
|
+
const { done, value } = await reader.read();
|
|
9403
|
+
if (done) break;
|
|
9404
|
+
size += value.byteLength;
|
|
9405
|
+
if (size > 16384) throw new Error("verify response exceeds 16KiB");
|
|
9406
|
+
text += decoder.decode(value, { stream: true });
|
|
9407
|
+
}
|
|
9408
|
+
text += decoder.decode();
|
|
9409
|
+
} finally {
|
|
9410
|
+
await reader.cancel();
|
|
9411
|
+
reader.releaseLock();
|
|
9412
|
+
}
|
|
9413
|
+
try {
|
|
9414
|
+
return JSON.parse(text);
|
|
9415
|
+
} catch {
|
|
9416
|
+
throw new Error("verify returned invalid JSON");
|
|
9417
|
+
}
|
|
9418
|
+
}
|
|
9419
|
+
async function transferSiteAsset(capability, bytes, expected) {
|
|
9420
|
+
const options = {
|
|
9421
|
+
headers: capability.headers,
|
|
9422
|
+
redirect: "error",
|
|
9423
|
+
signal: AbortSignal.timeout(6e4)
|
|
9424
|
+
};
|
|
9425
|
+
let put;
|
|
9426
|
+
try {
|
|
9427
|
+
put = await fetch(capability.uploadUrl, { ...options, method: "PUT", body: bytes });
|
|
9428
|
+
} catch {
|
|
9429
|
+
throw new Error("Upload transfer failed or timed out; retry this file");
|
|
9430
|
+
}
|
|
9431
|
+
await put.body?.cancel();
|
|
9432
|
+
if (!put.ok) throw new Error(`upload HTTP ${put.status}; retry or check site access`);
|
|
9433
|
+
let verify;
|
|
9434
|
+
try {
|
|
9435
|
+
verify = await fetch(`${new URL(capability.uploadUrl).origin}/_site-assets/verify`, {
|
|
9436
|
+
...options,
|
|
9437
|
+
method: "POST",
|
|
9438
|
+
signal: AbortSignal.timeout(6e4)
|
|
9439
|
+
});
|
|
9440
|
+
} catch {
|
|
9441
|
+
throw new Error("Upload verification failed or timed out; retry this file");
|
|
9442
|
+
}
|
|
9443
|
+
if (!verify.ok) {
|
|
9444
|
+
await verify.body?.cancel();
|
|
9445
|
+
throw new Error(`verify HTTP ${verify.status}; retry or check site access`);
|
|
9446
|
+
}
|
|
9447
|
+
return {
|
|
9448
|
+
...validateSiteAssetResult(await readReply(verify), expected),
|
|
9449
|
+
status: put.status === 201 ? "uploaded" : "existing"
|
|
9450
|
+
};
|
|
9451
|
+
}
|
|
9346
9452
|
var TOOL_CONTRACTS = Object.fromEntries(
|
|
9347
9453
|
[
|
|
9348
9454
|
...tasksContracts,
|
|
@@ -9361,7 +9467,8 @@ var TOOL_CONTRACTS = Object.fromEntries(
|
|
|
9361
9467
|
...logsContracts,
|
|
9362
9468
|
...ciWaitContracts,
|
|
9363
9469
|
...evaluateContracts,
|
|
9364
|
-
...incidentsContracts
|
|
9470
|
+
...incidentsContracts,
|
|
9471
|
+
...siteAssetsContracts
|
|
9365
9472
|
].map((contract) => [contract.name, contract])
|
|
9366
9473
|
);
|
|
9367
9474
|
|
|
@@ -9407,6 +9514,97 @@ function formatCliEvent(e) {
|
|
|
9407
9514
|
return formatter ? formatter(e) : JSON.stringify(e);
|
|
9408
9515
|
}
|
|
9409
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
|
+
|
|
9410
9608
|
// src/tools/task-context-tools.ts
|
|
9411
9609
|
function buildReadTaskChatTool(connection) {
|
|
9412
9610
|
return defineContractTool(
|
|
@@ -9595,18 +9793,23 @@ function buildGetAttachmentTool(connection) {
|
|
|
9595
9793
|
const file = await connection.call("getTaskFile", {
|
|
9596
9794
|
sessionId: connection.sessionId,
|
|
9597
9795
|
fileId,
|
|
9598
|
-
...task_id ? { taskId: task_id } : {}
|
|
9796
|
+
...task_id ? { taskId: task_id } : {},
|
|
9797
|
+
agentDownload: true
|
|
9599
9798
|
});
|
|
9600
|
-
const { content: rawContent, ...metadata } = file;
|
|
9601
|
-
const content = [
|
|
9602
|
-
{ type: "text", text: JSON.stringify(metadata, null, 2) }
|
|
9603
|
-
];
|
|
9799
|
+
const { content: rawContent, agentDownloadUrl, ...metadata } = file;
|
|
9604
9800
|
if (rawContent && file.contentEncoding === "base64" && isImageMimeType(file.mimeType)) {
|
|
9605
|
-
|
|
9606
|
-
|
|
9607
|
-
|
|
9801
|
+
return {
|
|
9802
|
+
content: [
|
|
9803
|
+
{ type: "text", text: JSON.stringify(metadata, null, 2) },
|
|
9804
|
+
imageBlock(rawContent, file.mimeType)
|
|
9805
|
+
]
|
|
9806
|
+
};
|
|
9608
9807
|
}
|
|
9609
|
-
|
|
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));
|
|
9610
9813
|
} catch (error) {
|
|
9611
9814
|
return textResult(
|
|
9612
9815
|
`Failed to get task file: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
@@ -9616,6 +9819,26 @@ function buildGetAttachmentTool(connection) {
|
|
|
9616
9819
|
{ annotations: { readOnlyHint: true } }
|
|
9617
9820
|
);
|
|
9618
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
|
+
}
|
|
9619
9842
|
function buildTaskContextTools(connection) {
|
|
9620
9843
|
return [
|
|
9621
9844
|
buildReadTaskChatTool(connection),
|
|
@@ -10160,7 +10383,7 @@ function buildMutationTools(connection, config) {
|
|
|
10160
10383
|
}
|
|
10161
10384
|
|
|
10162
10385
|
// src/tools/attachment-tools.ts
|
|
10163
|
-
import { basename as
|
|
10386
|
+
import { basename as basename3, extname, isAbsolute, join as join18 } from "path";
|
|
10164
10387
|
var MIME_BY_EXT = {
|
|
10165
10388
|
".png": "image/png",
|
|
10166
10389
|
".jpg": "image/jpeg",
|
|
@@ -10239,7 +10462,7 @@ function buildUploadAttachmentTool(connection, config) {
|
|
|
10239
10462
|
async ({ path, title, comment, tags, showcase, supersedes }) => {
|
|
10240
10463
|
const caption = title ?? comment;
|
|
10241
10464
|
try {
|
|
10242
|
-
const filePath = isAbsolute(path) ? path :
|
|
10465
|
+
const filePath = isAbsolute(path) ? path : join18(config.workspaceDir, path);
|
|
10243
10466
|
const mimeType = inferMimeType(filePath);
|
|
10244
10467
|
const info = await statWorkspacePath(filePath);
|
|
10245
10468
|
if (!info.isFile) {
|
|
@@ -10250,7 +10473,7 @@ function buildUploadAttachmentTool(connection, config) {
|
|
|
10250
10473
|
`File is ${info.size} bytes \u2014 exceeds the ${MAX_FILE_SIZE_BYTES} byte (25MB) upload limit.`
|
|
10251
10474
|
);
|
|
10252
10475
|
}
|
|
10253
|
-
const fileName =
|
|
10476
|
+
const fileName = basename3(filePath);
|
|
10254
10477
|
const { fileId, uploadUrl } = await connection.call("requestFileUpload", {
|
|
10255
10478
|
sessionId: connection.sessionId,
|
|
10256
10479
|
fileName,
|
|
@@ -10899,7 +11122,7 @@ import { z as z9 } from "zod";
|
|
|
10899
11122
|
|
|
10900
11123
|
// src/execution/context-path-verifier.ts
|
|
10901
11124
|
import { readFile as readFile4 } from "fs/promises";
|
|
10902
|
-
import { isAbsolute as isAbsolute2, join as
|
|
11125
|
+
import { isAbsolute as isAbsolute2, join as join19, normalize } from "path";
|
|
10903
11126
|
var PROBLEM_TEXT = {
|
|
10904
11127
|
not_found: "does not exist in the repo",
|
|
10905
11128
|
expected_folder: "is a file, not a folder \u2014 use type 'file', 'rule', or 'doc'",
|
|
@@ -10944,7 +11167,7 @@ async function verifyContextPaths(links, workspaceDir) {
|
|
|
10944
11167
|
problems.push({ type: link.type, path: link.path, reason: shape });
|
|
10945
11168
|
continue;
|
|
10946
11169
|
}
|
|
10947
|
-
const absolutePath =
|
|
11170
|
+
const absolutePath = join19(workspaceDir, toRelativePath(link.path));
|
|
10948
11171
|
const stat = await statWorkspacePath(absolutePath);
|
|
10949
11172
|
const wantsDirectory = expectsDirectory(link.type);
|
|
10950
11173
|
if (!stat.exists) {
|
|
@@ -11893,8 +12116,60 @@ function buildEvaluateTools(connection, projectId) {
|
|
|
11893
12116
|
];
|
|
11894
12117
|
}
|
|
11895
12118
|
|
|
12119
|
+
// src/tools/site-asset-tools.ts
|
|
12120
|
+
import crypto from "crypto";
|
|
12121
|
+
import { extname as extname2, isAbsolute as isAbsolute3, join as join20 } from "path";
|
|
12122
|
+
var MAX_SITE_ASSET_BYTES = 25 * 1024 * 1024;
|
|
12123
|
+
function buildSiteAssetTools(connection, config, projectId) {
|
|
12124
|
+
const list = defineContractTool(listSiteAssetTargetsContract, async () => {
|
|
12125
|
+
try {
|
|
12126
|
+
return textResult(
|
|
12127
|
+
JSON.stringify(await connection.call("listSiteAssetTargets", { projectId }), null, 2)
|
|
12128
|
+
);
|
|
12129
|
+
} catch (error) {
|
|
12130
|
+
return textResult(
|
|
12131
|
+
`Failed to list static-site targets: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
12132
|
+
);
|
|
12133
|
+
}
|
|
12134
|
+
});
|
|
12135
|
+
const upload = defineContractTool(uploadSiteAssetsContract, async ({ siteId, paths }) => {
|
|
12136
|
+
const results = [];
|
|
12137
|
+
for (const requestedPath of [...paths].sort()) {
|
|
12138
|
+
const path = isAbsolute3(requestedPath) ? requestedPath : join20(config.workspaceDir, requestedPath);
|
|
12139
|
+
try {
|
|
12140
|
+
const info = await statWorkspacePath(path);
|
|
12141
|
+
if (!info.isFile) throw new Error("not a file");
|
|
12142
|
+
if (info.size > MAX_SITE_ASSET_BYTES) throw new Error("asset exceeds 25MiB limit");
|
|
12143
|
+
const bytes = await readWorkspaceBytes(path);
|
|
12144
|
+
if (bytes.length !== info.size || bytes.length > MAX_SITE_ASSET_BYTES)
|
|
12145
|
+
throw new Error("asset changed during read or exceeds 25MiB limit");
|
|
12146
|
+
const sha256 = crypto.createHash("sha256").update(bytes).digest("hex");
|
|
12147
|
+
const capability = await connection.call("requestSiteAssetUpload", {
|
|
12148
|
+
projectId,
|
|
12149
|
+
siteId,
|
|
12150
|
+
sha256,
|
|
12151
|
+
ext: extname2(path).slice(1).toLowerCase(),
|
|
12152
|
+
sizeBytes: bytes.length
|
|
12153
|
+
});
|
|
12154
|
+
const result = await transferSiteAsset(capability, new Uint8Array(bytes), {
|
|
12155
|
+
key: capability.key,
|
|
12156
|
+
publicUrl: capability.publicUrl,
|
|
12157
|
+
sha256,
|
|
12158
|
+
sizeBytes: bytes.length,
|
|
12159
|
+
mimeType: capability.headers["content-type"]
|
|
12160
|
+
});
|
|
12161
|
+
results.push({ path, ...result });
|
|
12162
|
+
} catch (error) {
|
|
12163
|
+
results.push({ path, error: error instanceof Error ? error.message : "Upload failed" });
|
|
12164
|
+
}
|
|
12165
|
+
}
|
|
12166
|
+
return textResult(JSON.stringify({ results }, null, 2));
|
|
12167
|
+
});
|
|
12168
|
+
return [list, upload];
|
|
12169
|
+
}
|
|
12170
|
+
|
|
11896
12171
|
// src/tools/connected-tools.ts
|
|
11897
|
-
function connectedToolsFor(connection, context) {
|
|
12172
|
+
function connectedToolsFor(connection, context, config) {
|
|
11898
12173
|
const projectId = context?.projectId;
|
|
11899
12174
|
if (!projectId) return [];
|
|
11900
12175
|
return [
|
|
@@ -11910,7 +12185,8 @@ function connectedToolsFor(connection, context) {
|
|
|
11910
12185
|
...buildEvaluateTools(connection, projectId),
|
|
11911
12186
|
...context.googleAnalyticsConfigured ? [buildAnalyticsSummaryTool(connection, projectId)] : [],
|
|
11912
12187
|
...context.gcpLogsConfigured ? [buildQueryGcpLogsTool(connection, projectId)] : [],
|
|
11913
|
-
...context.grafanaLogsConfigured ? [buildQueryGrafanaLogsTool(connection, projectId)] : []
|
|
12188
|
+
...context.grafanaLogsConfigured ? [buildQueryGrafanaLogsTool(connection, projectId)] : [],
|
|
12189
|
+
...config && context.siteAssetTargetsConfigured ? buildSiteAssetTools(connection, config, projectId) : []
|
|
11914
12190
|
];
|
|
11915
12191
|
}
|
|
11916
12192
|
|
|
@@ -12125,7 +12401,7 @@ function buildConveyorTools(connection, config, context, agentMode) {
|
|
|
12125
12401
|
const handoffTools = config.mode === "pm" && (effectiveMode === "discovery" || effectiveMode === "auto") ? [buildHandoffTool(connection)] : [];
|
|
12126
12402
|
const emergencyTools = [buildForceUpdateTaskStatusTool(connection)];
|
|
12127
12403
|
const glossaryTools = glossaryToolsFor(connection, config, context);
|
|
12128
|
-
const connectedTools = connectedToolsFor(connection, context);
|
|
12404
|
+
const connectedTools = connectedToolsFor(connection, context, config);
|
|
12129
12405
|
const isPack = config.mode === "pack" || Boolean(context?.isParentTask);
|
|
12130
12406
|
return withAlwaysLoad(
|
|
12131
12407
|
[
|
|
@@ -12709,7 +12985,7 @@ function fallbackResetIso(rateLimitType, now = Date.now()) {
|
|
|
12709
12985
|
}
|
|
12710
12986
|
|
|
12711
12987
|
// src/execution/tool-access.ts
|
|
12712
|
-
import { isAbsolute as
|
|
12988
|
+
import { isAbsolute as isAbsolute4, posix } from "path";
|
|
12713
12989
|
|
|
12714
12990
|
// src/execution/task-property-utils.ts
|
|
12715
12991
|
function collectMissingProps(taskProps) {
|
|
@@ -12855,7 +13131,7 @@ function isPlanFile(input) {
|
|
|
12855
13131
|
}
|
|
12856
13132
|
function isScratchPath(input) {
|
|
12857
13133
|
const filePath = String(input.file_path ?? input.path ?? "");
|
|
12858
|
-
if (!
|
|
13134
|
+
if (!isAbsolute4(filePath)) return false;
|
|
12859
13135
|
return posix.normalize(filePath).startsWith("/tmp/");
|
|
12860
13136
|
}
|
|
12861
13137
|
var ARTIFACT_DENIED = "Publish deliverables on the card with upload_attachment; the Artifact tool is not available in Conveyor sessions.";
|
|
@@ -13186,7 +13462,7 @@ function buildHooks(host) {
|
|
|
13186
13462
|
};
|
|
13187
13463
|
}
|
|
13188
13464
|
function taskIdToSessionUuid(lineageKey) {
|
|
13189
|
-
const hash =
|
|
13465
|
+
const hash = createHash5("sha256").update(lineageKey).digest("hex");
|
|
13190
13466
|
return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-8${hash.slice(13, 16)}-a${hash.slice(17, 20)}-${hash.slice(20, 32)}`;
|
|
13191
13467
|
}
|
|
13192
13468
|
function sessionLineageKey(taskId, agentMode, runnerMode) {
|
|
@@ -13323,12 +13599,6 @@ function buildQueryOptions(host, context) {
|
|
|
13323
13599
|
context,
|
|
13324
13600
|
{
|
|
13325
13601
|
...host.config,
|
|
13326
|
-
// ModeController's live value, NOT the boot-frozen `config.isAuto` the
|
|
13327
|
-
// spread carries: the pack gate reads this, and the turn prompt below
|
|
13328
|
-
// gates on `host.isAuto`. Letting the two read different sources is how
|
|
13329
|
-
// a codespace parent card got "you cannot write or edit files" beside
|
|
13330
|
-
// "run /conveyor-build".
|
|
13331
|
-
isAuto: host.isAuto,
|
|
13332
13602
|
runtimeTui: process.env.CONVEYOR_TUI
|
|
13333
13603
|
},
|
|
13334
13604
|
host.setupLog,
|
|
@@ -13800,7 +14070,7 @@ function freshSessionOptions(host, context, options) {
|
|
|
13800
14070
|
markSpawnedTranscript(host.config.workspaceDir, lineageUuid);
|
|
13801
14071
|
return { ...options, sessionId: lineageUuid };
|
|
13802
14072
|
}
|
|
13803
|
-
return { ...options, sessionId:
|
|
14073
|
+
return { ...options, sessionId: randomUUID3() };
|
|
13804
14074
|
}
|
|
13805
14075
|
async function buildRetryQuery(host, context, options, lastErrorWasImage) {
|
|
13806
14076
|
if (lastErrorWasImage) {
|
|
@@ -15067,11 +15337,9 @@ var SessionRunner = class _SessionRunner {
|
|
|
15067
15337
|
this.config = config;
|
|
15068
15338
|
this.callbacks = callbacks;
|
|
15069
15339
|
this.connection = new AgentConnection(config.connection);
|
|
15070
|
-
const portVisibility = new CodespacePortVisibility();
|
|
15071
15340
|
this.portDiscovery = deps.portDiscovery ?? new PortDiscovery({
|
|
15072
15341
|
report: (ports) => this.connection.reportDiscoveredPorts(ports),
|
|
15073
|
-
annotate: (ports) => loadAndAnnotateDiscoveredPorts(config.workspaceDir, ports)
|
|
15074
|
-
onReported: (ports) => portVisibility.ensureVisible(ports.map(({ port }) => port))
|
|
15342
|
+
annotate: (ports) => loadAndAnnotateDiscoveredPorts(config.workspaceDir, ports)
|
|
15075
15343
|
});
|
|
15076
15344
|
const initialMode = config.agentMode ?? (config.runnerMode === "pm" ? config.isAuto ? "auto" : "discovery" : "building");
|
|
15077
15345
|
this.mode = new ModeController(initialMode, config.runnerMode, config.isAuto);
|
|
@@ -15404,7 +15672,6 @@ var SessionRunner = class _SessionRunner {
|
|
|
15404
15672
|
await this.setState("connected");
|
|
15405
15673
|
this.connection.sendEvent({ type: "connected", sessionId: this.sessionId });
|
|
15406
15674
|
this.wireConnectionCallbacks();
|
|
15407
|
-
registerBootMilestoneSocketFallback((key) => this.connection.reportBootMilestone(key));
|
|
15408
15675
|
this.lifecycle.startHeartbeat();
|
|
15409
15676
|
this.loopLag.start();
|
|
15410
15677
|
this.connection.startHeartbeatWorker(this.loopLag.sharedBuffer);
|
|
@@ -16189,6 +16456,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
16189
16456
|
baseBranch: ctx.baseBranch ?? "",
|
|
16190
16457
|
projectName: ctx.projectName ?? null,
|
|
16191
16458
|
projectDescription: ctx.projectDescription ?? null,
|
|
16459
|
+
siteAssetTargetsConfigured: ctx.siteAssetTargetsConfigured ?? false,
|
|
16192
16460
|
githubPRUrl: ctx.githubPRUrl,
|
|
16193
16461
|
claudeSessionId: ctx.claudeSessionId ?? null,
|
|
16194
16462
|
lastSeenMessageId: ctx.lastSeenMessageId ?? null,
|
|
@@ -16585,7 +16853,7 @@ ${outcome.failures.join("\n")}
|
|
|
16585
16853
|
}
|
|
16586
16854
|
};
|
|
16587
16855
|
|
|
16588
|
-
// src/setup/
|
|
16856
|
+
// src/setup/unshallow.ts
|
|
16589
16857
|
import { execSync } from "child_process";
|
|
16590
16858
|
function unshallowRepo(workspaceDir) {
|
|
16591
16859
|
try {
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
readWorkspaceBytes,
|
|
9
9
|
statWorkspacePath,
|
|
10
10
|
workspacePathExists
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-SKAFB6DG.js";
|
|
12
12
|
import {
|
|
13
13
|
reportBootMilestone
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-VIUZS7V4.js";
|
|
15
15
|
import {
|
|
16
16
|
runSetupCommand,
|
|
17
17
|
runStartCommand,
|