mcoda 0.1.9 → 0.1.12

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 (55) hide show
  1. package/README.md +4 -4
  2. package/dist/bin/McodaEntrypoint.d.ts.map +1 -1
  3. package/dist/bin/McodaEntrypoint.js +40 -3
  4. package/dist/commands/agents/AgentRunCommand.d.ts.map +1 -1
  5. package/dist/commands/agents/AgentRunCommand.js +16 -2
  6. package/dist/commands/agents/AgentsCommands.d.ts.map +1 -1
  7. package/dist/commands/agents/AgentsCommands.js +209 -6
  8. package/dist/commands/agents/GatewayAgentCommand.js +1 -1
  9. package/dist/commands/agents/TestAgentCommand.d.ts.map +1 -1
  10. package/dist/commands/agents/TestAgentCommand.js +3 -0
  11. package/dist/commands/backlog/BacklogCommands.d.ts +5 -0
  12. package/dist/commands/backlog/BacklogCommands.d.ts.map +1 -1
  13. package/dist/commands/backlog/BacklogCommands.js +155 -34
  14. package/dist/commands/backlog/OrderTasksCommand.d.ts +3 -1
  15. package/dist/commands/backlog/OrderTasksCommand.d.ts.map +1 -1
  16. package/dist/commands/backlog/OrderTasksCommand.js +71 -31
  17. package/dist/commands/docs/DocsCommands.d.ts +14 -0
  18. package/dist/commands/docs/DocsCommands.d.ts.map +1 -1
  19. package/dist/commands/docs/DocsCommands.js +252 -4
  20. package/dist/commands/estimate/EstimateCommands.d.ts +1 -0
  21. package/dist/commands/estimate/EstimateCommands.d.ts.map +1 -1
  22. package/dist/commands/estimate/EstimateCommands.js +85 -7
  23. package/dist/commands/jobs/JobsCommands.d.ts +4 -0
  24. package/dist/commands/jobs/JobsCommands.d.ts.map +1 -1
  25. package/dist/commands/jobs/JobsCommands.js +117 -16
  26. package/dist/commands/openapi/OpenapiCommands.d.ts +1 -0
  27. package/dist/commands/openapi/OpenapiCommands.d.ts.map +1 -1
  28. package/dist/commands/openapi/OpenapiCommands.js +39 -5
  29. package/dist/commands/planning/CreateTasksCommand.d.ts +4 -0
  30. package/dist/commands/planning/CreateTasksCommand.d.ts.map +1 -1
  31. package/dist/commands/planning/CreateTasksCommand.js +43 -5
  32. package/dist/commands/planning/MigrateTasksCommand.js +1 -1
  33. package/dist/commands/planning/QaTasksCommand.d.ts +3 -1
  34. package/dist/commands/planning/QaTasksCommand.d.ts.map +1 -1
  35. package/dist/commands/planning/QaTasksCommand.js +28 -4
  36. package/dist/commands/planning/RefineTasksCommand.d.ts.map +1 -1
  37. package/dist/commands/planning/RefineTasksCommand.js +6 -1
  38. package/dist/commands/review/CodeReviewCommand.d.ts +1 -0
  39. package/dist/commands/review/CodeReviewCommand.d.ts.map +1 -1
  40. package/dist/commands/review/CodeReviewCommand.js +29 -6
  41. package/dist/commands/routing/RoutingCommands.d.ts.map +1 -1
  42. package/dist/commands/routing/RoutingCommands.js +48 -6
  43. package/dist/commands/telemetry/TelemetryCommands.d.ts +2 -0
  44. package/dist/commands/telemetry/TelemetryCommands.d.ts.map +1 -1
  45. package/dist/commands/telemetry/TelemetryCommands.js +3 -3
  46. package/dist/commands/work/GatewayTrioCommand.d.ts +4 -0
  47. package/dist/commands/work/GatewayTrioCommand.d.ts.map +1 -1
  48. package/dist/commands/work/GatewayTrioCommand.js +264 -19
  49. package/dist/commands/work/WorkOnTasksCommand.d.ts +3 -0
  50. package/dist/commands/work/WorkOnTasksCommand.d.ts.map +1 -1
  51. package/dist/commands/work/WorkOnTasksCommand.js +101 -12
  52. package/dist/commands/workspace/SetWorkspaceCommand.d.ts +64 -0
  53. package/dist/commands/workspace/SetWorkspaceCommand.d.ts.map +1 -1
  54. package/dist/commands/workspace/SetWorkspaceCommand.js +1377 -3
  55. package/package.json +5 -5
