@great-arrow/cli 0.1.2 → 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 +195 -140
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -14,11 +14,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
14
14
  throw Error('Dynamic require of "' + x + '" is not supported');
15
15
  });
16
16
  var __commonJS = (cb, mod) => function __require2() {
17
- try {
18
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
19
- } catch (e) {
20
- throw mod = 0, e;
21
- }
17
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
22
18
  };
23
19
  var __copyProps = (to, from, except, desc) => {
24
20
  if (from && typeof from === "object" || typeof from === "function") {
@@ -37,9 +33,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
37
33
  mod
38
34
  ));
39
35
 
40
- // node_modules/commander/lib/error.js
36
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/error.js
41
37
  var require_error = __commonJS({
42
- "node_modules/commander/lib/error.js"(exports) {
38
+ "node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/error.js"(exports) {
43
39
  var CommanderError2 = class extends Error {
44
40
  /**
45
41
  * Constructs the CommanderError class
@@ -72,9 +68,9 @@ var require_error = __commonJS({
72
68
  }
73
69
  });
74
70
 
75
- // node_modules/commander/lib/argument.js
71
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/argument.js
76
72
  var require_argument = __commonJS({
77
- "node_modules/commander/lib/argument.js"(exports) {
73
+ "node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/argument.js"(exports) {
78
74
  var { InvalidArgumentError: InvalidArgumentError2 } = require_error();
79
75
  var Argument2 = class {
80
76
  /**
@@ -199,9 +195,9 @@ var require_argument = __commonJS({
199
195
  }
200
196
  });
201
197
 
202
- // node_modules/commander/lib/help.js
198
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/help.js
203
199
  var require_help = __commonJS({
204
- "node_modules/commander/lib/help.js"(exports) {
200
+ "node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/help.js"(exports) {
205
201
  var { humanReadableArgName } = require_argument();
206
202
  var Help2 = class {
207
203
  constructor() {
@@ -768,9 +764,9 @@ ${itemIndentStr}`);
768
764
  }
769
765
  });
770
766
 
771
- // node_modules/commander/lib/option.js
767
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/option.js
772
768
  var require_option = __commonJS({
773
- "node_modules/commander/lib/option.js"(exports) {
769
+ "node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/option.js"(exports) {
774
770
  var { InvalidArgumentError: InvalidArgumentError2 } = require_error();
775
771
  var Option2 = class {
776
772
  /**
@@ -1069,9 +1065,9 @@ var require_option = __commonJS({
1069
1065
  }
1070
1066
  });
1071
1067
 
1072
- // node_modules/commander/lib/suggestSimilar.js
1068
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/suggestSimilar.js
1073
1069
  var require_suggestSimilar = __commonJS({
1074
- "node_modules/commander/lib/suggestSimilar.js"(exports) {
1070
+ "node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/suggestSimilar.js"(exports) {
1075
1071
  var maxDistance = 3;
1076
1072
  function editDistance(a, b) {
1077
1073
  if (Math.abs(a.length - b.length) > maxDistance)
@@ -1149,9 +1145,9 @@ var require_suggestSimilar = __commonJS({
1149
1145
  }
1150
1146
  });
1151
1147
 
1152
- // node_modules/commander/lib/command.js
1148
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/command.js
1153
1149
  var require_command = __commonJS({
1154
- "node_modules/commander/lib/command.js"(exports) {
1150
+ "node_modules/.pnpm/commander@13.1.0/node_modules/commander/lib/command.js"(exports) {
1155
1151
  var EventEmitter = __require("node:events").EventEmitter;
1156
1152
  var childProcess = __require("node:child_process");
1157
1153
  var path = __require("node:path");
@@ -3308,9 +3304,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3308
3304
  }
3309
3305
  });
3310
3306
 
3311
- // node_modules/commander/index.js
3307
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/index.js
3312
3308
  var require_commander = __commonJS({
3313
- "node_modules/commander/index.js"(exports) {
3309
+ "node_modules/.pnpm/commander@13.1.0/node_modules/commander/index.js"(exports) {
3314
3310
  var { Argument: Argument2 } = require_argument();
3315
3311
  var { Command: Command2 } = require_command();
3316
3312
  var { CommanderError: CommanderError2, InvalidArgumentError: InvalidArgumentError2 } = require_error();
@@ -3330,7 +3326,7 @@ var require_commander = __commonJS({
3330
3326
  }
3331
3327
  });
3332
3328
 
3333
- // node_modules/commander/esm.mjs
3329
+ // node_modules/.pnpm/commander@13.1.0/node_modules/commander/esm.mjs
3334
3330
  var import_index = __toESM(require_commander(), 1);
3335
3331
  var {
3336
3332
  program,
@@ -3862,6 +3858,61 @@ async function resolveToken(configToken) {
3862
3858
 
3863
3859
  // src/lib/client.ts
3864
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
3865
3916
  var DEFAULT_TIMEOUT_MS = 3e4;
3866
3917
  var MAX_RETRIES = 3;
3867
3918
  var BASE_DELAY_MS = 1e3;
@@ -3995,7 +4046,7 @@ var GadClient = class {
3995
4046
  * @param toolName - The MCP tool name to invoke
3996
4047
  * @param args - Arguments to pass to the tool
3997
4048
  * @param timeoutMs - Optional timeout override (e.g., 90s for agent calls)
3998
- * @returns The tool result content
4049
+ * @returns The decoded JSON payload from the tool result content
3999
4050
  */
4000
4051
  async mcpCall(toolName, args, timeoutMs) {
4001
4052
  const url = `${this.apiUrl}/api/mcp`;
@@ -4035,7 +4086,15 @@ var GadClient = class {
4035
4086
  data.error.data ?? void 0
4036
4087
  );
4037
4088
  }
4038
- 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;
4039
4098
  }
4040
4099
  /**
4041
4100
  * Make a GET request to a REST API endpoint.
@@ -4094,6 +4153,18 @@ var GadClient = class {
4094
4153
  }
4095
4154
  };
4096
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
+
4097
4168
  // src/commands/whoami.ts
4098
4169
  function maskToken2(token) {
4099
4170
  if (token.length <= 8) {
@@ -4108,7 +4179,8 @@ function extractWorkspaceName(data) {
4108
4179
  return data.workspace?.name || data.workspaceName || "unknown";
4109
4180
  }
4110
4181
  function whoamiCommand() {
4111
- 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);
4112
4184
  const auth = await resolveAuth();
4113
4185
  const client = new GadClient({
4114
4186
  token: auth.token,
@@ -4131,10 +4203,10 @@ function whoamiCommand() {
4131
4203
  const workspaceName = extractWorkspaceName(introspect);
4132
4204
  const tokenPrefix = maskToken2(auth.token);
4133
4205
  const fmt = createFormatter({
4134
- json: options.json ?? false,
4135
- quiet: options.quiet ?? false,
4206
+ json: g.json,
4207
+ quiet: g.quiet,
4136
4208
  isTTY: isTTY(),
4137
- noColor: options.color === false
4209
+ noColor: g.noColor
4138
4210
  });
4139
4211
  const data = {
4140
4212
  email,
@@ -4225,7 +4297,7 @@ var memoryCommand = new Command("memory").description(
4225
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(
4226
4298
  "--layer <layer>",
4227
4299
  "Memory layer (WORKING, EPISODIC, SEMANTIC, PROCEDURAL)"
4228
- ).action(async (opts) => {
4300
+ ).action(async (opts, command) => {
4229
4301
  const client = await buildClient();
4230
4302
  let content = opts.content;
4231
4303
  if (!content) {
@@ -4262,7 +4334,8 @@ memoryCommand.command("create").description("Create a new memory in the active w
4262
4334
  const memoryId = typeof rawId === "string" ? rawId : "created";
4263
4335
  fmt.success(`Memory created: ${memoryId}`);
4264
4336
  });
4265
- 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);
4266
4339
  const client = await buildClient();
4267
4340
  const args = {
4268
4341
  query,
@@ -4272,22 +4345,27 @@ memoryCommand.command("search <query>").description("Semantic search across memo
4272
4345
  args.layer = opts.layer;
4273
4346
  }
4274
4347
  const result = await client.mcpCall("memory_search", args);
4275
- const rawResults = Array.isArray(result) ? result : result?.results ?? [];
4348
+ const data = result ?? {};
4349
+ const rawResults = Array.isArray(result) ? result : data.hits ?? data.results ?? [];
4276
4350
  const rows = rawResults.map((item) => ({
4277
4351
  ...item,
4352
+ title: item.title ?? item.memoryTitle,
4278
4353
  preview: extractPreview(item)
4279
4354
  }));
4280
4355
  const fmt = createFormatter({
4281
- json: Boolean(opts.json),
4356
+ json: g.json,
4282
4357
  quiet: false,
4283
4358
  isTTY: isTTY(),
4284
4359
  noColor: false
4285
4360
  });
4286
4361
  fmt.table(rows, searchColumns);
4287
4362
  });
4288
- 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);
4289
4365
  const client = await buildClient();
4290
- const args = {};
4366
+ const args = {
4367
+ limit: Number.parseInt(opts.limit, 10)
4368
+ };
4291
4369
  if (opts.layer) {
4292
4370
  args.layer = opts.layer;
4293
4371
  }
@@ -4295,21 +4373,23 @@ memoryCommand.command("list").description("List recent memories with optional fi
4295
4373
  args.tag = opts.tag;
4296
4374
  }
4297
4375
  const result = await client.mcpCall("memory_list", args);
4298
- const rawResults = Array.isArray(result) ? result : result?.results ?? [];
4376
+ const data = result ?? {};
4377
+ const rawResults = Array.isArray(result) ? result : data.memories ?? data.results ?? [];
4299
4378
  const fmt = createFormatter({
4300
- json: Boolean(opts.json),
4379
+ json: g.json,
4301
4380
  quiet: false,
4302
4381
  isTTY: isTTY(),
4303
4382
  noColor: false
4304
4383
  });
4305
4384
  fmt.table(rawResults, listColumns);
4306
4385
  });
4307
- 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);
4308
4388
  const client = await buildClient();
4309
4389
  const result = await client.mcpCall("memory_get", { id });
4310
4390
  const data = result ?? {};
4311
4391
  const fmt = createFormatter({
4312
- json: Boolean(opts.json),
4392
+ json: g.json,
4313
4393
  quiet: false,
4314
4394
  isTTY: isTTY(),
4315
4395
  noColor: false
@@ -4380,22 +4460,10 @@ async function createClient() {
4380
4460
  const auth = await resolveAuth();
4381
4461
  return new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
4382
4462
  }
4383
- function extractMcpContent(result) {
4384
- if (Array.isArray(result) && result.length > 0) {
4385
- const first = result[0];
4386
- if (typeof first === "object" && first !== null && "type" in first && first.type === "text" && "text" in first) {
4387
- try {
4388
- return JSON.parse(first.text);
4389
- } catch {
4390
- return first.text;
4391
- }
4392
- }
4393
- }
4394
- return result;
4395
- }
4396
4463
  var listCommand = new Command("list").description("List all accessible workspaces").option("--json", "Output as JSON").action(async (options) => {
4397
- const parentOpts = listCommand.parent?.opts() ?? {};
4398
- const jsonFlag = options.json || parentOpts.json || false;
4464
+ const jsonFlag = Boolean(
4465
+ options.json || listCommand.optsWithGlobals().json
4466
+ );
4399
4467
  const fmt = createFormatter({
4400
4468
  json: jsonFlag,
4401
4469
  quiet: false,
@@ -4404,7 +4472,7 @@ var listCommand = new Command("list").description("List all accessible workspace
4404
4472
  });
4405
4473
  const client = await createClient();
4406
4474
  const result = await client.mcpCall("workspace_list", {});
4407
- const data = extractMcpContent(result);
4475
+ const data = result;
4408
4476
  let workspaces = [];
4409
4477
  if (Array.isArray(data)) {
4410
4478
  workspaces = data;
@@ -4466,8 +4534,9 @@ var infoColumns = [
4466
4534
  }
4467
4535
  ];
4468
4536
  var infoCommand = new Command("info").description("Show active workspace settings, member count, and integrations").option("--json", "Output as JSON").action(async (options) => {
4469
- const parentOpts = infoCommand.parent?.opts() ?? {};
4470
- const jsonFlag = options.json || parentOpts.json || false;
4537
+ const jsonFlag = Boolean(
4538
+ options.json || infoCommand.optsWithGlobals().json
4539
+ );
4471
4540
  const fmt = createFormatter({
4472
4541
  json: jsonFlag,
4473
4542
  quiet: false,
@@ -4476,13 +4545,14 @@ var infoCommand = new Command("info").description("Show active workspace setting
4476
4545
  });
4477
4546
  const client = await createClient();
4478
4547
  const result = await client.mcpCall("workspace_settings_get", {});
4479
- const data = extractMcpContent(result);
4548
+ const data = result;
4480
4549
  const workspace = typeof data === "object" && data !== null ? data : {};
4481
4550
  fmt.detail(workspace, infoColumns);
4482
4551
  });
4483
4552
  var membersCommand = new Command("members").description("List workspace members with roles and last-active timestamps").option("--json", "Output as JSON").action(async (options) => {
4484
- const parentOpts = membersCommand.parent?.opts() ?? {};
4485
- const jsonFlag = options.json || parentOpts.json || false;
4553
+ const jsonFlag = Boolean(
4554
+ options.json || membersCommand.optsWithGlobals().json
4555
+ );
4486
4556
  const fmt = createFormatter({
4487
4557
  json: jsonFlag,
4488
4558
  quiet: false,
@@ -4491,7 +4561,7 @@ var membersCommand = new Command("members").description("List workspace members
4491
4561
  });
4492
4562
  const client = await createClient();
4493
4563
  const result = await client.mcpCall("workspace_members", {});
4494
- const data = extractMcpContent(result);
4564
+ const data = result;
4495
4565
  let members = [];
4496
4566
  if (Array.isArray(data)) {
4497
4567
  members = data;
@@ -4544,7 +4614,7 @@ var listCommand2 = new Command("list").description("List open todos sorted by pr
4544
4614
  "Filter by status (open, in_progress, review, done, dismissed)"
4545
4615
  ).option("--json", "Output as JSON").action(
4546
4616
  async (options, cmd) => {
4547
- const parentOpts = cmd.parent?.opts() ?? {};
4617
+ const parentOpts = cmd.optsWithGlobals();
4548
4618
  const jsonOutput = options.json || parentOpts.json || false;
4549
4619
  const fmt = createFormatter({
4550
4620
  json: jsonOutput,
@@ -4554,10 +4624,9 @@ var listCommand2 = new Command("list").description("List open todos sorted by pr
4554
4624
  });
4555
4625
  const auth = await resolveAuth();
4556
4626
  const client = new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
4557
- const args = {};
4558
- if (options.status) {
4559
- args.status = options.status;
4560
- }
4627
+ const args = {
4628
+ status: options.status ?? "open"
4629
+ };
4561
4630
  const result = await client.mcpCall("todo_list", args);
4562
4631
  let todos = [];
4563
4632
  if (Array.isArray(result)) {
@@ -4717,8 +4786,12 @@ async function checkIntegrations(auth) {
4717
4786
  const client = new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
4718
4787
  try {
4719
4788
  const result = await client.mcpCall("integrations_list", {});
4720
- const integrations = Array.isArray(result) ? result : [];
4721
- 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
+ });
4722
4795
  if (errorIntegrations.length === 0) {
4723
4796
  return {
4724
4797
  name: "Integrations",
@@ -4730,7 +4803,7 @@ async function checkIntegrations(auth) {
4730
4803
  return {
4731
4804
  name: "Integrations",
4732
4805
  status: "warn",
4733
- message: `${errorIntegrations.length} integration(s) with errors: ${kinds}`,
4806
+ message: `${errorIntegrations.length} of ${integrations.length} integration(s) need attention: ${kinds}`,
4734
4807
  hint: "Run 'gad integrations list' for details, or 'gad integrations sync <kind>' to retry."
4735
4808
  };
4736
4809
  } catch {
@@ -4769,17 +4842,17 @@ async function checkMcp(auth) {
4769
4842
  }
4770
4843
  }
4771
4844
  function doctorCommand() {
4772
- 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) => {
4773
- const noColor = options.color === false;
4774
- 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);
4775
4848
  const fmt = createFormatter({
4776
- json: options.json ?? false,
4777
- quiet: options.quiet ?? false,
4849
+ json: g.json,
4850
+ quiet: g.quiet,
4778
4851
  isTTY: isTTY(),
4779
- noColor
4852
+ noColor: g.noColor
4780
4853
  });
4781
4854
  const checks = [];
4782
- const isJson = options.json ?? false;
4855
+ const isJson = g.json;
4783
4856
  const { check: tokenCheck, auth } = await checkToken();
4784
4857
  checks.push(tokenCheck);
4785
4858
  if (!isJson) {
@@ -4802,7 +4875,7 @@ function doctorCommand() {
4802
4875
  }
4803
4876
  if (isJson) {
4804
4877
  process.stdout.write(JSON.stringify(checks) + "\n");
4805
- } else if (!options.quiet) {
4878
+ } else if (!g.quiet) {
4806
4879
  const passed = checks.filter((c) => c.status === "pass").length;
4807
4880
  const warned = checks.filter((c) => c.status === "warn").length;
4808
4881
  const failed = checks.filter((c) => c.status === "fail").length;
@@ -4865,19 +4938,6 @@ async function createClient2() {
4865
4938
  const auth = await resolveAuth();
4866
4939
  return new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
4867
4940
  }
4868
- function extractMcpContent2(result) {
4869
- if (Array.isArray(result) && result.length > 0) {
4870
- const first = result[0];
4871
- if (typeof first === "object" && first !== null && "type" in first && first.type === "text" && "text" in first) {
4872
- try {
4873
- return JSON.parse(first.text);
4874
- } catch {
4875
- return first.text;
4876
- }
4877
- }
4878
- }
4879
- return result;
4880
- }
4881
4941
  function formatErrorDetail(rawError) {
4882
4942
  if (rawError === null || rawError === void 0) return null;
4883
4943
  if (typeof rawError === "string") return rawError;
@@ -4927,8 +4987,9 @@ function handleSyncResponse(fmt, kind, response) {
4927
4987
  }
4928
4988
  }
4929
4989
  var listCommand3 = new Command("list").description("List all connected integrations with sync status").option("--json", "Output as JSON").action(async (options) => {
4930
- const parentOpts = listCommand3.parent?.opts() ?? {};
4931
- const jsonFlag = options.json || parentOpts.json || false;
4990
+ const jsonFlag = Boolean(
4991
+ options.json || listCommand3.optsWithGlobals().json
4992
+ );
4932
4993
  const fmt = createFormatter({
4933
4994
  json: jsonFlag,
4934
4995
  quiet: false,
@@ -4937,7 +4998,7 @@ var listCommand3 = new Command("list").description("List all connected integrati
4937
4998
  });
4938
4999
  const client = await createClient2();
4939
5000
  const result = await client.mcpCall("integrations_list", {});
4940
- const data = extractMcpContent2(result);
5001
+ const data = result;
4941
5002
  let integrations = [];
4942
5003
  if (Array.isArray(data)) {
4943
5004
  integrations = data;
@@ -4964,7 +5025,7 @@ var syncCommand = new Command("sync").description("Trigger a manual sync for the
4964
5025
  fmt.info(`Triggering sync for "${kind}"...`);
4965
5026
  try {
4966
5027
  const result = await client.mcpCall("integration_sync", { kind });
4967
- const data = extractMcpContent2(result);
5028
+ const data = result;
4968
5029
  if (typeof data === "object" && data !== null) {
4969
5030
  handleSyncResponse(fmt, kind, data);
4970
5031
  } else {
@@ -5009,19 +5070,6 @@ async function createClient3() {
5009
5070
  const client = new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
5010
5071
  return { client, apiUrl: auth.apiUrl };
5011
5072
  }
5012
- function extractMcpContent3(result) {
5013
- if (Array.isArray(result) && result.length > 0) {
5014
- const first = result[0];
5015
- if (typeof first === "object" && first !== null && "type" in first && first.type === "text" && "text" in first) {
5016
- try {
5017
- return JSON.parse(first.text);
5018
- } catch {
5019
- return first.text;
5020
- }
5021
- }
5022
- }
5023
- return result;
5024
- }
5025
5073
  function generateMcpConfig(client, apiUrl, token) {
5026
5074
  const endpoint = mcpEndpoint(apiUrl);
5027
5075
  if (client === "codex") {
@@ -5141,8 +5189,9 @@ var statusColumns = [
5141
5189
  var statusCommand = new Command("status").description(
5142
5190
  "Show MCP server connection status, proxy version, and session count"
5143
5191
  ).option("--json", "Output as JSON").action(async (options) => {
5144
- const parentOpts = statusCommand.parent?.opts() ?? {};
5145
- const jsonFlag = options.json || parentOpts.json || false;
5192
+ const jsonFlag = Boolean(
5193
+ options.json || statusCommand.optsWithGlobals().json
5194
+ );
5146
5195
  const fmt = createFormatter({
5147
5196
  json: jsonFlag,
5148
5197
  quiet: false,
@@ -5158,7 +5207,7 @@ var statusCommand = new Command("status").description(
5158
5207
  };
5159
5208
  try {
5160
5209
  const result = await client.mcpCall("workspace_introspect", {});
5161
- const data = extractMcpContent3(result);
5210
+ const data = result;
5162
5211
  if (typeof data === "object" && data !== null) {
5163
5212
  const info = data;
5164
5213
  statusData = {
@@ -5197,8 +5246,9 @@ function renderLogEntry(entry, c) {
5197
5246
  `);
5198
5247
  }
5199
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) => {
5200
- const parentOpts = logsCommand.parent?.opts() ?? {};
5201
- const jsonFlag = options.json || parentOpts.json || false;
5249
+ const jsonFlag = Boolean(
5250
+ options.json || logsCommand.optsWithGlobals().json
5251
+ );
5202
5252
  const fmt = createFormatter({
5203
5253
  json: jsonFlag,
5204
5254
  quiet: false,
@@ -5212,7 +5262,7 @@ var logsCommand = new Command("logs").description("Tail MCP connection log with
5212
5262
  const result = await client.mcpCall("integration_sync_logs", {
5213
5263
  limit: lineCount
5214
5264
  });
5215
- const data = extractMcpContent3(result);
5265
+ const data = result;
5216
5266
  if (jsonFlag) {
5217
5267
  fmt.table(Array.isArray(data) ? data : [], [
5218
5268
  { key: "timestamp", header: "Timestamp" },
@@ -5278,7 +5328,7 @@ async function checkJsonRpc(client, verbose, c) {
5278
5328
  if (verbose) process.stdout.write(`${c.dim("\u2192")} JSON-RPC handshake... `);
5279
5329
  try {
5280
5330
  const result = await client.mcpCall("mcp_capabilities", {});
5281
- const data = extractMcpContent3(result);
5331
+ const data = result;
5282
5332
  let toolCount = "ok";
5283
5333
  if (typeof data === "object" && data !== null) {
5284
5334
  const record = data;
@@ -5300,8 +5350,9 @@ async function checkJsonRpc(client, verbose, c) {
5300
5350
  var testCommand = new Command("test").description(
5301
5351
  "Perform full MCP handshake diagnostic (DNS, edge ping, JSON-RPC)"
5302
5352
  ).option("--json", "Output as JSON").action(async (options) => {
5303
- const parentOpts = testCommand.parent?.opts() ?? {};
5304
- const jsonFlag = options.json || parentOpts.json || false;
5353
+ const jsonFlag = Boolean(
5354
+ options.json || testCommand.optsWithGlobals().json
5355
+ );
5305
5356
  const fmt = createFormatter({
5306
5357
  json: jsonFlag,
5307
5358
  quiet: false,
@@ -5390,13 +5441,13 @@ var mcp_default = mcpCommand;
5390
5441
  // src/commands/deploy.ts
5391
5442
  var DEPLOY_TIMEOUT_MS = 9e4;
5392
5443
  function deployCommand() {
5393
- 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) => {
5394
- 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);
5395
5446
  const fmt = createFormatter({
5396
- json: options.json ?? false,
5397
- quiet: options.quiet ?? false,
5447
+ json: g.json,
5448
+ quiet: g.quiet,
5398
5449
  isTTY: isTTY(),
5399
- noColor
5450
+ noColor: g.noColor
5400
5451
  });
5401
5452
  if (!options.confirm) {
5402
5453
  if (!isTTY()) {
@@ -5424,7 +5475,7 @@ function deployCommand() {
5424
5475
  fmt.info("Deploying to production...");
5425
5476
  }
5426
5477
  const result = await client.mcpCall("deploy_to_vercel", {});
5427
- if (options.json) {
5478
+ if (g.json) {
5428
5479
  process.stdout.write(JSON.stringify(result) + "\n");
5429
5480
  return;
5430
5481
  }
@@ -5484,11 +5535,12 @@ function displayResults(result, fmt) {
5484
5535
  ]);
5485
5536
  }
5486
5537
  }
5487
- 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);
5488
5540
  const tty = isTTY();
5489
5541
  const fmt = createFormatter({
5490
- json: Boolean(opts.json),
5491
- quiet: Boolean(opts.quiet),
5542
+ json: g.json,
5543
+ quiet: g.quiet,
5492
5544
  isTTY: tty,
5493
5545
  noColor: !tty
5494
5546
  });
@@ -5500,7 +5552,7 @@ var migrateCommand = new Command("migrate").description("Run pending database mi
5500
5552
  const client = new GadClient({ token: auth.token, apiUrl: auth.apiUrl });
5501
5553
  fmt.info("Running pending migrations\u2026");
5502
5554
  const result = await client.mcpCall("apply_migration", {});
5503
- if (opts.json) {
5555
+ if (g.json) {
5504
5556
  const applied = result?.applied ?? 0;
5505
5557
  const status = result?.status ?? "complete";
5506
5558
  fmt.table(
@@ -5590,17 +5642,17 @@ function outputJsonSummary(results, totalDurationMs) {
5590
5642
  process.stdout.write(JSON.stringify(output) + "\n");
5591
5643
  }
5592
5644
  function smokeCommand() {
5593
- 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) => {
5594
- const noColor = options.color === false;
5595
- 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);
5596
5648
  const fmt = createFormatter({
5597
- json: options.json ?? false,
5598
- quiet: options.quiet ?? false,
5649
+ json: g.json,
5650
+ quiet: g.quiet,
5599
5651
  isTTY: isTTY(),
5600
- noColor
5652
+ noColor: g.noColor
5601
5653
  });
5602
- const isJson = options.json ?? false;
5603
- const isQuiet = options.quiet ?? false;
5654
+ const isJson = g.json;
5655
+ const isQuiet = g.quiet;
5604
5656
  const auth = await resolveAuth();
5605
5657
  const client = new GadClient({
5606
5658
  token: auth.token,
@@ -5656,7 +5708,8 @@ async function buildClient2() {
5656
5708
  var agentCommand = new Command("agent").description(
5657
5709
  "List and invoke AI agents"
5658
5710
  );
5659
- 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);
5660
5713
  const client = await buildClient2();
5661
5714
  const result = await client.mcpCall("agent_list", {});
5662
5715
  let agents;
@@ -5667,14 +5720,15 @@ agentCommand.command("list").description("Display available specialist and custo
5667
5720
  agents = data?.agents ?? data?.results ?? [];
5668
5721
  }
5669
5722
  const fmt = createFormatter({
5670
- json: Boolean(opts.json),
5723
+ json: g.json,
5671
5724
  quiet: false,
5672
5725
  isTTY: isTTY(),
5673
5726
  noColor: false
5674
5727
  });
5675
5728
  fmt.table(agents, agentListColumns);
5676
5729
  });
5677
- 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);
5678
5732
  const client = await buildClient2();
5679
5733
  const args = {
5680
5734
  agentId,
@@ -5684,7 +5738,7 @@ agentCommand.command("invoke <agent-id>").description("Execute an agent with a t
5684
5738
  args.context = opts.context;
5685
5739
  }
5686
5740
  const result = await client.mcpCall("agent_invoke", args, AGENT_TIMEOUT_MS);
5687
- if (opts.json) {
5741
+ if (g.json) {
5688
5742
  const output = typeof result === "string" ? result : JSON.stringify(result, null, 2);
5689
5743
  process.stdout.write(output + "\n");
5690
5744
  return;
@@ -5720,15 +5774,16 @@ function extractAnswer(data) {
5720
5774
  return result.answer || result.text || result.result || result.content || "";
5721
5775
  }
5722
5776
  function askCommand() {
5723
- 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);
5724
5779
  const auth = await resolveAuth();
5725
5780
  const client = new GadClient({
5726
5781
  token: auth.token,
5727
5782
  apiUrl: auth.apiUrl
5728
5783
  });
5729
5784
  const fmt = createFormatter({
5730
- json: options.json ?? false,
5731
- quiet: options.quiet ?? false,
5785
+ json: g.json,
5786
+ quiet: g.quiet,
5732
5787
  isTTY: isTTY(),
5733
5788
  noColor: options.color === false
5734
5789
  });
@@ -5737,7 +5792,7 @@ function askCommand() {
5737
5792
  { query: question },
5738
5793
  ORCHESTRATOR_TIMEOUT_MS
5739
5794
  );
5740
- if (options.json) {
5795
+ if (g.json) {
5741
5796
  process.stdout.write(JSON.stringify(result) + "\n");
5742
5797
  return;
5743
5798
  }
@@ -6002,7 +6057,7 @@ if (nodeVersion < 20) {
6002
6057
  console.error(" Upgrade Node.js: https://nodejs.org/");
6003
6058
  process.exit(1);
6004
6059
  }
6005
- var VERSION = "0.1.2";
6060
+ var VERSION = "0.1.3";
6006
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");
6007
6062
  program2.addCommand(login_default);
6008
6063
  program2.addCommand(logoutCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@great-arrow/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Great Arrow Digital CLI tool",
5
5
  "type": "module",
6
6
  "bin": {