claude-task-worker 0.104.0 → 0.105.0
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/index.js +74 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1470,6 +1470,61 @@ async function listPrsClosingIssue(issueNumber) {
|
|
|
1470
1470
|
createdAt: node.createdAt ?? ""
|
|
1471
1471
|
}));
|
|
1472
1472
|
}
|
|
1473
|
+
async function fetchPrRef(owner, name, prNumber) {
|
|
1474
|
+
try {
|
|
1475
|
+
const parsed = JSON.parse(await execGh(["api", `repos/${owner}/${name}/pulls/${prNumber}`]));
|
|
1476
|
+
return {
|
|
1477
|
+
number: prNumber,
|
|
1478
|
+
state: parsed?.merged_at ? "MERGED" : String(parsed?.state ?? "").toUpperCase(),
|
|
1479
|
+
headRefName: parsed?.head?.ref ?? "",
|
|
1480
|
+
baseRefName: parsed?.base?.ref ?? "",
|
|
1481
|
+
createdAt: parsed?.created_at ?? "",
|
|
1482
|
+
body: typeof parsed?.body === "string" ? parsed.body : ""
|
|
1483
|
+
};
|
|
1484
|
+
} catch (err) {
|
|
1485
|
+
console.error(`[gh] failed to read PR #${prNumber}: ${err}`);
|
|
1486
|
+
return null;
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
function bodyClosesIssue(body, issueNumber) {
|
|
1490
|
+
const pattern = new RegExp(`\\b(close[sd]?|fix(?:e[sd])?|resolve[sd]?)\\s*:?\\s*#${issueNumber}\\b(?!\\d)`, "i");
|
|
1491
|
+
return pattern.test(body);
|
|
1492
|
+
}
|
|
1493
|
+
async function listPrsCrossReferencingIssue(issueNumber) {
|
|
1494
|
+
const { owner, name } = await getRepoInfo();
|
|
1495
|
+
const output = await execGh(["api", `repos/${owner}/${name}/issues/${issueNumber}/timeline`, "--paginate"]);
|
|
1496
|
+
const events = JSON.parse(output);
|
|
1497
|
+
const numbers = [
|
|
1498
|
+
...new Set(
|
|
1499
|
+
events.filter(
|
|
1500
|
+
(e) => e.event === "cross-referenced" && e.source?.issue?.pull_request != null && e.source.issue.repository?.full_name === `${owner}/${name}` && typeof e.source.issue.number === "number"
|
|
1501
|
+
).map((e) => e.source?.issue?.number)
|
|
1502
|
+
)
|
|
1503
|
+
];
|
|
1504
|
+
const refs = await Promise.all(numbers.map((number) => fetchPrRef(owner, name, number)));
|
|
1505
|
+
return refs.filter((ref) => ref !== null && bodyClosesIssue(ref.body, issueNumber)).map(({ body: _body, ...ref }) => ref);
|
|
1506
|
+
}
|
|
1507
|
+
var ADD_CLOSE_ISSUE_REFERENCES = `mutation($issueId: ID!, $prId: ID!) {
|
|
1508
|
+
addCloseIssueReferences(input: { issueId: $issueId, pullRequestIds: [$prId] }) { issue { number } }
|
|
1509
|
+
}`;
|
|
1510
|
+
async function linkClosingPr(issueNumber, prNumber) {
|
|
1511
|
+
const { owner, name } = await getRepoInfo();
|
|
1512
|
+
const issueId = JSON.parse(await execGh(["api", `repos/${owner}/${name}/issues/${issueNumber}`]))?.node_id;
|
|
1513
|
+
const prId = JSON.parse(await execGh(["api", `repos/${owner}/${name}/pulls/${prNumber}`]))?.node_id;
|
|
1514
|
+
if (typeof issueId !== "string" || typeof prId !== "string") {
|
|
1515
|
+
throw new Error(`node_id not found (issue #${issueNumber} / PR #${prNumber})`);
|
|
1516
|
+
}
|
|
1517
|
+
await execGh([
|
|
1518
|
+
"api",
|
|
1519
|
+
"graphql",
|
|
1520
|
+
"-f",
|
|
1521
|
+
`query=${ADD_CLOSE_ISSUE_REFERENCES}`,
|
|
1522
|
+
"-F",
|
|
1523
|
+
`issueId=${issueId}`,
|
|
1524
|
+
"-F",
|
|
1525
|
+
`prId=${prId}`
|
|
1526
|
+
]);
|
|
1527
|
+
}
|
|
1473
1528
|
async function getIssueSubIssuesSummary(issueNumber) {
|
|
1474
1529
|
const output = await execGh(["issue", "view", String(issueNumber), "--json", "subIssuesSummary"]);
|
|
1475
1530
|
const parsed = JSON.parse(output);
|
|
@@ -4007,19 +4062,31 @@ async function verifyPrCreated(issueNumber, worktreeId, output, ctx) {
|
|
|
4007
4062
|
console.log(`[exec-issue] #${issueNumber}: issue closed by skill (no-change path), skip cc-pr-created`);
|
|
4008
4063
|
return;
|
|
4009
4064
|
}
|
|
4065
|
+
const ownership = {
|
|
4066
|
+
cloud: ctx.cloud,
|
|
4067
|
+
expectedHeadRefName: worktreeId,
|
|
4068
|
+
baseBranch: ctx.baseBranch,
|
|
4069
|
+
startedAt: ctx.startedAt,
|
|
4070
|
+
now: Date.now()
|
|
4071
|
+
};
|
|
4010
4072
|
let prNumber = null;
|
|
4011
4073
|
if (!ctx.cloud) {
|
|
4012
4074
|
prNumber = await findPrNumberByHeadRef(worktreeId, "all");
|
|
4013
4075
|
}
|
|
4014
4076
|
if (prNumber === null) {
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
now: Date.now()
|
|
4077
|
+
prNumber = selectOwnedClosingPr(await listPrsClosingIssue(issueNumber), ownership);
|
|
4078
|
+
}
|
|
4079
|
+
if (prNumber === null) {
|
|
4080
|
+
const candidates = await listPrsCrossReferencingIssue(issueNumber).catch((err) => {
|
|
4081
|
+
console.error(`[exec-issue] listPrsCrossReferencingIssue failed for #${issueNumber}: ${err}`);
|
|
4082
|
+
return [];
|
|
4022
4083
|
});
|
|
4084
|
+
prNumber = selectOwnedClosingPr(candidates, ownership);
|
|
4085
|
+
if (prNumber !== null) {
|
|
4086
|
+
await linkClosingPr(issueNumber, prNumber).catch(
|
|
4087
|
+
(err) => console.error(`[exec-issue] linkClosingPr failed for #${issueNumber} -> #${prNumber}: ${err}`)
|
|
4088
|
+
);
|
|
4089
|
+
}
|
|
4023
4090
|
}
|
|
4024
4091
|
if (prNumber !== null) {
|
|
4025
4092
|
await addLabel("issue", issueNumber, "cc-pr-created");
|