dispatch-ai 0.1.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.
Files changed (91) hide show
  1. package/LICENSE +229 -0
  2. package/README.md +177 -0
  3. package/dist/bin/dispatch.d.ts +3 -0
  4. package/dist/bin/dispatch.d.ts.map +1 -0
  5. package/dist/bin/dispatch.js +42 -0
  6. package/dist/bin/dispatch.js.map +1 -0
  7. package/dist/src/commands/create.d.ts +3 -0
  8. package/dist/src/commands/create.d.ts.map +1 -0
  9. package/dist/src/commands/create.js +154 -0
  10. package/dist/src/commands/create.js.map +1 -0
  11. package/dist/src/commands/init.d.ts +3 -0
  12. package/dist/src/commands/init.d.ts.map +1 -0
  13. package/dist/src/commands/init.js +100 -0
  14. package/dist/src/commands/init.js.map +1 -0
  15. package/dist/src/commands/run.d.ts +3 -0
  16. package/dist/src/commands/run.d.ts.map +1 -0
  17. package/dist/src/commands/run.js +72 -0
  18. package/dist/src/commands/run.js.map +1 -0
  19. package/dist/src/commands/status.d.ts +3 -0
  20. package/dist/src/commands/status.d.ts.map +1 -0
  21. package/dist/src/commands/status.js +34 -0
  22. package/dist/src/commands/status.js.map +1 -0
  23. package/dist/src/engine/base.d.ts +12 -0
  24. package/dist/src/engine/base.d.ts.map +1 -0
  25. package/dist/src/engine/base.js +161 -0
  26. package/dist/src/engine/base.js.map +1 -0
  27. package/dist/src/engine/claude.d.ts +25 -0
  28. package/dist/src/engine/claude.d.ts.map +1 -0
  29. package/dist/src/engine/claude.js +215 -0
  30. package/dist/src/engine/claude.js.map +1 -0
  31. package/dist/src/engine/types.d.ts +88 -0
  32. package/dist/src/engine/types.d.ts.map +1 -0
  33. package/dist/src/engine/types.js +2 -0
  34. package/dist/src/engine/types.js.map +1 -0
  35. package/dist/src/github/client.d.ts +58 -0
  36. package/dist/src/github/client.d.ts.map +1 -0
  37. package/dist/src/github/client.js +189 -0
  38. package/dist/src/github/client.js.map +1 -0
  39. package/dist/src/github/issues.d.ts +13 -0
  40. package/dist/src/github/issues.d.ts.map +1 -0
  41. package/dist/src/github/issues.js +67 -0
  42. package/dist/src/github/issues.js.map +1 -0
  43. package/dist/src/github/pulls.d.ts +15 -0
  44. package/dist/src/github/pulls.d.ts.map +1 -0
  45. package/dist/src/github/pulls.js +65 -0
  46. package/dist/src/github/pulls.js.map +1 -0
  47. package/dist/src/index.d.ts +7 -0
  48. package/dist/src/index.d.ts.map +1 -0
  49. package/dist/src/index.js +5 -0
  50. package/dist/src/index.js.map +1 -0
  51. package/dist/src/orchestrator/classifier.d.ts +4 -0
  52. package/dist/src/orchestrator/classifier.d.ts.map +1 -0
  53. package/dist/src/orchestrator/classifier.js +45 -0
  54. package/dist/src/orchestrator/classifier.js.map +1 -0
  55. package/dist/src/orchestrator/pipeline.d.ts +13 -0
  56. package/dist/src/orchestrator/pipeline.d.ts.map +1 -0
  57. package/dist/src/orchestrator/pipeline.js +246 -0
  58. package/dist/src/orchestrator/pipeline.js.map +1 -0
  59. package/dist/src/orchestrator/planner.d.ts +13 -0
  60. package/dist/src/orchestrator/planner.d.ts.map +1 -0
  61. package/dist/src/orchestrator/planner.js +95 -0
  62. package/dist/src/orchestrator/planner.js.map +1 -0
  63. package/dist/src/orchestrator/scorer.d.ts +8 -0
  64. package/dist/src/orchestrator/scorer.d.ts.map +1 -0
  65. package/dist/src/orchestrator/scorer.js +41 -0
  66. package/dist/src/orchestrator/scorer.js.map +1 -0
  67. package/dist/src/reporter/summary.d.ts +29 -0
  68. package/dist/src/reporter/summary.d.ts.map +1 -0
  69. package/dist/src/reporter/summary.js +77 -0
  70. package/dist/src/reporter/summary.js.map +1 -0
  71. package/dist/src/utils/config.d.ts +37 -0
  72. package/dist/src/utils/config.d.ts.map +1 -0
  73. package/dist/src/utils/config.js +60 -0
  74. package/dist/src/utils/config.js.map +1 -0
  75. package/dist/src/utils/git.d.ts +30 -0
  76. package/dist/src/utils/git.d.ts.map +1 -0
  77. package/dist/src/utils/git.js +95 -0
  78. package/dist/src/utils/git.js.map +1 -0
  79. package/dist/src/utils/logger.d.ts +22 -0
  80. package/dist/src/utils/logger.d.ts.map +1 -0
  81. package/dist/src/utils/logger.js +109 -0
  82. package/dist/src/utils/logger.js.map +1 -0
  83. package/dist/src/utils/semaphore.d.ts +19 -0
  84. package/dist/src/utils/semaphore.d.ts.map +1 -0
  85. package/dist/src/utils/semaphore.js +41 -0
  86. package/dist/src/utils/semaphore.js.map +1 -0
  87. package/dist/src/utils/worktree.d.ts +20 -0
  88. package/dist/src/utils/worktree.d.ts.map +1 -0
  89. package/dist/src/utils/worktree.js +92 -0
  90. package/dist/src/utils/worktree.js.map +1 -0
  91. package/package.json +62 -0
