@a5c-ai/tasks-adapter 5.1.1-staging.0007199a1cb2

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,150 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, unlinkSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { AuthTokenSchema } from "../auth/index.js";
5
+ // ── Constants ─────────────────────────────────────────────────────────────
6
+ const BMUX_DIR = ".tasks-adapter";
7
+ const AUTH_FILE = "auth.json";
8
+ const CONFIG_FILE = "config.json";
9
+ const KEYS_DIR = "keys";
10
+ // ── Path helpers ─────────────────────────────────────────────────────────
11
+ /**
12
+ * Get the path to the tasks-adapter config directory (~/.tasks-adapter).
13
+ */
14
+ export function getBmuxDir() {
15
+ return join(homedir(), BMUX_DIR);
16
+ }
17
+ /**
18
+ * Get the path to the auth state file (~/.tasks-adapter/auth.json).
19
+ */
20
+ export function getAuthStorePath() {
21
+ return join(getBmuxDir(), AUTH_FILE);
22
+ }
23
+ /**
24
+ * Get the path to the client config file (~/.tasks-adapter/config.json).
25
+ */
26
+ export function getClientConfigPath() {
27
+ return join(getBmuxDir(), CONFIG_FILE);
28
+ }
29
+ /**
30
+ * Get the path to the SSH keys directory (~/.tasks-adapter/keys).
31
+ */
32
+ export function getKeysDir() {
33
+ return join(getBmuxDir(), KEYS_DIR);
34
+ }
35
+ // ── Generic client config ───────────────────────────────────────────────
36
+ /**
37
+ * Load CLI/MCP client configuration from ~/.tasks-adapter/config.json.
38
+ */
39
+ export function loadClientConfig() {
40
+ const filePath = getClientConfigPath();
41
+ if (!existsSync(filePath)) {
42
+ return {};
43
+ }
44
+ try {
45
+ const raw = readFileSync(filePath, "utf-8");
46
+ const parsed = JSON.parse(raw);
47
+ const config = {};
48
+ if (typeof parsed.serverUrl === "string" && parsed.serverUrl.trim().length > 0) {
49
+ config.serverUrl = parsed.serverUrl.trim();
50
+ }
51
+ if (typeof parsed.authToken === "string" && parsed.authToken.trim().length > 0) {
52
+ config.authToken = parsed.authToken.trim();
53
+ }
54
+ return config;
55
+ }
56
+ catch {
57
+ return {};
58
+ }
59
+ }
60
+ /**
61
+ * Save or update CLI/MCP client configuration in ~/.tasks-adapter/config.json.
62
+ */
63
+ export function saveClientConfig(next) {
64
+ const dir = getBmuxDir();
65
+ mkdirSync(dir, { recursive: true });
66
+ const merged = { ...loadClientConfig() };
67
+ if (next.serverUrl !== undefined) {
68
+ const normalized = next.serverUrl.trim();
69
+ if (normalized.length > 0) {
70
+ merged.serverUrl = normalized;
71
+ }
72
+ else {
73
+ delete merged.serverUrl;
74
+ }
75
+ }
76
+ if (next.authToken !== undefined) {
77
+ const normalized = next.authToken.trim();
78
+ if (normalized.length > 0) {
79
+ merged.authToken = normalized;
80
+ }
81
+ else {
82
+ delete merged.authToken;
83
+ }
84
+ }
85
+ const filePath = getClientConfigPath();
86
+ if (Object.keys(merged).length === 0) {
87
+ if (existsSync(filePath)) {
88
+ unlinkSync(filePath);
89
+ }
90
+ return;
91
+ }
92
+ writeFileSync(filePath, JSON.stringify(merged, null, 2), {
93
+ encoding: "utf-8",
94
+ mode: 0o600,
95
+ });
96
+ }
97
+ // ── Auth state persistence ───────────────────────────────────────────────
98
+ /**
99
+ * Load the stored authentication state from ~/.tasks-adapter/auth.json.
100
+ * Returns null if no auth file exists or the contents are invalid.
101
+ */
102
+ export function loadAuthState() {
103
+ const filePath = getAuthStorePath();
104
+ if (!existsSync(filePath)) {
105
+ return null;
106
+ }
107
+ try {
108
+ const raw = readFileSync(filePath, "utf-8");
109
+ const parsed = JSON.parse(raw);
110
+ const result = AuthTokenSchema.safeParse(parsed);
111
+ if (!result.success) {
112
+ return null;
113
+ }
114
+ return result.data;
115
+ }
116
+ catch {
117
+ return null;
118
+ }
119
+ }
120
+ /**
121
+ * Save authentication state to ~/.tasks-adapter/auth.json.
122
+ * Creates the directory if it does not exist.
123
+ * Sets file permissions to 0600 (owner read/write only).
124
+ */
125
+ export function saveAuthState(state) {
126
+ const dir = getBmuxDir();
127
+ mkdirSync(dir, { recursive: true });
128
+ const filePath = getAuthStorePath();
129
+ writeFileSync(filePath, JSON.stringify(state, null, 2), {
130
+ encoding: "utf-8",
131
+ mode: 0o600,
132
+ });
133
+ }
134
+ /**
135
+ * Clear the stored authentication state by removing ~/.tasks-adapter/auth.json.
136
+ */
137
+ export function clearAuthState() {
138
+ const filePath = getAuthStorePath();
139
+ if (existsSync(filePath)) {
140
+ unlinkSync(filePath);
141
+ }
142
+ }
143
+ // ── Token expiration ─────────────────────────────────────────────────────
144
+ /**
145
+ * Check whether a token has expired based on its expiresAt timestamp.
146
+ */
147
+ export function isTokenExpired(expiresAt) {
148
+ const expiry = new Date(expiresAt).getTime();
149
+ return Date.now() >= expiry;
150
+ }
@@ -0,0 +1,10 @@
1
+ import { ServerClient } from "../client/index.js";
2
+ export interface CliConnectionOptions {
3
+ serverUrl?: string;
4
+ authToken?: string;
5
+ }
6
+ export declare function resolveServerUrl(explicit?: string): string;
7
+ export declare function resolveApiBaseUrl(explicit?: string): string;
8
+ export declare function resolveAuthToken(serverUrl?: string, explicit?: string): Promise<string | undefined>;
9
+ export declare function createCliServerClient(options?: CliConnectionOptions): Promise<ServerClient>;
10
+ //# sourceMappingURL=client-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-config.d.ts","sourceRoot":"","sources":["../../src/cli/client-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuC,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvF,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA4BD,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAS1D;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED,wBAAsB,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAyDzG;AAED,wBAAsB,qBAAqB,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,YAAY,CAAC,CAQrG"}
@@ -0,0 +1,87 @@
1
+ import { AuthClient, DEFAULT_BMUX_SERVER_URL, ServerClient } from "../client/index.js";
2
+ import { isTokenExpired, loadAuthState, loadClientConfig, saveAuthState } from "./auth-store.js";
3
+ function normalizeTrimmed(value) {
4
+ const normalized = value?.trim();
5
+ return normalized && normalized.length > 0 ? normalized : undefined;
6
+ }
7
+ function decodeJwtExpiry(token) {
8
+ const parts = token.split(".");
9
+ if (parts.length < 2) {
10
+ return undefined;
11
+ }
12
+ try {
13
+ const payload = JSON.parse(Buffer.from(parts[1].replace(/-/g, "+").replace(/_/g, "/"), "base64").toString("utf-8"));
14
+ if (typeof payload.exp !== "number") {
15
+ return undefined;
16
+ }
17
+ return new Date(payload.exp * 1000).toISOString();
18
+ }
19
+ catch {
20
+ return undefined;
21
+ }
22
+ }
23
+ export function resolveServerUrl(explicit) {
24
+ const config = loadClientConfig();
25
+ return (normalizeTrimmed(explicit) ??
26
+ normalizeTrimmed(process.env.BMUX_SERVER_URL) ??
27
+ normalizeTrimmed(process.env.SERVER_URL) ??
28
+ normalizeTrimmed(config.serverUrl) ??
29
+ DEFAULT_BMUX_SERVER_URL).replace(/\/+$/, "");
30
+ }
31
+ export function resolveApiBaseUrl(explicit) {
32
+ const serverUrl = resolveServerUrl(explicit);
33
+ return serverUrl.endsWith("/api/v1") ? serverUrl : `${serverUrl}/api/v1`;
34
+ }
35
+ export async function resolveAuthToken(serverUrl, explicit) {
36
+ const config = loadClientConfig();
37
+ const configuredToken = normalizeTrimmed(explicit) ??
38
+ normalizeTrimmed(process.env.BMUX_AUTH_TOKEN) ??
39
+ normalizeTrimmed(process.env.AUTH_TOKEN) ??
40
+ normalizeTrimmed(config.authToken);
41
+ if (configuredToken) {
42
+ return configuredToken;
43
+ }
44
+ const session = loadAuthState();
45
+ if (!session?.accessToken) {
46
+ return undefined;
47
+ }
48
+ if (!isTokenExpired(session.expiresAt)) {
49
+ return session.accessToken;
50
+ }
51
+ if (!session.refreshToken) {
52
+ return session.accessToken;
53
+ }
54
+ let refreshedTokens;
55
+ const client = new AuthClient({
56
+ serverUrl: resolveApiBaseUrl(serverUrl),
57
+ token: session.accessToken,
58
+ refreshToken: session.refreshToken,
59
+ onTokenRefresh: (tokens) => {
60
+ refreshedTokens = tokens;
61
+ },
62
+ });
63
+ try {
64
+ const user = await client.getUser();
65
+ if (refreshedTokens) {
66
+ saveAuthState({
67
+ accessToken: refreshedTokens.accessToken,
68
+ refreshToken: refreshedTokens.refreshToken,
69
+ expiresAt: decodeJwtExpiry(refreshedTokens.accessToken) ?? session.expiresAt,
70
+ user,
71
+ });
72
+ return refreshedTokens.accessToken;
73
+ }
74
+ }
75
+ catch {
76
+ // Fall back to the stored token and let the command surface the real server error.
77
+ }
78
+ return session.accessToken;
79
+ }
80
+ export async function createCliServerClient(options = {}) {
81
+ const baseUrl = resolveApiBaseUrl(options.serverUrl);
82
+ const token = await resolveAuthToken(options.serverUrl, options.authToken);
83
+ return new ServerClient({
84
+ baseUrl,
85
+ defaultHeaders: token ? { Authorization: `Bearer ${token}` } : undefined,
86
+ });
87
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createAskCommand(): Command;
3
+ //# sourceMappingURL=ask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/ask.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiGpC,wBAAgB,gBAAgB,IAAI,OAAO,CAsH1C"}
@@ -0,0 +1,171 @@
1
+ import { Command } from "commander";
2
+ import { readFileSync } from "node:fs";
3
+ import { spawn } from "node:child_process";
4
+ import { AnswerPoller, } from "../../client/index.js";
5
+ import { DEFAULT_POLL_INTERVAL_MS } from "../../types.js";
6
+ import { formatBreakpoint, formatAnswer, printError } from "../output.js";
7
+ import { createCliServerClient } from "../client-config.js";
8
+ function collectValues(value, previous = []) {
9
+ previous.push(value);
10
+ return previous;
11
+ }
12
+ function parseContextFile(filePath) {
13
+ const raw = readFileSync(filePath, "utf-8");
14
+ if (filePath.toLowerCase().endsWith(".json")) {
15
+ return JSON.parse(raw);
16
+ }
17
+ return { description: raw };
18
+ }
19
+ function parseLinks(values = []) {
20
+ return values.map((value) => {
21
+ const [label, url] = value.includes("=") ? value.split(/=(.*)/s, 2) : [value, value];
22
+ return {
23
+ label: label.trim(),
24
+ url: url.trim(),
25
+ kind: "reference",
26
+ };
27
+ });
28
+ }
29
+ function buildBreakpointContext(opts) {
30
+ const fileContext = opts.contextFile ? parseContextFile(opts.contextFile) : {};
31
+ const markdownFromFile = opts.markdownFile ? readFileSync(opts.markdownFile, "utf-8") : undefined;
32
+ const parsedLinks = parseLinks(opts.link);
33
+ return {
34
+ description: opts.context ?? fileContext.description ?? "",
35
+ codeSnippets: opts.code ?? fileContext.codeSnippets ?? [],
36
+ fileReferences: opts.fileRef ?? fileContext.fileReferences ?? [],
37
+ tags: opts.tag ?? fileContext.tags ?? [],
38
+ title: fileContext.title,
39
+ summary: fileContext.summary,
40
+ markdown: opts.markdown ?? markdownFromFile ?? fileContext.markdown,
41
+ links: (parsedLinks.length > 0 ? parsedLinks : fileContext.links),
42
+ sections: fileContext.sections,
43
+ artifacts: fileContext.artifacts,
44
+ metadata: fileContext.metadata,
45
+ };
46
+ }
47
+ function openBrowser(url) {
48
+ if (process.env.VITEST || process.env.CI || process.env.NODE_ENV === "test" || process.env.BMUX_NO_BROWSER)
49
+ return;
50
+ const platform = process.platform;
51
+ if (platform === "win32") {
52
+ spawn("cmd", ["/c", "start", "", url], { detached: true, stdio: "ignore" }).unref();
53
+ return;
54
+ }
55
+ if (platform === "darwin") {
56
+ spawn("open", [url], { detached: true, stdio: "ignore" }).unref();
57
+ return;
58
+ }
59
+ spawn("xdg-open", [url], { detached: true, stdio: "ignore" }).unref();
60
+ }
61
+ export function createAskCommand() {
62
+ const cmd = new Command("ask")
63
+ .description("Submit a breakpoint to responders")
64
+ .requiredOption("-q, --question <text>", "Breakpoint text")
65
+ .option("-c, --context <text>", "Additional context for the breakpoint", "")
66
+ .option("--context-file <path>", "Load structured context from a JSON or text file")
67
+ .option("--markdown <text>", "Markdown body to render in the browser session")
68
+ .option("--markdown-file <path>", "Load markdown body from a file")
69
+ .option("--code <snippet>", "Add a code snippet to the context", collectValues, [])
70
+ .option("--file-ref <path>", "Add a file reference to the context", collectValues, [])
71
+ .option("--tag <tag>", "Add a tag to the context", collectValues, [])
72
+ .option("--link <label=url>", "Add a rich reference link to the context", collectValues, [])
73
+ .option("-e, --responders <ids>", "Comma-separated list of responder IDs")
74
+ .requiredOption("-p, --project <id>", "Associate the breakpoint with a project ID")
75
+ .requiredOption("-r, --repo <id>", "Associate the breakpoint with a repository ID")
76
+ .option("-s, --strategy <strategy>", "Routing strategy (single, first-response-wins, collect-all, quorum)", "first-response-wins")
77
+ .option("-t, --timeout <seconds>", "Timeout in seconds", "300")
78
+ .option("-w, --wait", "Wait for an answer before returning", false)
79
+ .option("--open-browser", "Open a browser session for answering", false)
80
+ .option("--answerer-id <id>", "Identity to attach to browser-session answers")
81
+ .option("--answerer-name <name>", "Display name for browser-session answers")
82
+ .action(async (opts, command) => {
83
+ const allOpts = command.optsWithGlobals();
84
+ const localOpts = opts;
85
+ const jsonMode = allOpts.json === true;
86
+ try {
87
+ const client = await createCliServerClient({
88
+ serverUrl: allOpts.serverUrl,
89
+ authToken: allOpts.authToken,
90
+ });
91
+ const timeoutMs = parseInt(localOpts.timeout ?? "300", 10) * 1000;
92
+ const responderIds = localOpts.responders
93
+ ? localOpts.responders.split(",").map((e) => e.trim())
94
+ : [];
95
+ const projectId = localOpts.project?.trim();
96
+ const repoId = localOpts.repo?.trim();
97
+ if (!projectId || !repoId) {
98
+ throw new Error("Both --project and --repo are required.");
99
+ }
100
+ const context = buildBreakpointContext(localOpts);
101
+ const routing = {
102
+ strategy: (localOpts.strategy ?? "first-response-wins"),
103
+ targetResponders: responderIds,
104
+ timeoutMs,
105
+ presentToUser: false,
106
+ };
107
+ const breakpoint = await client.submitBreakpoint({
108
+ text: localOpts.question,
109
+ context,
110
+ routing,
111
+ projectId,
112
+ repoId,
113
+ });
114
+ let browserSession;
115
+ if (localOpts.wait || localOpts.openBrowser) {
116
+ browserSession = await client.createBrowserSession(breakpoint.id, {
117
+ mode: "same-user",
118
+ responderId: localOpts.answererId,
119
+ responderName: localOpts.answererName,
120
+ });
121
+ try {
122
+ openBrowser(browserSession.url);
123
+ }
124
+ catch {
125
+ // Opening the browser is best-effort. The URL is still surfaced below.
126
+ }
127
+ }
128
+ if (localOpts.wait) {
129
+ const poller = new AnswerPoller(client);
130
+ const result = await poller.waitForAnswer(breakpoint.id, {
131
+ timeoutMs,
132
+ pollIntervalMs: DEFAULT_POLL_INTERVAL_MS,
133
+ useSSE: true,
134
+ });
135
+ if (jsonMode) {
136
+ console.log(JSON.stringify({ ...result, browserSession }, null, 2));
137
+ }
138
+ else {
139
+ console.log(formatBreakpoint(result.breakpoint, false));
140
+ if (browserSession) {
141
+ console.log(`\nBrowser session: ${browserSession.url}`);
142
+ }
143
+ if (result.answer) {
144
+ console.log("");
145
+ console.log(formatAnswer(result.answer, false));
146
+ }
147
+ else {
148
+ console.log("\nNo answer received within timeout.");
149
+ }
150
+ }
151
+ }
152
+ else {
153
+ if (jsonMode) {
154
+ console.log(JSON.stringify({ breakpoint, browserSession }, null, 2));
155
+ }
156
+ else {
157
+ console.log(formatBreakpoint(breakpoint, false));
158
+ if (browserSession) {
159
+ console.log(`\nBrowser session: ${browserSession.url}`);
160
+ }
161
+ console.log(`\nUse "tasks-adapter breakpoints poll ${breakpoint.id}" to wait for answers.`);
162
+ }
163
+ }
164
+ }
165
+ catch (error) {
166
+ printError(error, jsonMode);
167
+ process.exitCode = 1;
168
+ }
169
+ });
170
+ return cmd;
171
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function createAuthCommand(): Command;
3
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2CpC,wBAAgB,iBAAiB,IAAI,OAAO,CAa3C"}