@rallycry/conveyor-agent 11.0.26 → 11.0.28
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/{chunk-7WO6NTOS.js → chunk-DMTBXIA4.js} +1 -1
- package/dist/{chunk-BZZ4B37Q.js → chunk-GHNYP67H.js} +797 -663
- package/dist/{chunk-4L22UNZD.js → chunk-ND5INHM4.js} +239 -145
- package/dist/cli.js +4 -4
- package/dist/index.js +2 -2
- package/dist/{serve-boot-T7MNWASE.js → serve-boot-CYVW7Z27.js} +2 -2
- package/package.json +1 -1
- package/skills/conveyor-build/SKILL.md +19 -13
- package/skills/conveyor-consensus/SKILL.md +4 -3
- package/skills/conveyor-plan/SKILL.md +4 -0
- package/skills/conveyor-plan/references/plan-format.md +7 -3
- package/skills/conveyor-prune/SKILL.md +181 -0
- package/skills/conveyor-triage/SKILL.md +3 -1
- package/skills/conveyor-workflows/SKILL.md +8 -5
|
@@ -47,13 +47,14 @@ import {
|
|
|
47
47
|
Lifecycle,
|
|
48
48
|
MAX_CI_WAIT_TIMEOUT_MINUTES,
|
|
49
49
|
MAX_FILE_SIZE_BYTES,
|
|
50
|
+
MAX_MANUAL_TESTS_PER_TASK,
|
|
51
|
+
MAX_MANUAL_TEST_TITLE_LENGTH,
|
|
50
52
|
PM_CHAT_HISTORY_LIMIT,
|
|
51
53
|
PRE_BUILD_TASK_STATUSES,
|
|
52
54
|
PTY_STREAM_PORT_ATTEMPTS,
|
|
53
55
|
PTY_STREAM_PORT_BASE,
|
|
54
56
|
PortDiscovery,
|
|
55
57
|
PtyStreamFrameReader,
|
|
56
|
-
ReviewGuideContentSchema,
|
|
57
58
|
SEVERITY_ENUM,
|
|
58
59
|
TAG_DESCRIPTION_MAX,
|
|
59
60
|
TAG_OVERVIEW_MAX,
|
|
@@ -63,17 +64,20 @@ import {
|
|
|
63
64
|
awaitGitReady,
|
|
64
65
|
clearForceFreshCooldown,
|
|
65
66
|
createServiceLogger,
|
|
67
|
+
describeManualTestRejection,
|
|
66
68
|
encodePtyStreamFrame,
|
|
67
69
|
ensureOnTaskBranch,
|
|
68
70
|
flushAllPendingWork,
|
|
69
71
|
flushPendingChanges,
|
|
70
72
|
forceFreshCooldownNotice,
|
|
71
73
|
forceFreshMintBlocked,
|
|
74
|
+
formatEvaluateQuestionsResult,
|
|
72
75
|
getCurrentBranch,
|
|
73
76
|
git,
|
|
74
77
|
hasTaskPlan,
|
|
75
78
|
hasUncommittedChanges,
|
|
76
79
|
hasUnpushedCommits,
|
|
80
|
+
isCapabilityServableMime,
|
|
77
81
|
isCodexReasoningEffort,
|
|
78
82
|
isPlaceholderLocator,
|
|
79
83
|
locatorMatchesContent,
|
|
@@ -91,7 +95,7 @@ import {
|
|
|
91
95
|
statWorkspacePath,
|
|
92
96
|
updateRemoteToken,
|
|
93
97
|
verifyGitCredential
|
|
94
|
-
} from "./chunk-
|
|
98
|
+
} from "./chunk-GHNYP67H.js";
|
|
95
99
|
import {
|
|
96
100
|
registerBootMilestoneSocketFallback,
|
|
97
101
|
reportBootMilestone
|
|
@@ -5440,6 +5444,20 @@ function formatChatFile(file) {
|
|
|
5440
5444
|
}
|
|
5441
5445
|
return [`[Attached: ${file.fileName} (${file.mimeType}${sizeStr})]`];
|
|
5442
5446
|
}
|
|
5447
|
+
function formatParentTaskFiles(parent) {
|
|
5448
|
+
const lines = [
|
|
5449
|
+
`
|
|
5450
|
+
## Files on the parent card ${parent.slug}`,
|
|
5451
|
+
`These are attached to the parent card "${parent.title}", not to this one. Read one with get_attachment(fileId, task_id: "${parent.slug}"); list_task_files(task_id: "${parent.slug}") shows the current set.`
|
|
5452
|
+
];
|
|
5453
|
+
for (const file of parent.files) {
|
|
5454
|
+
const size = formatFileSize(file.fileSize);
|
|
5455
|
+
lines.push(
|
|
5456
|
+
`- **${file.fileName}** (${file.mimeType}${size ? `, ${size}` : ""}) fileId: ${file.fileId}`
|
|
5457
|
+
);
|
|
5458
|
+
}
|
|
5459
|
+
return lines;
|
|
5460
|
+
}
|
|
5443
5461
|
function formatTaskFile(file) {
|
|
5444
5462
|
if (file.content && file.contentEncoding === "utf-8") {
|
|
5445
5463
|
return [`
|
|
@@ -5792,7 +5810,7 @@ var PACK_RUNNER_FOOTER = [
|
|
|
5792
5810
|
``,
|
|
5793
5811
|
`Your turn output appears ONLY in the live agent terminal \u2014 it is NOT posted to the task chat. The team does NOT see your replies unless you post them.`,
|
|
5794
5812
|
`Use post_to_chat (omit task_id \u2192 this task's chat) to report which child you are on, status as you work the pack, and any blocker or escalation the team needs to act on.`,
|
|
5795
|
-
`Pass task_id only to
|
|
5813
|
+
`Pass task_id only to reach a DIFFERENT card: a child task's chat on post_to_chat and read_task_chat, or a child's files on list_task_files and get_attachment.`,
|
|
5796
5814
|
`Use read_task_chat only if you need to re-read earlier messages beyond the chat context above.`,
|
|
5797
5815
|
``,
|
|
5798
5816
|
`If a Conveyor tool call fails or reports the MCP server is unavailable/disconnected, this is almost always a transient socket reconnect \u2014 RETRY the same call; it will succeed once the connection re-establishes. A tool error is NOT a reason to go idle or stop the pack. (When a turn may end is the pack path's call \u2014 see its goal and finish line.)`,
|
|
@@ -6395,7 +6413,7 @@ ${context.agentInstructions}`);
|
|
|
6395
6413
|
Your turn output appears ONLY in the live agent terminal \u2014 it is NOT posted to the task chat. The team does NOT see your replies unless you post them.`,
|
|
6396
6414
|
`Use post_to_chat (omit task_id \u2192 your own task's chat) to share meaningful status as you work, a summary when you finish, and any blocker or question you need a human to answer.`,
|
|
6397
6415
|
`A question you need answered goes through AskUserQuestion \u2014 that is what pages a person. post_to_chat with milestone: "blocked" records that you are parked and does not page anyone.`,
|
|
6398
|
-
`Pass task_id only to
|
|
6416
|
+
`Pass task_id only to reach a DIFFERENT card: a child task's chat on post_to_chat and read_task_chat, or any card in this project's files on list_task_files and get_attachment (a pack parent's source documents, for example). Omit it for your own card.`,
|
|
6399
6417
|
`Use read_task_chat only if you need to re-read earlier messages beyond the chat context above.`,
|
|
6400
6418
|
`
|
|
6401
6419
|
If a Conveyor tool call fails or reports the MCP server is unavailable/disconnected, this is almost always a transient socket reconnect \u2014 simply RETRY the same call and it will succeed once the connection re-establishes. Do NOT stop work, go idle, or treat a tool error as a reason to end your turn. Keep making progress on the code; only post_to_chat to ask for a human if a tool keeps failing across several retries over a sustained period.`,
|
|
@@ -6570,6 +6588,9 @@ ${truncatePlanForPrompt(context.plan)}`);
|
|
|
6570
6588
|
parts.push(...formatTaskFile(file));
|
|
6571
6589
|
}
|
|
6572
6590
|
}
|
|
6591
|
+
if (context.parentTaskFiles && context.parentTaskFiles.files.length > 0) {
|
|
6592
|
+
parts.push(...formatParentTaskFiles(context.parentTaskFiles));
|
|
6593
|
+
}
|
|
6573
6594
|
if (context.repoRefs && context.repoRefs.length > 0) {
|
|
6574
6595
|
parts.push(...formatRepoRefs(context.repoRefs));
|
|
6575
6596
|
}
|
|
@@ -6730,6 +6751,7 @@ function compileNumber(z11, spec) {
|
|
|
6730
6751
|
function compileArray(z11, spec) {
|
|
6731
6752
|
let schema = z11.array(compileField(z11, spec.item));
|
|
6732
6753
|
if (spec.min !== void 0) schema = schema.min(spec.min);
|
|
6754
|
+
if (spec.max !== void 0) schema = schema.max(spec.max);
|
|
6733
6755
|
return schema;
|
|
6734
6756
|
}
|
|
6735
6757
|
function compileBase(z11, spec) {
|
|
@@ -6859,16 +6881,24 @@ var readTaskChatContract = defineToolContract({
|
|
|
6859
6881
|
}
|
|
6860
6882
|
}
|
|
6861
6883
|
});
|
|
6884
|
+
var listTagsDetail = f.optional(
|
|
6885
|
+
f.enum(["summary", "full"], {
|
|
6886
|
+
desc: `"summary" (default) returns one compact row per tag with a contextPathCount. "full" also ships each tag's contextPaths inline (each link with its verification status). Full mode can exceed a client's tool-output budget on a large glossary; use get_tag for one term instead.`
|
|
6887
|
+
})
|
|
6888
|
+
);
|
|
6862
6889
|
var listTagsContract = defineToolContract({
|
|
6863
6890
|
name: "list_tags",
|
|
6864
6891
|
agent: {
|
|
6865
|
-
description: "List the project glossary
|
|
6866
|
-
fields: {
|
|
6892
|
+
description: "List the whole project glossary in one call. The default summary gives every tag's id, name, color, description, parent/child tag ids, whether it carries a full overview (hasOverview), its attachmentCount (files labelled as examples of the term), and its contextPathCount (the rule/doc/file/folder links it wires into agent context \u2014 `0` means none). Pass detail: \"full\" to ship the contextPaths themselves inline. Use get_tag for one term's full overview and full link verification. Use the ids with get_tag / update_tag.",
|
|
6893
|
+
fields: {
|
|
6894
|
+
detail: listTagsDetail
|
|
6895
|
+
}
|
|
6867
6896
|
},
|
|
6868
6897
|
mcp: {
|
|
6869
|
-
description:
|
|
6898
|
+
description: 'List all project tags in one call. The default summary gives names, IDs, colors, descriptions, hierarchy (parent/child ids), a hasOverview flag, an attachmentCount (files labelled as examples of the term \u2014 read the tiles with list_tag_attachments), and a contextPathCount (the rule/doc/file/folder links each tag wires into agent context \u2014 `0` means none). Pass detail: "full" to ship the contextPaths themselves inline. Call get_tag for one term\'s full overview and full link verification. Pass projectId to target a specific project; otherwise the configured default project is used.',
|
|
6870
6899
|
fields: {
|
|
6871
|
-
projectId: mcpProjectId
|
|
6900
|
+
projectId: mcpProjectId,
|
|
6901
|
+
detail: listTagsDetail
|
|
6872
6902
|
}
|
|
6873
6903
|
}
|
|
6874
6904
|
});
|
|
@@ -7004,7 +7034,7 @@ var updateTaskContract = defineToolContract({
|
|
|
7004
7034
|
}
|
|
7005
7035
|
},
|
|
7006
7036
|
mcp: {
|
|
7007
|
-
description: "Update task fields: title, description, plan, status, risk, story points, assignment, githubBranch, or tags. Set status to claim a card (InProgress), triage it (Open), or cancel it (Cancelled); for review approvals prefer approve_task / request_changes, which guard against stale-state races. Tags are additive/subtractive \u2014 pass addTags/removeTags with tag names (not a replace-set). Pass projectId to target a specific project; otherwise the configured default project is used. Moving a task beyond Planning auto-fills any missing icon, story points, and agent assignment \u2014 don't spend turns on them; pass storyPointValue only to correct the sizing yourself. For subtasks use update_subtask.",
|
|
7037
|
+
description: "Update task fields: title, description, plan, status, risk, story points, assignment, githubBranch, onHold, or tags. Set status to claim a card (InProgress), triage it (Open), or cancel it (Cancelled); for review approvals prefer approve_task / request_changes, which guard against stale-state races. Set onHold to park a card (true) or bring it back to the active board (false) without cancelling it. Tags are additive/subtractive \u2014 pass addTags/removeTags with tag names (not a replace-set). Pass projectId to target a specific project; otherwise the configured default project is used. Moving a task beyond Planning auto-fills any missing icon, story points, and agent assignment \u2014 don't spend turns on them; pass storyPointValue only to correct the sizing yourself. For subtasks use update_subtask.",
|
|
7008
7038
|
fields: {
|
|
7009
7039
|
projectId: mcpProjectId,
|
|
7010
7040
|
taskId: f.string({ desc: "The task ID" }),
|
|
@@ -7035,6 +7065,11 @@ var updateTaskContract = defineToolContract({
|
|
|
7035
7065
|
)
|
|
7036
7066
|
),
|
|
7037
7067
|
githubBranch: f.optional(f.nullable(f.string({ desc: GITHUB_BRANCH_DESC }))),
|
|
7068
|
+
onHold: f.optional(
|
|
7069
|
+
f.boolean({
|
|
7070
|
+
desc: "Park the card on hold (true) or return it to the active board (false). On hold hides the card from the active columns without cancelling it; a card already at an active work status is demoted to Open when parked."
|
|
7071
|
+
})
|
|
7072
|
+
),
|
|
7038
7073
|
addTags: f.optional(
|
|
7039
7074
|
f.array(f.string(), {
|
|
7040
7075
|
desc: 'Tag names to add to the card (e.g. ["refactor"]). Additive \u2014 existing tags are kept. Unknown names are rejected; use list_tags to see available tags or manage_tags to create one.'
|
|
@@ -7078,9 +7113,20 @@ var testStatuses = f.optional(
|
|
|
7078
7113
|
})
|
|
7079
7114
|
);
|
|
7080
7115
|
var setManualTestItems = f.array(
|
|
7081
|
-
f.object({
|
|
7082
|
-
|
|
7116
|
+
f.object({
|
|
7117
|
+
title: f.string({
|
|
7118
|
+
min: 1,
|
|
7119
|
+
max: MAX_MANUAL_TEST_TITLE_LENGTH,
|
|
7120
|
+
desc: "One sentence a non-engineer can follow: where to go, what to do, what they should see. No commands, no code."
|
|
7121
|
+
})
|
|
7122
|
+
}),
|
|
7123
|
+
{
|
|
7124
|
+
min: 1,
|
|
7125
|
+
max: MAX_MANUAL_TESTS_PER_TASK,
|
|
7126
|
+
desc: `Manual tests to add. A card holds at most ${MAX_MANUAL_TESTS_PER_TASK}; most changes need 1, and a change with no user-visible behavior needs none.`
|
|
7127
|
+
}
|
|
7083
7128
|
);
|
|
7129
|
+
var setManualTestsBar = 'A manual test is a real user path in plain language ("Open a card with a PR: the Pull Request slat sits directly under Description"), not an engineering check. Never record lint, typecheck, unit tests, CI, curl, database, log, or deploy steps; those run automatically. Record at most 5 per card, usually 1, and none when the change has no user-visible behavior. Existing items with the same title are skipped; items that name an automated step or exceed the cap are rejected and reported back.';
|
|
7084
7130
|
var titleToEdit = f.string({ min: 1, desc: "The current title of the manual test to edit" });
|
|
7085
7131
|
var newTitle = f.string({ min: 1, desc: "The new title for the manual test" });
|
|
7086
7132
|
var titleToRemove = f.string({ min: 1, desc: "The title of the manual test to remove" });
|
|
@@ -7134,13 +7180,13 @@ var queryManualTestsContract = defineToolContract({
|
|
|
7134
7180
|
var setManualTestsContract = defineToolContract({
|
|
7135
7181
|
name: "set_manual_tests",
|
|
7136
7182
|
agent: {
|
|
7137
|
-
description:
|
|
7183
|
+
description: `Record the manual tests a person should run in the app to sign off on this card. ${setManualTestsBar}`,
|
|
7138
7184
|
fields: {
|
|
7139
7185
|
items: setManualTestItems
|
|
7140
7186
|
}
|
|
7141
7187
|
},
|
|
7142
7188
|
mcp: {
|
|
7143
|
-
description:
|
|
7189
|
+
description: `Record the manual tests a person should run in the app to sign off on a card. Pass projectId to target a specific project; otherwise the configured default project is used. ${setManualTestsBar}`,
|
|
7144
7190
|
fields: {
|
|
7145
7191
|
projectId: mcpProjectId,
|
|
7146
7192
|
taskId: mcpChecklistTaskId,
|
|
@@ -7463,11 +7509,18 @@ var subtasksContracts = [
|
|
|
7463
7509
|
setTaskParentContract
|
|
7464
7510
|
];
|
|
7465
7511
|
var mcpTaskIdOrSlug = f.string({ desc: "The task ID or slug" });
|
|
7512
|
+
var agentTaskIdOrSlug = f.optional(
|
|
7513
|
+
f.string({
|
|
7514
|
+
desc: "Omit for the current card; pass a parent, sibling, or any other card in this project (id or slug) to read its files instead."
|
|
7515
|
+
})
|
|
7516
|
+
);
|
|
7466
7517
|
var listTaskFilesContract = defineToolContract({
|
|
7467
7518
|
name: "list_task_files",
|
|
7468
7519
|
agent: {
|
|
7469
|
-
description: "List all files attached to this task with metadata. Use before fetching a specific file to see what is available and how large each is. For file contents use get_attachment.",
|
|
7470
|
-
fields: {
|
|
7520
|
+
description: "List all files attached to this task with metadata. Use before fetching a specific file to see what is available and how large each is. For file contents use get_attachment. Pass task_id to list another card's files in this project, for example the pack parent's source documents.",
|
|
7521
|
+
fields: {
|
|
7522
|
+
task_id: agentTaskIdOrSlug
|
|
7523
|
+
}
|
|
7471
7524
|
},
|
|
7472
7525
|
mcp: {
|
|
7473
7526
|
description: "List all files attached to a task with metadata (no contents \u2014 fast and small). Pass projectId to target a specific project; otherwise the configured default project is used. Use before fetching a specific file to see what is available and how large each is. For file contents use get_attachment.",
|
|
@@ -7480,13 +7533,14 @@ var listTaskFilesContract = defineToolContract({
|
|
|
7480
7533
|
var getAttachmentContract = defineToolContract({
|
|
7481
7534
|
name: "get_attachment",
|
|
7482
7535
|
agent: {
|
|
7483
|
-
description: "Fetch one task file's content plus metadata by file ID. Call list_task_files first to discover IDs and check sizes \u2014 large binaries may be truncated by the service's size limit.",
|
|
7536
|
+
description: "Fetch one task file's content plus metadata by file ID. This is the way to read attachment bytes: a document `downloadUrl` (anything that is not an image or video) answers 404 without a signed-in project member's session, so do not curl or WebFetch it from the pod. Call list_task_files first to discover IDs and check sizes \u2014 large binaries may be truncated by the service's size limit. Pass task_id when the file is attached to another card in this project, such as the pack parent.",
|
|
7484
7537
|
fields: {
|
|
7485
|
-
fileId: f.string({ desc: "The file ID to retrieve" })
|
|
7538
|
+
fileId: f.string({ desc: "The file ID to retrieve" }),
|
|
7539
|
+
task_id: agentTaskIdOrSlug
|
|
7486
7540
|
}
|
|
7487
7541
|
},
|
|
7488
7542
|
mcp: {
|
|
7489
|
-
description: "Fetch one task file's content plus metadata by file ID (accepts task id or slug). Pass projectId to target a specific project; otherwise the configured default project is used. Images are returned as viewable image blocks. Large text files (logs, JSON) are returned in pages \u2014 use `offset`/`maxBytes` to read more
|
|
7543
|
+
description: "Fetch one task file's content plus metadata by file ID (accepts task id or slug). Pass projectId to target a specific project; otherwise the configured default project is used. Images are returned as viewable image blocks. Large text files (logs, JSON) are returned in pages \u2014 use `offset`/`maxBytes` to read more. This tool is the way to read bytes: a document `downloadUrl` (anything that is not an image or video) answers 404 unless the request carries a signed-in project member's session, so do not curl or fetch it. Call list_task_files first to discover IDs and sizes.",
|
|
7490
7544
|
fields: {
|
|
7491
7545
|
projectId: mcpProjectId,
|
|
7492
7546
|
taskId: mcpTaskIdOrSlug,
|
|
@@ -7553,10 +7607,29 @@ var uploadAttachmentContract = defineToolContract({
|
|
|
7553
7607
|
}
|
|
7554
7608
|
}
|
|
7555
7609
|
});
|
|
7610
|
+
var DELETE_ATTACHMENT_WARNING = "Permanent, with no trash and no undo (unlike drive_delete_file): the file and its bytes are gone, and the chat message that announced it keeps its text but loses the attachment. Use it to remove a superseded upload once its replacement is attached. `fileId` comes from list_task_files.";
|
|
7611
|
+
var deleteAttachmentContract = defineToolContract({
|
|
7612
|
+
name: "delete_attachment",
|
|
7613
|
+
agent: {
|
|
7614
|
+
description: `Delete one attachment from this task. ${DELETE_ATTACHMENT_WARNING} A pod can only delete files on its own card.`,
|
|
7615
|
+
fields: {
|
|
7616
|
+
fileId: f.string({ desc: "The file ID to delete" })
|
|
7617
|
+
}
|
|
7618
|
+
},
|
|
7619
|
+
mcp: {
|
|
7620
|
+
description: `Delete one attachment from a task (accepts task id or slug). ${DELETE_ATTACHMENT_WARNING} Requires Moderate on the project, the same bar as the web Files delete button. Pass projectId to target a specific project; otherwise the configured default project is used.`,
|
|
7621
|
+
fields: {
|
|
7622
|
+
projectId: mcpProjectId,
|
|
7623
|
+
taskId: mcpTaskIdOrSlug,
|
|
7624
|
+
fileId: f.string({ desc: "The file ID to delete" })
|
|
7625
|
+
}
|
|
7626
|
+
}
|
|
7627
|
+
});
|
|
7556
7628
|
var attachmentsContracts = [
|
|
7557
7629
|
listTaskFilesContract,
|
|
7558
7630
|
getAttachmentContract,
|
|
7559
|
-
uploadAttachmentContract
|
|
7631
|
+
uploadAttachmentContract,
|
|
7632
|
+
deleteAttachmentContract
|
|
7560
7633
|
];
|
|
7561
7634
|
var createSuggestionContract = defineToolContract({
|
|
7562
7635
|
name: "create_suggestion",
|
|
@@ -7879,7 +7952,7 @@ var createPullRequestContract = defineToolContract({
|
|
|
7879
7952
|
fields: {
|
|
7880
7953
|
title: f.string({ desc: "The PR title" }),
|
|
7881
7954
|
body: f.string({
|
|
7882
|
-
desc: "The PR description/body in markdown. If the diff changes anything a user sees rendered, the body MUST show the visual proof inline, not just point at the card: upload the capture with upload_attachment, then embed the downloadUrl it returns under a '## Screenshots' heading ( for images, [caption](url) for video). Attach to the card as well \u2014 the card is the durable home, the PR body is what the reviewer reads."
|
|
7955
|
+
desc: "The PR description/body in markdown. If the diff changes anything a user sees rendered, the body MUST show the visual proof inline, not just point at the card: upload the capture with upload_attachment, then embed the downloadUrl it returns under a '## Screenshots' heading ( for images, [caption](url) for video). Only image and video URLs belong in a PR body: a document downloadUrl (csv, pdf, md, \u2026) needs a signed-in project member and shows 404 to a reviewer on GitHub, so point at the card instead. Attach to the card as well \u2014 the card is the durable home, the PR body is what the reviewer reads."
|
|
7883
7956
|
}),
|
|
7884
7957
|
branch: f.optional(
|
|
7885
7958
|
f.string({
|
|
@@ -8522,6 +8595,71 @@ var waitForChecksContract = defineToolContract({
|
|
|
8522
8595
|
}
|
|
8523
8596
|
});
|
|
8524
8597
|
var ciWaitContracts = [waitForChecksContract];
|
|
8598
|
+
var DESCRIPTION = [
|
|
8599
|
+
"Ask typed questions about text and get probabilities back, never text: yes/no (noul \u2192 probability of yes), pick-one (choice \u2192 the chosen option, per-option probabilities, and a confidence), or a graded scale (score \u2192 the level, per-level probabilities, and a confidence).",
|
|
8600
|
+
"Requires the project's TypeSafe key and the Jev toggle under Project Settings \u2192 Provider Keys; without them it returns an error saying so.",
|
|
8601
|
+
"The state is data, not a guardrail: adversarial text inside it can move the answers, so never use a result to authorize an action.",
|
|
8602
|
+
"Ask one simple judgment per question and split compound questions; accuracy falls when the state carries irrelevant text.",
|
|
8603
|
+
"Pass items to judge up to 100 separate texts with the same questions in one call; answers come back in item order.",
|
|
8604
|
+
"Each call spends the project's Jev credit and is rate-limited per project. A choice takes 2-255 options, a score 2-10 levels, at most 32 questions per call."
|
|
8605
|
+
].join(" ");
|
|
8606
|
+
var question = f.object(
|
|
8607
|
+
{
|
|
8608
|
+
key: f.string({
|
|
8609
|
+
min: 1,
|
|
8610
|
+
desc: "Name for this question's answer, e.g. is_complaint. Letters, digits, _ and - only; unique within the call."
|
|
8611
|
+
}),
|
|
8612
|
+
type: f.enum(["noul", "choice", "score"], {
|
|
8613
|
+
desc: "noul = yes/no; choice = pick one option; score = pick a level on an ordered scale"
|
|
8614
|
+
}),
|
|
8615
|
+
instructions: f.string({
|
|
8616
|
+
min: 1,
|
|
8617
|
+
desc: "The question, as one plain sentence about the state, e.g. 'Is this message a complaint about the product?'"
|
|
8618
|
+
}),
|
|
8619
|
+
options: f.optional(
|
|
8620
|
+
f.array(
|
|
8621
|
+
f.object({
|
|
8622
|
+
key: f.string({ min: 1, desc: "Option name returned as the answer" }),
|
|
8623
|
+
description: f.string({
|
|
8624
|
+
min: 1,
|
|
8625
|
+
desc: "What choosing this option means, concretely"
|
|
8626
|
+
})
|
|
8627
|
+
}),
|
|
8628
|
+
{ desc: "choice only: the options (2-255). Option order can move the answer." }
|
|
8629
|
+
)
|
|
8630
|
+
),
|
|
8631
|
+
levels: f.optional(
|
|
8632
|
+
f.array(f.string({ min: 1 }), {
|
|
8633
|
+
desc: "score only: 2-10 level descriptions, lowest first"
|
|
8634
|
+
})
|
|
8635
|
+
)
|
|
8636
|
+
},
|
|
8637
|
+
{ desc: "One typed question" }
|
|
8638
|
+
);
|
|
8639
|
+
var stateDesc = "The thing being judged, as plain text or JSON. Required unless items is given; with items it is ignored.";
|
|
8640
|
+
var itemsDesc = "Up to 100 separate texts (each up to 8,000 characters), each judged on its own with the same questions. Use this for bulk classification instead of one call per item.";
|
|
8641
|
+
var questionsDesc = "1-32 questions, all answered independently against the same state.";
|
|
8642
|
+
var evaluateQuestionsContract = defineToolContract({
|
|
8643
|
+
name: "evaluate_questions",
|
|
8644
|
+
agent: {
|
|
8645
|
+
description: DESCRIPTION,
|
|
8646
|
+
fields: {
|
|
8647
|
+
state: f.optional(f.string({ desc: stateDesc })),
|
|
8648
|
+
questions: f.array(question, { min: 1, desc: questionsDesc }),
|
|
8649
|
+
items: f.optional(f.array(f.string(), { desc: itemsDesc }))
|
|
8650
|
+
}
|
|
8651
|
+
},
|
|
8652
|
+
mcp: {
|
|
8653
|
+
description: `${DESCRIPTION} Pass projectId to target a specific project; otherwise the configured default project is used.`,
|
|
8654
|
+
fields: {
|
|
8655
|
+
projectId: mcpProjectId,
|
|
8656
|
+
state: f.optional(f.string({ desc: stateDesc })),
|
|
8657
|
+
questions: f.array(question, { min: 1, desc: questionsDesc }),
|
|
8658
|
+
items: f.optional(f.array(f.string(), { desc: itemsDesc }))
|
|
8659
|
+
}
|
|
8660
|
+
}
|
|
8661
|
+
});
|
|
8662
|
+
var evaluateContracts = [evaluateQuestionsContract];
|
|
8525
8663
|
var TOOL_CONTRACTS = Object.fromEntries(
|
|
8526
8664
|
[
|
|
8527
8665
|
...tasksContracts,
|
|
@@ -8538,7 +8676,8 @@ var TOOL_CONTRACTS = Object.fromEntries(
|
|
|
8538
8676
|
...driveContracts,
|
|
8539
8677
|
...meetingsContracts,
|
|
8540
8678
|
...logsContracts,
|
|
8541
|
-
...ciWaitContracts
|
|
8679
|
+
...ciWaitContracts,
|
|
8680
|
+
...evaluateContracts
|
|
8542
8681
|
].map((contract) => [contract.name, contract])
|
|
8543
8682
|
);
|
|
8544
8683
|
|
|
@@ -8736,17 +8875,20 @@ function buildGetExecutionLogsTool(connection) {
|
|
|
8736
8875
|
function buildListTaskFilesTool(connection) {
|
|
8737
8876
|
return defineContractTool(
|
|
8738
8877
|
listTaskFilesContract,
|
|
8739
|
-
async () => {
|
|
8878
|
+
async ({ task_id }) => {
|
|
8740
8879
|
try {
|
|
8741
8880
|
const files = await connection.call("getTaskFiles", {
|
|
8742
|
-
sessionId: connection.sessionId
|
|
8881
|
+
sessionId: connection.sessionId,
|
|
8882
|
+
...task_id ? { taskId: task_id } : {}
|
|
8743
8883
|
});
|
|
8744
8884
|
const metadata = files.map((file) => {
|
|
8745
8885
|
const { content: _c, ...rest } = file;
|
|
8746
8886
|
return rest;
|
|
8747
8887
|
});
|
|
8888
|
+
const heading = task_id ? `Files on card ${task_id}:
|
|
8889
|
+
` : "";
|
|
8748
8890
|
const content = [
|
|
8749
|
-
{ type: "text", text: JSON.stringify(metadata, null, 2) }
|
|
8891
|
+
{ type: "text", text: heading + JSON.stringify(metadata, null, 2) }
|
|
8750
8892
|
];
|
|
8751
8893
|
for (const file of files) {
|
|
8752
8894
|
if (file.content && file.contentEncoding === "base64" && isImageMimeType(file.mimeType)) {
|
|
@@ -8764,11 +8906,12 @@ function buildListTaskFilesTool(connection) {
|
|
|
8764
8906
|
function buildGetAttachmentTool(connection) {
|
|
8765
8907
|
return defineContractTool(
|
|
8766
8908
|
getAttachmentContract,
|
|
8767
|
-
async ({ fileId }) => {
|
|
8909
|
+
async ({ fileId, task_id }) => {
|
|
8768
8910
|
try {
|
|
8769
8911
|
const file = await connection.call("getTaskFile", {
|
|
8770
8912
|
sessionId: connection.sessionId,
|
|
8771
|
-
fileId
|
|
8913
|
+
fileId,
|
|
8914
|
+
...task_id ? { taskId: task_id } : {}
|
|
8772
8915
|
});
|
|
8773
8916
|
const { content: rawContent, ...metadata } = file;
|
|
8774
8917
|
const content = [
|
|
@@ -9355,6 +9498,9 @@ var MIME_BY_EXT = {
|
|
|
9355
9498
|
".yaml": "application/yaml",
|
|
9356
9499
|
".yml": "application/yaml",
|
|
9357
9500
|
".pdf": "application/pdf",
|
|
9501
|
+
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
9502
|
+
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
9503
|
+
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
9358
9504
|
".zip": "application/zip",
|
|
9359
9505
|
".gz": "application/gzip",
|
|
9360
9506
|
".mp4": "video/mp4",
|
|
@@ -9377,11 +9523,21 @@ var EMBEDDABLE_IN_MARKDOWN = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", "
|
|
|
9377
9523
|
function describeEmbed(fileName, downloadUrl) {
|
|
9378
9524
|
if (!downloadUrl) return "";
|
|
9379
9525
|
const isImage = EMBEDDABLE_IN_MARKDOWN.has(extname(fileName).toLowerCase());
|
|
9380
|
-
|
|
9381
|
-
|
|
9526
|
+
if (isImage) {
|
|
9527
|
+
return `
|
|
9382
9528
|
|
|
9383
9529
|
Paste this into the PR description to show it inline:
|
|
9384
|
-
${
|
|
9530
|
+
`;
|
|
9531
|
+
}
|
|
9532
|
+
if (isCapabilityServableMime(inferMimeType(fileName))) {
|
|
9533
|
+
return `
|
|
9534
|
+
|
|
9535
|
+
Paste this into the PR description to link it:
|
|
9536
|
+
[${fileName}](${downloadUrl})`;
|
|
9537
|
+
}
|
|
9538
|
+
return `
|
|
9539
|
+
|
|
9540
|
+
downloadUrl (signed-in project members only; agents read it with get_attachment): ${downloadUrl}`;
|
|
9385
9541
|
}
|
|
9386
9542
|
function buildUploadAttachmentTool(connection, config) {
|
|
9387
9543
|
return defineContractTool(uploadAttachmentContract, async ({ path, title, comment, tags }) => {
|
|
@@ -9434,6 +9590,23 @@ function buildUploadAttachmentTool(connection, config) {
|
|
|
9434
9590
|
}
|
|
9435
9591
|
});
|
|
9436
9592
|
}
|
|
9593
|
+
function buildDeleteAttachmentTool(connection) {
|
|
9594
|
+
return defineContractTool(deleteAttachmentContract, async ({ fileId }) => {
|
|
9595
|
+
try {
|
|
9596
|
+
const result = await connection.call("deleteTaskFile", {
|
|
9597
|
+
sessionId: connection.sessionId,
|
|
9598
|
+
fileId
|
|
9599
|
+
});
|
|
9600
|
+
return textResult(
|
|
9601
|
+
`Deleted ${result.fileName} (${result.id}) permanently. Any chat message that announced it keeps its text without the attachment.`
|
|
9602
|
+
);
|
|
9603
|
+
} catch (error) {
|
|
9604
|
+
return textResult(
|
|
9605
|
+
`Failed to delete attachment: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
9606
|
+
);
|
|
9607
|
+
}
|
|
9608
|
+
});
|
|
9609
|
+
}
|
|
9437
9610
|
|
|
9438
9611
|
// src/tools/checklist-tools.ts
|
|
9439
9612
|
function buildListManualTestsTool(connection) {
|
|
@@ -9509,6 +9682,7 @@ function buildSetManualTestsTool(connection) {
|
|
|
9509
9682
|
});
|
|
9510
9683
|
const parts = [`Created ${result.created} manual test item(s).`];
|
|
9511
9684
|
if (result.skipped > 0) parts.push(`Skipped ${result.skipped} duplicate(s).`);
|
|
9685
|
+
for (const item of result.rejected ?? []) parts.push(describeManualTestRejection(item));
|
|
9512
9686
|
return textResult(parts.join(" "));
|
|
9513
9687
|
} catch (error) {
|
|
9514
9688
|
const msg = error instanceof Error ? error.message : "Unknown error";
|
|
@@ -9630,7 +9804,8 @@ function buildCommonTools(connection, config) {
|
|
|
9630
9804
|
buildApproveManualTestTool(connection),
|
|
9631
9805
|
buildRejectManualTestTool(connection),
|
|
9632
9806
|
...buildMutationTools(connection, config),
|
|
9633
|
-
buildUploadAttachmentTool(connection, config)
|
|
9807
|
+
buildUploadAttachmentTool(connection, config),
|
|
9808
|
+
buildDeleteAttachmentTool(connection)
|
|
9634
9809
|
];
|
|
9635
9810
|
}
|
|
9636
9811
|
|
|
@@ -10069,9 +10244,9 @@ async function rejectBadContextPaths(contextPaths, workspaceDir) {
|
|
|
10069
10244
|
function buildListTagsTool(connection, projectId) {
|
|
10070
10245
|
return defineContractTool(
|
|
10071
10246
|
listTagsContract,
|
|
10072
|
-
async () => {
|
|
10247
|
+
async ({ detail }) => {
|
|
10073
10248
|
try {
|
|
10074
|
-
const tags = await connection.call("listProjectTags", { projectId });
|
|
10249
|
+
const tags = await connection.call("listProjectTags", { projectId, detail });
|
|
10075
10250
|
return textResult(JSON.stringify(tags, null, 2));
|
|
10076
10251
|
} catch (error) {
|
|
10077
10252
|
return errText("Failed to list tags", error);
|
|
@@ -10936,6 +11111,31 @@ function settleTools(connection, projectId) {
|
|
|
10936
11111
|
];
|
|
10937
11112
|
}
|
|
10938
11113
|
|
|
11114
|
+
// src/tools/evaluate-tools.ts
|
|
11115
|
+
function buildEvaluateTools(connection, projectId) {
|
|
11116
|
+
return [
|
|
11117
|
+
defineContractTool(
|
|
11118
|
+
evaluateQuestionsContract,
|
|
11119
|
+
async (input) => {
|
|
11120
|
+
try {
|
|
11121
|
+
const res = await connection.call("evaluateQuestions", {
|
|
11122
|
+
projectId,
|
|
11123
|
+
state: input.state,
|
|
11124
|
+
items: input.items,
|
|
11125
|
+
questions: input.questions
|
|
11126
|
+
});
|
|
11127
|
+
return textResult(formatEvaluateQuestionsResult(res));
|
|
11128
|
+
} catch (error) {
|
|
11129
|
+
return textResult(
|
|
11130
|
+
`evaluate_questions failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
11131
|
+
);
|
|
11132
|
+
}
|
|
11133
|
+
},
|
|
11134
|
+
{ annotations: { readOnlyHint: true } }
|
|
11135
|
+
)
|
|
11136
|
+
];
|
|
11137
|
+
}
|
|
11138
|
+
|
|
10939
11139
|
// src/tools/connected-tools.ts
|
|
10940
11140
|
function connectedToolsFor(connection, context) {
|
|
10941
11141
|
const projectId = context?.projectId;
|
|
@@ -10948,6 +11148,9 @@ function connectedToolsFor(connection, context) {
|
|
|
10948
11148
|
// Always available: the decision tables exist on every project, and a fork
|
|
10949
11149
|
// an agent cannot file is a fork it assumes its way past instead.
|
|
10950
11150
|
...buildDecisionTools(connection, projectId),
|
|
11151
|
+
// Ungated: whether the project has Jev on is answered by calling it, and
|
|
11152
|
+
// the error names what an admin has to switch on.
|
|
11153
|
+
...buildEvaluateTools(connection, projectId),
|
|
10951
11154
|
...context.googleAnalyticsConfigured ? [buildAnalyticsSummaryTool(connection, projectId)] : [],
|
|
10952
11155
|
...context.gcpLogsConfigured ? [buildQueryGcpLogsTool(connection, projectId)] : [],
|
|
10953
11156
|
...context.grafanaLogsConfigured ? [buildQueryGrafanaLogsTool(connection, projectId)] : []
|
|
@@ -10955,8 +11158,6 @@ function connectedToolsFor(connection, context) {
|
|
|
10955
11158
|
}
|
|
10956
11159
|
|
|
10957
11160
|
// src/tools/code-review-tools.ts
|
|
10958
|
-
import { execFile } from "child_process";
|
|
10959
|
-
import { promisify } from "util";
|
|
10960
11161
|
import { z as z10 } from "zod";
|
|
10961
11162
|
async function endReviewSession(connection, reason) {
|
|
10962
11163
|
await connection.call("endReviewSession", {
|
|
@@ -10967,101 +11168,6 @@ async function endReviewSession(connection, reason) {
|
|
|
10967
11168
|
var RISK_LEVELS = ["critical", "high", "medium", "low"];
|
|
10968
11169
|
var reviewedShaSchema = z10.string().regex(/^[0-9a-f]{40}$/i).describe("REQUIRED. The full 40-character commit SHA this verdict reviews.");
|
|
10969
11170
|
var riskDescription = "REQUIRED. The risk level this change carries, judged by the surface area it touches: critical = touches critical/foundational surface, high = important surface, medium = moderate, low = small/isolated. Set this on every verdict. You have authority to override a risk level already set on the task if you disagree with it.";
|
|
10970
|
-
var ReviewGuideToolSchema = z10.strictObject({
|
|
10971
|
-
reviewedSha: z10.string().regex(/^[0-9a-f]{40}$/i).describe(
|
|
10972
|
-
"REQUIRED. The PR's current head as a full 40-char SHA. Run `git rev-parse HEAD` immediately before this call \u2014 never extend an abbreviated hash into 40 characters."
|
|
10973
|
-
),
|
|
10974
|
-
overview: z10.string().min(1).max(6e4).describe("REQUIRED. Plain-text walkthrough intro, max 3000 characters. Keep it short."),
|
|
10975
|
-
sections: z10.array(
|
|
10976
|
-
z10.strictObject({
|
|
10977
|
-
title: z10.string().min(1).max(160),
|
|
10978
|
-
explanation: z10.string().min(1).max(2e3),
|
|
10979
|
-
classification: z10.enum(["core", "supporting"]).optional(),
|
|
10980
|
-
files: z10.array(
|
|
10981
|
-
z10.strictObject({
|
|
10982
|
-
path: z10.string().min(1).max(500).describe(
|
|
10983
|
-
"A file the PR's diff actually changed. Context files you merely read are rejected."
|
|
10984
|
-
),
|
|
10985
|
-
startLine: z10.number().int().positive().max(1e6).optional(),
|
|
10986
|
-
endLine: z10.number().int().positive().max(1e6).optional(),
|
|
10987
|
-
hunkHeader: z10.string().min(1).max(300).optional().describe(
|
|
10988
|
-
"Optional anchor, matched byte-exactly against the full hunk header line from `git diff` INCLUDING the context text after the second @@. Copy it verbatim from `git diff <base>..HEAD -- <file> | grep '^@@'`, or omit anchors entirely (path-only entries always validate)."
|
|
10989
|
-
)
|
|
10990
|
-
})
|
|
10991
|
-
).min(1).max(20)
|
|
10992
|
-
})
|
|
10993
|
-
).min(1).max(12).optional().describe(
|
|
10994
|
-
"REQUIRED top-level array (never text appended to overview) of ordered conceptual sections."
|
|
10995
|
-
)
|
|
10996
|
-
});
|
|
10997
|
-
var FLATTENED_SECTIONS_PATTERN = /<\/overview>\s*(?:<parameter name="sections">|<sections>)/;
|
|
10998
|
-
var TRAILING_TAGS_PATTERN = /(?:\s*<\/(?:parameter|sections|invoke)>)+\s*$/;
|
|
10999
|
-
function sliceOutermostArray(tail) {
|
|
11000
|
-
const start = tail.indexOf("[");
|
|
11001
|
-
const end = tail.lastIndexOf("]");
|
|
11002
|
-
return start >= 0 && end > start ? tail.slice(start, end + 1) : null;
|
|
11003
|
-
}
|
|
11004
|
-
function recoverFlattenedGuide(overview) {
|
|
11005
|
-
const match = FLATTENED_SECTIONS_PATTERN.exec(overview);
|
|
11006
|
-
if (!match) return null;
|
|
11007
|
-
const head = overview.slice(0, match.index).trim();
|
|
11008
|
-
const tail = overview.slice(match.index + match[0].length).replace(TRAILING_TAGS_PATTERN, "").trim();
|
|
11009
|
-
for (const candidate of [tail, sliceOutermostArray(tail)]) {
|
|
11010
|
-
if (!candidate) continue;
|
|
11011
|
-
try {
|
|
11012
|
-
return { overview: head, sections: JSON.parse(candidate) };
|
|
11013
|
-
} catch {
|
|
11014
|
-
}
|
|
11015
|
-
}
|
|
11016
|
-
return null;
|
|
11017
|
-
}
|
|
11018
|
-
async function resolveGitHeadSha(cwd) {
|
|
11019
|
-
try {
|
|
11020
|
-
const stdout = workbenchEnabled() ? (await getWorkbenchClient().execFile("git", ["rev-parse", "HEAD"], {
|
|
11021
|
-
cwd,
|
|
11022
|
-
timeout: 1e4
|
|
11023
|
-
})).stdout : (await promisify(execFile)("git", ["rev-parse", "HEAD"], { cwd, timeout: 1e4 })).stdout;
|
|
11024
|
-
const sha = stdout.trim();
|
|
11025
|
-
return /^[0-9a-f]{40}$/i.test(sha) ? sha : null;
|
|
11026
|
-
} catch {
|
|
11027
|
-
return null;
|
|
11028
|
-
}
|
|
11029
|
-
}
|
|
11030
|
-
function buildPublishReviewGuideTool(connection, options = {}) {
|
|
11031
|
-
const { resolveHeadSha } = options;
|
|
11032
|
-
return defineTool(
|
|
11033
|
-
"publish_review_guide",
|
|
11034
|
-
"Publish or update the PR guide for the CURRENT PR head commit. Call right after create_pull_request succeeds, and again after every push to the branch. The head SHA is resolved from the local repo, so never hand-expand a short hash. Best-effort \u2014 it does not gate opening or updating the PR.",
|
|
11035
|
-
ReviewGuideToolSchema.shape,
|
|
11036
|
-
async ({ reviewedSha, overview, sections }) => {
|
|
11037
|
-
let resolvedOverview = overview;
|
|
11038
|
-
let resolvedSections = sections;
|
|
11039
|
-
if (resolvedSections === void 0) {
|
|
11040
|
-
const recovered = recoverFlattenedGuide(overview);
|
|
11041
|
-
if (!recovered) {
|
|
11042
|
-
throw new Error(
|
|
11043
|
-
"publish_review_guide requires a top-level `sections` array \u2014 an ordered list of conceptual sections, each with title, explanation, and files[]. Your call arrived with only `reviewedSha` and `overview`; the `sections` parameter never reached the server, which usually means the call encoding flattened it into `overview`. Do not append the sections to `overview` as text. Retry with sections as a real array argument, and shorten `overview` if the failure repeats."
|
|
11044
|
-
);
|
|
11045
|
-
}
|
|
11046
|
-
resolvedOverview = recovered.overview;
|
|
11047
|
-
resolvedSections = recovered.sections;
|
|
11048
|
-
}
|
|
11049
|
-
const content = ReviewGuideContentSchema.parse({
|
|
11050
|
-
overview: resolvedOverview,
|
|
11051
|
-
sections: resolvedSections
|
|
11052
|
-
});
|
|
11053
|
-
const result = await connection.call("publishReviewGuide", {
|
|
11054
|
-
sessionId: connection.sessionId,
|
|
11055
|
-
reviewedSha: (resolveHeadSha ? await resolveHeadSha() : null) ?? reviewedSha,
|
|
11056
|
-
...content
|
|
11057
|
-
});
|
|
11058
|
-
return textResult(
|
|
11059
|
-
`Review guide published for ${result.reviewedSha}${result.replaced ? " (replaced)" : ""}.`
|
|
11060
|
-
);
|
|
11061
|
-
},
|
|
11062
|
-
{ strict: true }
|
|
11063
|
-
);
|
|
11064
|
-
}
|
|
11065
11171
|
function buildApproveCodeReviewTool(connection) {
|
|
11066
11172
|
return defineTool(
|
|
11067
11173
|
"approve_code_review",
|
|
@@ -11171,15 +11277,6 @@ function getModeTools(agentMode, connection, config, context) {
|
|
|
11171
11277
|
return config.mode === "pm" ? buildPmTools(connection) : [];
|
|
11172
11278
|
}
|
|
11173
11279
|
}
|
|
11174
|
-
function buildPrGuideToolsFor(effectiveMode, connection, config, context) {
|
|
11175
|
-
const isLeafBuild = effectiveMode === "building" || effectiveMode === "auto" || effectiveMode === "chat";
|
|
11176
|
-
const isPackRunner = config.mode === "pack";
|
|
11177
|
-
return (isLeafBuild || isPackRunner) && (isPackRunner || !context?.isParentTask) ? [
|
|
11178
|
-
buildPublishReviewGuideTool(connection, {
|
|
11179
|
-
resolveHeadSha: () => resolveGitHeadSha(config.workspaceDir)
|
|
11180
|
-
})
|
|
11181
|
-
] : [];
|
|
11182
|
-
}
|
|
11183
11280
|
function ciWaitToolsFor(effectiveMode, connection, config) {
|
|
11184
11281
|
const isPackRunner = config.mode === "pack";
|
|
11185
11282
|
return effectiveMode === "review" && !isPackRunner ? [] : [buildWaitForChecksTool(connection)];
|
|
@@ -11214,8 +11311,6 @@ var ALWAYS_LOADED_TOOLS = /* @__PURE__ */ new Set([
|
|
|
11214
11311
|
// The shared-skill card write: one name whose fields match the mcp surface,
|
|
11215
11312
|
// so a single skill text drives a local session and a pod verbatim.
|
|
11216
11313
|
"update_task",
|
|
11217
|
-
// Building/auto — the PR guide is published as part of opening the PR
|
|
11218
|
-
"publish_review_guide",
|
|
11219
11314
|
// Review mode
|
|
11220
11315
|
"approve_code_review",
|
|
11221
11316
|
"request_code_changes"
|
|
@@ -11269,7 +11364,6 @@ function buildConveyorTools(connection, config, context, agentMode) {
|
|
|
11269
11364
|
const modeTools = getModeTools(effectiveMode, connection, config, context);
|
|
11270
11365
|
const discoveryTools = effectiveMode === "discovery" || effectiveMode === "auto" || effectiveMode === "building" || effectiveMode === "chat" ? buildDiscoveryTools(connection) : [];
|
|
11271
11366
|
const codeReviewTools = effectiveMode === "review" ? buildCodeReviewTools(connection) : [];
|
|
11272
|
-
const prGuideTools = buildPrGuideToolsFor(effectiveMode, connection, config, context);
|
|
11273
11367
|
const ciWaitTools = ciWaitToolsFor(effectiveMode, connection, config);
|
|
11274
11368
|
const handoffTools = config.mode === "pm" && (effectiveMode === "discovery" || effectiveMode === "auto") ? [buildHandoffTool(connection)] : [];
|
|
11275
11369
|
const emergencyTools = [buildForceUpdateTaskStatusTool(connection)];
|
|
@@ -11282,7 +11376,6 @@ function buildConveyorTools(connection, config, context, agentMode) {
|
|
|
11282
11376
|
...modeTools,
|
|
11283
11377
|
...discoveryTools,
|
|
11284
11378
|
...codeReviewTools,
|
|
11285
|
-
...prGuideTools,
|
|
11286
11379
|
...ciWaitTools,
|
|
11287
11380
|
...handoffTools,
|
|
11288
11381
|
...glossaryTools,
|
|
@@ -13847,9 +13940,9 @@ function buildUnmeasurableEvent(reason, codingAgentKeyId) {
|
|
|
13847
13940
|
}
|
|
13848
13941
|
|
|
13849
13942
|
// src/runner/parent-pull-handler.ts
|
|
13850
|
-
import { execFile
|
|
13851
|
-
import { promisify
|
|
13852
|
-
var execFileAsync =
|
|
13943
|
+
import { execFile } from "child_process";
|
|
13944
|
+
import { promisify } from "util";
|
|
13945
|
+
var execFileAsync = promisify(execFile);
|
|
13853
13946
|
async function handlePullBranch(workDir, branch) {
|
|
13854
13947
|
if (!branch) return;
|
|
13855
13948
|
const current = await getCurrentBranch(workDir);
|
|
@@ -15292,6 +15385,7 @@ var SessionRunner = class _SessionRunner {
|
|
|
15292
15385
|
claudeSessionId: ctx.claudeSessionId ?? null,
|
|
15293
15386
|
lastSeenMessageId: ctx.lastSeenMessageId ?? null,
|
|
15294
15387
|
isParentTask: ctx.isParentTask ?? false,
|
|
15388
|
+
parentTaskFiles: ctx.parentTaskFiles ?? null,
|
|
15295
15389
|
storyPoints: ctx.storyPoints ?? void 0,
|
|
15296
15390
|
agents: ctx.agents ?? void 0,
|
|
15297
15391
|
projectTags: ctx.projectTags ?? void 0,
|