package/README.md CHANGED
@@ -15,14 +15,14 @@ mcoda docs pdr generate --workspace-root . --project WEB --rfp-path docs/rfp/web
15
15
 
16
16
  ## Docdex & QA
17
17
  - mcoda depends on the `docdex` CLI for doc search and context stitching.
18
- - Run `docdex setup` to install Playwright and at least one browser for `qa-tasks`.
18
+ - Run `docdex setup` (or `docdexd browser install`) to install the headless Chromium browser used for web enrichment.
19
19
  - Docdex stores state under `~/.docdex`; mcoda does not create repo-local `.docdex` folders.
20
20
  - If `~/.docdex/agents.md` exists, it is prepended to every agent run.
21
21
 
22
22
  ## Workspace layout
23
- - `.mcoda/config.json` for defaults (docdex URL, branch metadata, telemetry preferences).
24
- - `.mcoda/mcoda.db` for backlog, jobs, and telemetry.
25
- - `.mcoda/docs/` for generated artifacts.
23
+ - `~/.mcoda/workspaces/<fingerprint>/config.json` for defaults (docdex URL, branch metadata, telemetry preferences).
24
+ - `~/.mcoda/workspaces/<fingerprint>/mcoda.db` for backlog, jobs, and telemetry.
25
+ - `~/.mcoda/workspaces/<fingerprint>/docs/` for generated artifacts.
26
26
 
27
27
  ## Common commands
28
28
  - Docs: `mcoda docs pdr generate`, `mcoda docs sds generate`
@@ -1 +1 @@
1
- {"version":3,"file":"McodaEntrypoint.d.ts","sourceRoot":"","sources":["../../src/bin/McodaEntrypoint.ts"],"names":[],"mappings":";AA2BA,qBAAa,eAAe;WACb,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;CA4IxE"}
1
+ {"version":3,"file":"McodaEntrypoint.d.ts","sourceRoot":"","sources":["../../src/bin/McodaEntrypoint.ts"],"names":[],"mappings":";AA2BA,qBAAa,eAAe;WACb,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,OAAO,CAAC,IAAI,CAAC;CAkLxE"}
@@ -26,14 +26,51 @@ import { AgentRunCommand } from "../commands/agents/AgentRunCommand.js";
26
26
  import { SetWorkspaceCommand } from "../commands/workspace/SetWorkspaceCommand.js";
