@a5c-ai/tasks-adapter 5.1.1-staging.00ceebd28cf2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -0
- package/dist/auth/forge-interface.d.ts +67 -0
- package/dist/auth/forge-interface.d.ts.map +1 -0
- package/dist/auth/forge-interface.js +69 -0
- package/dist/auth/github-app.d.ts +64 -0
- package/dist/auth/github-app.d.ts.map +1 -0
- package/dist/auth/github-app.js +141 -0
- package/dist/auth/github-oauth.d.ts +27 -0
- package/dist/auth/github-oauth.d.ts.map +1 -0
- package/dist/auth/github-oauth.js +89 -0
- package/dist/auth/index.d.ts +8 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +14 -0
- package/dist/auth/jwt.d.ts +24 -0
- package/dist/auth/jwt.d.ts.map +1 -0
- package/dist/auth/jwt.js +43 -0
- package/dist/auth/middleware.d.ts +22 -0
- package/dist/auth/middleware.d.ts.map +1 -0
- package/dist/auth/middleware.js +36 -0
- package/dist/auth/ssh-keys.d.ts +21 -0
- package/dist/auth/ssh-keys.d.ts.map +1 -0
- package/dist/auth/ssh-keys.js +59 -0
- package/dist/auth/types.d.ts +165 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +53 -0
- package/dist/backend.d.ts +248 -0
- package/dist/backend.d.ts.map +1 -0
- package/dist/backend.js +40 -0
- package/dist/backends/adapters.d.ts +99 -0
- package/dist/backends/adapters.d.ts.map +1 -0
- package/dist/backends/adapters.js +308 -0
- package/dist/backends/external-tracker.d.ts +133 -0
- package/dist/backends/external-tracker.d.ts.map +1 -0
- package/dist/backends/external-tracker.js +731 -0
- package/dist/backends/git-native.d.ts +69 -0
- package/dist/backends/git-native.d.ts.map +1 -0
- package/dist/backends/git-native.js +797 -0
- package/dist/backends/github-issues.d.ts +78 -0
- package/dist/backends/github-issues.d.ts.map +1 -0
- package/dist/backends/github-issues.js +806 -0
- package/dist/backends/index.d.ts +52 -0
- package/dist/backends/index.d.ts.map +1 -0
- package/dist/backends/index.js +151 -0
- package/dist/backends/server.d.ts +42 -0
- package/dist/backends/server.d.ts.map +1 -0
- package/dist/backends/server.js +305 -0
- package/dist/cli/auth-store.d.ts +49 -0
- package/dist/cli/auth-store.d.ts.map +1 -0
- package/dist/cli/auth-store.js +150 -0
- package/dist/cli/client-config.d.ts +10 -0
- package/dist/cli/client-config.d.ts.map +1 -0
- package/dist/cli/client-config.js +87 -0
- package/dist/cli/commands/ask.d.ts +3 -0
- package/dist/cli/commands/ask.d.ts.map +1 -0
- package/dist/cli/commands/ask.js +171 -0
- package/dist/cli/commands/auth.d.ts +3 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +510 -0
- package/dist/cli/commands/breakpoints.d.ts +3 -0
- package/dist/cli/commands/breakpoints.d.ts.map +1 -0
- package/dist/cli/commands/breakpoints.js +311 -0
- package/dist/cli/commands/responder-loop.d.ts +3 -0
- package/dist/cli/commands/responder-loop.d.ts.map +1 -0
- package/dist/cli/commands/responder-loop.js +78 -0
- package/dist/cli/commands/responders.d.ts +3 -0
- package/dist/cli/commands/responders.d.ts.map +1 -0
- package/dist/cli/commands/responders.js +157 -0
- package/dist/cli/commands/rules.d.ts +3 -0
- package/dist/cli/commands/rules.d.ts.map +1 -0
- package/dist/cli/commands/rules.js +105 -0
- package/dist/cli/commands/server.d.ts +3 -0
- package/dist/cli/commands/server.d.ts.map +1 -0
- package/dist/cli/commands/server.js +34 -0
- package/dist/cli/commands/tasks.d.ts +3 -0
- package/dist/cli/commands/tasks.d.ts.map +1 -0
- package/dist/cli/commands/tasks.js +281 -0
- package/dist/cli/commands/templates.d.ts +3 -0
- package/dist/cli/commands/templates.d.ts.map +1 -0
- package/dist/cli/commands/templates.js +100 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +9 -0
- package/dist/cli/output.d.ts +26 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +143 -0
- package/dist/cli/program.d.ts +6 -0
- package/dist/cli/program.d.ts.map +1 -0
- package/dist/cli/program.js +38 -0
- package/dist/cli/tasks-adapter.d.ts +3 -0
- package/dist/cli/tasks-adapter.d.ts.map +1 -0
- package/dist/cli/tasks-adapter.js +4 -0
- package/dist/client/answer-poller.d.ts +52 -0
- package/dist/client/answer-poller.d.ts.map +1 -0
- package/dist/client/answer-poller.js +200 -0
- package/dist/client/auth-client.d.ts +200 -0
- package/dist/client/auth-client.d.ts.map +1 -0
- package/dist/client/auth-client.js +309 -0
- package/dist/client/breakpoint-router.d.ts +45 -0
- package/dist/client/breakpoint-router.d.ts.map +1 -0
- package/dist/client/breakpoint-router.js +45 -0
- package/dist/client/index.d.ts +17 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +16 -0
- package/dist/client/profile-validator.d.ts +34 -0
- package/dist/client/profile-validator.d.ts.map +1 -0
- package/dist/client/profile-validator.js +89 -0
- package/dist/client/responder-client.d.ts +39 -0
- package/dist/client/responder-client.d.ts.map +1 -0
- package/dist/client/responder-client.js +72 -0
- package/dist/client/responder-matcher.d.ts +49 -0
- package/dist/client/responder-matcher.d.ts.map +1 -0
- package/dist/client/responder-matcher.js +226 -0
- package/dist/client/server-client.d.ts +124 -0
- package/dist/client/server-client.d.ts.map +1 -0
- package/dist/client/server-client.js +266 -0
- package/dist/client/timeout-manager.d.ts +47 -0
- package/dist/client/timeout-manager.d.ts.map +1 -0
- package/dist/client/timeout-manager.js +77 -0
- package/dist/config.d.ts +20 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +93 -0
- package/dist/harness/index.d.ts +4 -0
- package/dist/harness/index.d.ts.map +1 -0
- package/dist/harness/index.js +2 -0
- package/dist/harness/interaction-provider.d.ts +71 -0
- package/dist/harness/interaction-provider.d.ts.map +1 -0
- package/dist/harness/interaction-provider.js +124 -0
- package/dist/harness/routing-rules.d.ts +7 -0
- package/dist/harness/routing-rules.d.ts.map +1 -0
- package/dist/harness/routing-rules.js +37 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/mcp/backend-resolver.d.ts +43 -0
- package/dist/mcp/backend-resolver.d.ts.map +1 -0
- package/dist/mcp/backend-resolver.js +111 -0
- package/dist/mcp/http-transport.d.ts +37 -0
- package/dist/mcp/http-transport.d.ts.map +1 -0
- package/dist/mcp/http-transport.js +103 -0
- package/dist/mcp/index.d.ts +16 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +12 -0
- package/dist/mcp/server.d.ts +20 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +259 -0
- package/dist/mcp/tools/answer-breakpoint.d.ts +32 -0
- package/dist/mcp/tools/answer-breakpoint.d.ts.map +1 -0
- package/dist/mcp/tools/answer-breakpoint.js +45 -0
- package/dist/mcp/tools/ask-breakpoint.d.ts +58 -0
- package/dist/mcp/tools/ask-breakpoint.d.ts.map +1 -0
- package/dist/mcp/tools/ask-breakpoint.js +78 -0
- package/dist/mcp/tools/check-status.d.ts +16 -0
- package/dist/mcp/tools/check-status.d.ts.map +1 -0
- package/dist/mcp/tools/check-status.js +18 -0
- package/dist/mcp/tools/claim-breakpoint.d.ts +18 -0
- package/dist/mcp/tools/claim-breakpoint.d.ts.map +1 -0
- package/dist/mcp/tools/claim-breakpoint.js +28 -0
- package/dist/mcp/tools/list-breakpoints.d.ts +16 -0
- package/dist/mcp/tools/list-breakpoints.d.ts.map +1 -0
- package/dist/mcp/tools/list-breakpoints.js +14 -0
- package/dist/mcp/tools/list-responders.d.ts +18 -0
- package/dist/mcp/tools/list-responders.d.ts.map +1 -0
- package/dist/mcp/tools/list-responders.js +37 -0
- package/dist/mcp/tools/native-tasks.d.ts +270 -0
- package/dist/mcp/tools/native-tasks.d.ts.map +1 -0
- package/dist/mcp/tools/native-tasks.js +481 -0
- package/dist/mcp/tools/poll-breakpoints.d.ts +18 -0
- package/dist/mcp/tools/poll-breakpoints.d.ts.map +1 -0
- package/dist/mcp/tools/poll-breakpoints.js +36 -0
- package/dist/mcp/tools/verify-answer.d.ts +16 -0
- package/dist/mcp/tools/verify-answer.d.ts.map +1 -0
- package/dist/mcp/tools/verify-answer.js +38 -0
- package/dist/proven/index.d.ts +5 -0
- package/dist/proven/index.d.ts.map +1 -0
- package/dist/proven/index.js +3 -0
- package/dist/proven/keys.d.ts +33 -0
- package/dist/proven/keys.d.ts.map +1 -0
- package/dist/proven/keys.js +117 -0
- package/dist/proven/sign.d.ts +16 -0
- package/dist/proven/sign.d.ts.map +1 -0
- package/dist/proven/sign.js +60 -0
- package/dist/proven/types.d.ts +26 -0
- package/dist/proven/types.d.ts.map +1 -0
- package/dist/proven/types.js +5 -0
- package/dist/proven/verify.d.ts +6 -0
- package/dist/proven/verify.d.ts.map +1 -0
- package/dist/proven/verify.js +58 -0
- package/dist/responders/types.d.ts +38 -0
- package/dist/responders/types.d.ts.map +1 -0
- package/dist/responders/types.js +1 -0
- package/dist/router.d.ts +51 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +200 -0
- package/dist/types.d.ts +7711 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +479 -0
- package/package.json +96 -0
- package/responder/README.md +42 -0
- package/responder/backend-responder.json +9 -0
- package/responder/devops-responder.json +9 -0
- package/responder/frontend-responder.json +9 -0
- 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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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"}
|