@neturely/okffs 0.2.1

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.
Files changed (96) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/LICENSE +21 -0
  3. package/README.md +251 -0
  4. package/dist/config.d.ts +13 -0
  5. package/dist/config.d.ts.map +1 -0
  6. package/dist/config.js +27 -0
  7. package/dist/config.js.map +1 -0
  8. package/dist/docs.d.ts +11 -0
  9. package/dist/docs.d.ts.map +1 -0
  10. package/dist/docs.js +203 -0
  11. package/dist/docs.js.map +1 -0
  12. package/dist/git.d.ts +7 -0
  13. package/dist/git.d.ts.map +1 -0
  14. package/dist/git.js +22 -0
  15. package/dist/git.js.map +1 -0
  16. package/dist/github.d.ts +111 -0
  17. package/dist/github.d.ts.map +1 -0
  18. package/dist/github.js +301 -0
  19. package/dist/github.js.map +1 -0
  20. package/dist/index.d.ts +3 -0
  21. package/dist/index.d.ts.map +1 -0
  22. package/dist/index.js +63 -0
  23. package/dist/index.js.map +1 -0
  24. package/dist/prompts/address_pr_review.d.ts +18 -0
  25. package/dist/prompts/address_pr_review.d.ts.map +1 -0
  26. package/dist/prompts/address_pr_review.js +35 -0
  27. package/dist/prompts/address_pr_review.js.map +1 -0
  28. package/dist/prompts/update_guidance.d.ts +18 -0
  29. package/dist/prompts/update_guidance.d.ts.map +1 -0
  30. package/dist/prompts/update_guidance.js +47 -0
  31. package/dist/prompts/update_guidance.js.map +1 -0
  32. package/dist/tools/close_issue.d.ts +17 -0
  33. package/dist/tools/close_issue.d.ts.map +1 -0
  34. package/dist/tools/close_issue.js +28 -0
  35. package/dist/tools/close_issue.js.map +1 -0
  36. package/dist/tools/comment_issue.d.ts +20 -0
  37. package/dist/tools/comment_issue.d.ts.map +1 -0
  38. package/dist/tools/comment_issue.js +23 -0
  39. package/dist/tools/comment_issue.js.map +1 -0
  40. package/dist/tools/commit_and_update.d.ts +20 -0
  41. package/dist/tools/commit_and_update.d.ts.map +1 -0
  42. package/dist/tools/commit_and_update.js +80 -0
  43. package/dist/tools/commit_and_update.js.map +1 -0
  44. package/dist/tools/create_issue.d.ts +29 -0
  45. package/dist/tools/create_issue.d.ts.map +1 -0
  46. package/dist/tools/create_issue.js +82 -0
  47. package/dist/tools/create_issue.js.map +1 -0
  48. package/dist/tools/create_issues_from_list.d.ts +50 -0
  49. package/dist/tools/create_issues_from_list.d.ts.map +1 -0
  50. package/dist/tools/create_issues_from_list.js +48 -0
  51. package/dist/tools/create_issues_from_list.js.map +1 -0
  52. package/dist/tools/create_pull_request.d.ts +20 -0
  53. package/dist/tools/create_pull_request.d.ts.map +1 -0
  54. package/dist/tools/create_pull_request.js +170 -0
  55. package/dist/tools/create_pull_request.js.map +1 -0
  56. package/dist/tools/delete_branch.d.ts +20 -0
  57. package/dist/tools/delete_branch.d.ts.map +1 -0
  58. package/dist/tools/delete_branch.js +39 -0
  59. package/dist/tools/delete_branch.js.map +1 -0
  60. package/dist/tools/delete_issue.d.ts +20 -0
  61. package/dist/tools/delete_issue.d.ts.map +1 -0
  62. package/dist/tools/delete_issue.js +46 -0
  63. package/dist/tools/delete_issue.js.map +1 -0
  64. package/dist/tools/get_issue.d.ts +17 -0
  65. package/dist/tools/get_issue.d.ts.map +1 -0
  66. package/dist/tools/get_issue.js +27 -0
  67. package/dist/tools/get_issue.js.map +1 -0
  68. package/dist/tools/link_issues.d.ts +23 -0
  69. package/dist/tools/link_issues.d.ts.map +1 -0
  70. package/dist/tools/link_issues.js +42 -0
  71. package/dist/tools/link_issues.js.map +1 -0
  72. package/dist/tools/list_issues.d.ts +11 -0
  73. package/dist/tools/list_issues.d.ts.map +1 -0
  74. package/dist/tools/list_issues.js +61 -0
  75. package/dist/tools/list_issues.js.map +1 -0
  76. package/dist/tools/list_pr_review_comments.d.ts +17 -0
  77. package/dist/tools/list_pr_review_comments.d.ts.map +1 -0
  78. package/dist/tools/list_pr_review_comments.js +43 -0
  79. package/dist/tools/list_pr_review_comments.js.map +1 -0
  80. package/dist/tools/plan.d.ts +79 -0
  81. package/dist/tools/plan.d.ts.map +1 -0
  82. package/dist/tools/plan.js +159 -0
  83. package/dist/tools/plan.js.map +1 -0
  84. package/dist/tools/prepare_release.d.ts +23 -0
  85. package/dist/tools/prepare_release.d.ts.map +1 -0
  86. package/dist/tools/prepare_release.js +172 -0
  87. package/dist/tools/prepare_release.js.map +1 -0
  88. package/dist/tools/reply_to_review_comment.d.ts +23 -0
  89. package/dist/tools/reply_to_review_comment.d.ts.map +1 -0
  90. package/dist/tools/reply_to_review_comment.js +25 -0
  91. package/dist/tools/reply_to_review_comment.js.map +1 -0
  92. package/dist/tools/resolve_review_thread.d.ts +17 -0
  93. package/dist/tools/resolve_review_thread.d.ts.map +1 -0
  94. package/dist/tools/resolve_review_thread.js +27 -0
  95. package/dist/tools/resolve_review_thread.js.map +1 -0
  96. package/package.json +48 -0
