@great-arrow/cli 0.1.1 → 0.1.3

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 (2) hide show
  1. package/dist/index.js +181 -120
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire as __createRequire } from 'node:module';
3
+ const require = __createRequire(import.meta.url);
2
4
  var __create = Object.create;
3
5
  var __defProp = Object.defineProperty;
4
6
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -3856,6 +3858,61 @@ async function resolveToken(configToken) {
3856
3858
 
3857
3859
  // src/lib/client.ts
3858
3860
  import { execSync } from "node:child_process";
3861
+
3862
+ // src/lib/mcp-payload.ts
3863
+ function isTextBlock(value) {
3864
+ return typeof value === "object" && value !== null && value.type === "text" && typeof value.text === "string";
3865
+ }
3866
+ function extractJsonSlice(text) {
3867
+ const start = text.search(/[{[]/);
3868
+ if (start === -1) return null;
3869
+ let depth = 0;
3870
+ let inString = false;
3871
+ let escaped = false;
3872
+ for (let i = start; i < text.length; i++) {
3873
+ const ch = text[i];
3874
+ if (escaped) {
3875
+ escaped = false;
3876
+ continue;
3877
+ }
3878
+ if (inString) {
3879
+ if (ch === "\\") escaped = true;
3880
+ else if (ch === '"') inString = false;
3881
+ continue;
3882
+ }
3883
+ if (ch === '"') inString = true;
3884
+ else if (ch === "{" || ch === "[") depth++;
3885
+ else if (ch === "}" || ch === "]") {
3886
+ depth--;
3887
+ if (depth === 0) return text.slice(start, i + 1);
3888
+ }
3889
+ }
3890
+ return null;
3891
+ }
3892
+ function parseMcpPayload(result) {
3893
+ let text = null;
3894
+ if (typeof result === "string") {
3895
+ text = result;
3896
+ } else if (Array.isArray(result)) {
3897
+ const block = result.find(isTextBlock);
3898
+ if (block) text = block.text;
3899
+ }
3900
+ if (text === null) return result;
3901
+ try {
3902
+ return JSON.parse(text);
3903
+ } catch {
3904
+ }
3905
+ const slice = extractJsonSlice(text);
3906
+ if (slice !== null) {
3907
+ try {
3908
+ return JSON.parse(slice);
3909
+ } catch {
3910
+ }
3911
+ }
3912
+ return text;
3913
+ }
3914
+
3915
+ // src/lib/client.ts
3859
3916
  var DEFAULT_TIMEOUT_MS = 3e4;
3860
3917
  var MAX_RETRIES = 3;
3861
3918
  var BASE_DELAY_MS = 1e3;
@@ -3989,7 +4046,7 @@ var GadClient = class {
3989
4046
  * @param toolName - The MCP tool name to invoke
3990
4047
  * @param args - Arguments to pass to the tool
3991
4048
  * @param timeoutMs - Optional timeout override (e.g., 90s for agent calls)
3992
- * @returns The tool result content
4049
+ * @returns The decoded JSON payload from the tool result content
3993
4050
  */
3994
4051
  async mcpCall(toolName, args, timeoutMs) {
3995
4052
  const url = `${this.apiUrl}/api/mcp`;
@@ -4029,7 +4086,15 @@ var GadClient = class {
4029
4086
  data.error.data ?? void 0
4030
4087
  );
4031
4088
  }
4032
- return data.result?.content ?? data.result;
4089
+ const payload = parseMcpPayload(data.result?.content ?? data.result);
4090
+ if (typeof payload === "string" && payload.includes("[truncated: result exceeded")) {
4091
+ throw new CliError(
4092
+ `Tool '${toolName}' response was truncated by the server before the data completed.`,
4093
+ 3 /* VALIDATION_ERROR */,
4094
+ "Narrow the request (lower --limit / -k, or add filters) and try again."
4095
+ );
4096
+ }
4097
+ return payload;
4033
4098
  }
4034
4099
  /**
4035
4100
  * Make a GET request to a REST API endpoint.
@@ -4088,6 +4153,18 @@ var GadClient = class {
4088
4153
  }
4089
4154
  };
4090
4155
 
4156
+ // src/lib/global-opts.ts
4157
+ function globalOutputOpts(cmd) {
4158
+ const merged = cmd.optsWithGlobals();
4159
+ return {
4160
+ json: Boolean(merged.json),
4161
+ quiet: Boolean(merged.quiet),
4162
+ // --no-color sets `color: false`; some commands declare `--no-color`
4163
+ // locally which surfaces as `noColor`.
4164
+ noColor: merged.color === false || Boolean(merged.noColor)
4165
+ };
4166
+ }
4167
+
4091
4168
  // src/commands/whoami.ts
4092
4169
  function maskToken2(token) {
4093
4170
  if (token.length <= 8) {
@@ -4102,7 +4179,8 @@ function extractWorkspaceName(data) {
4102
4179
  return data.workspace?.name || data.workspaceName || "unknown";
4103
4180
  }
4104
4181
  function whoamiCommand() {
4105
- const cmd = new Command("whoami").description("Display authenticated user info").option("--json", "Output as JSON").option("--quiet", "Suppress decorative output").option("--no-color", "Disable color output").action(async (options) => {
4182
+ const cmd = new Command("whoami").description("Display authenticated user info").option("--json", "Output as JSON").option("--quiet", "Suppress decorative output").option("--no-color", "Disable color output").action(async (options, command) => {
4183
+ const g = globalOutputOpts(command);
4106
4184
  const auth = await resolveAuth();
4107
4185
  const client = new GadClient({
4108
4186
  token: auth.token,
@@ -4125,10 +4203,10 @@ function whoamiCommand() {
4125
4203
  const workspaceName = extractWorkspaceName(introspect);
4126
4204
  const tokenPrefix = maskToken2(auth.token);
4127
4205
  const fmt = createFormatter({
4128
- json: options.json ?? false,
4129
- quiet: options.quiet ?? false,
4206
+ json: g.json,
4207
+ quiet: g.quiet,
4130
4208
  isTTY: isTTY(),
4131
- noColor: options.color === false
4209
+ noColor: g.noColor
4132
4210
  });
4133
4211
  const data = {
4134
4212
  email,
@@ -4219,7 +4297,7 @@ var memoryCommand = new Command("memory").description(
4219
4297
  memoryCommand.command("create").description("Create a new memory in the active workspace").requiredOption("--title <title>", "Memory title").option("--content <content>", "Memory content (or pipe via stdin)").option("--tags <tags>", "Comma-separated tags").option(
4220
4298
  "--layer <layer>",
4221
4299
  "Memory layer (WORKING, EPISODIC, SEMANTIC, PROCEDURAL)"
4222
- ).action(async (opts) => {
4300
+ ).action(async (opts, command) => {
4223
4301
  const client = await buildClient();
4224
4302
  let content = opts.content;
4225
4303
  if (!content) {
@@ -4256,7 +4334,8 @@ memoryCommand.command("create").description("Create a new memory in the active w
4256
4334
  const memoryId = typeof rawId === "string" ? rawId : "created";
4257
4335
  fmt.success(`Memory created: ${memoryId}`);
4258
4336
  });
4259
- memoryCommand.command("search <query>").description("Semantic search across memories").option("--json", "Output as JSON").option("-k, --limit <number>", "Max results", "10").option("--layer <layer>", "Filter by layer").action(async (query, opts) => {
4337
+ memoryCommand.command("search <query>").description("Semantic search across memories").option("--json", "Output as JSON").option("-k, --limit <number>", "Max results", "10").option("--layer <layer>", "Filter by layer").action(async (query, opts, command) => {
4338
+ const g = globalOutputOpts(command);
4260
4339
  const client = await buildClient();
4261
4340
  const args = {
4262
4341
  query,
@@ -4266,22 +4345,27 @@ memoryCommand.command("search <query>").description("Semantic search across memo
4266
4345
  args.layer = opts.layer;
4267
4346
  }
4268
4347
  const result = await client.mcpCall("memory_search", args);
4269
- const rawResults = Array.isArray(result) ? result : result?.results ?? [];
4348
+ const data = result ?? {};
4349
+ const rawResults = Array.isArray(result) ? result : data.hits ?? data.results ?? [];
4270
4350
  const rows = rawResults.map((item) => ({
4271
4351
  ...item,
4352
+ title: item.title ?? item.memoryTitle,
4272
4353
  preview: extractPreview(item)
4273
4354
  }));
4274
4355
  const fmt = createFormatter({
4275
- json: Boolean(opts.json),
4356
+ json: g.json,
4276
4357
  quiet: false,
4277
4358
  isTTY: isTTY(),
4278
4359
  noColor: false
4279
4360
  });
4280
4361
  fmt.table(rows, searchColumns);
4281
4362
  });
4282
- memoryCommand.command("list").description("List recent memories with optional filters").option("--json", "Output as JSON").option("--layer <layer>", "Filter by memory layer").option("--tag <tag>", "Filter by tag").action(async (opts) => {
4363
+ memoryCommand.command("list").description("List recent memories with optional filters").option("--json", "Output as JSON").option("--limit <number>", "Max results", "20").option("--layer <layer>", "Filter by memory layer").option("--tag <tag>", "Filter by tag").action(async (opts, command) => {
4364
+ const g = globalOutputOpts(command);
4283
4365
  const client = await buildClient();
4284
- const args = {};
4366
+ const args = {
4367
+ limit: Number.parseInt(opts.limit, 10)
4368
+ };
4285
4369
  if (opts.layer) {
4286
4370
  args.layer = opts.layer;
4287
4371
  }
@@ -4289,21 +4373,23 @@ memoryCommand.command("list").description("List recent memories with optional fi
4289
4373
  args.tag = opts.tag;
4290
4374
  }
4291
4375
  const result = await client.mcpCall("memory_list", args);
4292
- const rawResults = Array.isArray(result) ? result : result?.results ?? [];
4376
+ const data = result ?? {};
4377
+ const rawResults = Array.isArray(result) ? result : data.memories ?? data.results ?? [];
4293
4378
  const fmt = createFormatter({
4294
- json: Boolean(opts.json),
4379
+ json: g.json,
4295
4380
  quiet: false,
4296
4381
  isTTY: isTTY(),
4297
4382
  noColor: false
4298
4383
  });
4299
4384
  fmt.table(rawResults, listColumns);
4300
4385
  });
4301
- memoryCommand.command("get <id>").description("Show full content and metadata of a memory").option("--json", "Output as JSON").action(async (id, opts) => {
4386
+ memoryCommand.command("get <id>").description("Show full content and metadata of a memory").option("--json", "Output as JSON").action(async (id, opts, command) => {
4387
+ const g = globalOutputOpts(command);
4302
4388
  const client = await buildClient();
4303
4389
  const result = await client.mcpCall("memory_get", { id });
4304
4390
  const data = result ?? {};
4305
4391
  const fmt = createFormatter({
4306
- json: Boolean(opts.json),
4392
+ json: g.json,
4307
4393
  quiet: false,
4308
4394
  isTTY: isTTY(),
4309
4395
  noColor: false
@@ -4374,22 +4460,10 @@ async function createClient() {
4374
4460
  const auth = await resolveAuth();
4375
4461
  return new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
4376
4462
  }
4377
- function extractMcpContent(result) {
4378
- if (Array.isArray(result) && result.length > 0) {
4379
- const first = result[0];
4380
- if (typeof first === "object" && first !== null && "type" in first && first.type === "text" && "text" in first) {
4381
- try {
4382
- return JSON.parse(first.text);
4383
- } catch {
4384
- return first.text;
4385
- }
4386
- }
4387
- }
4388
- return result;
4389
- }
4390
4463
  var listCommand = new Command("list").description("List all accessible workspaces").option("--json", "Output as JSON").action(async (options) => {
4391
- const parentOpts = listCommand.parent?.opts() ?? {};
4392
- const jsonFlag = options.json || parentOpts.json || false;
4464
+ const jsonFlag = Boolean(
4465
+ options.json || listCommand.optsWithGlobals().json
4466
+ );
4393
4467
  const fmt = createFormatter({
4394
4468
  json: jsonFlag,
4395
4469
  quiet: false,
@@ -4398,7 +4472,7 @@ var listCommand = new Command("list").description("List all accessible workspace
4398
4472
  });
4399
4473
  const client = await createClient();
4400
4474
  const result = await client.mcpCall("workspace_list", {});
4401
- const data = extractMcpContent(result);
4475
+ const data = result;
4402
4476
  let workspaces = [];
4403
4477
  if (Array.isArray(data)) {
4404
4478
  workspaces = data;
@@ -4460,8 +4534,9 @@ var infoColumns = [
4460
4534
  }
4461
4535
  ];
4462
4536
  var infoCommand = new Command("info").description("Show active workspace settings, member count, and integrations").option("--json", "Output as JSON").action(async (options) => {
4463
- const parentOpts = infoCommand.parent?.opts() ?? {};
4464
- const jsonFlag = options.json || parentOpts.json || false;
4537
+ const jsonFlag = Boolean(
4538
+ options.json || infoCommand.optsWithGlobals().json
4539
+ );
4465
4540
  const fmt = createFormatter({
4466
4541
  json: jsonFlag,
4467
4542
  quiet: false,
@@ -4470,13 +4545,14 @@ var infoCommand = new Command("info").description("Show active workspace setting
4470
4545
  });
4471
4546
  const client = await createClient();
4472
4547
  const result = await client.mcpCall("workspace_settings_get", {});
4473
- const data = extractMcpContent(result);
4548
+ const data = result;
4474
4549
  const workspace = typeof data === "object" && data !== null ? data : {};
4475
4550
  fmt.detail(workspace, infoColumns);
4476
4551
  });
4477
4552
  var membersCommand = new Command("members").description("List workspace members with roles and last-active timestamps").option("--json", "Output as JSON").action(async (options) => {
4478
- const parentOpts = membersCommand.parent?.opts() ?? {};
4479
- const jsonFlag = options.json || parentOpts.json || false;
4553
+ const jsonFlag = Boolean(
4554
+ options.json || membersCommand.optsWithGlobals().json
4555
+ );
4480
4556
  const fmt = createFormatter({
4481
4557
  json: jsonFlag,
4482
4558
  quiet: false,
@@ -4485,7 +4561,7 @@ var membersCommand = new Command("members").description("List workspace members
4485
4561
  });
4486
4562
  const client = await createClient();
4487
4563
  const result = await client.mcpCall("workspace_members", {});
4488
- const data = extractMcpContent(result);
4564
+ const data = result;
4489
4565
  let members = [];
4490
4566
  if (Array.isArray(data)) {
4491
4567
  members = data;
@@ -4538,7 +4614,7 @@ var listCommand2 = new Command("list").description("List open todos sorted by pr
4538
4614
  "Filter by status (open, in_progress, review, done, dismissed)"
4539
4615
  ).option("--json", "Output as JSON").action(
4540
4616
  async (options, cmd) => {
4541
- const parentOpts = cmd.parent?.opts() ?? {};
4617
+ const parentOpts = cmd.optsWithGlobals();
4542
4618
  const jsonOutput = options.json || parentOpts.json || false;
4543
4619
  const fmt = createFormatter({
4544
4620
  json: jsonOutput,
@@ -4548,10 +4624,9 @@ var listCommand2 = new Command("list").description("List open todos sorted by pr
4548
4624
  });
4549
4625
  const auth = await resolveAuth();
4550
4626
  const client = new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
4551
- const args = {};
4552
- if (options.status) {
4553
- args.status = options.status;
4554
- }
4627
+ const args = {
4628
+ status: options.status ?? "open"
4629
+ };
4555
4630
  const result = await client.mcpCall("todo_list", args);
4556
4631
  let todos = [];
4557
4632
  if (Array.isArray(result)) {
@@ -4711,8 +4786,12 @@ async function checkIntegrations(auth) {
4711
4786
  const client = new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
4712
4787
  try {
4713
4788
  const result = await client.mcpCall("integrations_list", {});
4714
- const integrations = Array.isArray(result) ? result : [];
4715
- const errorIntegrations = integrations.filter((i) => i.status === "error");
4789
+ const data = result ?? {};
4790
+ const integrations = Array.isArray(result) ? result : Array.isArray(data.integrations) ? data.integrations : [];
4791
+ const errorIntegrations = integrations.filter((i) => {
4792
+ const status = (i.status ?? "").toUpperCase();
4793
+ return status === "ERROR" || status === "NEEDS_REAUTH";
4794
+ });
4716
4795
  if (errorIntegrations.length === 0) {
4717
4796
  return {
4718
4797
  name: "Integrations",
@@ -4724,7 +4803,7 @@ async function checkIntegrations(auth) {
4724
4803
  return {
4725
4804
  name: "Integrations",
4726
4805
  status: "warn",
4727
- message: `${errorIntegrations.length} integration(s) with errors: ${kinds}`,
4806
+ message: `${errorIntegrations.length} of ${integrations.length} integration(s) need attention: ${kinds}`,
4728
4807
  hint: "Run 'gad integrations list' for details, or 'gad integrations sync <kind>' to retry."
4729
4808
  };
4730
4809
  } catch {
@@ -4763,17 +4842,17 @@ async function checkMcp(auth) {
4763
4842
  }
4764
4843
  }
4765
4844
  function doctorCommand() {
4766
- const cmd = new Command("doctor").description("Run a comprehensive health check").option("--json", "Output as JSON").option("--quiet", "Suppress decorative output").option("--no-color", "Disable color output").action(async (options) => {
4767
- const noColor = options.color === false;
4768
- const color2 = createColor(noColor);
4845
+ const cmd = new Command("doctor").description("Run a comprehensive health check").option("--json", "Output as JSON").option("--quiet", "Suppress decorative output").option("--no-color", "Disable color output").action(async (options, command) => {
4846
+ const g = globalOutputOpts(command);
4847
+ const color2 = createColor(g.noColor);
4769
4848
  const fmt = createFormatter({
4770
- json: options.json ?? false,
4771
- quiet: options.quiet ?? false,
4849
+ json: g.json,
4850
+ quiet: g.quiet,
4772
4851
  isTTY: isTTY(),
4773
- noColor
4852
+ noColor: g.noColor
4774
4853
  });
4775
4854
  const checks = [];
4776
- const isJson = options.json ?? false;
4855
+ const isJson = g.json;
4777
4856
  const { check: tokenCheck, auth } = await checkToken();
4778
4857
  checks.push(tokenCheck);
4779
4858
  if (!isJson) {
@@ -4796,7 +4875,7 @@ function doctorCommand() {
4796
4875
  }
4797
4876
  if (isJson) {
4798
4877
  process.stdout.write(JSON.stringify(checks) + "\n");
4799
- } else if (!options.quiet) {
4878
+ } else if (!g.quiet) {
4800
4879
  const passed = checks.filter((c) => c.status === "pass").length;
4801
4880
  const warned = checks.filter((c) => c.status === "warn").length;
4802
4881
  const failed = checks.filter((c) => c.status === "fail").length;
@@ -4859,19 +4938,6 @@ async function createClient2() {
4859
4938
  const auth = await resolveAuth();
4860
4939
  return new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
4861
4940
  }
4862
- function extractMcpContent2(result) {
4863
- if (Array.isArray(result) && result.length > 0) {
4864
- const first = result[0];
4865
- if (typeof first === "object" && first !== null && "type" in first && first.type === "text" && "text" in first) {
4866
- try {
4867
- return JSON.parse(first.text);
4868
- } catch {
4869
- return first.text;
4870
- }
4871
- }
4872
- }
4873
- return result;
4874
- }
4875
4941
  function formatErrorDetail(rawError) {
4876
4942
  if (rawError === null || rawError === void 0) return null;
4877
4943
  if (typeof rawError === "string") return rawError;
@@ -4921,8 +4987,9 @@ function handleSyncResponse(fmt, kind, response) {
4921
4987
  }
4922
4988
  }
4923
4989
  var listCommand3 = new Command("list").description("List all connected integrations with sync status").option("--json", "Output as JSON").action(async (options) => {
4924
- const parentOpts = listCommand3.parent?.opts() ?? {};
4925
- const jsonFlag = options.json || parentOpts.json || false;
4990
+ const jsonFlag = Boolean(
4991
+ options.json || listCommand3.optsWithGlobals().json
4992
+ );
4926
4993
  const fmt = createFormatter({
4927
4994
  json: jsonFlag,
4928
4995
  quiet: false,
@@ -4931,7 +4998,7 @@ var listCommand3 = new Command("list").description("List all connected integrati
4931
4998
  });
4932
4999
  const client = await createClient2();
4933
5000
  const result = await client.mcpCall("integrations_list", {});
4934
- const data = extractMcpContent2(result);
5001
+ const data = result;
4935
5002
  let integrations = [];
4936
5003
  if (Array.isArray(data)) {
4937
5004
  integrations = data;
@@ -4958,7 +5025,7 @@ var syncCommand = new Command("sync").description("Trigger a manual sync for the
4958
5025
  fmt.info(`Triggering sync for "${kind}"...`);
4959
5026
  try {
4960
5027
  const result = await client.mcpCall("integration_sync", { kind });
4961
- const data = extractMcpContent2(result);
5028
+ const data = result;
4962
5029
  if (typeof data === "object" && data !== null) {
4963
5030
  handleSyncResponse(fmt, kind, data);
4964
5031
  } else {
@@ -5003,19 +5070,6 @@ async function createClient3() {
5003
5070
  const client = new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
5004
5071
  return { client, apiUrl: auth.apiUrl };
5005
5072
  }
5006
- function extractMcpContent3(result) {
5007
- if (Array.isArray(result) && result.length > 0) {
5008
- const first = result[0];
5009
- if (typeof first === "object" && first !== null && "type" in first && first.type === "text" && "text" in first) {
5010
- try {
5011
- return JSON.parse(first.text);
5012
- } catch {
5013
- return first.text;
5014
- }
5015
- }
5016
- }
5017
- return result;
5018
- }
5019
5073
  function generateMcpConfig(client, apiUrl, token) {
5020
5074
  const endpoint = mcpEndpoint(apiUrl);
5021
5075
  if (client === "codex") {
@@ -5135,8 +5189,9 @@ var statusColumns = [
5135
5189
  var statusCommand = new Command("status").description(
5136
5190
  "Show MCP server connection status, proxy version, and session count"
5137
5191
  ).option("--json", "Output as JSON").action(async (options) => {
5138
- const parentOpts = statusCommand.parent?.opts() ?? {};
5139
- const jsonFlag = options.json || parentOpts.json || false;
5192
+ const jsonFlag = Boolean(
5193
+ options.json || statusCommand.optsWithGlobals().json
5194
+ );
5140
5195
  const fmt = createFormatter({
5141
5196
  json: jsonFlag,
5142
5197
  quiet: false,
@@ -5152,7 +5207,7 @@ var statusCommand = new Command("status").description(
5152
5207
  };
5153
5208
  try {
5154
5209
  const result = await client.mcpCall("workspace_introspect", {});
5155
- const data = extractMcpContent3(result);
5210
+ const data = result;
5156
5211
  if (typeof data === "object" && data !== null) {
5157
5212
  const info = data;
5158
5213
  statusData = {
@@ -5191,8 +5246,9 @@ function renderLogEntry(entry, c) {
5191
5246
  `);
5192
5247
  }
5193
5248
  var logsCommand = new Command("logs").description("Tail MCP connection log with colorized output").option("--lines <n>", "Number of recent log lines to show", "20").option("--json", "Output as JSON").action(async (options) => {
5194
- const parentOpts = logsCommand.parent?.opts() ?? {};
5195
- const jsonFlag = options.json || parentOpts.json || false;
5249
+ const jsonFlag = Boolean(
5250
+ options.json || logsCommand.optsWithGlobals().json
5251
+ );
5196
5252
  const fmt = createFormatter({
5197
5253
  json: jsonFlag,
5198
5254
  quiet: false,
@@ -5206,7 +5262,7 @@ var logsCommand = new Command("logs").description("Tail MCP connection log with
5206
5262
  const result = await client.mcpCall("integration_sync_logs", {
5207
5263
  limit: lineCount
5208
5264
  });
5209
- const data = extractMcpContent3(result);
5265
+ const data = result;
5210
5266
  if (jsonFlag) {
5211
5267
  fmt.table(Array.isArray(data) ? data : [], [
5212
5268
  { key: "timestamp", header: "Timestamp" },
@@ -5272,7 +5328,7 @@ async function checkJsonRpc(client, verbose, c) {
5272
5328
  if (verbose) process.stdout.write(`${c.dim("\u2192")} JSON-RPC handshake... `);
5273
5329
  try {
5274
5330
  const result = await client.mcpCall("mcp_capabilities", {});
5275
- const data = extractMcpContent3(result);
5331
+ const data = result;
5276
5332
  let toolCount = "ok";
5277
5333
  if (typeof data === "object" && data !== null) {
5278
5334
  const record = data;
@@ -5294,8 +5350,9 @@ async function checkJsonRpc(client, verbose, c) {
5294
5350
  var testCommand = new Command("test").description(
5295
5351
  "Perform full MCP handshake diagnostic (DNS, edge ping, JSON-RPC)"
5296
5352
  ).option("--json", "Output as JSON").action(async (options) => {
5297
- const parentOpts = testCommand.parent?.opts() ?? {};
5298
- const jsonFlag = options.json || parentOpts.json || false;
5353
+ const jsonFlag = Boolean(
5354
+ options.json || testCommand.optsWithGlobals().json
5355
+ );
5299
5356
  const fmt = createFormatter({
5300
5357
  json: jsonFlag,
5301
5358
  quiet: false,
@@ -5384,13 +5441,13 @@ var mcp_default = mcpCommand;
5384
5441
  // src/commands/deploy.ts
5385
5442
  var DEPLOY_TIMEOUT_MS = 9e4;
5386
5443
  function deployCommand() {
5387
- const cmd = new Command("deploy").description("Trigger a production deployment").option("--confirm", "Skip interactive confirmation (required in CI)").option("--json", "Output as JSON").option("--quiet", "Suppress decorative output").option("--no-color", "Disable color output").action(async (options) => {
5388
- const noColor = options.color === false;
5444
+ const cmd = new Command("deploy").description("Trigger a production deployment").option("--confirm", "Skip interactive confirmation (required in CI)").option("--json", "Output as JSON").option("--quiet", "Suppress decorative output").option("--no-color", "Disable color output").action(async (options, command) => {
5445
+ const g = globalOutputOpts(command);
5389
5446
  const fmt = createFormatter({
5390
- json: options.json ?? false,
5391
- quiet: options.quiet ?? false,
5447
+ json: g.json,
5448
+ quiet: g.quiet,
5392
5449
  isTTY: isTTY(),
5393
- noColor
5450
+ noColor: g.noColor
5394
5451
  });
5395
5452
  if (!options.confirm) {
5396
5453
  if (!isTTY()) {
@@ -5418,7 +5475,7 @@ function deployCommand() {
5418
5475
  fmt.info("Deploying to production...");
5419
5476
  }
5420
5477
  const result = await client.mcpCall("deploy_to_vercel", {});
5421
- if (options.json) {
5478
+ if (g.json) {
5422
5479
  process.stdout.write(JSON.stringify(result) + "\n");
5423
5480
  return;
5424
5481
  }
@@ -5478,11 +5535,12 @@ function displayResults(result, fmt) {
5478
5535
  ]);
5479
5536
  }
5480
5537
  }
5481
- var migrateCommand = new Command("migrate").description("Run pending database migrations").option("--confirm", "Skip confirmation prompt (required in non-TTY)").option("--json", "Output results as JSON").option("--quiet", "Suppress decorative output").action(async (opts) => {
5538
+ var migrateCommand = new Command("migrate").description("Run pending database migrations").option("--confirm", "Skip confirmation prompt (required in non-TTY)").option("--json", "Output results as JSON").option("--quiet", "Suppress decorative output").action(async (opts, command) => {
5539
+ const g = globalOutputOpts(command);
5482
5540
  const tty = isTTY();
5483
5541
  const fmt = createFormatter({
5484
- json: Boolean(opts.json),
5485
- quiet: Boolean(opts.quiet),
5542
+ json: g.json,
5543
+ quiet: g.quiet,
5486
5544
  isTTY: tty,
5487
5545
  noColor: !tty
5488
5546
  });
@@ -5494,7 +5552,7 @@ var migrateCommand = new Command("migrate").description("Run pending database mi
5494
5552
  const client = new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
5495
5553
  fmt.info("Running pending migrations\u2026");
5496
5554
  const result = await client.mcpCall("apply_migration", {});
5497
- if (opts.json) {
5555
+ if (g.json) {
5498
5556
  const applied = result?.applied ?? 0;
5499
5557
  const status = result?.status ?? "complete";
5500
5558
  fmt.table(
@@ -5584,17 +5642,17 @@ function outputJsonSummary(results, totalDurationMs) {
5584
5642
  process.stdout.write(JSON.stringify(output) + "\n");
5585
5643
  }
5586
5644
  function smokeCommand() {
5587
- const cmd = new Command("smoke").description("Run MCP smoke tests to verify platform connectivity").option("--json", "Output as JSON").option("--quiet", "Suppress decorative output").option("--no-color", "Disable color output").action(async (options) => {
5588
- const noColor = options.color === false;
5589
- const color2 = createColor(noColor);
5645
+ const cmd = new Command("smoke").description("Run MCP smoke tests to verify platform connectivity").option("--json", "Output as JSON").option("--quiet", "Suppress decorative output").option("--no-color", "Disable color output").action(async (options, command) => {
5646
+ const g = globalOutputOpts(command);
5647
+ const color2 = createColor(g.noColor);
5590
5648
  const fmt = createFormatter({
5591
- json: options.json ?? false,
5592
- quiet: options.quiet ?? false,
5649
+ json: g.json,
5650
+ quiet: g.quiet,
5593
5651
  isTTY: isTTY(),
5594
- noColor
5652
+ noColor: g.noColor
5595
5653
  });
5596
- const isJson = options.json ?? false;
5597
- const isQuiet = options.quiet ?? false;
5654
+ const isJson = g.json;
5655
+ const isQuiet = g.quiet;
5598
5656
  const auth = await resolveAuth();
5599
5657
  const client = new GadClient({
5600
5658
  token: auth.token,
@@ -5650,7 +5708,8 @@ async function buildClient2() {
5650
5708
  var agentCommand = new Command("agent").description(
5651
5709
  "List and invoke AI agents"
5652
5710
  );
5653
- agentCommand.command("list").description("Display available specialist and custom agents").option("--json", "Output as JSON").action(async (opts) => {
5711
+ agentCommand.command("list").description("Display available specialist and custom agents").option("--json", "Output as JSON").action(async (opts, command) => {
5712
+ const g = globalOutputOpts(command);
5654
5713
  const client = await buildClient2();
5655
5714
  const result = await client.mcpCall("agent_list", {});
5656
5715
  let agents;
@@ -5661,14 +5720,15 @@ agentCommand.command("list").description("Display available specialist and custo
5661
5720
  agents = data?.agents ?? data?.results ?? [];
5662
5721
  }
5663
5722
  const fmt = createFormatter({
5664
- json: Boolean(opts.json),
5723
+ json: g.json,
5665
5724
  quiet: false,
5666
5725
  isTTY: isTTY(),
5667
5726
  noColor: false
5668
5727
  });
5669
5728
  fmt.table(agents, agentListColumns);
5670
5729
  });
5671
- agentCommand.command("invoke <agent-id>").description("Execute an agent with a task").requiredOption("--task <task>", "Task description for the agent").option("--json", "Output raw agent response as JSON").option("--context <context>", "Additional context for the agent").action(async (agentId, opts) => {
5730
+ agentCommand.command("invoke <agent-id>").description("Execute an agent with a task").requiredOption("--task <task>", "Task description for the agent").option("--json", "Output raw agent response as JSON").option("--context <context>", "Additional context for the agent").action(async (agentId, opts, command) => {
5731
+ const g = globalOutputOpts(command);
5672
5732
  const client = await buildClient2();
5673
5733
  const args = {
5674
5734
  agentId,
@@ -5678,7 +5738,7 @@ agentCommand.command("invoke <agent-id>").description("Execute an agent with a t
5678
5738
  args.context = opts.context;
5679
5739
  }
5680
5740
  const result = await client.mcpCall("agent_invoke", args, AGENT_TIMEOUT_MS);
5681
- if (opts.json) {
5741
+ if (g.json) {
5682
5742
  const output = typeof result === "string" ? result : JSON.stringify(result, null, 2);
5683
5743
  process.stdout.write(output + "\n");
5684
5744
  return;
@@ -5714,15 +5774,16 @@ function extractAnswer(data) {
5714
5774
  return result.answer || result.text || result.result || result.content || "";
5715
5775
  }
5716
5776
  function askCommand() {
5717
- const cmd = new Command("ask").description("Ask the orchestrator a question").argument("<question>", "The question to ask").option("--json", "Output raw response as JSON").option("--quiet", "Suppress decorative output").option("--no-color", "Disable color output").action(async (question, options) => {
5777
+ const cmd = new Command("ask").description("Ask the orchestrator a question").argument("<question>", "The question to ask").option("--json", "Output raw response as JSON").option("--quiet", "Suppress decorative output").option("--no-color", "Disable color output").action(async (question, options, command) => {
5778
+ const g = globalOutputOpts(command);
5718
5779
  const auth = await resolveAuth();
5719
5780
  const client = new GadClient({
5720
5781
  token: auth.token,
5721
5782
  apiUrl: auth.apiUrl
5722
5783
  });
5723
5784
  const fmt = createFormatter({
5724
- json: options.json ?? false,
5725
- quiet: options.quiet ?? false,
5785
+ json: g.json,
5786
+ quiet: g.quiet,
5726
5787
  isTTY: isTTY(),
5727
5788
  noColor: options.color === false
5728
5789
  });
@@ -5731,7 +5792,7 @@ function askCommand() {
5731
5792
  { query: question },
5732
5793
  ORCHESTRATOR_TIMEOUT_MS
5733
5794
  );
5734
- if (options.json) {
5795
+ if (g.json) {
5735
5796
  process.stdout.write(JSON.stringify(result) + "\n");
5736
5797
  return;
5737
5798
  }
@@ -5996,7 +6057,7 @@ if (nodeVersion < 20) {
5996
6057
  console.error(" Upgrade Node.js: https://nodejs.org/");
5997
6058
  process.exit(1);
5998
6059
  }
5999
- var VERSION = "0.1.1";
6060
+ var VERSION = "0.1.3";
6000
6061
  var program2 = new Command().name("gad").description("Great Arrow Digital CLI \u2014 terminal access to the GAD platform").version(VERSION, "-v, --version").option("--json", "Output as JSON").option("--quiet", "Suppress decorative output").option("--no-color", "Disable color output");
6001
6062
  program2.addCommand(login_default);
6002
6063
  program2.addCommand(logoutCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@great-arrow/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Great Arrow Digital CLI tool",
5
5
  "type": "module",
6
6
  "bin": {