@a5c-ai/tasks-adapter 5.1.1-staging.52898ebfc24f

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 (202) hide show
  1. package/README.md +125 -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 +248 -0
  27. package/dist/backend.d.ts.map +1 -0
  28. package/dist/backend.js +40 -0
  29. package/dist/backends/adapters.d.ts +99 -0
  30. package/dist/backends/adapters.d.ts.map +1 -0
  31. package/dist/backends/adapters.js +308 -0
  32. package/dist/backends/external-tracker.d.ts +133 -0
  33. package/dist/backends/external-tracker.d.ts.map +1 -0
  34. package/dist/backends/external-tracker.js +731 -0
  35. package/dist/backends/git-native.d.ts +69 -0
  36. package/dist/backends/git-native.d.ts.map +1 -0
  37. package/dist/backends/git-native.js +797 -0
  38. package/dist/backends/github-issues.d.ts +78 -0
  39. package/dist/backends/github-issues.d.ts.map +1 -0
  40. package/dist/backends/github-issues.js +806 -0
  41. package/dist/backends/index.d.ts +52 -0
  42. package/dist/backends/index.d.ts.map +1 -0
  43. package/dist/backends/index.js +151 -0
  44. package/dist/backends/server.d.ts +42 -0
  45. package/dist/backends/server.d.ts.map +1 -0
  46. package/dist/backends/server.js +305 -0
  47. package/dist/cli/auth-store.d.ts +49 -0
  48. package/dist/cli/auth-store.d.ts.map +1 -0
  49. package/dist/cli/auth-store.js +150 -0
  50. package/dist/cli/client-config.d.ts +10 -0
  51. package/dist/cli/client-config.d.ts.map +1 -0
  52. package/dist/cli/client-config.js +87 -0
  53. package/dist/cli/commands/ask.d.ts +3 -0
  54. package/dist/cli/commands/ask.d.ts.map +1 -0
  55. package/dist/cli/commands/ask.js +171 -0
  56. package/dist/cli/commands/auth.d.ts +3 -0
  57. package/dist/cli/commands/auth.d.ts.map +1 -0
  58. package/dist/cli/commands/auth.js +510 -0
  59. package/dist/cli/commands/breakpoints.d.ts +3 -0
  60. package/dist/cli/commands/breakpoints.d.ts.map +1 -0
  61. package/dist/cli/commands/breakpoints.js +311 -0
  62. package/dist/cli/commands/responder-loop.d.ts +3 -0
  63. package/dist/cli/commands/responder-loop.d.ts.map +1 -0
  64. package/dist/cli/commands/responder-loop.js +78 -0
  65. package/dist/cli/commands/responders.d.ts +3 -0
  66. package/dist/cli/commands/responders.d.ts.map +1 -0
  67. package/dist/cli/commands/responders.js +157 -0
  68. package/dist/cli/commands/rules.d.ts +3 -0
  69. package/dist/cli/commands/rules.d.ts.map +1 -0
  70. package/dist/cli/commands/rules.js +105 -0
  71. package/dist/cli/commands/server.d.ts +3 -0
  72. package/dist/cli/commands/server.d.ts.map +1 -0
  73. package/dist/cli/commands/server.js +34 -0
  74. package/dist/cli/commands/tasks.d.ts +3 -0
  75. package/dist/cli/commands/tasks.d.ts.map +1 -0
  76. package/dist/cli/commands/tasks.js +281 -0
  77. package/dist/cli/commands/templates.d.ts +3 -0
  78. package/dist/cli/commands/templates.d.ts.map +1 -0
  79. package/dist/cli/commands/templates.js +100 -0
  80. package/dist/cli/index.d.ts +4 -0
  81. package/dist/cli/index.d.ts.map +1 -0
  82. package/dist/cli/index.js +9 -0
  83. package/dist/cli/output.d.ts +26 -0
  84. package/dist/cli/output.d.ts.map +1 -0
  85. package/dist/cli/output.js +143 -0
  86. package/dist/cli/program.d.ts +6 -0
  87. package/dist/cli/program.d.ts.map +1 -0
  88. package/dist/cli/program.js +38 -0
  89. package/dist/cli/tasks-adapter.d.ts +3 -0
  90. package/dist/cli/tasks-adapter.d.ts.map +1 -0
  91. package/dist/cli/tasks-adapter.js +4 -0
  92. package/dist/client/answer-poller.d.ts +52 -0
  93. package/dist/client/answer-poller.d.ts.map +1 -0
  94. package/dist/client/answer-poller.js +200 -0
  95. package/dist/client/auth-client.d.ts +200 -0
  96. package/dist/client/auth-client.d.ts.map +1 -0
  97. package/dist/client/auth-client.js +309 -0
  98. package/dist/client/breakpoint-router.d.ts +45 -0
  99. package/dist/client/breakpoint-router.d.ts.map +1 -0
  100. package/dist/client/breakpoint-router.js +45 -0
  101. package/dist/client/index.d.ts +17 -0
  102. package/dist/client/index.d.ts.map +1 -0
  103. package/dist/client/index.js +16 -0
  104. package/dist/client/profile-validator.d.ts +34 -0
  105. package/dist/client/profile-validator.d.ts.map +1 -0
  106. package/dist/client/profile-validator.js +89 -0
  107. package/dist/client/responder-client.d.ts +39 -0
  108. package/dist/client/responder-client.d.ts.map +1 -0
  109. package/dist/client/responder-client.js +72 -0
  110. package/dist/client/responder-matcher.d.ts +49 -0
  111. package/dist/client/responder-matcher.d.ts.map +1 -0
  112. package/dist/client/responder-matcher.js +226 -0
  113. package/dist/client/server-client.d.ts +124 -0
  114. package/dist/client/server-client.d.ts.map +1 -0
  115. package/dist/client/server-client.js +266 -0
  116. package/dist/client/timeout-manager.d.ts +47 -0
  117. package/dist/client/timeout-manager.d.ts.map +1 -0
  118. package/dist/client/timeout-manager.js +77 -0
  119. package/dist/config.d.ts +20 -0
  120. package/dist/config.d.ts.map +1 -0
  121. package/dist/config.js +93 -0
  122. package/dist/harness/index.d.ts +4 -0
  123. package/dist/harness/index.d.ts.map +1 -0
  124. package/dist/harness/index.js +2 -0
  125. package/dist/harness/interaction-provider.d.ts +71 -0
  126. package/dist/harness/interaction-provider.d.ts.map +1 -0
  127. package/dist/harness/interaction-provider.js +124 -0
  128. package/dist/harness/routing-rules.d.ts +7 -0
  129. package/dist/harness/routing-rules.d.ts.map +1 -0
  130. package/dist/harness/routing-rules.js +37 -0
  131. package/dist/index.d.ts +29 -0
  132. package/dist/index.d.ts.map +1 -0
  133. package/dist/index.js +33 -0
  134. package/dist/mcp/backend-resolver.d.ts +43 -0
  135. package/dist/mcp/backend-resolver.d.ts.map +1 -0
  136. package/dist/mcp/backend-resolver.js +111 -0
  137. package/dist/mcp/http-transport.d.ts +37 -0
  138. package/dist/mcp/http-transport.d.ts.map +1 -0
  139. package/dist/mcp/http-transport.js +103 -0
  140. package/dist/mcp/index.d.ts +16 -0
  141. package/dist/mcp/index.d.ts.map +1 -0
  142. package/dist/mcp/index.js +12 -0
  143. package/dist/mcp/server.d.ts +20 -0
  144. package/dist/mcp/server.d.ts.map +1 -0
  145. package/dist/mcp/server.js +259 -0
  146. package/dist/mcp/tools/answer-breakpoint.d.ts +32 -0
  147. package/dist/mcp/tools/answer-breakpoint.d.ts.map +1 -0
  148. package/dist/mcp/tools/answer-breakpoint.js +45 -0
  149. package/dist/mcp/tools/ask-breakpoint.d.ts +58 -0
  150. package/dist/mcp/tools/ask-breakpoint.d.ts.map +1 -0
  151. package/dist/mcp/tools/ask-breakpoint.js +78 -0
  152. package/dist/mcp/tools/check-status.d.ts +16 -0
  153. package/dist/mcp/tools/check-status.d.ts.map +1 -0
  154. package/dist/mcp/tools/check-status.js +18 -0
  155. package/dist/mcp/tools/claim-breakpoint.d.ts +18 -0
  156. package/dist/mcp/tools/claim-breakpoint.d.ts.map +1 -0
  157. package/dist/mcp/tools/claim-breakpoint.js +28 -0
  158. package/dist/mcp/tools/list-breakpoints.d.ts +16 -0
  159. package/dist/mcp/tools/list-breakpoints.d.ts.map +1 -0
  160. package/dist/mcp/tools/list-breakpoints.js +14 -0
  161. package/dist/mcp/tools/list-responders.d.ts +18 -0
  162. package/dist/mcp/tools/list-responders.d.ts.map +1 -0
  163. package/dist/mcp/tools/list-responders.js +37 -0
  164. package/dist/mcp/tools/native-tasks.d.ts +270 -0
  165. package/dist/mcp/tools/native-tasks.d.ts.map +1 -0
  166. package/dist/mcp/tools/native-tasks.js +481 -0
  167. package/dist/mcp/tools/poll-breakpoints.d.ts +18 -0
  168. package/dist/mcp/tools/poll-breakpoints.d.ts.map +1 -0
  169. package/dist/mcp/tools/poll-breakpoints.js +36 -0
  170. package/dist/mcp/tools/verify-answer.d.ts +16 -0
  171. package/dist/mcp/tools/verify-answer.d.ts.map +1 -0
  172. package/dist/mcp/tools/verify-answer.js +38 -0
  173. package/dist/proven/index.d.ts +5 -0
  174. package/dist/proven/index.d.ts.map +1 -0
  175. package/dist/proven/index.js +3 -0
  176. package/dist/proven/keys.d.ts +33 -0
  177. package/dist/proven/keys.d.ts.map +1 -0
  178. package/dist/proven/keys.js +117 -0
  179. package/dist/proven/sign.d.ts +16 -0
  180. package/dist/proven/sign.d.ts.map +1 -0
  181. package/dist/proven/sign.js +60 -0
  182. package/dist/proven/types.d.ts +26 -0
  183. package/dist/proven/types.d.ts.map +1 -0
  184. package/dist/proven/types.js +5 -0
  185. package/dist/proven/verify.d.ts +6 -0
  186. package/dist/proven/verify.d.ts.map +1 -0
  187. package/dist/proven/verify.js +58 -0
  188. package/dist/responders/types.d.ts +38 -0
  189. package/dist/responders/types.d.ts.map +1 -0
  190. package/dist/responders/types.js +1 -0
  191. package/dist/router.d.ts +51 -0
  192. package/dist/router.d.ts.map +1 -0
  193. package/dist/router.js +200 -0
  194. package/dist/types.d.ts +7711 -0
  195. package/dist/types.d.ts.map +1 -0
  196. package/dist/types.js +479 -0
  197. package/package.json +96 -0
  198. package/responder/README.md +42 -0
  199. package/responder/backend-responder.json +9 -0
  200. package/responder/devops-responder.json +9 -0
  201. package/responder/frontend-responder.json +9 -0
  202. package/responder/schema.json +89 -0
