@a5c-ai/tasks-mux 5.0.1-staging.a2e883985f51

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 (175) hide show
  1. package/README.md +103 -0
  2. package/dist/auth/forge-interface.d.ts +67 -0
  3. package/dist/auth/forge-interface.d.ts.map +1 -0
  4. package/dist/auth/forge-interface.js +69 -0
  5. package/dist/auth/github-app.d.ts +64 -0
  6. package/dist/auth/github-app.d.ts.map +1 -0
  7. package/dist/auth/github-app.js +141 -0
  8. package/dist/auth/github-oauth.d.ts +27 -0
  9. package/dist/auth/github-oauth.d.ts.map +1 -0
  10. package/dist/auth/github-oauth.js +89 -0
  11. package/dist/auth/index.d.ts +8 -0
  12. package/dist/auth/index.d.ts.map +1 -0
  13. package/dist/auth/index.js +14 -0
  14. package/dist/auth/jwt.d.ts +24 -0
  15. package/dist/auth/jwt.d.ts.map +1 -0
  16. package/dist/auth/jwt.js +43 -0
  17. package/dist/auth/middleware.d.ts +22 -0
  18. package/dist/auth/middleware.d.ts.map +1 -0
  19. package/dist/auth/middleware.js +36 -0
  20. package/dist/auth/ssh-keys.d.ts +21 -0
  21. package/dist/auth/ssh-keys.d.ts.map +1 -0
  22. package/dist/auth/ssh-keys.js +59 -0
  23. package/dist/auth/types.d.ts +165 -0
  24. package/dist/auth/types.d.ts.map +1 -0
  25. package/dist/auth/types.js +53 -0
  26. package/dist/backend.d.ts +117 -0
  27. package/dist/backend.d.ts.map +1 -0
  28. package/dist/backend.js +15 -0
  29. package/dist/backends/git-native.d.ts +51 -0
  30. package/dist/backends/git-native.d.ts.map +1 -0
  31. package/dist/backends/git-native.js +324 -0
  32. package/dist/backends/github-issues.d.ts +77 -0
  33. package/dist/backends/github-issues.d.ts.map +1 -0
  34. package/dist/backends/github-issues.js +796 -0
  35. package/dist/backends/index.d.ts +48 -0
  36. package/dist/backends/index.d.ts.map +1 -0
  37. package/dist/backends/index.js +139 -0
  38. package/dist/backends/server.d.ts +41 -0
  39. package/dist/backends/server.d.ts.map +1 -0
  40. package/dist/backends/server.js +298 -0
  41. package/dist/cli/auth-store.d.ts +49 -0
  42. package/dist/cli/auth-store.d.ts.map +1 -0
  43. package/dist/cli/auth-store.js +150 -0
  44. package/dist/cli/client-config.d.ts +10 -0
  45. package/dist/cli/client-config.d.ts.map +1 -0
  46. package/dist/cli/client-config.js +87 -0
  47. package/dist/cli/commands/ask.d.ts +3 -0
  48. package/dist/cli/commands/ask.d.ts.map +1 -0
  49. package/dist/cli/commands/ask.js +171 -0
  50. package/dist/cli/commands/auth.d.ts +3 -0
  51. package/dist/cli/commands/auth.d.ts.map +1 -0
  52. package/dist/cli/commands/auth.js +510 -0
  53. package/dist/cli/commands/breakpoints.d.ts +3 -0
  54. package/dist/cli/commands/breakpoints.d.ts.map +1 -0
  55. package/dist/cli/commands/breakpoints.js +152 -0
  56. package/dist/cli/commands/responder-loop.d.ts +3 -0
  57. package/dist/cli/commands/responder-loop.d.ts.map +1 -0
  58. package/dist/cli/commands/responder-loop.js +78 -0
  59. package/dist/cli/commands/responders.d.ts +3 -0
  60. package/dist/cli/commands/responders.d.ts.map +1 -0
  61. package/dist/cli/commands/responders.js +74 -0
  62. package/dist/cli/commands/server.d.ts +3 -0
  63. package/dist/cli/commands/server.d.ts.map +1 -0
  64. package/dist/cli/commands/server.js +34 -0
  65. package/dist/cli/index.d.ts +4 -0
  66. package/dist/cli/index.d.ts.map +1 -0
  67. package/dist/cli/index.js +9 -0
  68. package/dist/cli/output.d.ts +26 -0
  69. package/dist/cli/output.d.ts.map +1 -0
  70. package/dist/cli/output.js +143 -0
  71. package/dist/cli/program.d.ts +6 -0
  72. package/dist/cli/program.d.ts.map +1 -0
  73. package/dist/cli/program.js +32 -0
  74. package/dist/client/answer-poller.d.ts +52 -0
  75. package/dist/client/answer-poller.d.ts.map +1 -0
  76. package/dist/client/answer-poller.js +199 -0
  77. package/dist/client/auth-client.d.ts +200 -0
  78. package/dist/client/auth-client.d.ts.map +1 -0
  79. package/dist/client/auth-client.js +309 -0
  80. package/dist/client/breakpoint-router.d.ts +45 -0
  81. package/dist/client/breakpoint-router.d.ts.map +1 -0
  82. package/dist/client/breakpoint-router.js +45 -0
  83. package/dist/client/index.d.ts +17 -0
  84. package/dist/client/index.d.ts.map +1 -0
  85. package/dist/client/index.js +16 -0
  86. package/dist/client/profile-validator.d.ts +34 -0
  87. package/dist/client/profile-validator.d.ts.map +1 -0
  88. package/dist/client/profile-validator.js +89 -0
  89. package/dist/client/responder-client.d.ts +39 -0
  90. package/dist/client/responder-client.d.ts.map +1 -0
  91. package/dist/client/responder-client.js +72 -0
  92. package/dist/client/responder-matcher.d.ts +49 -0
  93. package/dist/client/responder-matcher.d.ts.map +1 -0
  94. package/dist/client/responder-matcher.js +226 -0
  95. package/dist/client/server-client.d.ts +124 -0
  96. package/dist/client/server-client.d.ts.map +1 -0
  97. package/dist/client/server-client.js +266 -0
  98. package/dist/client/timeout-manager.d.ts +47 -0
  99. package/dist/client/timeout-manager.d.ts.map +1 -0
  100. package/dist/client/timeout-manager.js +77 -0
  101. package/dist/config.d.ts +20 -0
  102. package/dist/config.d.ts.map +1 -0
  103. package/dist/config.js +93 -0
  104. package/dist/harness/index.d.ts +4 -0
  105. package/dist/harness/index.d.ts.map +1 -0
  106. package/dist/harness/index.js +2 -0
  107. package/dist/harness/interaction-provider.d.ts +71 -0
  108. package/dist/harness/interaction-provider.d.ts.map +1 -0
  109. package/dist/harness/interaction-provider.js +124 -0
  110. package/dist/harness/routing-rules.d.ts +7 -0
  111. package/dist/harness/routing-rules.d.ts.map +1 -0
  112. package/dist/harness/routing-rules.js +37 -0
  113. package/dist/index.d.ts +19 -0
  114. package/dist/index.d.ts.map +1 -0
  115. package/dist/index.js +26 -0
  116. package/dist/mcp/backend-resolver.d.ts +43 -0
  117. package/dist/mcp/backend-resolver.d.ts.map +1 -0
  118. package/dist/mcp/backend-resolver.js +111 -0
  119. package/dist/mcp/http-transport.d.ts +37 -0
  120. package/dist/mcp/http-transport.d.ts.map +1 -0
  121. package/dist/mcp/http-transport.js +103 -0
  122. package/dist/mcp/index.d.ts +14 -0
  123. package/dist/mcp/index.d.ts.map +1 -0
  124. package/dist/mcp/index.js +11 -0
  125. package/dist/mcp/server.d.ts +20 -0
  126. package/dist/mcp/server.d.ts.map +1 -0
  127. package/dist/mcp/server.js +121 -0
  128. package/dist/mcp/tools/answer-breakpoint.d.ts +32 -0
  129. package/dist/mcp/tools/answer-breakpoint.d.ts.map +1 -0
  130. package/dist/mcp/tools/answer-breakpoint.js +45 -0
  131. package/dist/mcp/tools/ask-breakpoint.d.ts +58 -0
  132. package/dist/mcp/tools/ask-breakpoint.d.ts.map +1 -0
  133. package/dist/mcp/tools/ask-breakpoint.js +78 -0
  134. package/dist/mcp/tools/check-status.d.ts +16 -0
  135. package/dist/mcp/tools/check-status.d.ts.map +1 -0
  136. package/dist/mcp/tools/check-status.js +18 -0
  137. package/dist/mcp/tools/claim-breakpoint.d.ts +18 -0
  138. package/dist/mcp/tools/claim-breakpoint.d.ts.map +1 -0
  139. package/dist/mcp/tools/claim-breakpoint.js +28 -0
  140. package/dist/mcp/tools/list-breakpoints.d.ts +16 -0
  141. package/dist/mcp/tools/list-breakpoints.d.ts.map +1 -0
  142. package/dist/mcp/tools/list-breakpoints.js +14 -0
  143. package/dist/mcp/tools/list-responders.d.ts +18 -0
  144. package/dist/mcp/tools/list-responders.d.ts.map +1 -0
  145. package/dist/mcp/tools/list-responders.js +37 -0
  146. package/dist/mcp/tools/poll-breakpoints.d.ts +18 -0
  147. package/dist/mcp/tools/poll-breakpoints.d.ts.map +1 -0
  148. package/dist/mcp/tools/poll-breakpoints.js +36 -0
  149. package/dist/mcp/tools/verify-answer.d.ts +16 -0
  150. package/dist/mcp/tools/verify-answer.d.ts.map +1 -0
  151. package/dist/mcp/tools/verify-answer.js +38 -0
  152. package/dist/proven/index.d.ts +5 -0
  153. package/dist/proven/index.d.ts.map +1 -0
  154. package/dist/proven/index.js +3 -0
  155. package/dist/proven/keys.d.ts +33 -0
  156. package/dist/proven/keys.d.ts.map +1 -0
  157. package/dist/proven/keys.js +117 -0
  158. package/dist/proven/sign.d.ts +16 -0
  159. package/dist/proven/sign.d.ts.map +1 -0
  160. package/dist/proven/sign.js +60 -0
  161. package/dist/proven/types.d.ts +26 -0
  162. package/dist/proven/types.d.ts.map +1 -0
  163. package/dist/proven/types.js +5 -0
  164. package/dist/proven/verify.d.ts +6 -0
  165. package/dist/proven/verify.d.ts.map +1 -0
  166. package/dist/proven/verify.js +58 -0
  167. package/dist/types.d.ts +4034 -0
  168. package/dist/types.d.ts.map +1 -0
  169. package/dist/types.js +244 -0
  170. package/package.json +86 -0
  171. package/responder/README.md +42 -0
  172. package/responder/backend-responder.json +9 -0
  173. package/responder/devops-responder.json +9 -0
  174. package/responder/frontend-responder.json +9 -0
  175. package/responder/schema.json +52 -0
