@rallycry/conveyor-agent 7.3.7 → 7.3.9
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-PC43BKMM.js → chunk-Y6IHF32X.js} +795 -175
- package/dist/chunk-Y6IHF32X.js.map +1 -0
- package/dist/cli.js +16 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +12 -0
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-PC43BKMM.js.map +0 -1
|
@@ -40,6 +40,8 @@ var AgentConnection = class _AgentConnection {
|
|
|
40
40
|
softStopCallback = null;
|
|
41
41
|
modeChangeCallback = null;
|
|
42
42
|
apiKeyUpdateCallback = null;
|
|
43
|
+
pullBranchCallback = null;
|
|
44
|
+
earlyPullBranches = [];
|
|
43
45
|
constructor(config) {
|
|
44
46
|
this.config = config;
|
|
45
47
|
}
|
|
@@ -130,6 +132,10 @@ var AgentConnection = class _AgentConnection {
|
|
|
130
132
|
this.socket.on("agentRunner:updateApiKey", (data) => {
|
|
131
133
|
if (this.apiKeyUpdateCallback) this.apiKeyUpdateCallback(data);
|
|
132
134
|
});
|
|
135
|
+
this.socket.on("session:pullBranch", (data) => {
|
|
136
|
+
if (this.pullBranchCallback) this.pullBranchCallback(data);
|
|
137
|
+
else this.earlyPullBranches.push(data);
|
|
138
|
+
});
|
|
133
139
|
this.socket.on("connect", () => {
|
|
134
140
|
process.stderr.write("[conveyor-agent] Socket connected\n");
|
|
135
141
|
if (!settled) {
|
|
@@ -251,6 +257,11 @@ var AgentConnection = class _AgentConnection {
|
|
|
251
257
|
onApiKeyUpdate(callback) {
|
|
252
258
|
this.apiKeyUpdateCallback = callback;
|
|
253
259
|
}
|
|
260
|
+
onPullBranch(callback) {
|
|
261
|
+
this.pullBranchCallback = callback;
|
|
262
|
+
for (const data of this.earlyPullBranches) callback(data);
|
|
263
|
+
this.earlyPullBranches = [];
|
|
264
|
+
}
|
|
254
265
|
// ── Convenience methods (thin wrappers around call / emit) ─────────
|
|
255
266
|
async emitStatus(status) {
|
|
256
267
|
this.lastEmittedStatus = status;
|
|
@@ -1384,6 +1395,8 @@ var DeleteSubtaskResponseSchema = z.object({
|
|
|
1384
1395
|
});
|
|
1385
1396
|
var RegisterProjectAgentResponseSchema = z.object({
|
|
1386
1397
|
registered: z.boolean(),
|
|
1398
|
+
/** ProjectCodespaceSession id — used by the runner to filter targeted chat messages. */
|
|
1399
|
+
sessionId: z.string(),
|
|
1387
1400
|
agentName: z.string(),
|
|
1388
1401
|
agentInstructions: z.string(),
|
|
1389
1402
|
model: z.string(),
|
|
@@ -1456,7 +1469,8 @@ var CreateProjectTaskRequestSchema = z2.object({
|
|
|
1456
1469
|
title: z2.string().min(1),
|
|
1457
1470
|
description: z2.string().optional(),
|
|
1458
1471
|
plan: z2.string().optional(),
|
|
1459
|
-
status: z2.string().optional()
|
|
1472
|
+
status: z2.string().optional(),
|
|
1473
|
+
requestingUserId: z2.string().optional()
|
|
1460
1474
|
});
|
|
1461
1475
|
var UpdateProjectTaskRequestSchema = z2.object({
|
|
1462
1476
|
projectId: z2.string(),
|
|
@@ -1465,7 +1479,8 @@ var UpdateProjectTaskRequestSchema = z2.object({
|
|
|
1465
1479
|
description: z2.string().optional(),
|
|
1466
1480
|
plan: z2.string().optional(),
|
|
1467
1481
|
status: z2.string().optional(),
|
|
1468
|
-
assignedUserId: z2.string().nullish()
|
|
1482
|
+
assignedUserId: z2.string().nullish(),
|
|
1483
|
+
requestingUserId: z2.string().optional()
|
|
1469
1484
|
});
|
|
1470
1485
|
var ReportProjectAgentEventRequestSchema = z2.object({
|
|
1471
1486
|
projectId: z2.string(),
|
|
@@ -1528,7 +1543,8 @@ var GetProjectCliHistoryRequestSchema = z2.object({
|
|
|
1528
1543
|
var PostToProjectTaskChatRequestSchema = z2.object({
|
|
1529
1544
|
projectId: z2.string(),
|
|
1530
1545
|
taskId: z2.string(),
|
|
1531
|
-
content: z2.string()
|
|
1546
|
+
content: z2.string(),
|
|
1547
|
+
requestingUserId: z2.string().optional()
|
|
1532
1548
|
});
|
|
1533
1549
|
var GetProjectTaskCliRequestSchema = z2.object({
|
|
1534
1550
|
projectId: z2.string(),
|
|
@@ -1538,15 +1554,71 @@ var GetProjectTaskCliRequestSchema = z2.object({
|
|
|
1538
1554
|
});
|
|
1539
1555
|
var StartProjectBuildRequestSchema = z2.object({
|
|
1540
1556
|
projectId: z2.string(),
|
|
1541
|
-
taskId: z2.string()
|
|
1557
|
+
taskId: z2.string(),
|
|
1558
|
+
requestingUserId: z2.string().optional()
|
|
1542
1559
|
});
|
|
1543
1560
|
var StopProjectBuildRequestSchema = z2.object({
|
|
1544
1561
|
projectId: z2.string(),
|
|
1545
|
-
taskId: z2.string()
|
|
1562
|
+
taskId: z2.string(),
|
|
1563
|
+
requestingUserId: z2.string().optional()
|
|
1546
1564
|
});
|
|
1547
1565
|
var ApproveProjectMergePRRequestSchema = z2.object({
|
|
1548
1566
|
projectId: z2.string(),
|
|
1549
|
-
childTaskId: z2.string()
|
|
1567
|
+
childTaskId: z2.string(),
|
|
1568
|
+
requestingUserId: z2.string().optional()
|
|
1569
|
+
});
|
|
1570
|
+
var ListProjectSubtasksRequestSchema = z2.object({
|
|
1571
|
+
projectId: z2.string(),
|
|
1572
|
+
taskId: z2.string()
|
|
1573
|
+
});
|
|
1574
|
+
var CreateProjectSubtaskRequestSchema = z2.object({
|
|
1575
|
+
projectId: z2.string(),
|
|
1576
|
+
parentTaskId: z2.string(),
|
|
1577
|
+
title: z2.string().min(1),
|
|
1578
|
+
description: z2.string().optional(),
|
|
1579
|
+
plan: z2.string().optional(),
|
|
1580
|
+
ordinal: z2.number().int().nonnegative().optional(),
|
|
1581
|
+
storyPointValue: z2.number().int().positive().optional(),
|
|
1582
|
+
requestingUserId: z2.string().optional()
|
|
1583
|
+
});
|
|
1584
|
+
var UpdateProjectSubtaskRequestSchema = z2.object({
|
|
1585
|
+
projectId: z2.string(),
|
|
1586
|
+
subtaskId: z2.string(),
|
|
1587
|
+
title: z2.string().optional(),
|
|
1588
|
+
description: z2.string().optional(),
|
|
1589
|
+
plan: z2.string().optional(),
|
|
1590
|
+
status: z2.string().optional(),
|
|
1591
|
+
ordinal: z2.number().int().nonnegative().optional(),
|
|
1592
|
+
storyPointValue: z2.number().int().positive().optional(),
|
|
1593
|
+
requestingUserId: z2.string().optional()
|
|
1594
|
+
});
|
|
1595
|
+
var DeleteProjectSubtaskRequestSchema = z2.object({
|
|
1596
|
+
projectId: z2.string(),
|
|
1597
|
+
subtaskId: z2.string(),
|
|
1598
|
+
requestingUserId: z2.string().optional()
|
|
1599
|
+
});
|
|
1600
|
+
var GetProjectTaskChatRequestSchema = z2.object({
|
|
1601
|
+
projectId: z2.string(),
|
|
1602
|
+
taskId: z2.string(),
|
|
1603
|
+
limit: z2.number().int().positive().optional().default(20)
|
|
1604
|
+
});
|
|
1605
|
+
var AddProjectTaskDependencyRequestSchema = z2.object({
|
|
1606
|
+
projectId: z2.string(),
|
|
1607
|
+
taskId: z2.string(),
|
|
1608
|
+
dependsOnSlugOrId: z2.string(),
|
|
1609
|
+
requestingUserId: z2.string().optional()
|
|
1610
|
+
});
|
|
1611
|
+
var RemoveProjectTaskDependencyRequestSchema = z2.object({
|
|
1612
|
+
projectId: z2.string(),
|
|
1613
|
+
taskId: z2.string(),
|
|
1614
|
+
dependsOnSlugOrId: z2.string(),
|
|
1615
|
+
requestingUserId: z2.string().optional()
|
|
1616
|
+
});
|
|
1617
|
+
var VoteProjectSuggestionRequestSchema = z2.object({
|
|
1618
|
+
projectId: z2.string(),
|
|
1619
|
+
suggestionId: z2.string(),
|
|
1620
|
+
value: z2.union([z2.literal(1), z2.literal(-1)]),
|
|
1621
|
+
requestingUserId: z2.string().optional()
|
|
1550
1622
|
});
|
|
1551
1623
|
var StartTaskAuditRequestSchema = z3.object({
|
|
1552
1624
|
projectId: z3.string(),
|
|
@@ -1566,7 +1638,8 @@ var CreateProjectSuggestionRequestSchema = z3.object({
|
|
|
1566
1638
|
projectId: z3.string(),
|
|
1567
1639
|
title: z3.string().min(1),
|
|
1568
1640
|
description: z3.string().optional(),
|
|
1569
|
-
tagNames: z3.array(z3.string()).optional()
|
|
1641
|
+
tagNames: z3.array(z3.string()).optional(),
|
|
1642
|
+
requestingUserId: z3.string().optional()
|
|
1570
1643
|
});
|
|
1571
1644
|
var ReportTaskAuditBatchCompleteRequestSchema = z3.object({
|
|
1572
1645
|
projectId: z3.string(),
|
|
@@ -6572,6 +6645,48 @@ function readAgentVersion() {
|
|
|
6572
6645
|
return null;
|
|
6573
6646
|
}
|
|
6574
6647
|
|
|
6648
|
+
// src/runner/parent-pull-handler.ts
|
|
6649
|
+
import { execSync as execSync2 } from "child_process";
|
|
6650
|
+
function handlePullBranch(workDir, branch) {
|
|
6651
|
+
if (!branch) return;
|
|
6652
|
+
const current = getCurrentBranch(workDir);
|
|
6653
|
+
if (current !== branch) {
|
|
6654
|
+
process.stderr.write(
|
|
6655
|
+
`[conveyor-agent] pull_branch ignored \u2014 current branch ${current ?? "(detached)"} != ${branch}
|
|
6656
|
+
`
|
|
6657
|
+
);
|
|
6658
|
+
return;
|
|
6659
|
+
}
|
|
6660
|
+
if (hasUncommittedChanges(workDir)) {
|
|
6661
|
+
process.stderr.write(
|
|
6662
|
+
`[conveyor-agent] pull_branch ignored \u2014 uncommitted changes on ${branch}
|
|
6663
|
+
`
|
|
6664
|
+
);
|
|
6665
|
+
return;
|
|
6666
|
+
}
|
|
6667
|
+
try {
|
|
6668
|
+
execSync2(`git fetch origin ${branch}`, { cwd: workDir, stdio: "ignore", timeout: 6e4 });
|
|
6669
|
+
} catch {
|
|
6670
|
+
process.stderr.write(`[conveyor-agent] pull_branch: fetch failed for ${branch}
|
|
6671
|
+
`);
|
|
6672
|
+
return;
|
|
6673
|
+
}
|
|
6674
|
+
try {
|
|
6675
|
+
execSync2(`git pull --ff-only origin ${branch}`, {
|
|
6676
|
+
cwd: workDir,
|
|
6677
|
+
stdio: "ignore",
|
|
6678
|
+
timeout: 6e4
|
|
6679
|
+
});
|
|
6680
|
+
process.stderr.write(`[conveyor-agent] pull_branch: pulled origin/${branch}
|
|
6681
|
+
`);
|
|
6682
|
+
} catch {
|
|
6683
|
+
process.stderr.write(
|
|
6684
|
+
`[conveyor-agent] pull_branch: ff-only pull failed for ${branch} (likely diverged)
|
|
6685
|
+
`
|
|
6686
|
+
);
|
|
6687
|
+
}
|
|
6688
|
+
}
|
|
6689
|
+
|
|
6575
6690
|
// src/runner/session-runner.ts
|
|
6576
6691
|
var SessionRunner = class _SessionRunner {
|
|
6577
6692
|
connection;
|
|
@@ -7134,6 +7249,9 @@ var SessionRunner = class _SessionRunner {
|
|
|
7134
7249
|
delete process.env.CLAUDE_CODE_OAUTH_TOKEN;
|
|
7135
7250
|
}
|
|
7136
7251
|
});
|
|
7252
|
+
this.connection.onPullBranch(({ branch }) => {
|
|
7253
|
+
handlePullBranch(this.config.workspaceDir, branch);
|
|
7254
|
+
});
|
|
7137
7255
|
}
|
|
7138
7256
|
/**
|
|
7139
7257
|
* Rehydrate CostTracker from server. Caps at 3s so a slow API call never
|
|
@@ -7417,7 +7535,7 @@ var ProjectConnection = class {
|
|
|
7417
7535
|
};
|
|
7418
7536
|
|
|
7419
7537
|
// src/runner/commit-watcher.ts
|
|
7420
|
-
import { execSync as
|
|
7538
|
+
import { execSync as execSync3 } from "child_process";
|
|
7421
7539
|
var logger5 = createServiceLogger("CommitWatcher");
|
|
7422
7540
|
var CommitWatcher = class {
|
|
7423
7541
|
constructor(config, callbacks) {
|
|
@@ -7451,7 +7569,7 @@ var CommitWatcher = class {
|
|
|
7451
7569
|
this.isSyncing = false;
|
|
7452
7570
|
}
|
|
7453
7571
|
getLocalHeadSha() {
|
|
7454
|
-
return
|
|
7572
|
+
return execSync3("git rev-parse HEAD", {
|
|
7455
7573
|
cwd: this.config.projectDir,
|
|
7456
7574
|
stdio: ["ignore", "pipe", "ignore"]
|
|
7457
7575
|
}).toString().trim();
|
|
@@ -7459,12 +7577,12 @@ var CommitWatcher = class {
|
|
|
7459
7577
|
poll() {
|
|
7460
7578
|
if (!this.branch || this.isSyncing) return;
|
|
7461
7579
|
try {
|
|
7462
|
-
|
|
7580
|
+
execSync3(`git fetch origin ${this.branch} --quiet`, {
|
|
7463
7581
|
cwd: this.config.projectDir,
|
|
7464
7582
|
stdio: "ignore",
|
|
7465
7583
|
timeout: 3e4
|
|
7466
7584
|
});
|
|
7467
|
-
const remoteSha =
|
|
7585
|
+
const remoteSha = execSync3(`git rev-parse origin/${this.branch}`, {
|
|
7468
7586
|
cwd: this.config.projectDir,
|
|
7469
7587
|
stdio: ["ignore", "pipe", "ignore"]
|
|
7470
7588
|
}).toString().trim();
|
|
@@ -7485,12 +7603,12 @@ var CommitWatcher = class {
|
|
|
7485
7603
|
let latestMessage = "";
|
|
7486
7604
|
let latestAuthor = "";
|
|
7487
7605
|
try {
|
|
7488
|
-
const countOutput =
|
|
7606
|
+
const countOutput = execSync3(`git rev-list --count ${previousSha}..origin/${this.branch}`, {
|
|
7489
7607
|
cwd: this.config.projectDir,
|
|
7490
7608
|
stdio: ["ignore", "pipe", "ignore"]
|
|
7491
7609
|
}).toString().trim();
|
|
7492
7610
|
commitCount = parseInt(countOutput, 10) || 1;
|
|
7493
|
-
const logOutput =
|
|
7611
|
+
const logOutput = execSync3(`git log -1 --format="%s|||%an" origin/${this.branch}`, {
|
|
7494
7612
|
cwd: this.config.projectDir,
|
|
7495
7613
|
stdio: ["ignore", "pipe", "ignore"]
|
|
7496
7614
|
}).toString().trim();
|
|
@@ -7525,7 +7643,7 @@ var CommitWatcher = class {
|
|
|
7525
7643
|
};
|
|
7526
7644
|
|
|
7527
7645
|
// src/runner/worktree.ts
|
|
7528
|
-
import { execSync as
|
|
7646
|
+
import { execSync as execSync4 } from "child_process";
|
|
7529
7647
|
import { existsSync as existsSync2 } from "fs";
|
|
7530
7648
|
import { join as join4 } from "path";
|
|
7531
7649
|
var WORKTREE_DIR = ".worktrees";
|
|
@@ -7540,7 +7658,7 @@ function ensureWorktree(projectDir, taskId, branch) {
|
|
|
7540
7658
|
return worktreePath;
|
|
7541
7659
|
}
|
|
7542
7660
|
try {
|
|
7543
|
-
|
|
7661
|
+
execSync4(`git checkout --detach origin/${branch}`, {
|
|
7544
7662
|
cwd: worktreePath,
|
|
7545
7663
|
stdio: "ignore"
|
|
7546
7664
|
});
|
|
@@ -7550,7 +7668,7 @@ function ensureWorktree(projectDir, taskId, branch) {
|
|
|
7550
7668
|
return worktreePath;
|
|
7551
7669
|
}
|
|
7552
7670
|
const ref = branch ? `origin/${branch}` : "HEAD";
|
|
7553
|
-
|
|
7671
|
+
execSync4(`git worktree add --detach "${worktreePath}" ${ref}`, {
|
|
7554
7672
|
cwd: projectDir,
|
|
7555
7673
|
stdio: "ignore"
|
|
7556
7674
|
});
|
|
@@ -7558,7 +7676,7 @@ function ensureWorktree(projectDir, taskId, branch) {
|
|
|
7558
7676
|
}
|
|
7559
7677
|
function detachWorktreeBranch(projectDir, branch) {
|
|
7560
7678
|
try {
|
|
7561
|
-
const output =
|
|
7679
|
+
const output = execSync4("git worktree list --porcelain", {
|
|
7562
7680
|
cwd: projectDir,
|
|
7563
7681
|
encoding: "utf-8"
|
|
7564
7682
|
});
|
|
@@ -7571,7 +7689,7 @@ function detachWorktreeBranch(projectDir, branch) {
|
|
|
7571
7689
|
const worktreePath = worktreeLine.replace("worktree ", "");
|
|
7572
7690
|
if (!worktreePath.includes(`/${WORKTREE_DIR}/`)) continue;
|
|
7573
7691
|
try {
|
|
7574
|
-
|
|
7692
|
+
execSync4("git checkout --detach", { cwd: worktreePath, stdio: "ignore" });
|
|
7575
7693
|
} catch {
|
|
7576
7694
|
}
|
|
7577
7695
|
}
|
|
@@ -7582,7 +7700,7 @@ function removeWorktree(projectDir, taskId) {
|
|
|
7582
7700
|
const worktreePath = join4(projectDir, WORKTREE_DIR, taskId);
|
|
7583
7701
|
if (!existsSync2(worktreePath)) return;
|
|
7584
7702
|
try {
|
|
7585
|
-
|
|
7703
|
+
execSync4(`git worktree remove "${worktreePath}" --force`, {
|
|
7586
7704
|
cwd: projectDir,
|
|
7587
7705
|
stdio: "ignore"
|
|
7588
7706
|
});
|
|
@@ -7591,7 +7709,7 @@ function removeWorktree(projectDir, taskId) {
|
|
|
7591
7709
|
}
|
|
7592
7710
|
|
|
7593
7711
|
// src/setup/commands.ts
|
|
7594
|
-
import { spawn, execSync as
|
|
7712
|
+
import { spawn, execSync as execSync5 } from "child_process";
|
|
7595
7713
|
function runSetupCommand(cmd, cwd, onOutput) {
|
|
7596
7714
|
return new Promise((resolve2, reject) => {
|
|
7597
7715
|
const child = spawn("sh", ["-c", cmd], {
|
|
@@ -7620,7 +7738,7 @@ function runSetupCommand(cmd, cwd, onOutput) {
|
|
|
7620
7738
|
var AUTH_TOKEN_TIMEOUT_MS = 3e4;
|
|
7621
7739
|
function runAuthTokenCommand(cmd, userEmail, cwd) {
|
|
7622
7740
|
try {
|
|
7623
|
-
const output =
|
|
7741
|
+
const output = execSync5(`${cmd} ${JSON.stringify(userEmail)}`, {
|
|
7624
7742
|
cwd,
|
|
7625
7743
|
timeout: AUTH_TOKEN_TIMEOUT_MS,
|
|
7626
7744
|
stdio: ["ignore", "pipe", "ignore"],
|
|
@@ -7650,158 +7768,645 @@ function runStartCommand(cmd, cwd, onOutput) {
|
|
|
7650
7768
|
}
|
|
7651
7769
|
|
|
7652
7770
|
// src/tools/project-tools.ts
|
|
7771
|
+
import { z as z14 } from "zod";
|
|
7772
|
+
|
|
7773
|
+
// src/tools/project-action-tools.ts
|
|
7653
7774
|
import { z as z13 } from "zod";
|
|
7654
|
-
|
|
7775
|
+
var SP_DESCRIPTION3 = "Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)";
|
|
7776
|
+
function withRequestingUser(payload, getRequestingUserId) {
|
|
7777
|
+
const requestingUserId = getRequestingUserId();
|
|
7778
|
+
return requestingUserId ? { ...payload, requestingUserId } : payload;
|
|
7779
|
+
}
|
|
7780
|
+
function buildCreateTaskTool(connection, getRequestingUserId) {
|
|
7655
7781
|
const projectId = connection.projectId;
|
|
7656
|
-
return
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
7660
|
-
|
|
7661
|
-
|
|
7662
|
-
|
|
7663
|
-
|
|
7664
|
-
|
|
7665
|
-
|
|
7666
|
-
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
|
|
7672
|
-
|
|
7673
|
-
}
|
|
7674
|
-
}
|
|
7675
|
-
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7679
|
-
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
7782
|
+
return defineTool(
|
|
7783
|
+
"create_task",
|
|
7784
|
+
"Create a new task in the project.",
|
|
7785
|
+
{
|
|
7786
|
+
title: z13.string().describe("Task title"),
|
|
7787
|
+
description: z13.string().optional().describe("Task description"),
|
|
7788
|
+
plan: z13.string().optional().describe("Implementation plan in markdown"),
|
|
7789
|
+
status: z13.string().optional().describe("Initial status (default: Planning)")
|
|
7790
|
+
},
|
|
7791
|
+
async (params) => {
|
|
7792
|
+
try {
|
|
7793
|
+
const result = await connection.call(
|
|
7794
|
+
"createProjectTask",
|
|
7795
|
+
withRequestingUser({ projectId, ...params }, getRequestingUserId)
|
|
7796
|
+
);
|
|
7797
|
+
return textResult(`Task created: ${result.slug} (ID: ${result.id})`);
|
|
7798
|
+
} catch (error) {
|
|
7799
|
+
return textResult(`Failed to create task: ${errorMessage(error)}`);
|
|
7800
|
+
}
|
|
7801
|
+
}
|
|
7802
|
+
);
|
|
7803
|
+
}
|
|
7804
|
+
function buildUpdateProjectTaskTool(connection, getRequestingUserId) {
|
|
7805
|
+
const projectId = connection.projectId;
|
|
7806
|
+
return defineTool(
|
|
7807
|
+
"update_project_task",
|
|
7808
|
+
"Update an existing task's title, description, plan, status, or assignee. Project-runner scope.",
|
|
7809
|
+
{
|
|
7810
|
+
task_id: z13.string().describe("The task ID to update"),
|
|
7811
|
+
title: z13.string().optional().describe("New title"),
|
|
7812
|
+
description: z13.string().optional().describe("New description"),
|
|
7813
|
+
plan: z13.string().optional().describe("New plan in markdown"),
|
|
7814
|
+
status: z13.string().optional().describe("New status"),
|
|
7815
|
+
assignedUserId: z13.string().nullable().optional().describe("Assign to user ID, or null to unassign")
|
|
7816
|
+
},
|
|
7817
|
+
async ({ task_id, ...fields }) => {
|
|
7818
|
+
try {
|
|
7819
|
+
await connection.call(
|
|
7820
|
+
"updateProjectTask",
|
|
7821
|
+
withRequestingUser({ projectId, taskId: task_id, ...fields }, getRequestingUserId)
|
|
7822
|
+
);
|
|
7823
|
+
return textResult("Task updated successfully.");
|
|
7824
|
+
} catch (error) {
|
|
7825
|
+
return textResult(`Failed to update task: ${errorMessage(error)}`);
|
|
7826
|
+
}
|
|
7827
|
+
}
|
|
7828
|
+
);
|
|
7829
|
+
}
|
|
7830
|
+
function buildUpdateTaskPlanTool(connection, getRequestingUserId) {
|
|
7831
|
+
const projectId = connection.projectId;
|
|
7832
|
+
return defineTool(
|
|
7833
|
+
"update_task_plan",
|
|
7834
|
+
"Save a plan or description to a task. Convenience wrapper around update_project_task for the common Plan-mode case.",
|
|
7835
|
+
{
|
|
7836
|
+
task_id: z13.string().describe("The task ID to update"),
|
|
7837
|
+
plan: z13.string().optional().describe("The task plan in markdown"),
|
|
7838
|
+
description: z13.string().optional().describe("Updated task description")
|
|
7839
|
+
},
|
|
7840
|
+
async ({ task_id, plan, description }) => {
|
|
7841
|
+
try {
|
|
7842
|
+
await connection.call(
|
|
7843
|
+
"updateProjectTask",
|
|
7844
|
+
withRequestingUser(
|
|
7845
|
+
{
|
|
7846
|
+
projectId,
|
|
7847
|
+
taskId: task_id,
|
|
7848
|
+
...plan !== void 0 && { plan },
|
|
7849
|
+
...description !== void 0 && { description }
|
|
7850
|
+
},
|
|
7851
|
+
getRequestingUserId
|
|
7852
|
+
)
|
|
7853
|
+
);
|
|
7854
|
+
return textResult("Task updated successfully.");
|
|
7855
|
+
} catch (error) {
|
|
7856
|
+
return textResult(`Failed to update task: ${errorMessage(error)}`);
|
|
7857
|
+
}
|
|
7858
|
+
}
|
|
7859
|
+
);
|
|
7860
|
+
}
|
|
7861
|
+
function buildForceUpdateStatusTool(connection, getRequestingUserId) {
|
|
7862
|
+
const projectId = connection.projectId;
|
|
7863
|
+
return defineTool(
|
|
7864
|
+
"force_update_task_status",
|
|
7865
|
+
"EMERGENCY ONLY: force-override a task's Kanban status. Use when an automatic transition failed and the task is wedged. Normal flow transitions status automatically.",
|
|
7866
|
+
{
|
|
7867
|
+
task_id: z13.string().describe("The task ID to update"),
|
|
7868
|
+
status: z13.enum(["Planning", "Open", "InProgress", "ReviewPR", "ReviewDev", "ReviewLive", "Complete"]).describe("The new status for the task")
|
|
7869
|
+
},
|
|
7870
|
+
async ({ task_id, status }) => {
|
|
7871
|
+
try {
|
|
7872
|
+
await connection.call(
|
|
7873
|
+
"updateProjectTask",
|
|
7874
|
+
withRequestingUser({ projectId, taskId: task_id, status }, getRequestingUserId)
|
|
7875
|
+
);
|
|
7876
|
+
return textResult(`Task status updated to ${status}.`);
|
|
7877
|
+
} catch (error) {
|
|
7878
|
+
return textResult(`Failed to update status: ${errorMessage(error)}`);
|
|
7879
|
+
}
|
|
7880
|
+
}
|
|
7881
|
+
);
|
|
7882
|
+
}
|
|
7883
|
+
function buildCreateSubtaskTool2(connection, getRequestingUserId) {
|
|
7884
|
+
const projectId = connection.projectId;
|
|
7885
|
+
return defineTool(
|
|
7886
|
+
"create_subtask",
|
|
7887
|
+
"Create a subtask under a parent task in this project. Use for breaking parent tasks into smaller pieces during planning.",
|
|
7888
|
+
{
|
|
7889
|
+
parent_task_id: z13.string().describe("The parent task ID"),
|
|
7890
|
+
title: z13.string().describe("Subtask title"),
|
|
7891
|
+
description: z13.string().optional().describe("Brief description"),
|
|
7892
|
+
plan: z13.string().optional().describe("Implementation plan in markdown"),
|
|
7893
|
+
ordinal: z13.number().optional().describe("Step/order number (0-based)"),
|
|
7894
|
+
storyPointValue: z13.number().optional().describe(SP_DESCRIPTION3)
|
|
7895
|
+
},
|
|
7896
|
+
async ({ parent_task_id, title, description, plan, ordinal, storyPointValue }) => {
|
|
7897
|
+
try {
|
|
7898
|
+
const result = await connection.call(
|
|
7899
|
+
"createProjectSubtask",
|
|
7900
|
+
withRequestingUser(
|
|
7901
|
+
{
|
|
7902
|
+
projectId,
|
|
7903
|
+
parentTaskId: parent_task_id,
|
|
7904
|
+
title,
|
|
7905
|
+
...description !== void 0 && { description },
|
|
7906
|
+
...plan !== void 0 && { plan },
|
|
7907
|
+
...ordinal !== void 0 && { ordinal },
|
|
7908
|
+
...storyPointValue !== void 0 && { storyPointValue }
|
|
7909
|
+
},
|
|
7910
|
+
getRequestingUserId
|
|
7911
|
+
)
|
|
7912
|
+
);
|
|
7913
|
+
return textResult(`Subtask created: ${result.slug} (ID: ${result.id})`);
|
|
7914
|
+
} catch (error) {
|
|
7915
|
+
return textResult(`Failed to create subtask: ${errorMessage(error)}`);
|
|
7916
|
+
}
|
|
7917
|
+
}
|
|
7918
|
+
);
|
|
7919
|
+
}
|
|
7920
|
+
function buildUpdateSubtaskTool2(connection, getRequestingUserId) {
|
|
7921
|
+
const projectId = connection.projectId;
|
|
7922
|
+
return defineTool(
|
|
7923
|
+
"update_subtask",
|
|
7924
|
+
"Update an existing subtask's fields (title, description, plan, status, ordinal, storyPointValue).",
|
|
7925
|
+
{
|
|
7926
|
+
subtask_id: z13.string().describe("The subtask ID to update"),
|
|
7927
|
+
title: z13.string().optional(),
|
|
7928
|
+
description: z13.string().optional(),
|
|
7929
|
+
plan: z13.string().optional(),
|
|
7930
|
+
status: z13.string().optional(),
|
|
7931
|
+
ordinal: z13.number().optional(),
|
|
7932
|
+
storyPointValue: z13.number().optional().describe(SP_DESCRIPTION3)
|
|
7933
|
+
},
|
|
7934
|
+
async ({ subtask_id, ...fields }) => {
|
|
7935
|
+
try {
|
|
7936
|
+
await connection.call(
|
|
7937
|
+
"updateProjectSubtask",
|
|
7938
|
+
withRequestingUser({ projectId, subtaskId: subtask_id, ...fields }, getRequestingUserId)
|
|
7939
|
+
);
|
|
7940
|
+
return textResult("Subtask updated.");
|
|
7941
|
+
} catch (error) {
|
|
7942
|
+
return textResult(`Failed: ${errorMessage(error)}`);
|
|
7943
|
+
}
|
|
7944
|
+
}
|
|
7945
|
+
);
|
|
7946
|
+
}
|
|
7947
|
+
function buildDeleteSubtaskTool2(connection, getRequestingUserId) {
|
|
7948
|
+
const projectId = connection.projectId;
|
|
7949
|
+
return defineTool(
|
|
7950
|
+
"delete_subtask",
|
|
7951
|
+
"Delete a subtask by id. Use when a subtask was created in error or is no longer needed.",
|
|
7952
|
+
{ subtask_id: z13.string().describe("The subtask ID to delete") },
|
|
7953
|
+
async ({ subtask_id }) => {
|
|
7954
|
+
try {
|
|
7955
|
+
await connection.call(
|
|
7956
|
+
"deleteProjectSubtask",
|
|
7957
|
+
withRequestingUser({ projectId, subtaskId: subtask_id }, getRequestingUserId)
|
|
7958
|
+
);
|
|
7959
|
+
return textResult("Subtask deleted.");
|
|
7960
|
+
} catch (error) {
|
|
7961
|
+
return textResult(`Failed: ${errorMessage(error)}`);
|
|
7962
|
+
}
|
|
7963
|
+
}
|
|
7964
|
+
);
|
|
7965
|
+
}
|
|
7966
|
+
function buildStartTaskTool(connection, getRequestingUserId) {
|
|
7967
|
+
const projectId = connection.projectId;
|
|
7968
|
+
return defineTool(
|
|
7969
|
+
"start_task",
|
|
7970
|
+
"Start a cloud build (codespace) for a task. Preconditions: task has a story point value and an agent assigned.",
|
|
7971
|
+
{ task_id: z13.string().describe("The task ID to start a build for") },
|
|
7972
|
+
async ({ task_id }) => {
|
|
7973
|
+
try {
|
|
7974
|
+
const result = await connection.call(
|
|
7975
|
+
"startProjectBuild",
|
|
7976
|
+
withRequestingUser({ projectId, taskId: task_id }, getRequestingUserId)
|
|
7977
|
+
);
|
|
7978
|
+
return textResult(
|
|
7979
|
+
`Cloud build started for task ${result.taskId} (status: ${result.status})`
|
|
7980
|
+
);
|
|
7981
|
+
} catch (error) {
|
|
7982
|
+
return textResult(`Failed to start task: ${errorMessage(error)}`);
|
|
7983
|
+
}
|
|
7984
|
+
}
|
|
7985
|
+
);
|
|
7986
|
+
}
|
|
7987
|
+
function buildStopTaskTool(connection, getRequestingUserId) {
|
|
7988
|
+
const projectId = connection.projectId;
|
|
7989
|
+
return defineTool(
|
|
7990
|
+
"stop_task",
|
|
7991
|
+
"Send a stop signal to a running task's cloud build. Not a force-kill \u2014 the agent may take a moment to wind down.",
|
|
7992
|
+
{ task_id: z13.string().describe("The task ID whose build should be stopped") },
|
|
7993
|
+
async ({ task_id }) => {
|
|
7994
|
+
try {
|
|
7995
|
+
await connection.call(
|
|
7996
|
+
"stopProjectBuild",
|
|
7997
|
+
withRequestingUser({ projectId, taskId: task_id }, getRequestingUserId)
|
|
7998
|
+
);
|
|
7999
|
+
return textResult(`Stop signal sent for task ${task_id}.`);
|
|
8000
|
+
} catch (error) {
|
|
8001
|
+
return textResult(`Failed to stop task: ${errorMessage(error)}`);
|
|
8002
|
+
}
|
|
8003
|
+
}
|
|
8004
|
+
);
|
|
8005
|
+
}
|
|
8006
|
+
function buildMergePRTool(connection, getRequestingUserId) {
|
|
8007
|
+
const projectId = connection.projectId;
|
|
8008
|
+
return defineTool(
|
|
8009
|
+
"merge_pr",
|
|
8010
|
+
"Approve and merge a task's PR. Preconditions: task in ReviewPR with an open PR. Returns { merged }: false means automerge queued \u2014 wait for status to flip to ReviewDev.",
|
|
8011
|
+
{ task_id: z13.string().describe("The task ID whose PR should be approved and merged") },
|
|
8012
|
+
async ({ task_id }) => {
|
|
8013
|
+
try {
|
|
8014
|
+
const result = await connection.call(
|
|
8015
|
+
"approveProjectMergePR",
|
|
8016
|
+
withRequestingUser({ projectId, childTaskId: task_id }, getRequestingUserId)
|
|
8017
|
+
);
|
|
8018
|
+
if (result.merged) {
|
|
7686
8019
|
return textResult(
|
|
7687
|
-
`
|
|
8020
|
+
`PR #${result.prNumber} approved and merged for task ${result.childTaskId}.`
|
|
7688
8021
|
);
|
|
7689
8022
|
}
|
|
7690
|
-
|
|
7691
|
-
|
|
7692
|
-
|
|
7693
|
-
|
|
7694
|
-
|
|
7695
|
-
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
8023
|
+
return textResult(
|
|
8024
|
+
`PR #${result.prNumber} merge queued for task ${result.childTaskId}. The PR will auto-merge when checks pass \u2014 wait for status to flip to ReviewDev.`
|
|
8025
|
+
);
|
|
8026
|
+
} catch (error) {
|
|
8027
|
+
return textResult(`Failed to merge PR: ${errorMessage(error)}`);
|
|
8028
|
+
}
|
|
8029
|
+
}
|
|
8030
|
+
);
|
|
8031
|
+
}
|
|
8032
|
+
function buildCreateSuggestionTool2(connection, getRequestingUserId) {
|
|
8033
|
+
const projectId = connection.projectId;
|
|
8034
|
+
return defineTool(
|
|
8035
|
+
"create_suggestion",
|
|
8036
|
+
"Suggest a feature, improvement, rule, or idea for the project. Duplicates are deduped and your upvote is recorded.",
|
|
8037
|
+
{
|
|
8038
|
+
title: z13.string().describe("Short title for the suggestion"),
|
|
8039
|
+
description: z13.string().optional().describe("1-2 sentence description of what should change and why."),
|
|
8040
|
+
tag_names: z13.array(z13.string()).optional().describe("Tag names to categorize the suggestion")
|
|
8041
|
+
},
|
|
8042
|
+
async ({ title, description, tag_names }) => {
|
|
8043
|
+
try {
|
|
8044
|
+
const result = await connection.call(
|
|
8045
|
+
"createProjectSuggestion",
|
|
8046
|
+
withRequestingUser(
|
|
8047
|
+
{
|
|
8048
|
+
projectId,
|
|
8049
|
+
title,
|
|
8050
|
+
...description !== void 0 && { description },
|
|
8051
|
+
...tag_names !== void 0 && { tagNames: tag_names }
|
|
8052
|
+
},
|
|
8053
|
+
getRequestingUserId
|
|
8054
|
+
)
|
|
8055
|
+
);
|
|
8056
|
+
if (result.merged) {
|
|
7707
8057
|
return textResult(
|
|
7708
|
-
`
|
|
8058
|
+
`Your suggestion was merged into an existing one (ID: ${result.mergedIntoId ?? result.id}). Your upvote has been recorded.`
|
|
7709
8059
|
);
|
|
7710
8060
|
}
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
8061
|
+
return textResult(`Suggestion created (ID: ${result.id}).`);
|
|
8062
|
+
} catch (error) {
|
|
8063
|
+
return textResult(`Failed to create suggestion: ${errorMessage(error)}`);
|
|
8064
|
+
}
|
|
8065
|
+
}
|
|
8066
|
+
);
|
|
8067
|
+
}
|
|
8068
|
+
function buildVoteSuggestionTool2(connection, getRequestingUserId) {
|
|
8069
|
+
const projectId = connection.projectId;
|
|
8070
|
+
return defineTool(
|
|
8071
|
+
"vote_suggestion",
|
|
8072
|
+
"Vote +1 or -1 on a project suggestion.",
|
|
8073
|
+
{
|
|
8074
|
+
suggestion_id: z13.string().describe("The suggestion ID to vote on"),
|
|
8075
|
+
value: z13.number().refine((v) => v === 1 || v === -1, { message: "Value must be 1 or -1" }).describe("+1 to upvote, -1 to downvote")
|
|
8076
|
+
},
|
|
8077
|
+
async ({ suggestion_id, value }) => {
|
|
8078
|
+
try {
|
|
8079
|
+
const result = await connection.call(
|
|
8080
|
+
"voteProjectSuggestion",
|
|
8081
|
+
withRequestingUser(
|
|
8082
|
+
{
|
|
8083
|
+
projectId,
|
|
8084
|
+
suggestionId: suggestion_id,
|
|
8085
|
+
value
|
|
8086
|
+
},
|
|
8087
|
+
getRequestingUserId
|
|
8088
|
+
)
|
|
8089
|
+
);
|
|
8090
|
+
return textResult(`Vote recorded. Current score: ${result.score}`);
|
|
8091
|
+
} catch (error) {
|
|
8092
|
+
return textResult(`Failed to vote: ${errorMessage(error)}`);
|
|
8093
|
+
}
|
|
8094
|
+
}
|
|
8095
|
+
);
|
|
8096
|
+
}
|
|
8097
|
+
function buildAddDependencyTool2(connection, getRequestingUserId) {
|
|
8098
|
+
const projectId = connection.projectId;
|
|
8099
|
+
return defineTool(
|
|
8100
|
+
"add_dependency",
|
|
8101
|
+
"Add a blocking dependency \u2014 a task cannot start until the named task is merged to dev.",
|
|
8102
|
+
{
|
|
8103
|
+
task_id: z13.string().describe("The task that should be blocked"),
|
|
8104
|
+
depends_on_slug_or_id: z13.string().describe("Slug or ID of the task this task depends on")
|
|
8105
|
+
},
|
|
8106
|
+
async ({ task_id, depends_on_slug_or_id }) => {
|
|
8107
|
+
try {
|
|
8108
|
+
await connection.call(
|
|
8109
|
+
"addProjectTaskDependency",
|
|
8110
|
+
withRequestingUser(
|
|
8111
|
+
{
|
|
8112
|
+
projectId,
|
|
8113
|
+
taskId: task_id,
|
|
8114
|
+
dependsOnSlugOrId: depends_on_slug_or_id
|
|
8115
|
+
},
|
|
8116
|
+
getRequestingUserId
|
|
8117
|
+
)
|
|
8118
|
+
);
|
|
8119
|
+
return textResult(
|
|
8120
|
+
`Dependency added: task ${task_id} now depends on "${depends_on_slug_or_id}"`
|
|
8121
|
+
);
|
|
8122
|
+
} catch (error) {
|
|
8123
|
+
return textResult(`Failed to add dependency: ${errorMessage(error)}`);
|
|
8124
|
+
}
|
|
8125
|
+
}
|
|
8126
|
+
);
|
|
7715
8127
|
}
|
|
7716
|
-
function
|
|
8128
|
+
function buildRemoveDependencyTool2(connection, getRequestingUserId) {
|
|
7717
8129
|
const projectId = connection.projectId;
|
|
8130
|
+
return defineTool(
|
|
8131
|
+
"remove_dependency",
|
|
8132
|
+
"Remove a previously added dependency from a task.",
|
|
8133
|
+
{
|
|
8134
|
+
task_id: z13.string().describe("The task to update"),
|
|
8135
|
+
depends_on_slug_or_id: z13.string().describe("Slug or ID of the task to remove as dependency")
|
|
8136
|
+
},
|
|
8137
|
+
async ({ task_id, depends_on_slug_or_id }) => {
|
|
8138
|
+
try {
|
|
8139
|
+
await connection.call(
|
|
8140
|
+
"removeProjectTaskDependency",
|
|
8141
|
+
withRequestingUser(
|
|
8142
|
+
{
|
|
8143
|
+
projectId,
|
|
8144
|
+
taskId: task_id,
|
|
8145
|
+
dependsOnSlugOrId: depends_on_slug_or_id
|
|
8146
|
+
},
|
|
8147
|
+
getRequestingUserId
|
|
8148
|
+
)
|
|
8149
|
+
);
|
|
8150
|
+
return textResult("Dependency removed");
|
|
8151
|
+
} catch (error) {
|
|
8152
|
+
return textResult(`Failed to remove dependency: ${errorMessage(error)}`);
|
|
8153
|
+
}
|
|
8154
|
+
}
|
|
8155
|
+
);
|
|
8156
|
+
}
|
|
8157
|
+
function buildProjectActionTools(connection, getRequestingUserId = () => void 0) {
|
|
7718
8158
|
return [
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
{ annotations: { readOnlyHint: true } }
|
|
7734
|
-
),
|
|
7735
|
-
defineTool(
|
|
7736
|
-
"get_project_summary",
|
|
7737
|
-
"Get a summary of the project including task counts by status and active builds.",
|
|
7738
|
-
{},
|
|
7739
|
-
async () => {
|
|
7740
|
-
try {
|
|
7741
|
-
const summary = await connection.call("getProjectSummary", { projectId });
|
|
7742
|
-
return textResult(JSON.stringify(summary, null, 2));
|
|
7743
|
-
} catch (error) {
|
|
7744
|
-
return textResult(
|
|
7745
|
-
`Failed to get project summary: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
7746
|
-
);
|
|
7747
|
-
}
|
|
7748
|
-
},
|
|
7749
|
-
{ annotations: { readOnlyHint: true } }
|
|
7750
|
-
)
|
|
8159
|
+
buildCreateTaskTool(connection, getRequestingUserId),
|
|
8160
|
+
buildUpdateProjectTaskTool(connection, getRequestingUserId),
|
|
8161
|
+
buildUpdateTaskPlanTool(connection, getRequestingUserId),
|
|
8162
|
+
buildForceUpdateStatusTool(connection, getRequestingUserId),
|
|
8163
|
+
buildCreateSubtaskTool2(connection, getRequestingUserId),
|
|
8164
|
+
buildUpdateSubtaskTool2(connection, getRequestingUserId),
|
|
8165
|
+
buildDeleteSubtaskTool2(connection, getRequestingUserId),
|
|
8166
|
+
buildStartTaskTool(connection, getRequestingUserId),
|
|
8167
|
+
buildStopTaskTool(connection, getRequestingUserId),
|
|
8168
|
+
buildMergePRTool(connection, getRequestingUserId),
|
|
8169
|
+
buildCreateSuggestionTool2(connection, getRequestingUserId),
|
|
8170
|
+
buildVoteSuggestionTool2(connection, getRequestingUserId),
|
|
8171
|
+
buildAddDependencyTool2(connection, getRequestingUserId),
|
|
8172
|
+
buildRemoveDependencyTool2(connection, getRequestingUserId)
|
|
7751
8173
|
];
|
|
7752
8174
|
}
|
|
7753
|
-
|
|
8175
|
+
|
|
8176
|
+
// src/tools/project-tools.ts
|
|
8177
|
+
function errorMessage(error) {
|
|
8178
|
+
return error instanceof Error ? error.message : "Unknown error";
|
|
8179
|
+
}
|
|
8180
|
+
function buildListTasksTool(connection) {
|
|
7754
8181
|
const projectId = connection.projectId;
|
|
7755
|
-
return
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
} catch (error) {
|
|
7770
|
-
return textResult(
|
|
7771
|
-
`Failed to create task: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
7772
|
-
);
|
|
7773
|
-
}
|
|
8182
|
+
return defineTool(
|
|
8183
|
+
"list_tasks",
|
|
8184
|
+
"List tasks in the project. Optionally filter by status or assignee.",
|
|
8185
|
+
{
|
|
8186
|
+
status: z14.string().optional().describe("Filter by task status"),
|
|
8187
|
+
assigneeId: z14.string().optional().describe("Filter by assigned user ID"),
|
|
8188
|
+
limit: z14.number().optional().describe("Max number of tasks to return (default 50)")
|
|
8189
|
+
},
|
|
8190
|
+
async (params) => {
|
|
8191
|
+
try {
|
|
8192
|
+
const tasks = await connection.call("listProjectTasks", { projectId, ...params });
|
|
8193
|
+
return textResult(JSON.stringify(tasks, null, 2));
|
|
8194
|
+
} catch (error) {
|
|
8195
|
+
return textResult(`Failed to list tasks: ${errorMessage(error)}`);
|
|
7774
8196
|
}
|
|
7775
|
-
|
|
7776
|
-
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
7784
|
-
|
|
7785
|
-
|
|
7786
|
-
|
|
7787
|
-
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
7794
|
-
|
|
8197
|
+
},
|
|
8198
|
+
{ annotations: { readOnlyHint: true } }
|
|
8199
|
+
);
|
|
8200
|
+
}
|
|
8201
|
+
function buildGetProjectTaskTool(connection) {
|
|
8202
|
+
const projectId = connection.projectId;
|
|
8203
|
+
return defineTool(
|
|
8204
|
+
"get_project_task",
|
|
8205
|
+
"Get detailed information about a task in this project (chat messages, child tasks, session). Project-runner scope.",
|
|
8206
|
+
{ task_id: z14.string().describe("The task ID to look up") },
|
|
8207
|
+
async ({ task_id }) => {
|
|
8208
|
+
try {
|
|
8209
|
+
const task = await connection.call("getProjectTask", { projectId, taskId: task_id });
|
|
8210
|
+
return textResult(JSON.stringify(task, null, 2));
|
|
8211
|
+
} catch (error) {
|
|
8212
|
+
return textResult(`Failed to get task: ${errorMessage(error)}`);
|
|
8213
|
+
}
|
|
8214
|
+
},
|
|
8215
|
+
{ annotations: { readOnlyHint: true } }
|
|
8216
|
+
);
|
|
8217
|
+
}
|
|
8218
|
+
function buildSearchTasksTool(connection) {
|
|
8219
|
+
const projectId = connection.projectId;
|
|
8220
|
+
return defineTool(
|
|
8221
|
+
"search_tasks",
|
|
8222
|
+
"Search tasks by tags, text query, or status filters.",
|
|
8223
|
+
{
|
|
8224
|
+
tagNames: z14.array(z14.string()).optional().describe("Filter by tag names"),
|
|
8225
|
+
searchQuery: z14.string().optional().describe("Text search in title/description"),
|
|
8226
|
+
statusFilters: z14.array(z14.string()).optional().describe("Filter by statuses"),
|
|
8227
|
+
limit: z14.number().optional().describe("Max results (default 20)")
|
|
8228
|
+
},
|
|
8229
|
+
async (params) => {
|
|
8230
|
+
try {
|
|
8231
|
+
const tasks = await connection.call("searchProjectTasks", { projectId, ...params });
|
|
8232
|
+
return textResult(JSON.stringify(tasks, null, 2));
|
|
8233
|
+
} catch (error) {
|
|
8234
|
+
return textResult(`Failed to search tasks: ${errorMessage(error)}`);
|
|
8235
|
+
}
|
|
8236
|
+
},
|
|
8237
|
+
{ annotations: { readOnlyHint: true } }
|
|
8238
|
+
);
|
|
8239
|
+
}
|
|
8240
|
+
function buildListSubtasksTool2(connection) {
|
|
8241
|
+
const projectId = connection.projectId;
|
|
8242
|
+
return defineTool(
|
|
8243
|
+
"list_subtasks",
|
|
8244
|
+
"List the immediate child tasks under a parent task. Use to coordinate subtask work \u2014 see status, ordering, and PR state.",
|
|
8245
|
+
{ task_id: z14.string().describe("Parent task ID") },
|
|
8246
|
+
async ({ task_id }) => {
|
|
8247
|
+
try {
|
|
8248
|
+
const subtasks = await connection.call("listProjectSubtasks", {
|
|
8249
|
+
projectId,
|
|
8250
|
+
taskId: task_id
|
|
8251
|
+
});
|
|
8252
|
+
return textResult(JSON.stringify(subtasks, null, 2));
|
|
8253
|
+
} catch (error) {
|
|
8254
|
+
return textResult(`Failed to list subtasks: ${errorMessage(error)}`);
|
|
8255
|
+
}
|
|
8256
|
+
},
|
|
8257
|
+
{ annotations: { readOnlyHint: true } }
|
|
8258
|
+
);
|
|
8259
|
+
}
|
|
8260
|
+
function buildListTagsTool(connection) {
|
|
8261
|
+
const projectId = connection.projectId;
|
|
8262
|
+
return defineTool(
|
|
8263
|
+
"list_tags",
|
|
8264
|
+
"List all tags available in the project.",
|
|
8265
|
+
{},
|
|
8266
|
+
async () => {
|
|
8267
|
+
try {
|
|
8268
|
+
const tags = await connection.call("listProjectTags", { projectId });
|
|
8269
|
+
return textResult(JSON.stringify(tags, null, 2));
|
|
8270
|
+
} catch (error) {
|
|
8271
|
+
return textResult(`Failed to list tags: ${errorMessage(error)}`);
|
|
8272
|
+
}
|
|
8273
|
+
},
|
|
8274
|
+
{ annotations: { readOnlyHint: true } }
|
|
8275
|
+
);
|
|
8276
|
+
}
|
|
8277
|
+
function buildGetProjectSummaryTool(connection) {
|
|
8278
|
+
const projectId = connection.projectId;
|
|
8279
|
+
return defineTool(
|
|
8280
|
+
"get_project_summary",
|
|
8281
|
+
"Get a summary of the project including task counts by status and active builds.",
|
|
8282
|
+
{},
|
|
8283
|
+
async () => {
|
|
8284
|
+
try {
|
|
8285
|
+
const summary = await connection.call("getProjectSummary", { projectId });
|
|
8286
|
+
return textResult(JSON.stringify(summary, null, 2));
|
|
8287
|
+
} catch (error) {
|
|
8288
|
+
return textResult(`Failed to get project summary: ${errorMessage(error)}`);
|
|
8289
|
+
}
|
|
8290
|
+
},
|
|
8291
|
+
{ annotations: { readOnlyHint: true } }
|
|
8292
|
+
);
|
|
8293
|
+
}
|
|
8294
|
+
function buildPostToChatTool2(connection, getRequestingUserId) {
|
|
8295
|
+
const projectId = connection.projectId;
|
|
8296
|
+
return defineTool(
|
|
8297
|
+
"post_to_chat",
|
|
8298
|
+
"Post an out-of-band message into a chat. Omit task_id to post into the project chat; pass task_id to post into a specific task's chat. Normal replies already appear in chat automatically.",
|
|
8299
|
+
{
|
|
8300
|
+
message: z14.string().describe("The message content to post"),
|
|
8301
|
+
task_id: z14.string().optional().describe("Task ID to post into a specific task's chat. Omit for the project chat.")
|
|
8302
|
+
},
|
|
8303
|
+
async ({ message, task_id }) => {
|
|
8304
|
+
try {
|
|
8305
|
+
const requestingUserId = getRequestingUserId();
|
|
8306
|
+
if (task_id) {
|
|
8307
|
+
await connection.call("postToProjectTaskChat", {
|
|
8308
|
+
projectId,
|
|
8309
|
+
taskId: task_id,
|
|
8310
|
+
content: message,
|
|
8311
|
+
...requestingUserId ? { requestingUserId } : {}
|
|
8312
|
+
});
|
|
8313
|
+
return textResult(JSON.stringify({ posted: true, target: `task:${task_id}` }));
|
|
7795
8314
|
}
|
|
8315
|
+
await connection.call("postProjectAgentMessage", { projectId, content: message });
|
|
8316
|
+
return textResult(JSON.stringify({ posted: true, target: "project" }));
|
|
8317
|
+
} catch (error) {
|
|
8318
|
+
return textResult(`Failed to post message: ${errorMessage(error)}`);
|
|
7796
8319
|
}
|
|
7797
|
-
|
|
7798
|
-
|
|
8320
|
+
}
|
|
8321
|
+
);
|
|
8322
|
+
}
|
|
8323
|
+
function buildReadChatHistoryTool(connection) {
|
|
8324
|
+
const projectId = connection.projectId;
|
|
8325
|
+
return defineTool(
|
|
8326
|
+
"read_chat_history",
|
|
8327
|
+
"Read recent messages from a chat. Omit chat_id to read the project chat; pass a chat_id to read a specific chat.",
|
|
8328
|
+
{
|
|
8329
|
+
chat_id: z14.string().optional().describe("Chat ID to read. Omit for the project chat."),
|
|
8330
|
+
limit: z14.number().optional().describe("Number of recent messages to fetch (default 50)")
|
|
8331
|
+
},
|
|
8332
|
+
async ({ chat_id, limit }) => {
|
|
8333
|
+
try {
|
|
8334
|
+
const messages = await connection.call("getProjectChatHistory", {
|
|
8335
|
+
projectId,
|
|
8336
|
+
...chat_id !== void 0 && { chatId: chat_id },
|
|
8337
|
+
...limit !== void 0 && { limit }
|
|
8338
|
+
});
|
|
8339
|
+
return textResult(JSON.stringify(messages, null, 2));
|
|
8340
|
+
} catch (error) {
|
|
8341
|
+
return textResult(`Failed to read chat history: ${errorMessage(error)}`);
|
|
8342
|
+
}
|
|
8343
|
+
},
|
|
8344
|
+
{ annotations: { readOnlyHint: true } }
|
|
8345
|
+
);
|
|
7799
8346
|
}
|
|
7800
|
-
function
|
|
8347
|
+
function buildReadTaskChatTool2(connection) {
|
|
8348
|
+
const projectId = connection.projectId;
|
|
8349
|
+
return defineTool(
|
|
8350
|
+
"read_task_chat",
|
|
8351
|
+
"Read recent human/user chat messages for a specific task in this project. For agent execution logs use get_task_logs.",
|
|
8352
|
+
{
|
|
8353
|
+
task_id: z14.string().describe("The task ID whose chat to read"),
|
|
8354
|
+
limit: z14.number().optional().describe("Number of recent messages to fetch (default 20)")
|
|
8355
|
+
},
|
|
8356
|
+
async ({ task_id, limit }) => {
|
|
8357
|
+
try {
|
|
8358
|
+
const messages = await connection.call("getProjectTaskChat", {
|
|
8359
|
+
projectId,
|
|
8360
|
+
taskId: task_id,
|
|
8361
|
+
...limit !== void 0 && { limit }
|
|
8362
|
+
});
|
|
8363
|
+
return textResult(JSON.stringify(messages, null, 2));
|
|
8364
|
+
} catch (error) {
|
|
8365
|
+
return textResult(`Failed to read task chat: ${errorMessage(error)}`);
|
|
8366
|
+
}
|
|
8367
|
+
},
|
|
8368
|
+
{ annotations: { readOnlyHint: true } }
|
|
8369
|
+
);
|
|
8370
|
+
}
|
|
8371
|
+
function buildGetTaskLogsTool(connection) {
|
|
8372
|
+
const projectId = connection.projectId;
|
|
8373
|
+
return defineTool(
|
|
8374
|
+
"get_task_logs",
|
|
8375
|
+
"Read CLI execution logs for a task \u2014 agent reasoning, tool calls, and setup/dev-server output. For human chat use read_task_chat.",
|
|
8376
|
+
{
|
|
8377
|
+
task_id: z14.string().describe("Task ID to read logs from"),
|
|
8378
|
+
source: z14.enum(["agent", "application"]).optional().describe("Filter by log source. Omit for all logs."),
|
|
8379
|
+
limit: z14.number().optional().describe("Max number of log entries to return (default 50, max 500).")
|
|
8380
|
+
},
|
|
8381
|
+
async ({ task_id, source, limit }) => {
|
|
8382
|
+
try {
|
|
8383
|
+
const logs = await connection.call("getProjectTaskCli", {
|
|
8384
|
+
projectId,
|
|
8385
|
+
taskId: task_id,
|
|
8386
|
+
...source !== void 0 && { source },
|
|
8387
|
+
...limit !== void 0 && { limit }
|
|
8388
|
+
});
|
|
8389
|
+
return textResult(JSON.stringify(logs, null, 2));
|
|
8390
|
+
} catch (error) {
|
|
8391
|
+
return textResult(`Failed to fetch task logs: ${errorMessage(error)}`);
|
|
8392
|
+
}
|
|
8393
|
+
},
|
|
8394
|
+
{ annotations: { readOnlyHint: true } }
|
|
8395
|
+
);
|
|
8396
|
+
}
|
|
8397
|
+
function buildProjectTools(connection, getRequestingUserId = () => void 0) {
|
|
7801
8398
|
return [
|
|
7802
|
-
|
|
7803
|
-
|
|
7804
|
-
|
|
8399
|
+
buildListTasksTool(connection),
|
|
8400
|
+
buildGetProjectTaskTool(connection),
|
|
8401
|
+
buildSearchTasksTool(connection),
|
|
8402
|
+
buildListSubtasksTool2(connection),
|
|
8403
|
+
buildListTagsTool(connection),
|
|
8404
|
+
buildGetProjectSummaryTool(connection),
|
|
8405
|
+
buildPostToChatTool2(connection, getRequestingUserId),
|
|
8406
|
+
buildReadChatHistoryTool(connection),
|
|
8407
|
+
buildReadTaskChatTool2(connection),
|
|
8408
|
+
buildGetTaskLogsTool(connection),
|
|
8409
|
+
...buildProjectActionTools(connection, getRequestingUserId)
|
|
7805
8410
|
];
|
|
7806
8411
|
}
|
|
7807
8412
|
|
|
@@ -7867,13 +8472,13 @@ async function fetchContext(connection, chatId) {
|
|
|
7867
8472
|
}
|
|
7868
8473
|
return { agentCtx, chatHistory };
|
|
7869
8474
|
}
|
|
7870
|
-
function buildChatQueryOptions(agentCtx, projectDir, connection) {
|
|
8475
|
+
function buildChatQueryOptions(agentCtx, projectDir, connection, getRequestingUserId) {
|
|
7871
8476
|
const model = agentCtx?.model || FALLBACK_MODEL;
|
|
7872
8477
|
const settings = agentCtx?.agentSettings ?? {};
|
|
7873
8478
|
const harness = createHarness();
|
|
7874
8479
|
const mcpServer = harness.createMcpServer({
|
|
7875
8480
|
name: "conveyor",
|
|
7876
|
-
tools: buildProjectTools(connection)
|
|
8481
|
+
tools: buildProjectTools(connection, getRequestingUserId)
|
|
7877
8482
|
});
|
|
7878
8483
|
return {
|
|
7879
8484
|
options: {
|
|
@@ -7942,7 +8547,13 @@ function emitResultCost(event, connection) {
|
|
|
7942
8547
|
}
|
|
7943
8548
|
async function runChatQuery(message, connection, projectDir, sessionId) {
|
|
7944
8549
|
const { agentCtx, chatHistory } = await fetchContext(connection, message.chatId);
|
|
7945
|
-
const
|
|
8550
|
+
const requestingUserId = message.userId;
|
|
8551
|
+
const { options, harness } = buildChatQueryOptions(
|
|
8552
|
+
agentCtx,
|
|
8553
|
+
projectDir,
|
|
8554
|
+
connection,
|
|
8555
|
+
() => requestingUserId
|
|
8556
|
+
);
|
|
7946
8557
|
const prompt = buildPrompt(message, chatHistory);
|
|
7947
8558
|
connection.emitStatus("busy");
|
|
7948
8559
|
const events = harness.executeQuery({
|
|
@@ -8003,15 +8614,15 @@ function parseErrorMessage(error) {
|
|
|
8003
8614
|
|
|
8004
8615
|
// src/runner/project-runner-children.ts
|
|
8005
8616
|
import { fork } from "child_process";
|
|
8006
|
-
import { execSync as
|
|
8617
|
+
import { execSync as execSync8 } from "child_process";
|
|
8007
8618
|
import * as path from "path";
|
|
8008
8619
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8009
8620
|
|
|
8010
8621
|
// src/runner/project-runner-git.ts
|
|
8011
|
-
import { execSync as
|
|
8622
|
+
import { execSync as execSync7 } from "child_process";
|
|
8012
8623
|
|
|
8013
8624
|
// src/runner/project-runner-sync.ts
|
|
8014
|
-
import { execSync as
|
|
8625
|
+
import { execSync as execSync6 } from "child_process";
|
|
8015
8626
|
var logger7 = createServiceLogger("ProjectRunner");
|
|
8016
8627
|
var START_CMD_KILL_TIMEOUT_MS = 5e3;
|
|
8017
8628
|
async function executeSetupCommand(projectDir, connection) {
|
|
@@ -8108,7 +8719,7 @@ async function handleSyncEnvironment(projectDir, branchSwitchCommand, state, con
|
|
|
8108
8719
|
}
|
|
8109
8720
|
function getChangedFiles(projectDir, previousSha, newSha) {
|
|
8110
8721
|
try {
|
|
8111
|
-
return
|
|
8722
|
+
return execSync6(`git diff --name-only ${previousSha}..${newSha}`, {
|
|
8112
8723
|
cwd: projectDir,
|
|
8113
8724
|
stdio: ["ignore", "pipe", "ignore"]
|
|
8114
8725
|
}).toString().trim().split("\n").filter(Boolean);
|
|
@@ -8119,7 +8730,7 @@ function getChangedFiles(projectDir, previousSha, newSha) {
|
|
|
8119
8730
|
function runIndividualSyncSteps(projectDir, needsInstall, needsPrisma, stepsRun) {
|
|
8120
8731
|
if (needsInstall) {
|
|
8121
8732
|
try {
|
|
8122
|
-
|
|
8733
|
+
execSync6("bun install", { cwd: projectDir, timeout: 12e4, stdio: "pipe" });
|
|
8123
8734
|
stepsRun.push("install");
|
|
8124
8735
|
} catch (err) {
|
|
8125
8736
|
const msg = parseErrorMessage(err);
|
|
@@ -8128,8 +8739,8 @@ function runIndividualSyncSteps(projectDir, needsInstall, needsPrisma, stepsRun)
|
|
|
8128
8739
|
}
|
|
8129
8740
|
if (needsPrisma) {
|
|
8130
8741
|
try {
|
|
8131
|
-
|
|
8132
|
-
|
|
8742
|
+
execSync6("bunx prisma generate", { cwd: projectDir, timeout: 6e4, stdio: "pipe" });
|
|
8743
|
+
execSync6("bunx prisma db push --accept-data-loss", {
|
|
8133
8744
|
cwd: projectDir,
|
|
8134
8745
|
timeout: 6e4,
|
|
8135
8746
|
stdio: "pipe"
|
|
@@ -8173,7 +8784,7 @@ async function smartSync(projectDir, branchSwitchCommand, state, connection, pre
|
|
|
8173
8784
|
}
|
|
8174
8785
|
await killStartCommand(state);
|
|
8175
8786
|
try {
|
|
8176
|
-
|
|
8787
|
+
execSync6(`git pull origin ${branch}`, {
|
|
8177
8788
|
cwd: projectDir,
|
|
8178
8789
|
stdio: "pipe",
|
|
8179
8790
|
timeout: 6e4
|
|
@@ -8209,10 +8820,10 @@ function setupWorkDir(projectDir, assignment) {
|
|
|
8209
8820
|
logger8.warn("Uncommitted changes, skipping checkout", { taskId: shortId, branch });
|
|
8210
8821
|
} else {
|
|
8211
8822
|
try {
|
|
8212
|
-
|
|
8823
|
+
execSync7(`git checkout ${branch}`, { cwd: workDir, stdio: "ignore" });
|
|
8213
8824
|
} catch {
|
|
8214
8825
|
try {
|
|
8215
|
-
|
|
8826
|
+
execSync7(`git checkout -b ${branch}`, { cwd: workDir, stdio: "ignore" });
|
|
8216
8827
|
} catch {
|
|
8217
8828
|
logger8.warn("Could not checkout branch", { taskId: shortId, branch });
|
|
8218
8829
|
}
|
|
@@ -8231,8 +8842,8 @@ function checkoutWorkspaceBranch(projectDir) {
|
|
|
8231
8842
|
return;
|
|
8232
8843
|
}
|
|
8233
8844
|
try {
|
|
8234
|
-
|
|
8235
|
-
|
|
8845
|
+
execSync7(`git fetch origin ${workspaceBranch}`, { cwd: projectDir, stdio: "pipe" });
|
|
8846
|
+
execSync7(`git checkout ${workspaceBranch}`, { cwd: projectDir, stdio: "pipe" });
|
|
8236
8847
|
logger8.info("Checked out workspace branch", { workspaceBranch });
|
|
8237
8848
|
} catch {
|
|
8238
8849
|
logger8.warn("Failed to checkout workspace branch", { workspaceBranch });
|
|
@@ -8241,20 +8852,20 @@ function checkoutWorkspaceBranch(projectDir) {
|
|
|
8241
8852
|
async function handleSwitchBranch(projectDir, branchSwitchCommand, startCmd, connection, commitWatcher, data, callback) {
|
|
8242
8853
|
try {
|
|
8243
8854
|
try {
|
|
8244
|
-
|
|
8855
|
+
execSync7("git fetch origin", { cwd: projectDir, stdio: "pipe" });
|
|
8245
8856
|
} catch {
|
|
8246
8857
|
logger8.warn("Git fetch failed during branch switch");
|
|
8247
8858
|
}
|
|
8248
8859
|
detachWorktreeBranch(projectDir, data.branch);
|
|
8249
8860
|
try {
|
|
8250
|
-
|
|
8861
|
+
execSync7(`git checkout ${data.branch}`, { cwd: projectDir, stdio: "pipe" });
|
|
8251
8862
|
} catch (err) {
|
|
8252
8863
|
const msg = parseErrorMessage(err);
|
|
8253
8864
|
callback({ ok: false, error: `Failed to checkout branch: ${msg}` });
|
|
8254
8865
|
return;
|
|
8255
8866
|
}
|
|
8256
8867
|
try {
|
|
8257
|
-
|
|
8868
|
+
execSync7(`git pull origin ${data.branch}`, { cwd: projectDir, stdio: "pipe" });
|
|
8258
8869
|
} catch {
|
|
8259
8870
|
logger8.warn("Git pull failed during branch switch");
|
|
8260
8871
|
}
|
|
@@ -8397,7 +9008,7 @@ async function handleAssignment(assignment, activeAgents, projectDir, connection
|
|
|
8397
9008
|
}
|
|
8398
9009
|
try {
|
|
8399
9010
|
try {
|
|
8400
|
-
|
|
9011
|
+
execSync8("git fetch origin", { cwd: projectDir, stdio: "ignore" });
|
|
8401
9012
|
} catch {
|
|
8402
9013
|
logger9.warn("Git fetch failed", { taskId: shortId });
|
|
8403
9014
|
}
|
|
@@ -8458,6 +9069,10 @@ var ProjectRunner = class {
|
|
|
8458
9069
|
stopping = false;
|
|
8459
9070
|
resolveLifecycle = null;
|
|
8460
9071
|
chatSessionIds = /* @__PURE__ */ new Map();
|
|
9072
|
+
/** ProjectCodespaceSession id assigned at register time. Used to filter
|
|
9073
|
+
* targeted incoming chat messages so we only react to ones addressed
|
|
9074
|
+
* to this specific runner. */
|
|
9075
|
+
projectSessionId = null;
|
|
8461
9076
|
startCmd = { child: null, running: false };
|
|
8462
9077
|
setupComplete = false;
|
|
8463
9078
|
branchSwitchCommand;
|
|
@@ -8497,6 +9112,7 @@ var ProjectRunner = class {
|
|
|
8497
9112
|
projectId: this.connection.projectId,
|
|
8498
9113
|
capabilities: ["task", "pm", "code-review", "audit"]
|
|
8499
9114
|
});
|
|
9115
|
+
this.projectSessionId = registration.sessionId;
|
|
8500
9116
|
this.branchSwitchCommand = registration.branchSwitchCommand ?? process.env.CONVEYOR_BRANCH_SWITCH_COMMAND;
|
|
8501
9117
|
logger10.info("Registered as project agent", { agentName: registration.agentName });
|
|
8502
9118
|
try {
|
|
@@ -8603,6 +9219,9 @@ var ProjectRunner = class {
|
|
|
8603
9219
|
);
|
|
8604
9220
|
this.connection.onShutdown(() => void this.stop());
|
|
8605
9221
|
this.connection.onChatMessage((msg) => {
|
|
9222
|
+
if (msg.targetSessionId && this.projectSessionId && msg.targetSessionId !== this.projectSessionId) {
|
|
9223
|
+
return;
|
|
9224
|
+
}
|
|
8606
9225
|
const chatId = msg.chatId ?? "default";
|
|
8607
9226
|
const existingSessionId = this.chatSessionIds.get(chatId);
|
|
8608
9227
|
void handleProjectChatMessage(msg, this.connection, this.projectDir, existingSessionId).then(
|
|
@@ -8641,10 +9260,11 @@ var ProjectRunner = class {
|
|
|
8641
9260
|
}
|
|
8642
9261
|
async handleReconnect() {
|
|
8643
9262
|
try {
|
|
8644
|
-
await this.connection.call("registerProjectAgent", {
|
|
9263
|
+
const registration = await this.connection.call("registerProjectAgent", {
|
|
8645
9264
|
projectId: this.connection.projectId,
|
|
8646
9265
|
capabilities: ["task", "pm", "code-review", "audit"]
|
|
8647
9266
|
});
|
|
9267
|
+
this.projectSessionId = registration.sessionId;
|
|
8648
9268
|
this.connection.emitStatus(this.activeAgents.size > 0 ? "busy" : "idle");
|
|
8649
9269
|
logger10.info("Re-registered after reconnect");
|
|
8650
9270
|
} catch (error) {
|
|
@@ -8804,4 +9424,4 @@ export {
|
|
|
8804
9424
|
buildSessionPreviewPorts,
|
|
8805
9425
|
loadConveyorConfig
|
|
8806
9426
|
};
|
|
8807
|
-
//# sourceMappingURL=chunk-
|
|
9427
|
+
//# sourceMappingURL=chunk-Y6IHF32X.js.map
|