@@ -0,0 +1,170 @@
1
+ import { z } from "zod";
2
+ import { getIssue, extractBranchFromBody, getDefaultBranch, getBranchCommits, getIssueComments, createPullRequest, getOpenPullRequestForBranch, updatePullRequest, markPullRequestReady, getRepoDefaultBranch, addIssueComment, } from "../github.js";
3
+ import { config } from "../config.js";
4
+ import { updateProjectDocs } from "../docs.js";
5
+ import { git, currentBranch } from "../git.js";
6
+ export const name = "create_pull_request";
7
+ export const description = "Create a pull request for the current issue branch. Reads the issue, its comments, and commits to generate a PR title and body. Always includes Closes #N. If OKFFS_UPDATE_DOCS is true, updates the project docs (CHANGELOG.md, and when relevant CLAUDE.md, CONTRIBUTING.md, SECURITY.md) and commits them onto the branch before creating the PR. If a PR already exists for the branch (e.g. a draft opened by create_issue under OKFFS_AUTO_PR=true), it is updated and marked ready for review instead of erroring. Posts a summary comment to the issue.";
8
+ export const inputSchema = z.object({
9
+ issue_number: z.number().int().positive().describe("The issue number to create a PR for"),
10
+ summary: z.string().optional().describe("Optional summary of what was done — used in PR body and issue comment"),
11
+ });
12
+ export async function handler(input) {
13
+ const issue = await getIssue(input.issue_number);
14
+ const branchName = extractBranchFromBody(issue.body);
15
+ if (!branchName) {
16
+ await addIssueComment(input.issue_number, `PR not created — issue #${input.issue_number} has no associated branch. Add a **Branch:** line to the issue body first.`);
17
+ return {
18
+ content: [{ type: "text", text: `Issue #${input.issue_number} has no associated branch.` }],
19
+ };
20
+ }
21
+ const baseBranch = await getDefaultBranch();
22
+ // `Closes #N` only auto-closes the issue when the PR merges into the repo's
23
+ // default branch. If OKFFS_BASE_BRANCH targets a non-default branch (e.g.
24
+ // develop), warn that the issue must be closed manually after merge.
25
+ let autoCloseNote = "";
26
+ if (config.baseBranch) {
27
+ const repoDefault = await getRepoDefaultBranch();
28
+ if (baseBranch !== repoDefault) {
29
+ autoCloseNote =
30
+ `\n\n⚠️ This PR targets \`${baseBranch}\`, not the default branch \`${repoDefault}\` — ` +
31
+ `merging will **not** auto-close #${input.issue_number}. Close it manually with \`close_issue\` after merge.`;
32
+ }
33
+ }
34
+ const commits = await getBranchCommits(branchName, baseBranch);
35
+ const comments = await getIssueComments(input.issue_number);
36
+ if (commits.length === 0) {
37
+ await addIssueComment(input.issue_number, `PR not created — branch \`${branchName}\` has no commits ahead of \`${baseBranch}\`. Push commits to the branch first, then create the PR.`);
38
+ return {
39
+ content: [{ type: "text", text: `PR not created — branch \`${branchName}\` has no commits ahead of \`${baseBranch}\`. Push commits first.` }],
40
+ };
41
+ }
42
+ const title = `Close #${input.issue_number} - ${issue.title}`;
43
+ const cleanedDescription = issue.body
44
+ ? issue.body
45
+ .replace(/\*\*Branch:\*\*\s*`[^`]+`/g, "")
46
+ .replace(/## Relationships[\s\S]*/g, "")
47
+ .trim()
48
+ : issue.title;
49
+ const summarySection = input.summary ?? cleanedDescription;
50
+ const changesSection = commits.length > 0
51
+ ? commits.map((c) => `- ${c.commit.message.split("\n")[0]}`).join("\n")
52
+ : "- No commits found";
53
+ const recentComments = comments.slice(0, 3).reverse();
54
+ const commentsSection = recentComments.length > 0
55
+ ? recentComments
56
+ .map((c) => `\n\`\`\`\n${c.body}\n\`\`\`\n`)
57
+ .join("\n\n---\n\n")
58
+ : null;
59
+ const bodyParts = [
60
+ `## Summary`,
61
+ summarySection,
62
+ ``,
63
+ `## Changes`,
64
+ changesSection,
65
+ ];
66
+ if (commentsSection) {
67
+ bodyParts.push(``, `## Issue comments`, commentsSection);
68
+ }
69
+ bodyParts.push(``, `Closes #${input.issue_number}`);
70
+ const body = bodyParts.join("\n");
71
+ let updatedDocs = [];
72
+ if (config.updateDocs) {
73
+ updatedDocs = await updateProjectDocs({
74
+ trigger: "create_pull_request",
75
+ issueNumber: input.issue_number,
76
+ issueTitle: issue.title,
77
+ summary: input.summary ?? cleanedDescription,
78
+ branchName,
79
+ });
80
+ }
81
+ // Commit any doc updates and push the branch before opening the PR. Operate on
82
+ // branchName explicitly so we never commit/push the wrong branch, and restore
83
+ // the caller's original branch afterward.
84
+ const previousBranch = currentBranch();
85
+ try {
86
+ git(["checkout", branchName]);
87
+ }
88
+ catch (err) {
89
+ console.warn(`[okffs] Failed to checkout branch ${branchName}.`, err instanceof Error ? err.message : err);
90
+ await addIssueComment(input.issue_number, `PR not created — could not switch to branch \`${branchName}\` locally. Check out the branch, then run \`create_pull_request\` again.`);
91
+ return {
92
+ content: [{ type: "text", text: `PR not created — could not switch to branch \`${branchName}\` locally.` }],
93
+ };
94
+ }
95
+ try {
96
+ // If docs were updated, commit all of them so they're in the PR diff —
97
+ // not just CHANGELOG.md (updateProjectDocs may also touch CLAUDE.md,
98
+ // CONTRIBUTING.md, SECURITY.md). A failure here must never block PR creation.
99
+ if (updatedDocs.length > 0) {
100
+ try {
101
+ const names = updatedDocs.map((p) => p.split(/[\\/]/).pop()).join(", ");
102
+ git(["add", ...updatedDocs]);
103
+ git(["commit", "-m", `docs: update ${names} for #${input.issue_number}`]);
104
+ }
105
+ catch (err) {
106
+ console.warn(`[okffs] Failed to commit doc updates for #${input.issue_number} — continuing without them.`, err instanceof Error ? err.message : err);
107
+ }
108
+ }
109
+ // Push so GitHub sees the commits before PR creation. If commits exist only
110
+ // locally, the API would report no commits ahead of base.
111
+ try {
112
+ git(["push", "origin", branchName]);
113
+ }
114
+ catch (err) {
115
+ console.warn(`[okffs] Failed to push branch ${branchName} to remote.`, err instanceof Error ? err.message : err);
116
+ await addIssueComment(input.issue_number, `PR not created — could not push branch \`${branchName}\` to remote. Please push manually (\`git push origin ${branchName}\`) then run \`create_pull_request\` to continue.`);
117
+ return {
118
+ content: [{ type: "text", text: `PR not created — could not push branch \`${branchName}\` to remote. Push manually (\`git push origin ${branchName}\`) then run create_pull_request to continue.` }],
119
+ };
120
+ }
121
+ }
122
+ finally {
123
+ if (previousBranch && previousBranch !== branchName) {
124
+ try {
125
+ git(["checkout", previousBranch]);
126
+ }
127
+ catch (err) {
128
+ console.warn(`[okffs] Failed to restore branch ${previousBranch}.`, err instanceof Error ? err.message : err);
129
+ }
130
+ }
131
+ }
132
+ // Under OKFFS_AUTO_PR=true a draft PR already exists for this branch (opened by
133
+ // create_issue), so creating one would fail. Detect and finalize it instead:
134
+ // update title/body and mark it ready for review. Otherwise create a new PR.
135
+ const existing = await getOpenPullRequestForBranch(branchName);
136
+ let pr;
137
+ let action;
138
+ if (existing) {
139
+ await updatePullRequest(existing.number, { title, body });
140
+ if (existing.draft) {
141
+ try {
142
+ await markPullRequestReady(existing.node_id);
143
+ }
144
+ catch (err) {
145
+ console.warn(`[okffs] Failed to mark PR #${existing.number} ready for review — leaving it as a draft.`, err instanceof Error ? err.message : err);
146
+ }
147
+ }
148
+ pr = { number: existing.number, html_url: existing.html_url };
149
+ action = existing.draft ? "finalized (marked ready)" : "updated";
150
+ }
151
+ else {
152
+ pr = await createPullRequest(title, body, branchName, baseBranch);
153
+ action = "created";
154
+ }
155
+ const comment = [
156
+ `PR ${action}: ${pr.html_url}`,
157
+ ``,
158
+ body,
159
+ ].join("\n") + autoCloseNote;
160
+ await addIssueComment(input.issue_number, comment);
161
+ // OKFFS_UPDATE_GUIDANCE: nudge the agent to keep CLAUDE.md in sync with any
162
+ // new/changed functionality. Pushing the edit to this branch updates the PR.
163
+ const guidanceNote = config.updateGuidance
164
+ ? `\n\n💡 OKFFS_UPDATE_GUIDANCE is on: if this PR adds or changes functionality, config, or conventions, update CLAUDE.md to match (run the update_guidance prompt) and commit it to \`${branchName}\` so it's part of this PR.`
165
+ : "";
166
+ return {
167
+ content: [{ type: "text", text: `PR #${pr.number} ${action}: ${pr.html_url}${autoCloseNote}${guidanceNote}` }],
168
+ };
169
+ }
170
+ //# sourceMappingURL=create_pull_request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_pull_request.js","sourceRoot":"","sources":["../../src/tools/create_pull_request.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ export declare const name = "delete_branch";
3
+ export declare const description = "Delete a branch and close its matching GitHub issue. Destructive \u2014 requires confirmed: true.";
4
+ export declare const inputSchema: z.ZodObject<{
5
+ branch_name: z.ZodString;
6
+ confirmed: z.ZodOptional<z.ZodBoolean>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ branch_name: string;
9
+ confirmed?: boolean | undefined;
10
+ }, {
11
+ branch_name: string;
12
+ confirmed?: boolean | undefined;
13
+ }>;
14
+ export declare function handler(input: z.infer<typeof inputSchema>): Promise<{
15
+ content: {
16
+ type: "text";
17
+ text: string;
18
+ }[];
19
+ }>;
20
+ //# sourceMappingURL=delete_branch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete_branch.d.ts","sourceRoot":"","sources":["../../src/tools/delete_branch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,IAAI,kBAAkB,CAAC;AAEpC,eAAO,MAAM,WAAW,sGACwE,CAAC;AAEjG,eAAO,MAAM,WAAW;;;;;;;;;EAGtB,CAAC;AAEH,wBAAsB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;GAkC/D"}
@@ -0,0 +1,39 @@
1
+ import { z } from "zod";
2
+ import { addIssueComment, deleteBranch, closeIssue } from "../github.js";
3
+ import { config } from "../config.js";
4
+ import { updateProjectDocs } from "../docs.js";
5
+ export const name = "delete_branch";
6
+ export const description = "Delete a branch and close its matching GitHub issue. Destructive — requires confirmed: true.";
7
+ export const inputSchema = z.object({
8
+ branch_name: z.string().describe("The branch name to delete (e.g. 42-add-hero-section)"),
9
+ confirmed: z.boolean().optional().describe("Must be true to proceed with the destructive action"),
10
+ });
11
+ export async function handler(input) {
12
+ const issueNumber = parseInt(input.branch_name.split("-")[0], 10);
13
+ if (!input.confirmed) {
14
+ return {
15
+ content: [{
16
+ type: "text",
17
+ text: `⚠️ This will delete branch \`${input.branch_name}\` and close issue #${issueNumber}.\nRe-call delete_branch with confirmed: true to proceed.`,
18
+ }],
19
+ };
20
+ }
21
+ await addIssueComment(issueNumber, `Branch \`${input.branch_name}\` was deleted. No working branch remains for this issue. Issue closed via okffs.`);
22
+ await deleteBranch(input.branch_name);
23
+ await closeIssue(issueNumber);
24
+ if (config.updateDocs) {
25
+ await updateProjectDocs({
26
+ trigger: "delete_branch",
27
+ issueNumber: issueNumber,
28
+ summary: `Branch \`${input.branch_name}\` deleted and issue #${issueNumber} closed.`,
29
+ branchName: input.branch_name,
30
+ });
31
+ }
32
+ return {
33
+ content: [{
34
+ type: "text",
35
+ text: `Branch \`${input.branch_name}\` deleted.\nIssue #${issueNumber} closed.`,
36
+ }],
37
+ };
38
+ }
39
+ //# sourceMappingURL=delete_branch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete_branch.js","sourceRoot":"","sources":["../../src/tools/delete_branch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,CAAC,MAAM,IAAI,GAAG,eAAe,CAAC;AAEpC,MAAM,CAAC,MAAM,WAAW,GACtB,8FAA8F,CAAC;AAEjG,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sDAAsD,CAAC;IACxF,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;CAClG,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,KAAkC;IAC9D,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAElE,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACrB,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,iCAAiC,KAAK,CAAC,WAAW,uBAAuB,WAAW,2DAA2D;iBACtJ,CAAC;SACH,CAAC;IACJ,CAAC;IAED,MAAM,eAAe,CACnB,WAAW,EACX,YAAY,KAAK,CAAC,WAAW,mFAAmF,CACjH,CAAC;IACF,MAAM,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACtC,MAAM,UAAU,CAAC,WAAW,CAAC,CAAC;IAE9B,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,iBAAiB,CAAC;YACtB,OAAO,EAAE,eAAe;YACxB,WAAW,EAAE,WAAW;YACxB,OAAO,EAAE,YAAY,KAAK,CAAC,WAAW,yBAAyB,WAAW,UAAU;YACpF,UAAU,EAAE,KAAK,CAAC,WAAW;SAC9B,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,OAAO,EAAE,CAAC;gBACR,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,YAAY,KAAK,CAAC,WAAW,uBAAuB,WAAW,UAAU;aAChF,CAAC;KACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+ export declare const name = "delete_issue";
3
+ export declare const description = "Close a GitHub issue and delete its matching branch. Destructive \u2014 requires confirmed: true.";
4
+ export declare const inputSchema: z.ZodObject<{
5
+ issue_number: z.ZodNumber;
6
+ confirmed: z.ZodOptional<z.ZodBoolean>;
7
+ }, "strip", z.ZodTypeAny, {
8
+ issue_number: number;
9
+ confirmed?: boolean | undefined;
10
+ }, {
11
+ issue_number: number;
12
+ confirmed?: boolean | undefined;
13
+ }>;
14
+ export declare function handler(input: z.infer<typeof inputSchema>): Promise<{
15
+ content: {
16
+ type: "text";
17
+ text: string;
18
+ }[];
19
+ }>;
20
+ //# sourceMappingURL=delete_issue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete_issue.d.ts","sourceRoot":"","sources":["../../src/tools/delete_issue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,IAAI,iBAAiB,CAAC;AAEnC,eAAO,MAAM,WAAW,sGACwE,CAAC;AAEjG,eAAO,MAAM,WAAW;;;;;;;;;EAGtB,CAAC;AAEH,wBAAsB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;GAsC/D"}
@@ -0,0 +1,46 @@
1
+ import { z } from "zod";
2
+ import { getIssue, addIssueComment, closeIssue, deleteBranch, extractBranchFromBody } from "../github.js";
3
+ import { config } from "../config.js";
4
+ import { updateProjectDocs } from "../docs.js";
5
+ export const name = "delete_issue";
6
+ export const description = "Close a GitHub issue and delete its matching branch. Destructive — requires confirmed: true.";
7
+ export const inputSchema = z.object({
8
+ issue_number: z.number().int().positive().describe("The issue number to close and whose branch to delete"),
9
+ confirmed: z.boolean().optional().describe("Must be true to proceed with the destructive action"),
10
+ });
11
+ export async function handler(input) {
12
+ const issue = await getIssue(input.issue_number);
13
+ const branchName = extractBranchFromBody(issue.body);
14
+ if (!input.confirmed) {
15
+ const branchNote = branchName ? `and delete branch \`${branchName}\`` : "(no branch found in issue body)";
16
+ return {
17
+ content: [{
18
+ type: "text",
19
+ text: `⚠️ This will close issue #${input.issue_number} ${branchNote}.\nRe-call delete_issue with confirmed: true to proceed.`,
20
+ }],
21
+ };
22
+ }
23
+ if (branchName) {
24
+ await addIssueComment(input.issue_number, `Issue closed and branch \`${branchName}\` deleted via okffs.`);
25
+ }
26
+ await closeIssue(input.issue_number);
27
+ if (branchName) {
28
+ await deleteBranch(branchName);
29
+ }
30
+ if (config.updateDocs) {
31
+ await updateProjectDocs({
32
+ trigger: "delete_issue",
33
+ issueNumber: input.issue_number,
34
+ issueTitle: issue.title,
35
+ summary: issue.body ? `Deleted: ${issue.title}. ${issue.body.slice(0, 200)}` : `Deleted: ${issue.title}`,
36
+ branchName: branchName ?? undefined,
37
+ });
38
+ }
39
+ const lines = [`Issue #${input.issue_number} closed.`];
40
+ if (branchName)
41
+ lines.push(`Branch \`${branchName}\` deleted.`);
42
+ return {
43
+ content: [{ type: "text", text: lines.join("\n") }],
44
+ };
45
+ }
46
+ //# sourceMappingURL=delete_issue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete_issue.js","sourceRoot":"","sources":["../../src/tools/delete_issue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAC1G,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,CAAC,MAAM,IAAI,GAAG,cAAc,CAAC;AAEnC,MAAM,CAAC,MAAM,WAAW,GACtB,8FAA8F,CAAC;AAEjG,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sDAAsD,CAAC;IAC1G,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;CAClG,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,KAAkC;IAC9D,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAErD,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACrB,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,uBAAuB,UAAU,IAAI,CAAC,CAAC,CAAC,iCAAiC,CAAC;QAC1G,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,8BAA8B,KAAK,CAAC,YAAY,IAAI,UAAU,0DAA0D;iBAC/H,CAAC;SACH,CAAC;IACJ,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,eAAe,CAAC,KAAK,CAAC,YAAY,EAAE,6BAA6B,UAAU,uBAAuB,CAAC,CAAC;IAC5G,CAAC;IACD,MAAM,UAAU,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACrC,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,YAAY,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,iBAAiB,CAAC;YACtB,OAAO,EAAE,cAAc;YACvB,WAAW,EAAE,KAAK,CAAC,YAAY;YAC/B,UAAU,EAAE,KAAK,CAAC,KAAK;YACvB,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,KAAK,EAAE;YACxG,UAAU,EAAE,UAAU,IAAI,SAAS;SACpC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,UAAU,KAAK,CAAC,YAAY,UAAU,CAAC,CAAC;IACvD,IAAI,UAAU;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,UAAU,aAAa,CAAC,CAAC;IAEhE,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;KAC7D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { z } from "zod";
2
+ export declare const name = "get_issue";
3
+ export declare const description = "Fetch full details of a GitHub issue by number \u2014 title, body, labels, assignees, branch, and status.";
4
+ export declare const inputSchema: z.ZodObject<{
5
+ issue_number: z.ZodNumber;
6
+ }, "strip", z.ZodTypeAny, {
7
+ issue_number: number;
8
+ }, {
9
+ issue_number: number;
10
+ }>;
11
+ export declare function handler(input: z.infer<typeof inputSchema>): Promise<{
12
+ content: {
13
+ type: "text";
14
+ text: string;
15
+ }[];
16
+ }>;
17
+ //# sourceMappingURL=get_issue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get_issue.d.ts","sourceRoot":"","sources":["../../src/tools/get_issue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,IAAI,cAAc,CAAC;AAEhC,eAAO,MAAM,WAAW,8GACgF,CAAC;AAEzG,eAAO,MAAM,WAAW;;;;;;EAEtB,CAAC;AAEH,wBAAsB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;GA6B/D"}
@@ -0,0 +1,27 @@
1
+ import { z } from "zod";
2
+ import { getIssue, extractBranchFromBody, owner, repo } from "../github.js";
3
+ export const name = "get_issue";
4
+ export const description = "Fetch full details of a GitHub issue by number — title, body, labels, assignees, branch, and status.";
5
+ export const inputSchema = z.object({
6
+ issue_number: z.number().int().positive(),
7
+ });
8
+ export async function handler(input) {
9
+ const issue = await getIssue(input.issue_number);
10
+ const branch = extractBranchFromBody(issue.body);
11
+ const assignees = issue.assignees.map((a) => a.login).join(", ") || "none";
12
+ const labels = issue.labels.map((l) => l.name).join(", ") || "none";
13
+ const lines = [
14
+ `#${issue.number} — ${issue.title}`,
15
+ `Status: ${issue.state}`,
16
+ ...(branch ? [`Branch: ${branch}`] : []),
17
+ `Assignees: ${assignees}`,
18
+ `Labels: ${labels}`,
19
+ `URL: https://github.com/${owner}/${repo}/issues/${issue.number}`,
20
+ ``,
21
+ issue.body ?? "(no description)",
22
+ ];
23
+ return {
24
+ content: [{ type: "text", text: lines.join("\n") }],
25
+ };
26
+ }
27
+ //# sourceMappingURL=get_issue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get_issue.js","sourceRoot":"","sources":["../../src/tools/get_issue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,qBAAqB,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAE5E,MAAM,CAAC,MAAM,IAAI,GAAG,WAAW,CAAC;AAEhC,MAAM,CAAC,MAAM,WAAW,GACtB,sGAAsG,CAAC;AAEzG,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CAC1C,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,KAAkC;IAC9D,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,YAAY,CAQ9C,CAAC;IAEF,MAAM,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;IAC3E,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;IAEpE,MAAM,KAAK,GAAG;QACZ,IAAI,KAAK,CAAC,MAAM,MAAM,KAAK,CAAC,KAAK,EAAE;QACnC,WAAW,KAAK,CAAC,KAAK,EAAE;QACxB,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,cAAc,SAAS,EAAE;QACzB,WAAW,MAAM,EAAE;QACnB,2BAA2B,KAAK,IAAI,IAAI,WAAW,KAAK,CAAC,MAAM,EAAE;QACjE,EAAE;QACF,KAAK,CAAC,IAAI,IAAI,kBAAkB;KACjC,CAAC;IAEF,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;KAC7D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { z } from "zod";
2
+ export declare const name = "link_issues";
3
+ export declare const description = "Link two GitHub issues with a relationship by editing the issue body. Supports blocked_by (this issue is blocked by another), blocking (this issue is blocking another), and parent (set a parent issue). Relationships are stored in a '## Relationships' section in the issue body.";
4
+ export declare const inputSchema: z.ZodObject<{
5
+ issue_number: z.ZodNumber;
6
+ related_issue_number: z.ZodNumber;
7
+ relationship: z.ZodEnum<["blocked_by", "blocking", "parent"]>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ issue_number: number;
10
+ related_issue_number: number;
11
+ relationship: "blocking" | "parent" | "blocked_by";
12
+ }, {
13
+ issue_number: number;
14
+ related_issue_number: number;
15
+ relationship: "blocking" | "parent" | "blocked_by";
16
+ }>;
17
+ export declare function handler(input: z.infer<typeof inputSchema>): Promise<{
18
+ content: {
19
+ type: "text";
20
+ text: string;
21
+ }[];
22
+ }>;
23
+ //# sourceMappingURL=link_issues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link_issues.d.ts","sourceRoot":"","sources":["../../src/tools/link_issues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,IAAI,gBAAgB,CAAC;AAElC,eAAO,MAAM,WAAW,0RACiQ,CAAC;AAE1R,eAAO,MAAM,WAAW;;;;;;;;;;;;EAMtB,CAAC;AAQH,wBAAsB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;GA8B/D"}
@@ -0,0 +1,42 @@
1
+ import { z } from "zod";
2
+ import { getIssue, updateIssueBody, owner, repo } from "../github.js";
3
+ export const name = "link_issues";
4
+ export const description = "Link two GitHub issues with a relationship by editing the issue body. Supports blocked_by (this issue is blocked by another), blocking (this issue is blocking another), and parent (set a parent issue). Relationships are stored in a '## Relationships' section in the issue body.";
5
+ export const inputSchema = z.object({
6
+ issue_number: z.number().int().positive().describe("The issue to set the relationship on"),
7
+ related_issue_number: z.number().int().positive().describe("The related issue"),
8
+ relationship: z.enum(["blocked_by", "blocking", "parent"]).describe("blocked_by: this issue is blocked by the related issue. blocking: this issue is blocking the related issue. parent: the related issue becomes the parent of this issue."),
9
+ });
10
+ const RELATIONSHIP_LABELS = {
11
+ blocked_by: "Blocked by",
12
+ blocking: "Blocking",
13
+ parent: "Parent:",
14
+ };
15
+ export async function handler(input) {
16
+ const issue = await getIssue(input.issue_number);
17
+ const label = RELATIONSHIP_LABELS[input.relationship];
18
+ const newLine = `- ${label} #${input.related_issue_number}`;
19
+ const currentBody = issue.body ?? "";
20
+ let newBody;
21
+ if (currentBody.includes("## Relationships")) {
22
+ newBody = currentBody.trimEnd() + "\n" + newLine;
23
+ }
24
+ else {
25
+ newBody = currentBody.trimEnd() + "\n\n## Relationships\n" + newLine;
26
+ }
27
+ await updateIssueBody(input.issue_number, newBody);
28
+ const humanRelationship = `${label} #${input.related_issue_number}`.toLowerCase();
29
+ return {
30
+ content: [
31
+ {
32
+ type: "text",
33
+ text: [
34
+ `✅ Relationship added to issue #${input.issue_number}`,
35
+ ` Issue #${input.issue_number} is ${humanRelationship}`,
36
+ ` https://github.com/${owner}/${repo}/issues/${input.issue_number}`,
37
+ ].join("\n"),
38
+ },
39
+ ],
40
+ };
41
+ }
42
+ //# sourceMappingURL=link_issues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link_issues.js","sourceRoot":"","sources":["../../src/tools/link_issues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEtE,MAAM,CAAC,MAAM,IAAI,GAAG,aAAa,CAAC;AAElC,MAAM,CAAC,MAAM,WAAW,GACtB,uRAAuR,CAAC;AAE1R,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sCAAsC,CAAC;IAC1F,oBAAoB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IAC/E,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CACjE,yKAAyK,CAC1K;CACF,CAAC,CAAC;AAEH,MAAM,mBAAmB,GAA2B;IAClD,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,SAAS;CAClB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,KAAkC;IAC9D,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,mBAAmB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,KAAK,KAAK,KAAK,KAAK,CAAC,oBAAoB,EAAE,CAAC;IAE5D,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;IACrC,IAAI,OAAe,CAAC;IAEpB,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC7C,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC;IACnD,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,WAAW,CAAC,OAAO,EAAE,GAAG,wBAAwB,GAAG,OAAO,CAAC;IACvE,CAAC;IAED,MAAM,eAAe,CAAC,KAAK,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAEnD,MAAM,iBAAiB,GAAG,GAAG,KAAK,KAAK,KAAK,CAAC,oBAAoB,EAAE,CAAC,WAAW,EAAE,CAAC;IAElF,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE;oBACJ,kCAAkC,KAAK,CAAC,YAAY,EAAE;oBACtD,aAAa,KAAK,CAAC,YAAY,OAAO,iBAAiB,EAAE;oBACzD,yBAAyB,KAAK,IAAI,IAAI,WAAW,KAAK,CAAC,YAAY,EAAE;iBACtE,CAAC,IAAI,CAAC,IAAI,CAAC;aACb;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { z } from "zod";
2
+ export declare const name = "list_issues";
3
+ export declare const description = "List all open GitHub issues, each with its branch, any linked open or draft PR, and its relationships (parent, children, blocked-by, blocking) shown as a tree. Replaces the need for a separate PR-listing tool.";
4
+ export declare const inputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
5
+ export declare function handler(_input: z.infer<typeof inputSchema>): Promise<{
6
+ content: {
7
+ type: "text";
8
+ text: string;
9
+ }[];
10
+ }>;
11
+ //# sourceMappingURL=list_issues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_issues.d.ts","sourceRoot":"","sources":["../../src/tools/list_issues.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAYxB,eAAO,MAAM,IAAI,gBAAgB,CAAC;AAElC,eAAO,MAAM,WAAW,sNAC6L,CAAC;AAEtN,eAAO,MAAM,WAAW,gDAAe,CAAC;AAExC,wBAAsB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;GA6DhE"}
@@ -0,0 +1,61 @@
1
+ import { z } from "zod";
2
+ import { listIssues, listOpenPullRequests, parseRelationships, buildBranchName, extractBranchFromBody, owner, repo, } from "../github.js";
3
+ export const name = "list_issues";
4
+ export const description = "List all open GitHub issues, each with its branch, any linked open or draft PR, and its relationships (parent, children, blocked-by, blocking) shown as a tree. Replaces the need for a separate PR-listing tool.";
5
+ export const inputSchema = z.object({});
6
+ export async function handler(_input) {
7
+ const [issues, prs] = await Promise.all([listIssues(), listOpenPullRequests()]);
8
+ if (issues.length === 0) {
9
+ return {
10
+ content: [{ type: "text", text: "No open issues." }],
11
+ };
12
+ }
13
+ // Match PRs to issues by head branch.
14
+ const prByBranch = new Map(prs.map((pr) => [pr.head.ref, pr]));
15
+ // Parse relationships once per issue and invert parent links to find children.
16
+ const relsByIssue = new Map();
17
+ const childrenOf = new Map();
18
+ for (const issue of issues) {
19
+ const rels = parseRelationships(issue.body);
20
+ relsByIssue.set(issue.number, rels);
21
+ for (const parent of rels.parent) {
22
+ childrenOf.set(parent, [...(childrenOf.get(parent) ?? []), issue.number]);
23
+ }
24
+ }
25
+ const fmt = (nums) => nums.map((n) => `#${n}`).join(", ");
26
+ const blocks = issues.map((issue) => {
27
+ const branch = extractBranchFromBody(issue.body) ?? buildBranchName(issue.number, issue.title);
28
+ const branchUrl = `https://github.com/${owner}/${repo}/tree/${branch}`;
29
+ const pr = prByBranch.get(branch);
30
+ const rels = relsByIssue.get(issue.number);
31
+ const children = childrenOf.get(issue.number) ?? [];
32
+ const lines = [
33
+ `#${issue.number} ${issue.title}`,
34
+ ` issue: ${issue.html_url}`,
35
+ ` branch: ${branch}`,
36
+ ` ${branchUrl}`,
37
+ ];
38
+ if (pr) {
39
+ lines.push(` PR: #${pr.number} (${pr.draft ? "draft" : "open"}) ${pr.html_url}`);
40
+ }
41
+ // Relationships as a small tree under the issue.
42
+ const relLines = [];
43
+ if (rels.parent.length)
44
+ relLines.push(`parent: ${fmt(rels.parent)}`);
45
+ if (children.length)
46
+ relLines.push(`children: ${fmt(children)}`);
47
+ if (rels.blockedBy.length)
48
+ relLines.push(`blocked by: ${fmt(rels.blockedBy)}`);
49
+ if (rels.blocking.length)
50
+ relLines.push(`blocking: ${fmt(rels.blocking)}`);
51
+ relLines.forEach((rl, idx) => {
52
+ const connector = idx === relLines.length - 1 ? "└─" : "├─";
53
+ lines.push(` ${connector} ${rl}`);
54
+ });
55
+ return lines.join("\n");
56
+ });
57
+ return {
58
+ content: [{ type: "text", text: blocks.join("\n\n") }],
59
+ };
60
+ }
61
+ //# sourceMappingURL=list_issues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_issues.js","sourceRoot":"","sources":["../../src/tools/list_issues.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { z } from "zod";
2
+ export declare const name = "list_pr_review_comments";
3
+ export declare const description = "Fetch review feedback for a pull request: inline review comment threads (each with comment ids, file/line, author, body, and resolved/unresolved state) plus overall review summaries. Use this to read PR review comments before addressing them. Typical workflow: read with this tool, fix the code for the valid comments, commit/push with commit_and_update, reply to each addressed thread with reply_to_review_comment, post an overall summary with comment_issue (PRs accept issue comments), and \u2014 only if OKFFS_RESOLVE_THREADS is enabled \u2014 mark threads resolved with resolve_review_thread.";
4
+ export declare const inputSchema: z.ZodObject<{
5
+ pr_number: z.ZodNumber;
6
+ }, "strip", z.ZodTypeAny, {
7
+ pr_number: number;
8
+ }, {
9
+ pr_number: number;
10
+ }>;
11
+ export declare function handler(input: z.infer<typeof inputSchema>): Promise<{
12
+ content: {
13
+ type: "text";
14
+ text: string;
15
+ }[];
16
+ }>;
17
+ //# sourceMappingURL=list_pr_review_comments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_pr_review_comments.d.ts","sourceRoot":"","sources":["../../src/tools/list_pr_review_comments.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,IAAI,4BAA4B,CAAC;AAE9C,eAAO,MAAM,WAAW,ylBACsjB,CAAC;AAE/kB,eAAO,MAAM,WAAW;;;;;;EAEtB,CAAC;AAEH,wBAAsB,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC;;;;;GAyC/D"}
@@ -0,0 +1,43 @@
1
+ import { z } from "zod";
2
+ import { getPullRequestReview } from "../github.js";
3
+ export const name = "list_pr_review_comments";
4
+ export const description = "Fetch review feedback for a pull request: inline review comment threads (each with comment ids, file/line, author, body, and resolved/unresolved state) plus overall review summaries. Use this to read PR review comments before addressing them. Typical workflow: read with this tool, fix the code for the valid comments, commit/push with commit_and_update, reply to each addressed thread with reply_to_review_comment, post an overall summary with comment_issue (PRs accept issue comments), and — only if OKFFS_RESOLVE_THREADS is enabled — mark threads resolved with resolve_review_thread.";
5
+ export const inputSchema = z.object({
6
+ pr_number: z.number().int().positive().describe("The pull request number"),
7
+ });
8
+ export async function handler(input) {
9
+ const { threads, reviews } = await getPullRequestReview(input.pr_number);
10
+ const unresolved = threads.filter((t) => !t.isResolved);
11
+ const resolved = threads.filter((t) => t.isResolved);
12
+ const parts = [
13
+ `PR #${input.pr_number}: ${threads.length} review thread(s) (${unresolved.length} unresolved), ${reviews.length} review summary(ies).`,
14
+ ];
15
+ const renderThread = (t) => {
16
+ const lines = [
17
+ `[${t.isResolved ? "resolved" : "UNRESOLVED"}] thread_id: ${t.id}`,
18
+ ];
19
+ t.comments.forEach((c, i) => {
20
+ const loc = c.path ? `${c.path}${c.line ? `:${c.line}` : ""}` : "(general)";
21
+ const label = i === 0 ? "comment" : "reply";
22
+ lines.push(` • ${label} id:${c.id} ${loc} by ${c.author}`);
23
+ lines.push(` ${c.body.replace(/\n/g, "\n ")}`);
24
+ });
25
+ return lines.join("\n");
26
+ };
27
+ if (unresolved.length > 0) {
28
+ parts.push(`\n## Unresolved threads\n${unresolved.map(renderThread).join("\n\n")}`);
29
+ }
30
+ if (resolved.length > 0) {
31
+ parts.push(`\n## Resolved threads\n${resolved.map(renderThread).join("\n\n")}`);
32
+ }
33
+ if (reviews.length > 0) {
34
+ parts.push(`\n## Review summaries\n${reviews
35
+ .map((r) => `[${r.author}] ${r.state}\n${r.body}`)
36
+ .join("\n\n---\n\n")}`);
37
+ }
38
+ if (threads.length === 0 && reviews.length === 0) {
39
+ parts.push("\nNo review comments or summaries found.");
40
+ }
41
+ return { content: [{ type: "text", text: parts.join("\n") }] };
42
+ }
43
+ //# sourceMappingURL=list_pr_review_comments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list_pr_review_comments.js","sourceRoot":"","sources":["../../src/tools/list_pr_review_comments.ts"],"names":[],"mappings":"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"}