27
27
  export class McodaEntrypoint {
28
28
  static async run(argv = process.argv.slice(2)) {
29
- const [command, ...rest] = argv;
29
+ const applyCodexNoSandboxFlag = (value) => {
30
+ if (value === undefined || value === "") {
31
+ process.env.MCODA_CODEX_NO_SANDBOX = "1";
32
+ return;
33
+ }
34
+ const normalized = value.trim().toLowerCase();
35
+ if (["0", "false", "off", "no"].includes(normalized)) {
36
+ process.env.MCODA_CODEX_NO_SANDBOX = "0";
37
+ return;
38
+ }
39
+ process.env.MCODA_CODEX_NO_SANDBOX = "1";
40
+ };
41
+ const filteredArgs = [];
42
+ for (let i = 0; i < argv.length; i += 1) {
43
+ const arg = argv[i];
44
+ if (arg === "--codex-no-sandbox") {
45
+ const next = argv[i + 1];
46
+ if (next && !next.startsWith("--")) {
47
+ applyCodexNoSandboxFlag(next);
48
+ i += 1;
49
+ }
50
+ else {
51
+ applyCodexNoSandboxFlag(undefined);
52
+ }
53
+ continue;
54
+ }
55
+ if (arg.startsWith("--codex-no-sandbox=")) {
56
+ const [, raw] = arg.split("=", 2);
57
+ applyCodexNoSandboxFlag(raw);
58
+ continue;
59
+ }
60
+ filteredArgs.push(arg);
61
+ }
62
+ const [command, ...rest] = filteredArgs;
30
63
  const wantsJson = argv.some((arg) => arg === "--json" || arg.startsWith("--json="));
31
64
  const wantsQuiet = argv.some((arg) => arg === "--quiet" || arg.startsWith("--quiet="));
32
65
  if (wantsJson || wantsQuiet) {
33
66
  process.env.MCODA_STREAM_IO = "0";
67
+ process.env.MCODA_STREAM_IO_PROMPT = "0";
34
68
  }
35
69
  else if (process.env.MCODA_STREAM_IO === undefined) {
36
- process.env.MCODA_STREAM_IO = "1";
70
+ process.env.MCODA_STREAM_IO = "0";
71
+ if (process.env.MCODA_STREAM_IO_PROMPT === undefined) {
72
+ process.env.MCODA_STREAM_IO_PROMPT = "0";
73
+ }
37
74
  }
38
75
  if (command === "--version" || command === "-v" || command === "version") {
39
76
  // Keep this simple so `mcoda --version` works even in thin installs.
@@ -111,7 +148,7 @@ export class McodaEntrypoint {
111
148
  if (command === "qa-tasks") {
112
149
  if (rest.includes("--help") || rest.includes("-h")) {
113
150
  // eslint-disable-next-line no-console
114
- console.log("Usage: mcoda qa-tasks [--workspace-root <path>] --project <PROJECT_KEY> [--task <TASK_KEY> ... | --epic <EPIC_KEY> | --story <STORY_KEY>] [--status <STATUS_FILTER>] [--mode auto|manual] [--profile <PROFILE_NAME>] [--level unit|integration|acceptance] [--test-command \"<CMD>\"] [--agent <NAME>] [--agent-stream true|false] [--resume <JOB_ID>] [--create-followup-tasks auto|none|prompt] [--result pass|fail|blocked] [--notes \"<text>\"] [--evidence-url \"<url>\"] [--dry-run] [--json]");
151
+ console.log("Usage: mcoda qa-tasks [--workspace-root <path>] --project <PROJECT_KEY> [--task <TASK_KEY> ... | --epic <EPIC_KEY> | --story <STORY_KEY>] [--status <STATUS_FILTER>] [--limit N] [--mode auto|manual] [--profile <PROFILE_NAME>] [--level unit|integration|acceptance] [--test-command \"<CMD>\"] [--agent <NAME>] [--agent-stream true|false] [--resume <JOB_ID>] [--create-followup-tasks auto|none|prompt] [--result pass|fail] [--notes \"<text>\"] [--evidence-url \"<url>\"] [--dry-run] [--json]");
115
152
  return;
116
153
  }
117
154
  await QaTasksCommand.run(rest);
@@ -1 +1 @@
1
- {"version":3,"file":"AgentRunCommand.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/AgentRunCommand.ts"],"names":[],"mappings":"AAyDA,qBAAa,eAAe;WACb,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CA0EhD"}
1
+ {"version":3,"file":"AgentRunCommand.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/AgentRunCommand.ts"],"names":[],"mappings":"AAyDA,qBAAa,eAAe;WACb,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAsFhD"}
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs/promises";
2
2
  import { AgentsApi } from "@mcoda/core";
3
- const USAGE = "Usage: mcoda agent-run <NAME> [--prompt \"<text>\"] [--prompt-file <PATH>] [--task-file <PATH>] [--json]";
3
+ const USAGE = "Usage: mcoda agent-run <NAME> [--prompt \"<text>\"] [--prompt-file <PATH>] [--task-file <PATH>] [--stdin] [--json]";
4
4
  const parseArgs = (argv) => {
5
5
  const flags = {};
6
6
  const positionals = [];
@@ -61,6 +61,15 @@ export class AgentRunCommand {
61
61
  if (!name || parsed.flags.help) {
62
62
  throw new Error(USAGE);
63
63
  }
64
+ if (parsed.flags.prompt === true) {
65
+ throw new Error("agent-run: missing value for --prompt");
66
+ }
67
+ if (parsed.flags["prompt-file"] === true) {
68
+ throw new Error("agent-run: missing value for --prompt-file");
69
+ }
70
+ if (parsed.flags["task-file"] === true) {
71
+ throw new Error("agent-run: missing value for --task-file");
72
+ }
64
73
  const prompts = [];
65
74
  const inlinePrompts = toArray(parsed.flags.prompt);
66
75
  for (const prompt of inlinePrompts) {
@@ -83,7 +92,12 @@ export class AgentRunCommand {
83
92
  prompts.push(entry);
84
93
  }
85
94
  }
86
- if (prompts.length === 0) {
95
+ if (parsed.flags.stdin) {
96
+ const stdinPrompt = await readStdinIfProvided();
97
+ if (stdinPrompt)
98
+ prompts.push(stdinPrompt);
99
+ }
100
+ else if (prompts.length === 0) {
87
101
  const stdinPrompt = await readStdinIfProvided();
88
102
  if (stdinPrompt)
89
103
  prompts.push(stdinPrompt);
@@ -1 +1 @@
1
- {"version":3,"file":"AgentsCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/AgentsCommands.ts"],"names":[],"mappings":"AAiNA,qBAAa,cAAc;WACZ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAkNhD"}
1
+ {"version":3,"file":"AgentsCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/AgentsCommands.ts"],"names":[],"mappings":"AA2TA,qBAAa,cAAc;WACZ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAuThD"}
@@ -38,15 +38,21 @@ const readSecret = async (promptText) => new Promise((resolve) => {
38
38
  });
39
39
  });
40
40
  const USAGE = `
41
- Usage: mcoda agent <list|add|update|delete|remove|auth|auth-status|set-default|use|ratings> ...
41
+ Usage: mcoda agent <list|details|add|update|delete|remove|auth|auth-status|set-default|use|ratings> ...
42
42
 
43
43
  Subcommands:
44
44
  list List agents (supports --json)
45
+ details <NAME> Show agent details (supports --json)
45
46
  add <NAME> Create a global agent
46
47
  --adapter <TYPE> Adapter slug (openai-api|zhipu-api|codex-cli|gemini-cli|local-model|qa-cli|ollama-remote)
47
48
  --model <MODEL> Default model name
48
49
  --rating <N> Relative capability rating (higher is stronger)
49
50
  --reasoning-rating <N> Relative reasoning strength rating (higher is stronger)
51
+ --max-complexity <N> Max task complexity the agent should handle (1-10)
52
+ --openai-compatible <B> OpenAI-compatible API support (true/false)
53
+ --context-window <N> Context window size (tokens)
54
+ --max-output-tokens <N> Max output tokens per response
55
+ --supports-tools <B> Tool-calling support (true/false)
50
56
  --best-usage <TEXT> Primary usage area (e.g., code_write, ui_ux_docs)
51
57
  --cost-per-million <N> Cost per 1M tokens (0 for local models)
52
58
  --capability <CAP> Repeatable capabilities to attach
@@ -56,6 +62,11 @@ Subcommands:
56
62
  --config-temperature <N> Temperature override for supported adapters
57
63
  --config-thinking <BOOL> Enable thinking mode for supported adapters
58
64
  update <NAME> Update adapter/model/capabilities/prompts for an agent
65
+ --max-complexity <N> Max task complexity the agent should handle (1-10)
66
+ --openai-compatible <B> OpenAI-compatible API support (true/false)
67
+ --context-window <N> Context window size (tokens)
68
+ --max-output-tokens <N> Max output tokens per response
69
+ --supports-tools <B> Tool-calling support (true/false)
59
70
  delete|remove <NAME> Remove an agent (use --force to ignore routing/default references)
60
71
  --force Force deletion even if referenced
61
72
  auth set <NAME> Store credentials (use --api-key or interactive prompt)
@@ -107,6 +118,44 @@ const parseReasoningRating = (value) => {
107
118
  }
108
119
  return parsed;
109
120
  };
121
+ const parseMaxComplexity = (value) => {
122
+ if (value === undefined)
123
+ return undefined;
124
+ const raw = Array.isArray(value) ? value[value.length - 1] : value;
125
+ if (typeof raw === "boolean")
126
+ return undefined;
127
+ const parsed = Number.parseInt(String(raw), 10);
128
+ if (!Number.isFinite(parsed) || parsed < 1 || parsed > 10) {
129
+ throw new Error("Invalid --max-complexity; expected an integer 1-10");
130
+ }
131
+ return parsed;
132
+ };
133
+ const parsePositiveInt = (value, label) => {
134
+ if (value === undefined)
135
+ return undefined;
136
+ const raw = Array.isArray(value) ? value[value.length - 1] : value;
137
+ if (typeof raw === "boolean") {
138
+ throw new Error(`Invalid ${label}; expected a number`);
139
+ }
140
+ const parsed = Number.parseInt(String(raw), 10);
141
+ if (!Number.isFinite(parsed) || parsed <= 0) {
142
+ throw new Error(`Invalid ${label}; expected a positive integer`);
143
+ }
144
+ return parsed;
145
+ };
146
+ const parseBooleanFlag = (value, label) => {
147
+ if (value === undefined)
148
+ return undefined;
149
+ const raw = Array.isArray(value) ? value[value.length - 1] : value;
150
+ if (typeof raw === "boolean")
151
+ return raw;
152
+ const normalized = String(raw).trim().toLowerCase();
153
+ if (["true", "1", "yes", "y"].includes(normalized))
154
+ return true;
155
+ if (["false", "0", "no", "n"].includes(normalized))
156
+ return false;
157
+ throw new Error(`Invalid ${label}; expected true/false`);
158
+ };
110
159
  const parseCostPerMillion = (value) => {
111
160
  if (value === undefined)
112
161
  return undefined;
@@ -178,6 +227,28 @@ const formatNumber = (value) => {
178
227
  return "-";
179
228
  return `${value}`;
180
229
  };
230
+ const formatCompactNumber = (value) => {
231
+ if (value === undefined || value === null || Number.isNaN(value))
232
+ return "-";
233
+ const abs = Math.abs(value);
234
+ const format = (num, suffix, digits) => {
235
+ const raw = num.toFixed(digits);
236
+ const trimmed = raw.replace(/\.0+$/, "").replace(/(\.\d*[1-9])0+$/, "$1");
237
+ return `${trimmed}${suffix}`;
238
+ };
239
+ if (abs < 1000)
240
+ return `${value}`;
241
+ if (abs < 1000000) {
242
+ const digits = abs >= 10000 ? 0 : 1;
243
+ return format(value / 1000, "k", digits);
244
+ }
245
+ if (abs < 1000000000) {
246
+ const digits = abs >= 10000000 ? 0 : 2;
247
+ return format(value / 1000000, "M", digits);
248
+ }
249
+ const digits = abs >= 10000000000 ? 0 : 2;
250
+ return format(value / 1000000000, "B", digits);
251
+ };
181
252
  const formatDuration = (value) => {
182
253
  if (value === undefined || value === null || Number.isNaN(value))
183
254
  return "-";
@@ -204,12 +275,51 @@ const formatBoxTable = (headers, rows, maxWidths) => {
204
275
  const body = rows.map((row) => `│ ${row.map((val, idx) => cell(val ?? "", idx)).join(" │ ")} │`).join("\n");
205
276
  return [top, headerLine, mid, body, bottom].join("\n");
206
277
  };
278
+ const formatCapabilitiesFull = (caps) => {
279
+ const list = (caps ?? []).slice().sort();
280
+ return list.length === 0 ? "none" : list.join(", ");
281
+ };
282
+ const formatModels = (models) => {
283
+ if (!models || models.length === 0)
284
+ return "-";
285
+ const names = models
286
+ .map((model) => (model.isDefault ? `${model.modelName}*` : model.modelName))
287
+ .sort();
288
+ return names.join(", ");
289
+ };
290
+ const formatCommandPrompts = (prompts) => {
291
+ if (!prompts || Object.keys(prompts).length === 0)
292
+ return "-";
293
+ return Object.entries(prompts)
294
+ .sort(([left], [right]) => left.localeCompare(right))
295
+ .map(([key, value]) => `${key}=${value}`)
296
+ .join("; ");
297
+ };
298
+ const formatLatency = (value) => {
299
+ if (value === undefined || value === null || Number.isNaN(value))
300
+ return "-";
301
+ return `${Math.round(value)}ms`;
302
+ };
303
+ const renderKeyValues = (entries) => {
304
+ const width = entries.reduce((max, [label]) => Math.max(max, label.length), 0);
305
+ const lines = entries.map(([label, value]) => `${pad(label, width)} : ${value}`);
306
+ // eslint-disable-next-line no-console
307
+ console.log(lines.join("\n"));
308
+ };
207
309
  export class AgentsCommands {
208
310
  static async run(argv) {
209
311
  const [rawSubcommand, ...rest] = argv;
210
- const subcommand = rawSubcommand === "use" ? "set-default" : rawSubcommand === "remove" ? "delete" : rawSubcommand;
211
- if (!subcommand || rest.includes("--help")) {
212
- throw new Error(USAGE);
312
+ const subcommand = rawSubcommand === "use"
313
+ ? "set-default"
314
+ : rawSubcommand === "remove"
315
+ ? "delete"
316
+ : rawSubcommand === "detail" || rawSubcommand === "show"
317
+ ? "details"
318
+ : rawSubcommand;
319
+ if (!subcommand || argv.includes("--help") || argv.includes("-h")) {
320
+ // eslint-disable-next-line no-console
321
+ console.log(USAGE);
322
+ return;
213
323
  }
214
324
  const api = await AgentsApi.create();
215
325
  const parsed = parseArgs(rest);
@@ -218,8 +328,9 @@ export class AgentsCommands {
218
328
  case "list": {
219
329
  const agents = await api.listAgents();
220
330
  if (parsed.flags.json) {
331
+ const detailed = await Promise.all(agents.map((agent) => api.getAgent(agent.id ?? agent.slug)));
221
332
  // eslint-disable-next-line no-console
222
- console.log(JSON.stringify(agents, null, 2));
333
+ console.log(JSON.stringify(detailed, null, 2));
223
334
  }
224
335
  else {
225
336
  if (agents.length === 0) {
@@ -233,19 +344,45 @@ export class AgentsCommands {
233
344
  "MODEL",
234
345
  "RATING",
235
346
  "REASON",
347
+ "MAX CPLX",
348
+ "OAI",
349
+ "CTX",
350
+ "OUT",
351
+ "TOOLS",
236
352
  "USAGE",
237
353
  "COST/1M",
238
354
  "HEALTH",
239
355
  "LAST CHECK",
240
356
  "CAPABILITIES",
241
357
  ];
242
- const maxWidths = [14, 14, 24, 6, 9, 10, 12, 10, 16, 36];
358
+ const maxWidths = [
359
+ undefined,
360
+ 14,
361
+ 24,
362
+ 6,
363
+ 9,
364
+ 8,
365
+ 4,
366
+ 7,
367
+ 7,
368
+ 6,
369
+ 10,
370
+ 12,
371
+ 10,
372
+ 16,
373
+ 36,
374
+ ];
243
375
  const rows = agents.map((agent) => [
244
376
  agent.slug,
245
377
  agent.adapter,
246
378
  agent.defaultModel ?? "-",
247
379
  agent.rating !== undefined ? String(agent.rating) : "-",
248
380
  agent.reasoningRating !== undefined ? String(agent.reasoningRating) : "-",
381
+ formatNumber(agent.maxComplexity),
382
+ agent.openaiCompatible === undefined ? "-" : agent.openaiCompatible ? "yes" : "no",
383
+ formatCompactNumber(agent.contextWindow),
384
+ formatCompactNumber(agent.maxOutputTokens),
385
+ agent.supportsTools === undefined ? "-" : agent.supportsTools ? "yes" : "no",
249
386
  agent.bestUsage ?? "-",
250
387
  formatCost(agent.costPerMillion),
251
388
  agent.health?.status ?? "unknown",
@@ -258,6 +395,52 @@ export class AgentsCommands {
258
395
  }
259
396
  break;
260
397
  }
398
+ case "details": {
399
+ const name = parsed.positionals[0];
400
+ if (!name)
401
+ throw new Error("Usage: mcoda agent details <NAME> [--json]");
402
+ const agent = await api.getAgent(name);
403
+ if (parsed.flags.json) {
404
+ // eslint-disable-next-line no-console
405
+ console.log(JSON.stringify(agent, null, 2));
406
+ }
407
+ else {
408
+ renderKeyValues([
409
+ ["Slug", agent.slug],
410
+ ["Adapter", agent.adapter],
411
+ ["Default model", agent.defaultModel ?? "-"],
412
+ ["Rating", formatNumber(agent.rating)],
413
+ ["Reasoning rating", formatNumber(agent.reasoningRating)],
414
+ ["Max complexity", formatNumber(agent.maxComplexity)],
415
+ ["OpenAI compatible", agent.openaiCompatible === undefined ? "-" : agent.openaiCompatible ? "yes" : "no"],
416
+ ["Context window", formatNumber(agent.contextWindow)],
417
+ ["Max output tokens", formatNumber(agent.maxOutputTokens)],
418
+ ["Supports tools", agent.supportsTools === undefined ? "-" : agent.supportsTools ? "yes" : "no"],
419
+ ["Best usage", agent.bestUsage ?? "-"],
420
+ ["Cost per 1M", formatCost(agent.costPerMillion)],
421
+ ["Rating samples", formatNumber(agent.ratingSamples)],
422
+ ["Rating last score", formatNumber(agent.ratingLastScore)],
423
+ ["Rating updated", formatDate(agent.ratingUpdatedAt)],
424
+ ["Complexity samples", formatNumber(agent.complexitySamples)],
425
+ ["Complexity updated", formatDate(agent.complexityUpdatedAt)],
426
+ ["Capabilities", formatCapabilitiesFull(agent.capabilities)],
427
+ ["Models", formatModels(agent.models)],
428
+ ["Health status", agent.health?.status ?? "unknown"],
429
+ ["Health last checked", formatDate(agent.health?.lastCheckedAt)],
430
+ ["Health latency", formatLatency(agent.health?.latencyMs)],
431
+ ["Auth configured", agent.auth?.configured ? "yes" : "no"],
432
+ ["Auth last updated", formatDate(agent.auth?.lastUpdatedAt)],
433
+ ["Auth last verified", formatDate(agent.auth?.lastVerifiedAt)],
434
+ ["Command prompts", formatCommandPrompts(agent.prompts?.commandPrompts)],
435
+ ["Job prompt path", agent.prompts?.jobPath ?? "-"],
436
+ ["Character prompt path", agent.prompts?.characterPath ?? "-"],
437
+ ["Config", agent.config ? JSON.stringify(agent.config) : "-"],
438
+ ["Created", formatDate(agent.createdAt)],
439
+ ["Updated", formatDate(agent.updatedAt)],
440
+ ]);
441
+ }
442
+ break;
443
+ }
261
444
  case "add": {
262
445
  const name = parsed.positionals[0];
263
446
  if (!name)
@@ -268,6 +451,11 @@ export class AgentsCommands {
268
451
  const config = parseConfig(parsed.flags);
269
452
  const rating = parseRating(parsed.flags.rating);
270
453
  const reasoningRating = parseReasoningRating(parsed.flags["reasoning-rating"]);
454
+ const maxComplexity = parseMaxComplexity(parsed.flags["max-complexity"]);
455
+ const openaiCompatible = parseBooleanFlag(parsed.flags["openai-compatible"], "--openai-compatible");
456
+ const contextWindow = parsePositiveInt(parsed.flags["context-window"], "--context-window");
457
+ const maxOutputTokens = parsePositiveInt(parsed.flags["max-output-tokens"], "--max-output-tokens");
458
+ const supportsTools = parseBooleanFlag(parsed.flags["supports-tools"], "--supports-tools");
271
459
  const bestUsage = parsed.flags["best-usage"] ? String(parsed.flags["best-usage"]) : undefined;
272
460
  const costPerMillion = parseCostPerMillion(parsed.flags["cost-per-million"]);
273
461
  const agent = await api.createAgent({
@@ -276,6 +464,11 @@ export class AgentsCommands {
276
464
  defaultModel: parsed.flags.model ? String(parsed.flags.model) : undefined,
277
465
  rating,
278
466
  reasoningRating,
467
+ maxComplexity,
468
+ openaiCompatible,
469
+ contextWindow,
470
+ maxOutputTokens,
471
+ supportsTools,
279
472
  bestUsage,
280
473
  costPerMillion,
281
474
  capabilities,
@@ -295,6 +488,11 @@ export class AgentsCommands {
295
488
  const config = parseConfig(parsed.flags);
296
489
  const rating = parseRating(parsed.flags.rating);
297
490
  const reasoningRating = parseReasoningRating(parsed.flags["reasoning-rating"]);
491
+ const maxComplexity = parseMaxComplexity(parsed.flags["max-complexity"]);
492
+ const openaiCompatible = parseBooleanFlag(parsed.flags["openai-compatible"], "--openai-compatible");
493
+ const contextWindow = parsePositiveInt(parsed.flags["context-window"], "--context-window");
494
+ const maxOutputTokens = parsePositiveInt(parsed.flags["max-output-tokens"], "--max-output-tokens");
495
+ const supportsTools = parseBooleanFlag(parsed.flags["supports-tools"], "--supports-tools");
298
496
  const bestUsage = parsed.flags["best-usage"] ? String(parsed.flags["best-usage"]) : undefined;
299
497
  const costPerMillion = parseCostPerMillion(parsed.flags["cost-per-million"]);
300
498
  const agent = await api.updateAgent(name, {
@@ -302,6 +500,11 @@ export class AgentsCommands {
302
500
  defaultModel: parsed.flags.model ? String(parsed.flags.model) : undefined,
303
501
  rating,
304
502
  reasoningRating,
503
+ maxComplexity,
504
+ openaiCompatible,
505
+ contextWindow,
506
+ maxOutputTokens,
507
+ supportsTools,
305
508
  bestUsage,
306
509
  costPerMillion,
307
510
  capabilities,
@@ -392,7 +392,7 @@ export class GatewayAgentCommand {
392
392
  }
393
393
  const service = await GatewayAgentService.create(workspace);
394
394
  try {
395
- const streamEnabled = (gatewayArgs.agentStream ?? true) && !gatewayArgs.json;
395
+ const streamEnabled = (gatewayArgs.agentStream ?? false) && !gatewayArgs.json;
396
396
  const ioEnabled = isIoEnabled();
397
397
  const shouldPrintStream = streamEnabled && !ioEnabled;
398
398
  let streamStarted = false;
@@ -1 +1 @@
1
- {"version":3,"file":"TestAgentCommand.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/TestAgentCommand.ts"],"names":[],"mappings":"AAyBA,qBAAa,gBAAgB;WACd,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAoChD"}
1
+ {"version":3,"file":"TestAgentCommand.d.ts","sourceRoot":"","sources":["../../../src/commands/agents/TestAgentCommand.ts"],"names":[],"mappings":"AAyBA,qBAAa,gBAAgB;WACd,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAuChD"}
@@ -29,6 +29,9 @@ export class TestAgentCommand {
29
29
  if (!name || parsed.flags.help) {
30
30
  throw new Error(USAGE);
31
31
  }
32
+ if (parsed.flags.prompt === true) {
33
+ throw new Error("test-agent: missing value for --prompt");
34
+ }
32
35
  const prompt = typeof parsed.flags.prompt === "string" ? parsed.flags.prompt : undefined;
33
36
  const api = await AgentsApi.create();
34
37
  try {
@@ -5,7 +5,12 @@ interface ParsedArgs {
5
5
  story?: string;
6
6
  assignee?: string;
7
7
  statuses?: string[];
8
+ statusAll?: boolean;
9
+ includeDone: boolean;
10
+ includeCancelled: boolean;
8
11
  orderDependencies: boolean;
12
+ view?: "summary" | "epics" | "stories" | "tasks";
13
+ limit?: number;
9
14
  json: boolean;
10
15
  verbose: boolean;
11
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"BacklogCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/backlog/BacklogCommands.ts"],"names":[],"mappings":"AAGA,UAAU,UAAU;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AAsBD,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,EAAE,KAAG,UAwEjD,CAAC;AAqIF,qBAAa,eAAe;WACb,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CA4ChD"}
1
+ {"version":3,"file":"BacklogCommands.d.ts","sourceRoot":"","sources":["../../../src/commands/backlog/BacklogCommands.ts"],"names":[],"mappings":"AAIA,UAAU,UAAU;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,EAAE,OAAO,CAAC;IACrB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,IAAI,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AA6BD,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,EAAE,KAAG,UAsHjD,CAAC;AAgLF,qBAAa,eAAe;WACb,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CA4DhD"}