@@ -0,0 +1,311 @@
1
+ import { Command } from "commander";
2
+ import { ResponderClient, AnswerPoller, } from "../../client/index.js";
3
+ import { formatBreakpoint, formatAnswer, formatTable, printError } from "../output.js";
4
+ import { createCliServerClient } from "../client-config.js";
5
+ import { GitNativeBackend } from "../../backends/git-native.js";
6
+ function backend(opts) {
7
+ return new GitNativeBackend({ breakpointsDir: opts.breakpointsDir });
8
+ }
9
+ function splitCsv(value) {
10
+ return value?.split(",").map((item) => item.trim()).filter(Boolean);
11
+ }
12
+ function printResult(value, jsonMode) {
13
+ if (jsonMode) {
14
+ console.log(JSON.stringify(value, null, 2));
15
+ return;
16
+ }
17
+ console.log(JSON.stringify(value, null, 2));
18
+ }
19
+ export function createBreakpointsCommand() {
20
+ const cmd = new Command("breakpoints")
21
+ .description("Manage breakpoints and answers")
22
+ .option("--breakpoints-dir <path>", "Path to .breakpoints directory for local lifecycle commands");
23
+ cmd
24
+ .command("list")
25
+ .description("List breakpoints, optionally filtered by status")
26
+ .option("--status <csv>", "Comma-separated statuses")
27
+ .option("--priority <csv>", "Comma-separated priorities")
28
+ .option("--assignee <id>", "Assignee responder id")
29
+ .option("--responder <id>", "Target/claimed/answering responder id")
30
+ .option("--limit <n>", "Maximum result count")
31
+ .action(async (opts, command) => {
32
+ const allOpts = command.optsWithGlobals();
33
+ const jsonMode = allOpts.json === true;
34
+ try {
35
+ const result = await backend(allOpts).searchBreakpoints({
36
+ status: splitCsv(opts.status),
37
+ priority: splitCsv(opts.priority),
38
+ assigneeId: opts.assignee,
39
+ responderId: opts.responder,
40
+ limit: opts.limit ? Number.parseInt(opts.limit, 10) : undefined,
41
+ });
42
+ if (jsonMode) {
43
+ printResult(result, true);
44
+ }
45
+ else {
46
+ const rows = result.items.map((b) => [
47
+ b.id,
48
+ b.status,
49
+ b.priority ?? "medium",
50
+ b.assigneeId ?? "",
51
+ b.text,
52
+ ]);
53
+ console.log(formatTable(rows, ["ID", "Status", "Priority", "Assignee", "Breakpoint"]));
54
+ }
55
+ }
56
+ catch (error) {
57
+ printError(error, jsonMode);
58
+ process.exitCode = 1;
59
+ }
60
+ });
61
+ cmd
62
+ .command("search")
63
+ .description("Search breakpoints across lifecycle states")
64
+ .option("-q, --query <text>", "Text query")
65
+ .option("--status <csv>", "Comma-separated statuses")
66
+ .option("--priority <csv>", "Comma-separated priorities")
67
+ .option("--assignee <id>", "Assignee responder id")
68
+ .option("--responder <id>", "Target/claimed/answering responder id")
69
+ .option("--tag <csv>", "Comma-separated tags")
70
+ .option("--domain <domain>", "Domain filter")
71
+ .option("--limit <n>", "Maximum result count")
72
+ .action(async (opts, command) => {
73
+ const allOpts = command.optsWithGlobals();
74
+ const jsonMode = allOpts.json === true;
75
+ try {
76
+ const result = await backend(allOpts).searchBreakpoints({
77
+ query: opts.query,
78
+ status: splitCsv(opts.status),
79
+ priority: splitCsv(opts.priority),
80
+ assigneeId: opts.assignee,
81
+ responderId: opts.responder,
82
+ tags: splitCsv(opts.tag),
83
+ domain: opts.domain,
84
+ limit: opts.limit ? Number.parseInt(opts.limit, 10) : undefined,
85
+ });
86
+ printResult(result, jsonMode);
87
+ }
88
+ catch (error) {
89
+ printError(error, jsonMode);
90
+ process.exitCode = 1;
91
+ }
92
+ });
93
+ for (const commandName of ["assign", "reassign"]) {
94
+ cmd
95
+ .command(commandName)
96
+ .description(`${commandName === "assign" ? "Assign" : "Reassign"} a breakpoint`)
97
+ .argument("<breakpointId>", "Breakpoint ID")
98
+ .requiredOption("--assignee <id>", "Assignee responder id")
99
+ .option("--assignee-name <name>", "Assignee display name")
100
+ .option("--actor <id>", "Actor id")
101
+ .action(async (breakpointId, opts, command) => {
102
+ const allOpts = command.optsWithGlobals();
103
+ const jsonMode = allOpts.json === true;
104
+ try {
105
+ const result = await backend(allOpts).assignBreakpoint(breakpointId, {
106
+ assigneeId: opts.assignee ?? "",
107
+ assigneeName: opts.assigneeName,
108
+ actorId: opts.actor,
109
+ });
110
+ printResult(result, jsonMode);
111
+ }
112
+ catch (error) {
113
+ printError(error, jsonMode);
114
+ process.exitCode = 1;
115
+ }
116
+ });
117
+ }
118
+ cmd
119
+ .command("close")
120
+ .description("Mark a breakpoint completed")
121
+ .argument("<breakpointId>", "Breakpoint ID")
122
+ .option("--actor <id>", "Actor id")
123
+ .option("--message <text>", "History message")
124
+ .action(async (breakpointId, opts, command) => {
125
+ const allOpts = command.optsWithGlobals();
126
+ const jsonMode = allOpts.json === true;
127
+ try {
128
+ const result = await backend(allOpts).transitionBreakpoint(breakpointId, {
129
+ status: "completed",
130
+ actorId: opts.actor,
131
+ message: opts.message,
132
+ });
133
+ printResult(result, jsonMode);
134
+ }
135
+ catch (error) {
136
+ printError(error, jsonMode);
137
+ process.exitCode = 1;
138
+ }
139
+ });
140
+ cmd
141
+ .command("approve")
142
+ .description("Approve a breakpoint by submitting an approved answer")
143
+ .argument("<breakpointId>", "Breakpoint ID")
144
+ .requiredOption("-a, --answer <text>", "Approved answer text")
145
+ .requiredOption("-e, --responder <responderId>", "Responder ID")
146
+ .option("--responder-name <name>", "Responder display name")
147
+ .option("--confidence <number>", "Confidence level (0-100)", "100")
148
+ .action(async (breakpointId, opts, command) => {
149
+ const allOpts = command.optsWithGlobals();
150
+ const jsonMode = allOpts.json === true;
151
+ try {
152
+ const answer = await backend(allOpts).answerBreakpoint(breakpointId, {
153
+ responderId: opts.responder ?? "",
154
+ responderName: opts.responderName ?? opts.responder ?? "",
155
+ text: opts.answer ?? "",
156
+ approved: true,
157
+ confidence: Number.parseInt(opts.confidence ?? "100", 10),
158
+ });
159
+ printResult(answer, jsonMode);
160
+ }
161
+ catch (error) {
162
+ printError(error, jsonMode);
163
+ process.exitCode = 1;
164
+ }
165
+ });
166
+ cmd
167
+ .command("pending")
168
+ .description("List pending breakpoints for a responder")
169
+ .requiredOption("-e, --responder <responderId>", "Responder ID")
170
+ .action(async (opts, command) => {
171
+ const allOpts = command.optsWithGlobals();
172
+ const localOpts = opts;
173
+ const jsonMode = allOpts.json === true;
174
+ try {
175
+ const client = await createCliServerClient({
176
+ serverUrl: allOpts.serverUrl,
177
+ authToken: allOpts.authToken,
178
+ });
179
+ const responderClient = new ResponderClient(client, localOpts.responder);
180
+ const breakpoints = await responderClient.fetchPendingBreakpoints();
181
+ if (jsonMode) {
182
+ console.log(JSON.stringify(breakpoints, null, 2));
183
+ }
184
+ else if (breakpoints.length === 0) {
185
+ console.log("No pending breakpoints.");
186
+ }
187
+ else {
188
+ const rows = breakpoints.map((b) => [
189
+ b.id,
190
+ b.status,
191
+ b.text.length > 60 ? b.text.substring(0, 57) + "..." : b.text,
192
+ b.createdAt,
193
+ ]);
194
+ console.log(formatTable(rows, ["ID", "Status", "Breakpoint", "Created"]));
195
+ }
196
+ }
197
+ catch (error) {
198
+ printError(error, jsonMode);
199
+ process.exitCode = 1;
200
+ }
201
+ });
202
+ cmd
203
+ .command("answer")
204
+ .description("Submit an answer to a breakpoint")
205
+ .argument("<breakpointId>", "Breakpoint ID")
206
+ .requiredOption("-a, --answer <text>", "Answer text")
207
+ .requiredOption("-e, --responder <responderId>", "Responder ID")
208
+ .option("--confidence <number>", "Confidence level (0-100)", "80")
209
+ .action(async (breakpointId, opts, command) => {
210
+ const allOpts = command.optsWithGlobals();
211
+ const localOpts = opts;
212
+ const jsonMode = allOpts.json === true;
213
+ try {
214
+ const client = await createCliServerClient({
215
+ serverUrl: allOpts.serverUrl,
216
+ authToken: allOpts.authToken,
217
+ });
218
+ const responderClient = new ResponderClient(client, localOpts.responder);
219
+ const confidence = parseInt(localOpts.confidence ?? "80", 10);
220
+ const answer = await responderClient.submitAnswer(breakpointId, localOpts.answer, confidence);
221
+ if (jsonMode) {
222
+ console.log(JSON.stringify(answer, null, 2));
223
+ }
224
+ else {
225
+ console.log(formatAnswer(answer, false));
226
+ }
227
+ }
228
+ catch (error) {
229
+ printError(error, jsonMode);
230
+ process.exitCode = 1;
231
+ }
232
+ });
233
+ cmd
234
+ .command("status")
235
+ .description("Check breakpoint status")
236
+ .argument("<breakpointId>", "Breakpoint ID")
237
+ .action(async (breakpointId, _opts, command) => {
238
+ const allOpts = command.optsWithGlobals();
239
+ const jsonMode = allOpts.json === true;
240
+ try {
241
+ const client = await createCliServerClient({
242
+ serverUrl: allOpts.serverUrl,
243
+ authToken: allOpts.authToken,
244
+ });
245
+ const breakpoint = await client.getBreakpoint(breakpointId);
246
+ if (jsonMode) {
247
+ console.log(JSON.stringify(breakpoint, null, 2));
248
+ }
249
+ else {
250
+ console.log(formatBreakpoint(breakpoint, false));
251
+ if (breakpoint.answers.length > 0) {
252
+ console.log("\nAnswers:");
253
+ for (const answer of breakpoint.answers) {
254
+ console.log("");
255
+ console.log(formatAnswer(answer, false));
256
+ }
257
+ }
258
+ }
259
+ }
260
+ catch (error) {
261
+ printError(error, jsonMode);
262
+ process.exitCode = 1;
263
+ }
264
+ });
265
+ cmd
266
+ .command("poll")
267
+ .description("Poll for an answer to a breakpoint")
268
+ .argument("<breakpointId>", "Breakpoint ID")
269
+ .option("-t, --timeout <seconds>", "Timeout in seconds", "300")
270
+ .option("-i, --interval <seconds>", "Polling interval in seconds", "5")
271
+ .action(async (breakpointId, opts, command) => {
272
+ const allOpts = command.optsWithGlobals();
273
+ const localOpts = opts;
274
+ const jsonMode = allOpts.json === true;
275
+ try {
276
+ const client = await createCliServerClient({
277
+ serverUrl: allOpts.serverUrl,
278
+ authToken: allOpts.authToken,
279
+ });
280
+ const poller = new AnswerPoller(client);
281
+ const timeoutMs = parseInt(localOpts.timeout ?? "300", 10) * 1000;
282
+ const pollIntervalMs = parseInt(localOpts.interval ?? "5", 10) * 1000;
283
+ if (!jsonMode) {
284
+ console.log(`Polling for answer to ${breakpointId}...`);
285
+ }
286
+ const result = await poller.waitForAnswer(breakpointId, {
287
+ timeoutMs,
288
+ pollIntervalMs,
289
+ useSSE: true,
290
+ });
291
+ if (jsonMode) {
292
+ console.log(JSON.stringify(result, null, 2));
293
+ }
294
+ else {
295
+ console.log(formatBreakpoint(result.breakpoint, false));
296
+ if (result.answer) {
297
+ console.log("");
298
+ console.log(formatAnswer(result.answer, false));
299
+ }
300
+ else {
301
+ console.log("\nNo answer received within timeout.");
302
+ }
303
+ }
304
+ }
305
+ catch (error) {
306
+ printError(error, jsonMode);
307
+ process.exitCode = 1;
308
+ }
309
+ });
310
+ return cmd;
311
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createResponderLoopCommand(): Command;
3
+ //# sourceMappingURL=responder-loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responder-loop.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/responder-loop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC,wBAAgB,0BAA0B,IAAI,OAAO,CAiEpD"}
@@ -0,0 +1,78 @@
1
+ import { Command } from "commander";
2
+ import { ResponderClient, } from "../../client/index.js";
3
+ import { formatTable, printError } from "../output.js";
4
+ import { createCliServerClient } from "../client-config.js";
5
+ export function createResponderLoopCommand() {
6
+ const cmd = new Command("responder-loop")
7
+ .description("Start a polling loop to check for new breakpoints")
8
+ .requiredOption("-e, --responder <responderId>", "Responder ID")
9
+ .option("-i, --interval <seconds>", "Polling interval in seconds", "30")
10
+ .option("--once", "Check once and exit (for agent integration)", false)
11
+ .action(async (opts, command) => {
12
+ const allOpts = command.optsWithGlobals();
13
+ const localOpts = opts;
14
+ const jsonMode = allOpts.json === true;
15
+ try {
16
+ const client = await createCliServerClient({
17
+ serverUrl: allOpts.serverUrl,
18
+ authToken: allOpts.authToken,
19
+ });
20
+ const responderClient = new ResponderClient(client, localOpts.responder);
21
+ const intervalMs = parseInt(localOpts.interval ?? "30", 10) * 1000;
22
+ if (localOpts.once) {
23
+ // Single check mode
24
+ const breakpoints = await responderClient.fetchPendingBreakpoints();
25
+ displayBreakpoints(breakpoints, jsonMode);
26
+ return;
27
+ }
28
+ // Continuous polling mode
29
+ if (!jsonMode) {
30
+ console.log(`Starting responder loop for ${localOpts.responder} (interval: ${localOpts.interval ?? "30"}s)`);
31
+ console.log("Press Ctrl+C to stop.\n");
32
+ }
33
+ const stop = responderClient.startPollingLoop((breakpoints) => {
34
+ displayBreakpoints(breakpoints, jsonMode);
35
+ }, intervalMs);
36
+ // Handle graceful shutdown
37
+ const shutdown = () => {
38
+ stop();
39
+ if (!jsonMode) {
40
+ console.log("\nResponder loop stopped.");
41
+ }
42
+ process.exit(0);
43
+ };
44
+ process.on("SIGTERM", shutdown);
45
+ process.on("SIGINT", shutdown);
46
+ // Keep the process alive
47
+ await new Promise(() => {
48
+ // This promise never resolves; the process is kept alive
49
+ // until SIGTERM/SIGINT is received.
50
+ });
51
+ }
52
+ catch (error) {
53
+ printError(error, jsonMode);
54
+ process.exitCode = 1;
55
+ }
56
+ });
57
+ return cmd;
58
+ }
59
+ function displayBreakpoints(breakpoints, jsonMode) {
60
+ if (jsonMode) {
61
+ console.log(JSON.stringify(breakpoints, null, 2));
62
+ return;
63
+ }
64
+ if (breakpoints.length === 0) {
65
+ console.log("No pending breakpoints.");
66
+ return;
67
+ }
68
+ console.log(`Found ${breakpoints.length} pending breakpoint(s):\n`);
69
+ const rows = breakpoints.map((b) => [
70
+ b.id,
71
+ b.status,
72
+ b.text.length > 60 ? b.text.substring(0, 57) + "..." : b.text,
73
+ b.routing.strategy,
74
+ b.createdAt,
75
+ ]);
76
+ console.log(formatTable(rows, ["ID", "Status", "Breakpoint", "Strategy", "Created"]));
77
+ console.log("");
78
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createRespondersCommand(): Command;
3
+ //# sourceMappingURL=responders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responders.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/responders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqBpC,wBAAgB,uBAAuB,IAAI,OAAO,CA8JjD"}
@@ -0,0 +1,157 @@
1
+ import { Command } from "commander";
2
+ import { ResponderMatcher } from "../../client/index.js";
3
+ import { formatResponder, formatTable, printError } from "../output.js";
4
+ export function createRespondersCommand() {
5
+ const cmd = new Command("responders").description("Manage and view responder profiles");
6
+ cmd
7
+ .command("list")
8
+ .description("List available responders")
9
+ .option("-d, --domain <domain>", "Filter by domain")
10
+ .action(async (opts, command) => {
11
+ const allOpts = command.optsWithGlobals();
12
+ const localOpts = opts;
13
+ const jsonMode = allOpts.json === true;
14
+ try {
15
+ const matcher = new ResponderMatcher({
16
+ responderDir: allOpts.responderDir,
17
+ repoRoot: allOpts.repoRoot,
18
+ configRoot: allOpts.configRoot,
19
+ });
20
+ const responders = await matcher.loadResponders();
21
+ let filtered = responders;
22
+ if (localOpts.domain) {
23
+ const domain = localOpts.domain.toLowerCase();
24
+ filtered = responders.filter((r) => r.domains.some((d) => d.toLowerCase().includes(domain)));
25
+ }
26
+ if (jsonMode) {
27
+ console.log(JSON.stringify(filtered, null, 2));
28
+ }
29
+ else if (filtered.length === 0) {
30
+ console.log("No responders found.");
31
+ }
32
+ else {
33
+ const rows = filtered.map((r) => [
34
+ r.id,
35
+ r.name,
36
+ r.title,
37
+ r.availability ? "yes" : "no",
38
+ r.domains.join(", "),
39
+ ]);
40
+ console.log(formatTable(rows, ["ID", "Name", "Title", "Available", "Domains"]));
41
+ }
42
+ }
43
+ catch (error) {
44
+ printError(error, jsonMode);
45
+ process.exitCode = 1;
46
+ }
47
+ });
48
+ cmd
49
+ .command("search")
50
+ .description("Search responder profiles")
51
+ .option("-q, --query <text>", "Text query")
52
+ .option("-d, --domain <domain>", "Filter by domain")
53
+ .action(async (opts, command) => {
54
+ const allOpts = command.optsWithGlobals();
55
+ const localOpts = opts;
56
+ const jsonMode = allOpts.json === true;
57
+ try {
58
+ const matcher = new ResponderMatcher({
59
+ responderDir: allOpts.responderDir,
60
+ repoRoot: allOpts.repoRoot,
61
+ configRoot: allOpts.configRoot,
62
+ });
63
+ const query = localOpts.query?.toLowerCase();
64
+ const domain = localOpts.domain?.toLowerCase();
65
+ const responders = (await matcher.loadResponders()).filter((responder) => {
66
+ if (domain && !responder.domains.some((item) => item.toLowerCase().includes(domain))) {
67
+ return false;
68
+ }
69
+ if (!query)
70
+ return true;
71
+ return [
72
+ responder.id,
73
+ responder.name,
74
+ responder.title,
75
+ ...responder.domains,
76
+ ].join("\n").toLowerCase().includes(query);
77
+ });
78
+ if (jsonMode) {
79
+ console.log(JSON.stringify(responders, null, 2));
80
+ }
81
+ else if (responders.length === 0) {
82
+ console.log("No responders found.");
83
+ }
84
+ else {
85
+ const rows = responders.map((r) => [
86
+ r.id,
87
+ r.name,
88
+ r.title,
89
+ r.availability ? "yes" : "no",
90
+ r.domains.join(", "),
91
+ ]);
92
+ console.log(formatTable(rows, ["ID", "Name", "Title", "Available", "Domains"]));
93
+ }
94
+ }
95
+ catch (error) {
96
+ printError(error, jsonMode);
97
+ process.exitCode = 1;
98
+ }
99
+ });
100
+ cmd
101
+ .command("stats")
102
+ .description("Show responder profile statistics")
103
+ .action(async (_opts, command) => {
104
+ const allOpts = command.optsWithGlobals();
105
+ const jsonMode = allOpts.json === true;
106
+ try {
107
+ const matcher = new ResponderMatcher({
108
+ responderDir: allOpts.responderDir,
109
+ repoRoot: allOpts.repoRoot,
110
+ configRoot: allOpts.configRoot,
111
+ });
112
+ const responders = await matcher.loadResponders();
113
+ const byDomain = responders.reduce((acc, responder) => {
114
+ for (const domain of responder.domains)
115
+ acc[domain] = (acc[domain] ?? 0) + 1;
116
+ return acc;
117
+ }, {});
118
+ const stats = {
119
+ total: responders.length,
120
+ available: responders.filter((responder) => responder.availability).length,
121
+ unavailable: responders.filter((responder) => !responder.availability).length,
122
+ byDomain,
123
+ };
124
+ console.log(JSON.stringify(stats, null, 2));
125
+ }
126
+ catch (error) {
127
+ printError(error, jsonMode);
128
+ process.exitCode = 1;
129
+ }
130
+ });
131
+ cmd
132
+ .command("show")
133
+ .description("Show responder profile details")
134
+ .argument("<responderId>", "Responder ID")
135
+ .action(async (responderId, _opts, command) => {
136
+ const allOpts = command.optsWithGlobals();
137
+ const jsonMode = allOpts.json === true;
138
+ try {
139
+ const matcher = new ResponderMatcher({
140
+ responderDir: allOpts.responderDir,
141
+ repoRoot: allOpts.repoRoot,
142
+ configRoot: allOpts.configRoot,
143
+ });
144
+ const responders = await matcher.loadResponders();
145
+ const responder = responders.find((r) => r.id === responderId);
146
+ if (!responder) {
147
+ throw new Error(`Responder not found: ${responderId}`);
148
+ }
149
+ console.log(formatResponder(responder, jsonMode));
150
+ }
151
+ catch (error) {
152
+ printError(error, jsonMode);
153
+ process.exitCode = 1;
154
+ }
155
+ });
156
+ return cmd;
157
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createRulesCommand(): Command;
3
+ //# sourceMappingURL=rules.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/rules.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+CpC,wBAAgB,kBAAkB,IAAI,OAAO,CAkE5C"}
@@ -0,0 +1,105 @@
1
+ import { promises as fs } from "node:fs";
2
+ import * as path from "node:path";
3
+ import { Command } from "commander";
4
+ import { resolveRoutingConfigPath, resolveConfigRoot } from "../../config.js";
5
+ import { printError } from "../output.js";
6
+ function routingPath(opts) {
7
+ return resolveRoutingConfigPath(resolveConfigRoot({
8
+ repoRoot: opts.repoRoot,
9
+ configRoot: opts.configRoot,
10
+ }));
11
+ }
12
+ async function readRoutingConfig(filePath) {
13
+ try {
14
+ const raw = await fs.readFile(filePath, "utf-8");
15
+ const parsed = JSON.parse(raw);
16
+ return {
17
+ defaultBackend: parsed.defaultBackend ?? "git-native",
18
+ routes: parsed.routes ?? [],
19
+ };
20
+ }
21
+ catch (error) {
22
+ if (error.code === "ENOENT") {
23
+ return { defaultBackend: "git-native", routes: [] };
24
+ }
25
+ throw error;
26
+ }
27
+ }
28
+ async function writeRoutingConfig(filePath, config) {
29
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
30
+ await fs.writeFile(filePath, JSON.stringify(config, null, 2) + "\n", "utf-8");
31
+ }
32
+ function printValue(value) {
33
+ console.log(JSON.stringify(value, null, 2));
34
+ }
35
+ export function createRulesCommand() {
36
+ const cmd = new Command("rules").description("Manage tasks-adapter routing rules");
37
+ cmd
38
+ .command("list")
39
+ .description("List routing rules")
40
+ .action(async (_opts, command) => {
41
+ const allOpts = command.optsWithGlobals();
42
+ try {
43
+ printValue((await readRoutingConfig(routingPath(allOpts))).routes);
44
+ }
45
+ catch (error) {
46
+ printError(error, allOpts.json === true);
47
+ process.exitCode = 1;
48
+ }
49
+ });
50
+ cmd
51
+ .command("add")
52
+ .description("Add or replace a routing rule")
53
+ .argument("<ruleId>", "Rule id")
54
+ .requiredOption("--backend <backend>", "Backend name")
55
+ .option("--domain <csv>", "Comma-separated domains")
56
+ .option("--tag <csv>", "Comma-separated tags")
57
+ .action(async (ruleId, opts, command) => {
58
+ const allOpts = command.optsWithGlobals();
59
+ try {
60
+ const filePath = routingPath(allOpts);
61
+ const config = await readRoutingConfig(filePath);
62
+ const rule = {
63
+ id: ruleId,
64
+ backend: opts.backend ?? "git-native",
65
+ backendConfig: {},
66
+ domains: splitCsv(opts.domain),
67
+ tags: splitCsv(opts.tag),
68
+ };
69
+ const existingIndex = config.routes.findIndex((item) => item.id === ruleId);
70
+ if (existingIndex === -1)
71
+ config.routes.push(rule);
72
+ else
73
+ config.routes[existingIndex] = rule;
74
+ await writeRoutingConfig(filePath, config);
75
+ printValue(rule);
76
+ }
77
+ catch (error) {
78
+ printError(error, allOpts.json === true);
79
+ process.exitCode = 1;
80
+ }
81
+ });
82
+ cmd
83
+ .command("remove")
84
+ .description("Remove a routing rule")
85
+ .argument("<ruleId>", "Rule id")
86
+ .action(async (ruleId, _opts, command) => {
87
+ const allOpts = command.optsWithGlobals();
88
+ try {
89
+ const filePath = routingPath(allOpts);
90
+ const config = await readRoutingConfig(filePath);
91
+ const before = config.routes.length;
92
+ config.routes = config.routes.filter((rule) => rule.id !== ruleId);
93
+ await writeRoutingConfig(filePath, config);
94
+ printValue({ id: ruleId, removed: before !== config.routes.length });
95
+ }
96
+ catch (error) {
97
+ printError(error, allOpts.json === true);
98
+ process.exitCode = 1;
99
+ }
100
+ });
101
+ return cmd;
102
+ }
103
+ function splitCsv(value) {
104
+ return value?.split(",").map((item) => item.trim()).filter(Boolean);
105
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createServerCommand(): Command;
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,mBAAmB,IAAI,OAAO,CAoC7C"}