@@ -0,0 +1,215 @@
1
+ import { spawn } from "node:child_process";
2
+ import { appendFile, writeFile } from "node:fs/promises";
3
+ import { buildIssuePrompt, SYSTEM_PROMPTS, CONFIDENCE_PROMPT, CLASSIFICATION_PROMPT, ISSUE_CREATION_PROMPT, } from "./base.js";
4
+ import { log } from "../utils/logger.js";
5
+ export class ClaudeEngine {
6
+ name = "claude";
7
+ model;
8
+ maxTurns;
9
+ constructor(options) {
10
+ this.model = options.model;
11
+ this.maxTurns = options.maxTurns;
12
+ }
13
+ /** Run claude CLI in print mode with streaming stderr output */
14
+ async runClaude(prompt, options = {}) {
15
+ const args = [
16
+ "--print",
17
+ "--model", this.model,
18
+ "--max-turns", String(options.maxTurns ?? this.maxTurns),
19
+ "--output-format", options.outputFormat ?? "text",
20
+ ];
21
+ if (options.systemPrompt) {
22
+ args.push("--system-prompt", options.systemPrompt);
23
+ }
24
+ if (options.allowedTools && options.allowedTools.length > 0) {
25
+ for (const tool of options.allowedTools) {
26
+ args.push("--allowedTools", tool);
27
+ }
28
+ }
29
+ // Always send the prompt via stdin. The `claude` CLI in --print mode
30
+ // reliably reads from stdin, and this avoids issues with:
31
+ // - Shell/OS argument length limits on large prompts
32
+ // - Special characters in prompts confusing argument parsing
33
+ // - Positional arg placement issues with Commander.js
34
+ log.debug(`Running claude with ${args.length} args in ${options.cwd || "cwd"}`);
35
+ log.debug(`Prompt length: ${prompt.length} chars (via stdin)`);
36
+ const timeout = options.timeout ?? 10 * 60 * 1000; // Default 10 min
37
+ // Create issue log file upfront so it's visible immediately
38
+ if (options.issueLogFile) {
39
+ await writeFile(options.issueLogFile, `--- dispatch: claude subprocess started at ${new Date().toISOString()} ---\n` +
40
+ `--- model: ${this.model} | maxTurns: ${options.maxTurns ?? this.maxTurns} | timeout: ${Math.round(timeout / 1000)}s ---\n` +
41
+ `--- prompt length: ${prompt.length} chars (via stdin) ---\n\n`);
42
+ }
43
+ return new Promise((resolve, reject) => {
44
+ const env = { ...process.env };
45
+ delete env.CLAUDECODE; // Allow nested claude calls
46
+ const child = spawn("claude", args, {
47
+ cwd: options.cwd || process.cwd(),
48
+ env,
49
+ stdio: ["pipe", "pipe", "pipe"],
50
+ });
51
+ const stdoutChunks = [];
52
+ child.stdout.on("data", (chunk) => {
53
+ stdoutChunks.push(chunk);
54
+ });
55
+ child.stderr.on("data", (chunk) => {
56
+ const text = chunk.toString().trim();
57
+ if (text) {
58
+ log.debug(`[claude] ${text}`);
59
+ }
60
+ if (options.issueLogFile) {
61
+ appendFile(options.issueLogFile, chunk.toString()).catch(() => { });
62
+ }
63
+ });
64
+ const timer = setTimeout(() => {
65
+ child.kill("SIGTERM");
66
+ // Give it a moment, then force-kill if still alive
67
+ setTimeout(() => {
68
+ try {
69
+ child.kill("SIGKILL");
70
+ }
71
+ catch { /* already dead */ }
72
+ }, 5000);
73
+ reject(new Error(`Claude process timed out after ${Math.round(timeout / 1000)}s`));
74
+ }, timeout);
75
+ child.on("close", (code) => {
76
+ clearTimeout(timer);
77
+ const stdout = Buffer.concat(stdoutChunks).toString().trim();
78
+ if (options.issueLogFile && stdout) {
79
+ appendFile(options.issueLogFile, `\n--- stdout ---\n${stdout}\n`).catch(() => { });
80
+ }
81
+ if (code !== 0 && !stdout) {
82
+ reject(new Error(`Claude process exited with code ${code}`));
83
+ }
84
+ else {
85
+ resolve(stdout);
86
+ }
87
+ });
88
+ child.on("error", (err) => {
89
+ clearTimeout(timer);
90
+ reject(err);
91
+ });
92
+ // Write the prompt to stdin and immediately close the stream.
93
+ // Closing stdin signals to `claude --print` that the input is complete.
94
+ child.stdin.write(prompt);
95
+ child.stdin.end();
96
+ });
97
+ }
98
+ /** Parse JSON from claude's response, handling markdown code blocks */
99
+ parseJSON(text) {
100
+ // Try direct parse first
101
+ try {
102
+ return JSON.parse(text);
103
+ }
104
+ catch {
105
+ // Try extracting from markdown code block
106
+ const jsonMatch = text.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
107
+ if (jsonMatch) {
108
+ return JSON.parse(jsonMatch[1].trim());
109
+ }
110
+ // Try finding JSON object in the text
111
+ const objectMatch = text.match(/\{[\s\S]*\}/);
112
+ if (objectMatch) {
113
+ return JSON.parse(objectMatch[0]);
114
+ }
115
+ throw new Error(`Could not parse JSON from response: ${text.substring(0, 200)}`);
116
+ }
117
+ }
118
+ async solve(issue, context) {
119
+ const classification = issue.classification || "code-fix";
120
+ const systemPrompt = SYSTEM_PROMPTS[classification];
121
+ const issuePrompt = buildIssuePrompt(issue);
122
+ log.info(`Solving #${issue.number} as "${classification}" with Claude (${this.model})...`);
123
+ // Combined solve + self-assess in a single claude call
124
+ const combinedPrompt = `${issuePrompt}
125
+
126
+ Please solve this issue. When done, DO NOT commit — just make the file changes.
127
+
128
+ After making all changes, output your self-assessment as a JSON block at the very end of your response.
129
+ ${CONFIDENCE_PROMPT}`;
130
+ const result = await this.runClaude(combinedPrompt, {
131
+ systemPrompt,
132
+ cwd: context.cwd,
133
+ maxTurns: this.maxTurns,
134
+ timeout: context.timeout,
135
+ issueLogFile: context.issueLogFile,
136
+ allowedTools: [
137
+ "Read", "Edit", "Write", "Glob", "Grep",
138
+ "Bash(npm test *)", "Bash(npm run *)",
139
+ ],
140
+ });
141
+ try {
142
+ const assessment = this.parseJSON(result);
143
+ return {
144
+ success: assessment.confidence >= 3,
145
+ changedFiles: assessment.changedFiles || [],
146
+ summary: assessment.summary || "Changes made to resolve the issue.",
147
+ confidence: Math.min(10, Math.max(1, assessment.confidence)),
148
+ uncertainties: assessment.uncertainties || [],
149
+ commitMessage: assessment.commitMessage || `fix: resolve issue #${issue.number}`,
150
+ };
151
+ }
152
+ catch (err) {
153
+ log.warn(`Could not parse assessment, using defaults`);
154
+ return {
155
+ success: true,
156
+ changedFiles: [],
157
+ summary: "Changes made to resolve the issue. Assessment parsing failed.",
158
+ confidence: 5,
159
+ uncertainties: ["Could not self-assess — manual review recommended"],
160
+ commitMessage: `fix: resolve issue #${issue.number}`,
161
+ };
162
+ }
163
+ }
164
+ async investigate(issue, context) {
165
+ // Investigation uses the same flow but with investigation system prompt
166
+ const investigationIssue = { ...issue, classification: "investigation" };
167
+ return this.solve(investigationIssue, context);
168
+ }
169
+ async createIssue(description, context) {
170
+ const prompt = ISSUE_CREATION_PROMPT.replace("{description}", description);
171
+ const result = await this.runClaude(prompt, {
172
+ cwd: context.cwd,
173
+ maxTurns: 1,
174
+ allowedTools: ["Read", "Glob", "Grep"],
175
+ });
176
+ return this.parseJSON(result);
177
+ }
178
+ async classifyIssue(issue) {
179
+ const prompt = CLASSIFICATION_PROMPT
180
+ .replace("{title}", () => issue.title)
181
+ .replace("{body}", () => (issue.body || "").substring(0, 500));
182
+ const result = await this.runClaude(prompt, {
183
+ maxTurns: 1,
184
+ allowedTools: [],
185
+ timeout: 30 * 1000, // 30s — classification is a single-turn task
186
+ });
187
+ const classification = result.trim().toLowerCase().replace(/[^a-z-]/g, "");
188
+ const valid = [
189
+ "code-fix", "feature", "investigation", "documentation", "audit", "refactor",
190
+ ];
191
+ if (valid.includes(classification)) {
192
+ return classification;
193
+ }
194
+ // Fuzzy matching
195
+ if (classification.includes("fix") || classification.includes("bug"))
196
+ return "code-fix";
197
+ if (classification.includes("feat") || classification.includes("enhance"))
198
+ return "feature";
199
+ if (classification.includes("invest") || classification.includes("research"))
200
+ return "investigation";
201
+ if (classification.includes("doc"))
202
+ return "documentation";
203
+ if (classification.includes("audit") || classification.includes("review"))
204
+ return "audit";
205
+ if (classification.includes("refact"))
206
+ return "refactor";
207
+ return "unknown";
208
+ }
209
+ async scoreConfidence(issue, changedFiles) {
210
+ // Confidence is already scored during solve() via self-assessment
211
+ // This method exists for re-scoring if needed
212
+ return { score: 5, uncertainties: ["Re-scoring not yet implemented"] };
213
+ }
214
+ }
215
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/engine/claude.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /** Classification of what kind of work an issue requires */
2
+ export type IssueClassification = "code-fix" | "feature" | "investigation" | "documentation" | "audit" | "refactor" | "unknown";
3
+ /** A GitHub issue with parsed metadata */
4
+ export interface Issue {
5
+ number: number;
6
+ title: string;
7
+ body: string;
8
+ labels: string[];
9
+ comments: IssueComment[];
10
+ author: string;
11
+ url: string;
12
+ createdAt: string;
13
+ reactions: number;
14
+ classification?: IssueClassification;
15
+ priority?: number;
16
+ }
17
+ export interface IssueComment {
18
+ author: string;
19
+ body: string;
20
+ createdAt: string;
21
+ }
22
+ /** Context about the repository for the AI engine */
23
+ export interface RepoContext {
24
+ owner: string;
25
+ repo: string;
26
+ baseBranch: string;
27
+ cwd: string;
28
+ /** Timeout in milliseconds for the solve/investigate operation */
29
+ timeout?: number;
30
+ /** Path to per-issue log file for capturing subprocess output */
31
+ issueLogFile?: string;
32
+ }
33
+ /** Events emitted by the AI engine during solving */
34
+ export type EngineEvent = {
35
+ type: "thinking";
36
+ message: string;
37
+ } | {
38
+ type: "tool_use";
39
+ tool: string;
40
+ input: string;
41
+ } | {
42
+ type: "progress";
43
+ message: string;
44
+ } | {
45
+ type: "result";
46
+ result: SolveResult;
47
+ } | {
48
+ type: "error";
49
+ error: string;
50
+ };
51
+ /** Result of solving a single issue */
52
+ export interface SolveResult {
53
+ success: boolean;
54
+ /** Files that were created or modified */
55
+ changedFiles: string[];
56
+ /** AI-generated summary of what was done */
57
+ summary: string;
58
+ /** AI self-assessed confidence score (1-10) */
59
+ confidence: number;
60
+ /** Areas the AI was unsure about */
61
+ uncertainties: string[];
62
+ /** Commit message used */
63
+ commitMessage: string;
64
+ }
65
+ /** A structured issue ready to be posted to GitHub */
66
+ export interface StructuredIssue {
67
+ title: string;
68
+ body: string;
69
+ labels: string[];
70
+ }
71
+ /** The AI engine interface — implement this for each AI backend */
72
+ export interface AIEngine {
73
+ readonly name: string;
74
+ /** Solve a code-related issue (fix, feature, refactor) */
75
+ solve(issue: Issue, context: RepoContext): Promise<SolveResult>;
76
+ /** Investigate a non-code issue (research, audit, documentation) */
77
+ investigate(issue: Issue, context: RepoContext): Promise<SolveResult>;
78
+ /** Generate a well-structured issue from a freeform description */
79
+ createIssue(description: string, context: RepoContext): Promise<StructuredIssue>;
80
+ /** Classify what type of work an issue requires */
81
+ classifyIssue(issue: Issue): Promise<IssueClassification>;
82
+ /** Score confidence of a completed solution */
83
+ scoreConfidence(issue: Issue, changedFiles: string[]): Promise<{
84
+ score: number;
85
+ uncertainties: string[];
86
+ }>;
87
+ }
88
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/engine/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/engine/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,58 @@
1
+ import { Octokit } from "@octokit/rest";
2
+ /** Create an authenticated Octokit client */
3
+ export declare function createOctokit(): Promise<Octokit>;
4
+ export declare class GitHubClient {
5
+ private octokit;
6
+ readonly owner: string;
7
+ readonly repo: string;
8
+ constructor(octokit: Octokit, owner: string, repo: string);
9
+ static create(owner: string, repo: string): Promise<GitHubClient>;
10
+ /** Fetch open issues with optional label filters (paginated) */
11
+ fetchOpenIssues(options?: {
12
+ labels?: string[];
13
+ excludeLabels?: string[];
14
+ maxIssues?: number;
15
+ }): Promise<Array<{
16
+ number: number;
17
+ title: string;
18
+ body: string | null;
19
+ labels: string[];
20
+ user: string;
21
+ html_url: string;
22
+ created_at: string;
23
+ reactions: number;
24
+ comments: number;
25
+ }>>;
26
+ /** Fetch comments for an issue (paginated) */
27
+ fetchIssueComments(issueNumber: number): Promise<Array<{
28
+ author: string;
29
+ body: string;
30
+ createdAt: string;
31
+ }>>;
32
+ /** Create a pull request */
33
+ createPullRequest(options: {
34
+ title: string;
35
+ body: string;
36
+ head: string;
37
+ base: string;
38
+ draft?: boolean;
39
+ labels?: string[];
40
+ }): Promise<{
41
+ number: number;
42
+ url: string;
43
+ }>;
44
+ /** Create a new issue */
45
+ createIssue(options: {
46
+ title: string;
47
+ body: string;
48
+ labels?: string[];
49
+ }): Promise<{
50
+ number: number;
51
+ url: string;
52
+ }>;
53
+ /** Add a comment to an issue */
54
+ addComment(issueNumber: number, body: string): Promise<void>;
55
+ /** Add a label to an issue */
56
+ addLabel(issueNumber: number, label: string): Promise<void>;
57
+ }
58
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/github/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAWxC,6CAA6C;AAC7C,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAgCtD;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;WAM5C,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAKvE,gEAAgE;IAC1D,eAAe,CAAC,OAAO,GAAE;QAC7B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,SAAS,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,KAAK,CAAC;QACrB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IAwDH,8CAA8C;IACxC,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3D,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC,CAAC;IAkBH,4BAA4B;IACtB,iBAAiB,CAAC,OAAO,EAAE;QAC/B,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IA4B5C,yBAAyB;IACnB,WAAW,CAAC,OAAO,EAAE;QACzB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAY5C,gCAAgC;IAC1B,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASlE,8BAA8B;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CA6BlE"}
@@ -0,0 +1,189 @@
1
+ import { Octokit } from "@octokit/rest";
2
+ import { retry } from "@octokit/plugin-retry";
3
+ import { throttling } from "@octokit/plugin-throttling";
4
+ import { execFile } from "node:child_process";
5
+ import { promisify } from "node:util";
6
+ import { log } from "../utils/logger.js";
7
+ const exec = promisify(execFile);
8
+ const OctokitWithPlugins = Octokit.plugin(retry, throttling);
9
+ /** Create an authenticated Octokit client */
10
+ export async function createOctokit() {
11
+ let token = process.env.GITHUB_TOKEN;
12
+ if (!token) {
13
+ // Try getting token from gh CLI
14
+ try {
15
+ const { stdout } = await exec("gh", ["auth", "token"]);
16
+ token = stdout.trim();
17
+ }
18
+ catch {
19
+ // gh not available or not authenticated
20
+ }
21
+ }
22
+ if (!token) {
23
+ throw new Error("GitHub token not found. Set GITHUB_TOKEN environment variable or authenticate with `gh auth login`.");
24
+ }
25
+ return new OctokitWithPlugins({
26
+ auth: token,
27
+ throttle: {
28
+ onRateLimit: (retryAfter, options, _octokit, retryCount) => {
29
+ log.warn(`Rate limit hit for ${options.method} ${options.url}, retrying after ${retryAfter}s`);
30
+ return retryCount < 2;
31
+ },
32
+ onSecondaryRateLimit: (retryAfter, options) => {
33
+ log.warn(`Secondary rate limit hit for ${options.method} ${options.url}, retrying after ${retryAfter}s`);
34
+ return true;
35
+ },
36
+ },
37
+ });
38
+ }
39
+ export class GitHubClient {
40
+ octokit;
41
+ owner;
42
+ repo;
43
+ constructor(octokit, owner, repo) {
44
+ this.octokit = octokit;
45
+ this.owner = owner;
46
+ this.repo = repo;
47
+ }
48
+ static async create(owner, repo) {
49
+ const octokit = await createOctokit();
50
+ return new GitHubClient(octokit, owner, repo);
51
+ }
52
+ /** Fetch open issues with optional label filters (paginated) */
53
+ async fetchOpenIssues(options = {}) {
54
+ const { labels = [], excludeLabels = [], maxIssues = 30 } = options;
55
+ const params = {
56
+ owner: this.owner,
57
+ repo: this.repo,
58
+ state: "open",
59
+ per_page: Math.min(maxIssues, 100),
60
+ sort: "created",
61
+ direction: "desc",
62
+ };
63
+ if (labels.length > 0) {
64
+ params.labels = labels.join(",");
65
+ }
66
+ // Use pagination to handle maxIssues > 100
67
+ const issues = await this.octokit.paginate(this.octokit.issues.listForRepo, params, (response, done) => {
68
+ const items = response.data;
69
+ // Stop paginating once we have enough
70
+ if (items.length >= maxIssues) {
71
+ done();
72
+ }
73
+ return items;
74
+ });
75
+ // Filter out pull requests (GitHub API returns PRs in issues endpoint)
76
+ let filtered = issues.filter((issue) => !issue.pull_request);
77
+ // Filter out excluded labels
78
+ if (excludeLabels.length > 0) {
79
+ filtered = filtered.filter((issue) => {
80
+ const issueLabels = issue.labels.map((l) => typeof l === "string" ? l : l.name || "");
81
+ return !issueLabels.some((label) => excludeLabels.includes(label));
82
+ });
83
+ }
84
+ return filtered.slice(0, maxIssues).map((issue) => ({
85
+ number: issue.number,
86
+ title: issue.title,
87
+ body: issue.body ?? null,
88
+ labels: issue.labels.map((l) => (typeof l === "string" ? l : l.name || "")),
89
+ user: issue.user?.login || "unknown",
90
+ html_url: issue.html_url,
91
+ created_at: issue.created_at,
92
+ reactions: issue.reactions?.total_count || 0,
93
+ comments: issue.comments,
94
+ }));
95
+ }
96
+ /** Fetch comments for an issue (paginated) */
97
+ async fetchIssueComments(issueNumber) {
98
+ const comments = await this.octokit.paginate(this.octokit.issues.listComments, {
99
+ owner: this.owner,
100
+ repo: this.repo,
101
+ issue_number: issueNumber,
102
+ per_page: 100,
103
+ });
104
+ return comments.map((c) => ({
105
+ author: c.user?.login || "unknown",
106
+ body: c.body || "",
107
+ createdAt: c.created_at,
108
+ }));
109
+ }
110
+ /** Create a pull request */
111
+ async createPullRequest(options) {
112
+ const { data: pr } = await this.octokit.pulls.create({
113
+ owner: this.owner,
114
+ repo: this.repo,
115
+ title: options.title,
116
+ body: options.body,
117
+ head: options.head,
118
+ base: options.base,
119
+ draft: options.draft || false,
120
+ });
121
+ // Add labels if provided
122
+ if (options.labels && options.labels.length > 0) {
123
+ try {
124
+ await this.octokit.issues.addLabels({
125
+ owner: this.owner,
126
+ repo: this.repo,
127
+ issue_number: pr.number,
128
+ labels: options.labels,
129
+ });
130
+ }
131
+ catch (err) {
132
+ log.warn(`Could not add labels to PR #${pr.number}: ${err}`);
133
+ }
134
+ }
135
+ return { number: pr.number, url: pr.html_url };
136
+ }
137
+ /** Create a new issue */
138
+ async createIssue(options) {
139
+ const { data: issue } = await this.octokit.issues.create({
140
+ owner: this.owner,
141
+ repo: this.repo,
142
+ title: options.title,
143
+ body: options.body,
144
+ labels: options.labels || [],
145
+ });
146
+ return { number: issue.number, url: issue.html_url };
147
+ }
148
+ /** Add a comment to an issue */
149
+ async addComment(issueNumber, body) {
150
+ await this.octokit.issues.createComment({
151
+ owner: this.owner,
152
+ repo: this.repo,
153
+ issue_number: issueNumber,
154
+ body,
155
+ });
156
+ }
157
+ /** Add a label to an issue */
158
+ async addLabel(issueNumber, label) {
159
+ try {
160
+ // Ensure label exists
161
+ try {
162
+ await this.octokit.issues.getLabel({
163
+ owner: this.owner,
164
+ repo: this.repo,
165
+ name: label,
166
+ });
167
+ }
168
+ catch {
169
+ await this.octokit.issues.createLabel({
170
+ owner: this.owner,
171
+ repo: this.repo,
172
+ name: label,
173
+ color: "7057ff",
174
+ description: "Auto-classified by dispatch",
175
+ });
176
+ }
177
+ await this.octokit.issues.addLabels({
178
+ owner: this.owner,
179
+ repo: this.repo,
180
+ issue_number: issueNumber,
181
+ labels: [label],
182
+ });
183
+ }
184
+ catch (err) {
185
+ log.warn(`Could not add label "${label}" to #${issueNumber}: ${err}`);
186
+ }
187
+ }
188
+ }
189
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/github/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { Issue } from "../engine/types.js";
2
+ import type { GitHubClient } from "./client.js";
3
+ /** Fetch and hydrate issues with comments and metadata */
4
+ export declare function fetchAndHydrateIssues(client: GitHubClient, options: {
5
+ labels?: string[];
6
+ excludeLabels?: string[];
7
+ maxIssues?: number;
8
+ }): Promise<Issue[]>;
9
+ /** Sort issues by priority */
10
+ export declare function prioritizeIssues(issues: Issue[]): Issue[];
11
+ /** Create a slug from issue title for branch names */
12
+ export declare function slugifyTitle(title: string): string;
13
+ //# sourceMappingURL=issues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issues.d.ts","sourceRoot":"","sources":["../../../src/github/issues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,0DAA0D;AAC1D,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE;IACP,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACA,OAAO,CAAC,KAAK,EAAE,CAAC,CAiClB;AAED,8BAA8B;AAC9B,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,CAuBzD;AAED,sDAAsD;AACtD,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQlD"}