@@ -0,0 +1,324 @@
1
+ import { promises as fs } from "node:fs";
2
+ import * as path from "node:path";
3
+ import { generateBreakpointId, DEFAULT_POLL_INTERVAL_MS, DEFAULT_TIMEOUT_MS, BREAKPOINTS_DIR, BreakpointSchema, BreakpointPublicAnswerSchema, ProvenBreakpointAnswerSchema, isProvenBreakpointAnswer, } from "../types.js";
4
+ import { signAnswer, signAnswerWithKeyRecord } from "../proven/sign.js";
5
+ import { verifyAnswer as verifyProvenAnswer } from "../proven/verify.js";
6
+ import { selectBreakpointAnswer as selectPublicBreakpointAnswer } from "../backend.js";
7
+ export class GitNativeBackend {
8
+ name = "git-native";
9
+ breakpointsDir;
10
+ defaultPollIntervalMs;
11
+ defaultTimeoutMs;
12
+ signingKeyPath;
13
+ constructor(options) {
14
+ this.breakpointsDir = options?.breakpointsDir
15
+ ?? path.resolve(process.cwd(), BREAKPOINTS_DIR);
16
+ this.defaultPollIntervalMs = options?.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
17
+ this.defaultTimeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
18
+ this.signingKeyPath = options?.signingKeyPath;
19
+ }
20
+ breakpointPath(id) {
21
+ return path.join(this.breakpointsDir, `${id}.json`);
22
+ }
23
+ answerPath(id) {
24
+ return path.join(this.breakpointsDir, `${id}.answer.json`);
25
+ }
26
+ provenPath(id) {
27
+ return path.join(this.breakpointsDir, `${id}.proven.json`);
28
+ }
29
+ /**
30
+ * Load the signing key from the configured signingKeyPath.
31
+ * Returns null if no signing key is configured or the file cannot be read.
32
+ */
33
+ async loadSigningKey() {
34
+ if (!this.signingKeyPath)
35
+ return null;
36
+ try {
37
+ const raw = await fs.readFile(this.signingKeyPath, "utf-8");
38
+ return JSON.parse(raw);
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
44
+ /**
45
+ * Load a proven answer file for a breakpoint, if it exists.
46
+ */
47
+ async loadProvenAnswer(id) {
48
+ try {
49
+ const raw = await fs.readFile(this.provenPath(id), "utf-8");
50
+ return ProvenBreakpointAnswerSchema.parse(JSON.parse(raw));
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ async loadStoredAnswer(id) {
57
+ try {
58
+ const raw = await fs.readFile(this.answerPath(id), "utf-8");
59
+ return BreakpointPublicAnswerSchema.parse(JSON.parse(raw));
60
+ }
61
+ catch {
62
+ return null;
63
+ }
64
+ }
65
+ async loadPublicAnswer(id) {
66
+ const [storedAnswer, provenAnswer] = await Promise.all([
67
+ this.loadStoredAnswer(id),
68
+ this.loadProvenAnswer(id),
69
+ ]);
70
+ return provenAnswer ?? storedAnswer;
71
+ }
72
+ async submitBreakpoint(params) {
73
+ await fs.mkdir(this.breakpointsDir, { recursive: true });
74
+ const id = generateBreakpointId();
75
+ const now = new Date().toISOString();
76
+ const timeoutMs = params.routing.timeoutMs || this.defaultTimeoutMs;
77
+ const breakpoint = {
78
+ id,
79
+ text: params.text,
80
+ context: params.context,
81
+ status: "pending",
82
+ routing: params.routing,
83
+ answers: [],
84
+ projectId: params.projectId,
85
+ repoId: params.repoId,
86
+ createdAt: now,
87
+ updatedAt: now,
88
+ expiresAt: new Date(Date.now() + timeoutMs).toISOString(),
89
+ };
90
+ // Validate before writing
91
+ BreakpointSchema.parse(breakpoint);
92
+ await fs.writeFile(this.breakpointPath(id), JSON.stringify(breakpoint, null, 2) + "\n", "utf-8");
93
+ return breakpoint;
94
+ }
95
+ async getBreakpoint(id) {
96
+ const raw = await fs.readFile(this.breakpointPath(id), "utf-8");
97
+ const breakpoint = BreakpointSchema.parse(JSON.parse(raw));
98
+ const answer = await this.loadPublicAnswer(id);
99
+ if (answer) {
100
+ const existingIndex = breakpoint.answers.findIndex((candidate) => candidate.id === answer.id);
101
+ if (existingIndex === -1) {
102
+ breakpoint.answers.push(answer);
103
+ }
104
+ else {
105
+ breakpoint.answers[existingIndex] = answer;
106
+ }
107
+ if (breakpoint.status === "pending" || breakpoint.status === "claimed") {
108
+ breakpoint.status = "answered";
109
+ }
110
+ }
111
+ const selectedAnswer = selectPublicBreakpointAnswer(breakpoint);
112
+ if (selectedAnswer && isProvenBreakpointAnswer(selectedAnswer)) {
113
+ const verification = await this.verifyProvenFile(selectedAnswer);
114
+ // Attach verification result as metadata on the breakpoint
115
+ breakpoint
116
+ .provenVerification = verification;
117
+ }
118
+ return breakpoint;
119
+ }
120
+ async waitForAnswer(id, options) {
121
+ const timeoutMs = options?.timeoutMs ?? this.defaultTimeoutMs;
122
+ const pollIntervalMs = options?.pollIntervalMs ?? this.defaultPollIntervalMs;
123
+ const signal = options?.signal;
124
+ const startTime = Date.now();
125
+ while (true) {
126
+ if (signal?.aborted) {
127
+ const breakpoint = await this.getBreakpoint(id);
128
+ return {
129
+ answered: false,
130
+ breakpoint,
131
+ allAnswers: breakpoint.answers,
132
+ resolution: "aborted",
133
+ elapsedMs: Date.now() - startTime,
134
+ };
135
+ }
136
+ // Check for answer file
137
+ try {
138
+ await fs.access(this.answerPath(id));
139
+ const breakpoint = await this.getBreakpoint(id);
140
+ const answer = selectPublicBreakpointAnswer(breakpoint);
141
+ return {
142
+ answered: true,
143
+ breakpoint: { ...breakpoint, status: "answered" },
144
+ answer,
145
+ allAnswers: breakpoint.answers,
146
+ resolution: "answered",
147
+ elapsedMs: Date.now() - startTime,
148
+ };
149
+ }
150
+ catch {
151
+ // No answer yet
152
+ }
153
+ // Check cancellation status
154
+ const breakpoint = await this.getBreakpoint(id);
155
+ if (breakpoint.status === "cancelled") {
156
+ return {
157
+ answered: false,
158
+ breakpoint,
159
+ allAnswers: breakpoint.answers,
160
+ resolution: "cancelled",
161
+ elapsedMs: Date.now() - startTime,
162
+ };
163
+ }
164
+ if (Date.now() - startTime >= timeoutMs) {
165
+ return {
166
+ answered: false,
167
+ breakpoint,
168
+ allAnswers: breakpoint.answers,
169
+ resolution: "timeout",
170
+ elapsedMs: Date.now() - startTime,
171
+ };
172
+ }
173
+ // Wait before next poll
174
+ await new Promise((resolve) => {
175
+ const timer = setTimeout(resolve, pollIntervalMs);
176
+ if (signal) {
177
+ const onAbort = () => {
178
+ clearTimeout(timer);
179
+ resolve();
180
+ };
181
+ signal.addEventListener("abort", onAbort, { once: true });
182
+ }
183
+ });
184
+ }
185
+ }
186
+ async listPendingBreakpoints(responderId) {
187
+ let files;
188
+ try {
189
+ files = await fs.readdir(this.breakpointsDir);
190
+ }
191
+ catch {
192
+ return [];
193
+ }
194
+ const pending = [];
195
+ for (const file of files) {
196
+ if (!file.endsWith(".json") || file.includes(".answer.") || file.includes(".proven.")) {
197
+ continue;
198
+ }
199
+ try {
200
+ const raw = await fs.readFile(path.join(this.breakpointsDir, file), "utf-8");
201
+ const bp = BreakpointSchema.parse(JSON.parse(raw));
202
+ if (bp.status !== "pending" && bp.status !== "routed")
203
+ continue;
204
+ // Check expiration
205
+ if (new Date(bp.expiresAt) < new Date())
206
+ continue;
207
+ // Filter by responder if specified
208
+ if (responderId && bp.routing.targetResponders.length > 0) {
209
+ if (!bp.routing.targetResponders.includes(responderId))
210
+ continue;
211
+ }
212
+ // Check if answer already exists
213
+ try {
214
+ await fs.access(this.answerPath(bp.id));
215
+ continue; // Already answered
216
+ }
217
+ catch {
218
+ // No answer, include it
219
+ }
220
+ pending.push(bp);
221
+ }
222
+ catch {
223
+ // Skip malformed files
224
+ }
225
+ }
226
+ return pending;
227
+ }
228
+ async answerBreakpoint(id, answer) {
229
+ // Verify breakpoint exists
230
+ await this.getBreakpoint(id);
231
+ const answerId = generateBreakpointId();
232
+ const now = new Date().toISOString();
233
+ const breakpointAnswer = {
234
+ id: answerId,
235
+ breakpointId: id,
236
+ responderId: answer.responderId,
237
+ responderName: answer.responderName,
238
+ text: answer.text,
239
+ approved: answer.approved,
240
+ confidence: answer.confidence ?? 80,
241
+ references: answer.references ?? [],
242
+ followUpQuestions: answer.followUpQuestions ?? [],
243
+ answeredAt: now,
244
+ decisionMemory: answer.decisionMemory
245
+ ? { ...answer.decisionMemory, savedAt: now }
246
+ : undefined,
247
+ };
248
+ if (answer.sign === false && answer.keyFingerprint) {
249
+ throw new Error("keyFingerprint cannot be used when sign=false");
250
+ }
251
+ let publicAnswer = breakpointAnswer;
252
+ if (answer.keyFingerprint) {
253
+ publicAnswer = await signAnswer(breakpointAnswer, answer.keyFingerprint, this.breakpointsDir);
254
+ }
255
+ else if (answer.sign === true) {
256
+ const signingKey = await this.loadSigningKey();
257
+ if (!signingKey) {
258
+ throw new Error("answer_breakpoint.sign requested, but no signing key is configured");
259
+ }
260
+ publicAnswer = signAnswerWithKeyRecord(breakpointAnswer, signingKey);
261
+ }
262
+ else if (answer.sign !== false) {
263
+ const signingKey = await this.loadSigningKey();
264
+ if (signingKey) {
265
+ publicAnswer = signAnswerWithKeyRecord(breakpointAnswer, signingKey);
266
+ }
267
+ }
268
+ BreakpointPublicAnswerSchema.parse(publicAnswer);
269
+ await fs.writeFile(this.answerPath(id), JSON.stringify(publicAnswer, null, 2) + "\n", "utf-8");
270
+ if (isProvenBreakpointAnswer(publicAnswer)) {
271
+ await fs.writeFile(this.provenPath(id), JSON.stringify(publicAnswer, null, 2) + "\n", "utf-8");
272
+ }
273
+ else {
274
+ await fs.rm(this.provenPath(id), { force: true });
275
+ }
276
+ // Update the breakpoint status
277
+ const breakpoint = await this.getBreakpoint(id);
278
+ delete breakpoint.provenVerification;
279
+ breakpoint.status = "answered";
280
+ breakpoint.updatedAt = now;
281
+ await fs.writeFile(this.breakpointPath(id), JSON.stringify(breakpoint, null, 2) + "\n", "utf-8");
282
+ return publicAnswer;
283
+ }
284
+ async cancelBreakpoint(id) {
285
+ const breakpoint = await this.getBreakpoint(id);
286
+ delete breakpoint.provenVerification;
287
+ breakpoint.status = "cancelled";
288
+ breakpoint.updatedAt = new Date().toISOString();
289
+ await fs.writeFile(this.breakpointPath(id), JSON.stringify(breakpoint, null, 2) + "\n", "utf-8");
290
+ }
291
+ async claimBreakpoint(id, responderId) {
292
+ const breakpoint = await this.getBreakpoint(id);
293
+ delete breakpoint.provenVerification;
294
+ breakpoint.status = "claimed";
295
+ breakpoint.claimedByResponderId = responderId;
296
+ breakpoint.updatedAt = new Date().toISOString();
297
+ await fs.writeFile(this.breakpointPath(id), JSON.stringify(breakpoint, null, 2) + "\n", "utf-8");
298
+ return breakpoint;
299
+ }
300
+ /**
301
+ * Verify the selected public answer against trusted public keys.
302
+ */
303
+ async verifyAnswer(id) {
304
+ const breakpoint = await this.getBreakpoint(id);
305
+ const answer = selectPublicBreakpointAnswer(breakpoint);
306
+ if (!answer || !isProvenBreakpointAnswer(answer)) {
307
+ return {
308
+ valid: false,
309
+ reason: "No signed answer found",
310
+ verifiedAt: new Date().toISOString(),
311
+ };
312
+ }
313
+ return this.verifyProvenFile(answer);
314
+ }
315
+ /**
316
+ * Verify a loaded ProvenBreakpointAnswer against trusted keys in the
317
+ * breakpoints directory.
318
+ */
319
+ async verifyProvenFile(provenAnswer) {
320
+ // The proven/verify module's loadTrustedPublicKeys uses baseDir/.keys/trusted/
321
+ // Our breakpointsDir IS the .breakpoints directory, so we pass it as baseDir.
322
+ return verifyProvenAnswer(provenAnswer, this.breakpointsDir);
323
+ }
324
+ }
@@ -0,0 +1,77 @@
1
+ import type { BreakpointBackend, SubmitBreakpointParams, WaitForAnswerOptions, SubmitAnswerParams, ListRespondersParams } from "../backend.js";
2
+ import type { Breakpoint, BreakpointAnswer, BreakpointWaitResult, ResponderProfile, GitHubIssuesBackendConfig } from "../types.js";
3
+ interface ParsedAnswer {
4
+ text: string;
5
+ confidence?: number;
6
+ references?: string[];
7
+ responderId?: string;
8
+ responderName?: string;
9
+ breakpointId?: string;
10
+ answeredAt?: string;
11
+ }
12
+ /**
13
+ * Resolve a GitHub token by trying `gh auth token` first,
14
+ * then falling back to the GITHUB_TOKEN environment variable.
15
+ */
16
+ export declare function getGitHubToken(): string;
17
+ /**
18
+ * Parse an answer from a GitHub issue comment body.
19
+ * Looks for a hidden JSON payload block, a "## Answer" heading anywhere
20
+ * in the body, a JSON code block with an "answer" field, or a sufficiently
21
+ * long plain-text comment (for assigned responders handled upstream).
22
+ */
23
+ export declare function parseAnswerFromComment(body: string, options?: {
24
+ isAssignedResponder?: boolean;
25
+ }): ParsedAnswer | null;
26
+ /**
27
+ * BreakpointBackend implementation backed by GitHub Issues.
28
+ *
29
+ * Each breakpoint maps to a GitHub issue; answers are detected
30
+ * from issue comments containing payload blocks, "## Answer" markers, or JSON blocks.
31
+ */
32
+ export declare class GitHubIssuesBackend implements BreakpointBackend {
33
+ readonly name = "github-issues";
34
+ private owner;
35
+ private repo;
36
+ private labels;
37
+ private assignees;
38
+ private defaultPollIntervalMs;
39
+ private defaultTimeoutMs;
40
+ /**
41
+ * Maps breakpointId -> GitHub issue number.
42
+ *
43
+ * Used for legacy non-`gh-{number}` IDs within a single process.
44
+ * New breakpoints always use `gh-{number}` IDs and remain durable
45
+ * across backend restarts without this map.
46
+ */
47
+ private issueMap;
48
+ private tokenOverride?;
49
+ /**
50
+ * Resolve the GitHub issue number from a breakpoint ID.
51
+ * Checks the in-memory map first, then parses the `gh-{number}` format
52
+ * so that IDs survive across backend instances.
53
+ */
54
+ private resolveIssueNumber;
55
+ constructor(config: GitHubIssuesBackendConfig);
56
+ /**
57
+ * Override the token resolution for testing.
58
+ * @internal
59
+ */
60
+ setToken(token: string): void;
61
+ private getToken;
62
+ private githubFetch;
63
+ private repoPath;
64
+ private mapIssueToBreakpoint;
65
+ private buildAnswerFromComment;
66
+ private formatIssueBody;
67
+ submitBreakpoint(params: SubmitBreakpointParams): Promise<Breakpoint>;
68
+ getBreakpoint(id: string): Promise<Breakpoint>;
69
+ waitForAnswer(id: string, options?: WaitForAnswerOptions): Promise<BreakpointWaitResult>;
70
+ listResponders(_params?: ListRespondersParams): Promise<ResponderProfile[]>;
71
+ claimBreakpoint(id: string, responderId: string): Promise<Breakpoint>;
72
+ answerBreakpoint(id: string, answer: SubmitAnswerParams): Promise<BreakpointAnswer>;
73
+ listPendingBreakpoints(responderId?: string): Promise<Breakpoint[]>;
74
+ cancelBreakpoint(id: string): Promise<void>;
75
+ }
76
+ export {};
77
+ //# sourceMappingURL=github-issues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"github-issues.d.ts","sourceRoot":"","sources":["../../src/backends/github-issues.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,oBAAoB,EACrB,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EAKpB,gBAAgB,EAChB,yBAAyB,EAC1B,MAAM,aAAa,CAAC;AAwDrB,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA0LD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAevC;AAQD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IAAE,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1C,YAAY,GAAG,IAAI,CAwDrB;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,YAAW,iBAAiB;IAC3D,QAAQ,CAAC,IAAI,mBAAmB;IAEhC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,SAAS,CAAW;IAC5B,OAAO,CAAC,qBAAqB,CAAS;IACtC,OAAO,CAAC,gBAAgB,CAAS;IAEjC;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAA6B;IAE7C,OAAO,CAAC,aAAa,CAAC,CAAS;IAE/B;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;gBAcd,MAAM,EAAE,yBAAyB;IAS7C;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,OAAO,CAAC,QAAQ;YAKF,WAAW;IA6CzB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,oBAAoB;IAsD5B,OAAO,CAAC,sBAAsB;IAuB9B,OAAO,CAAC,eAAe;IAgHjB,gBAAgB,CAAC,MAAM,EAAE,sBAAsB,GAAG,OAAO,CAAC,UAAU,CAAC;IAiCrE,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAsC9C,aAAa,CACjB,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,oBAAoB,CAAC;IAmG1B,cAAc,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAY3E,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IA4BrE,gBAAgB,CACpB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,gBAAgB,CAAC;IAwEtB,sBAAsB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IA0BnE,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAgBlD"}