@moda-ai/cli 1.55.14 → 1.55.16

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 (31) hide show
  1. package/README.md +12 -0
  2. package/dist/{agent-y47qgmf1.js → agent-a2xwfeeh.js} +9 -9
  3. package/dist/{cli-ryd7nzke.js → cli-2ars875d.js} +2 -2
  4. package/dist/{cli-bfmn3bsk.js → cli-3gwbg0xp.js} +2 -2
  5. package/dist/{cli-4qe6n8am.js → cli-438g4nwh.js} +122 -2
  6. package/dist/{cli-k7vwt56h.js → cli-53mvsfgn.js} +3 -3
  7. package/dist/{cli-ssqb8bfw.js → cli-6ca1sz0a.js} +1 -1
  8. package/dist/{cli-k9nae6t9.js → cli-7fc44hhq.js} +1123 -187
  9. package/dist/{cli-ndn5m6wn.js → cli-86q35fpq.js} +8 -8
  10. package/dist/{cli-09rr5smg.js → cli-atx672xv.js} +1 -1
  11. package/dist/{cli-kwz900s4.js → cli-b3cxcxgn.js} +5 -4
  12. package/dist/{cli-4x9w6ey7.js → cli-kf3d6y8c.js} +1 -1
  13. package/dist/{cli-weqp7xc1.js → cli-xy6zn80e.js} +5 -5
  14. package/dist/{cli-y8gbbe9k.js → cli-zdeywyn9.js} +4 -4
  15. package/dist/cli.js +504 -150
  16. package/dist/{doctor-grvx6xx0.js → doctor-e2xrbpmp.js} +9 -9
  17. package/dist/{fix-91sr76gw.js → fix-v8xka487.js} +7 -7
  18. package/dist/{harness-vm0xd80p.js → harness-28wbzncq.js} +6 -6
  19. package/dist/{harness-github-actions-tmy3gqwa.js → harness-github-actions-301nak95.js} +6 -6
  20. package/dist/{index-f6cydfxg.js → index-ccdpy9ma.js} +11 -11
  21. package/dist/{production-intelligence-mg3qp2dg.js → production-intelligence-0wqcvvxk.js} +6 -5
  22. package/dist/{profile-commands-2g5bjzj2.js → profile-commands-f5kysjrv.js} +3 -3
  23. package/dist/prompt-source-mcp.js +6 -6
  24. package/dist/{prompts-kw5kzm39.js → prompts-jg0stjfb.js} +7 -7
  25. package/dist/{provision-rm0yc08f.js → provision-25bw5rd7.js} +4 -4
  26. package/dist/{registry-mbz65bjy.js → registry-39xzetsc.js} +4 -4
  27. package/dist/{skills-sagxq9sc.js → skills-gjesa81c.js} +6 -6
  28. package/dist/{sync-xv04wnth.js → sync-7ts9psky.js} +8 -8
  29. package/package.json +1 -1
  30. package/skills/integration/index.json +2 -2
  31. package/skills/moda-cli/SKILL.md +31 -4
package/dist/cli.js CHANGED
@@ -1,19 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ BATCH_CONCURRENCY,
4
+ BATCH_MAX_TARGETS,
3
5
  MODA_INTELLIGENCE_V1_JSON_SCHEMA,
4
6
  asNumber,
5
7
  asRecord,
6
8
  asString,
9
+ collectBatchTargets,
10
+ contextTarget,
7
11
  embeddedWindowSize,
8
12
  frustrationsFromEmotions,
13
+ mapWithConcurrency,
14
+ parseBatchTarget,
9
15
  trimToolFailureConversations,
10
16
  withFrustrationAnchors,
11
17
  withToolFailureAnchors
12
- } from "./cli-4qe6n8am.js";
18
+ } from "./cli-438g4nwh.js";
13
19
  import {
14
20
  createCommandContext,
15
21
  parseBooleanFlagValue
16
- } from "./cli-4x9w6ey7.js";
22
+ } from "./cli-kf3d6y8c.js";
17
23
  import {
18
24
  SIGNALS_MANAGEMENT_SUBCOMMANDS,
19
25
  assertFlags,
@@ -23,17 +29,17 @@ import {
23
29
  runUserCommand,
24
30
  runUsersCommand,
25
31
  unknownSignalsSubcommandError
26
- } from "./cli-k7vwt56h.js";
32
+ } from "./cli-53mvsfgn.js";
27
33
  import {
28
34
  ApiError,
29
35
  callControlAPI,
30
36
  callDataAPI
31
- } from "./cli-ryd7nzke.js";
37
+ } from "./cli-2ars875d.js";
32
38
  import {
33
39
  apiKeyHeaders,
34
40
  isPlatformApiKey,
35
41
  setPlatformTenantOverride
36
- } from "./cli-09rr5smg.js";
42
+ } from "./cli-atx672xv.js";
37
43
  import {
38
44
  AGENT_ERROR_CODES,
39
45
  CliAccessError,
@@ -55,6 +61,7 @@ import {
55
61
  apiErrorStatus,
56
62
  createCliOutput,
57
63
  embeddedTenantIdFromApiKey,
64
+ errorToAgentError,
58
65
  getApiRequestCount,
59
66
  getModaDir,
60
67
  isApiLikeError,
@@ -70,7 +77,7 @@ import {
70
77
  setAgentUpdateNotice,
71
78
  validateConfig,
72
79
  wasOutputCancelled
73
- } from "./cli-kwz900s4.js";
80
+ } from "./cli-b3cxcxgn.js";
74
81
  import {
75
82
  __require
76
83
  } from "./cli-0v6na3yp.js";
@@ -142,7 +149,8 @@ var ContextSchema = z.object({
142
149
  metadata_only: boolFlag(),
143
150
  all: boolFlag(),
144
151
  from: z.number().int().min(0).optional(),
145
- max_messages: z.number().int().min(1).max(5000).optional()
152
+ max_messages: z.number().int().min(1).max(5000).optional(),
153
+ ids_from: z.string().min(1).optional()
146
154
  });
147
155
  var FrustrationsSchema = z.object({
148
156
  days_back: daysBackFlag(7),
@@ -378,7 +386,8 @@ var AuditSchema = z.object({
378
386
  include_raw: boolFlag(),
379
387
  include_bodies: boolFlag(),
380
388
  limit: z.number().min(1).max(1000).default(200).optional(),
381
- cursor: z.string().min(1).max(512).optional()
389
+ cursor: z.string().min(1).max(512).optional(),
390
+ ids_from: z.string().min(1).optional()
382
391
  });
383
392
  var TIME_RANGES = ["all", "1h", "3d", "7d", "24h", "30d", "90d"];
384
393
  var SEARCH_MODES = ["keyword", "semantic", "hybrid"];
@@ -675,10 +684,14 @@ async function runReplaysCommand(context) {
675
684
  }
676
685
 
677
686
  // src/telemetry.ts
687
+ import { spawn } from "node:child_process";
678
688
  import { randomUUID } from "node:crypto";
679
- var TELEMETRY_TIMEOUT_MS = 500;
689
+ var INLINE_TELEMETRY_TIMEOUT_MS = 500;
690
+ var DETACHED_TELEMETRY_TIMEOUT_MS = 5000;
680
691
  var INVOCATION_ID = randomUUID();
681
692
  var TELEMETRY_FLAG = "no-telemetry";
693
+ var TELEMETRY_REQUEST_ENV = "MODA_CLI_TELEMETRY_REQUEST";
694
+ var TELEMETRY_TRANSPORT_ENV = "MODA_CLI_TELEMETRY_TRANSPORT";
682
695
  var MAX_TELEMETRY_DURATION_MS = 86400000;
683
696
  var MAX_TELEMETRY_API_REQUEST_COUNT = 1e6;
684
697
  var SEARCH_SURFACE_BY_COMMAND = {
@@ -706,6 +719,8 @@ function buildSearchAdoptionTelemetry(input) {
706
719
  };
707
720
  if (positional && input.subcommands?.includes(positional)) {
708
721
  adoption.subcommand = positional;
722
+ } else if (positional === undefined && input.defaultSubcommand) {
723
+ adoption.subcommand = input.defaultSubcommand;
709
724
  }
710
725
  let queryText;
711
726
  if (command === "search")
@@ -733,6 +748,8 @@ function buildSearchAdoptionTelemetry(input) {
733
748
  }
734
749
  if (recorded.has_more)
735
750
  adoption.has_more = recorded.has_more;
751
+ if (recorded.degrade_reason)
752
+ adoption.degrade_reason = recorded.degrade_reason;
736
753
  const skill = input.skillVersion?.trim();
737
754
  if (skill)
738
755
  adoption.skill_version = skill.slice(0, 64);
@@ -767,6 +784,9 @@ function serializeAdoption(adoption) {
767
784
  out.zero_result = adoption.zero_result;
768
785
  if (adoption.has_more)
769
786
  out.has_more = adoption.has_more;
787
+ const degradeReason = sanitizeReasonCode(adoption.degrade_reason, DEGRADE_REASON_MAX);
788
+ if (degradeReason)
789
+ out.degrade_reason = degradeReason;
770
790
  if (adoption.used_msg_index !== undefined) {
771
791
  out.used_msg_index = adoption.used_msg_index ? 1 : 0;
772
792
  }
@@ -782,52 +802,152 @@ function isTelemetryDisabled(flags) {
782
802
  return flags[TELEMETRY_FLAG] === "true" || process.env.MODA_CLI_TELEMETRY === "0" || process.env.DO_NOT_TRACK === "1";
783
803
  }
784
804
  var VALIDATION_REASON_MAX = 128;
785
- function sanitizeValidationReason(reason) {
786
- const cleaned = reason?.replace(/[^A-Za-z0-9_.:-]/g, "_").slice(0, VALIDATION_REASON_MAX);
805
+ var DEGRADE_REASON_MAX = 64;
806
+ function sanitizeReasonCode(reason, max) {
807
+ const cleaned = reason?.replace(/[^A-Za-z0-9_.:-]/g, "_").slice(0, max);
787
808
  return cleaned ? cleaned : undefined;
788
809
  }
810
+ function sanitizeValidationReason(reason) {
811
+ return sanitizeReasonCode(reason, VALIDATION_REASON_MAX);
812
+ }
789
813
  function sanitizedFlagNames(flags) {
790
814
  return Object.keys(stripTelemetryFlag(flags)).sort();
791
815
  }
792
- async function sendCliUsageTelemetry(input) {
793
- if (!input.apiKey || isTelemetryDisabled(input.flags)) {
794
- return;
816
+ var TELEMETRY_SENDER_SCRIPT = [
817
+ "try {",
818
+ ` const raw = process.env.${TELEMETRY_REQUEST_ENV};`,
819
+ ` delete process.env.${TELEMETRY_REQUEST_ENV};`,
820
+ " const r = raw ? JSON.parse(raw) : null;",
821
+ " if (r && typeof r.url === 'string' && typeof fetch === 'function') {",
822
+ " const c = new AbortController();",
823
+ ` const t = setTimeout(() => c.abort(), ${DETACHED_TELEMETRY_TIMEOUT_MS});`,
824
+ " fetch(r.url, { method: 'POST', headers: r.headers, body: r.body, signal: c.signal })",
825
+ " .then((res) => (res.body && res.body.cancel ? res.body.cancel() : undefined))",
826
+ " .catch(() => {})",
827
+ " .finally(() => clearTimeout(t));",
828
+ " }",
829
+ "} catch {}"
830
+ ].join(`
831
+ `);
832
+ var INSPECTOR_VALUE_OPTIONS = new Set(["--inspect-port", "--debug-port", "--inspect-publish-uid"]);
833
+ function nodeOptionTokens(nodeOptions) {
834
+ const tokens = [];
835
+ let start = -1;
836
+ let quoted = false;
837
+ for (let i = 0;i < nodeOptions.length; i += 1) {
838
+ const ch = nodeOptions[i];
839
+ if (start === -1) {
840
+ if (/\s/.test(ch))
841
+ continue;
842
+ start = i;
843
+ }
844
+ if (quoted && ch === "\\") {
845
+ i += 1;
846
+ } else if (ch === '"') {
847
+ quoted = !quoted;
848
+ } else if (!quoted && /\s/.test(ch)) {
849
+ tokens.push(nodeOptions.slice(start, i));
850
+ start = -1;
851
+ }
795
852
  }
796
- const validationReason = sanitizeValidationReason(input.validationReason);
853
+ if (start !== -1)
854
+ tokens.push(nodeOptions.slice(start));
855
+ return tokens;
856
+ }
857
+ function withoutInspectorOptions(nodeOptions) {
858
+ const tokens = nodeOptionTokens(nodeOptions);
859
+ const kept = [];
860
+ for (let i = 0;i < tokens.length; i += 1) {
861
+ const name = tokens[i].split("=")[0];
862
+ if (!name.startsWith("--inspect") && name !== "--debug-port") {
863
+ kept.push(tokens[i]);
864
+ continue;
865
+ }
866
+ if (INSPECTOR_VALUE_OPTIONS.has(tokens[i]) && tokens[i + 1] && !tokens[i + 1].startsWith("-"))
867
+ i += 1;
868
+ }
869
+ return kept.join(" ");
870
+ }
871
+ function spawnDetachedTelemetrySender(request, spawnImpl = spawn) {
872
+ try {
873
+ const env = { ...process.env, [TELEMETRY_REQUEST_ENV]: JSON.stringify(request) };
874
+ if (env.NODE_OPTIONS?.includes("--inspect")) {
875
+ const kept = withoutInspectorOptions(env.NODE_OPTIONS);
876
+ if (kept)
877
+ env.NODE_OPTIONS = kept;
878
+ else
879
+ delete env.NODE_OPTIONS;
880
+ }
881
+ const child = spawnImpl(process.execPath, ["-e", TELEMETRY_SENDER_SCRIPT], {
882
+ detached: true,
883
+ stdio: "ignore",
884
+ windowsHide: true,
885
+ env
886
+ });
887
+ child.on("error", () => {});
888
+ if (child.pid === undefined)
889
+ return false;
890
+ child.unref();
891
+ return true;
892
+ } catch {
893
+ return false;
894
+ }
895
+ }
896
+ async function sendInline(request) {
797
897
  const controller = new AbortController;
798
- const timeout = setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS);
898
+ const timeout = setTimeout(() => controller.abort(), INLINE_TELEMETRY_TIMEOUT_MS);
799
899
  if (typeof timeout.unref === "function") {
800
900
  timeout.unref();
801
901
  }
802
902
  try {
803
- await fetch(`${resolveModaBaseUrl({ profile: input.profile })}/api/v1/data/cli-usage`, {
903
+ await fetch(request.url, {
804
904
  method: "POST",
805
- headers: {
806
- ...apiKeyHeaders(input.apiKey),
807
- "Content-Type": "application/json"
808
- },
809
- body: JSON.stringify({
810
- invocation_id: INVOCATION_ID,
811
- command: input.command.slice(0, 64),
812
- status: input.status,
813
- error_type: input.errorType,
814
- ...validationReason ? { validation_reason: validationReason } : {},
815
- exit_code: input.exitCode,
816
- duration_ms: clampInt(input.durationMs, 0, MAX_TELEMETRY_DURATION_MS) ?? 0,
817
- api_request_count: clampInt(input.apiRequestCount, 0, MAX_TELEMETRY_API_REQUEST_COUNT) ?? 0,
818
- cli_version: VERSION,
819
- node_version: process.versions.node,
820
- platform: process.platform,
821
- arch: process.arch,
822
- flags_json: { names: sanitizedFlagNames(input.flags) },
823
- ...serializeAdoption(input.adoption)
824
- }),
905
+ headers: request.headers,
906
+ body: request.body,
825
907
  signal: controller.signal
826
908
  });
827
909
  } catch {} finally {
828
910
  clearTimeout(timeout);
829
911
  }
830
912
  }
913
+ function buildCliUsageRequest(input) {
914
+ const validationReason = sanitizeValidationReason(input.validationReason);
915
+ return {
916
+ url: `${resolveModaBaseUrl({ profile: input.profile })}/api/v1/data/cli-usage`,
917
+ headers: {
918
+ ...apiKeyHeaders(input.apiKey),
919
+ "Content-Type": "application/json"
920
+ },
921
+ body: JSON.stringify({
922
+ invocation_id: INVOCATION_ID,
923
+ command: input.command.slice(0, 64),
924
+ status: input.status,
925
+ error_type: input.errorType,
926
+ ...validationReason ? { validation_reason: validationReason } : {},
927
+ exit_code: input.exitCode,
928
+ duration_ms: clampInt(input.durationMs, 0, MAX_TELEMETRY_DURATION_MS) ?? 0,
929
+ api_request_count: clampInt(input.apiRequestCount, 0, MAX_TELEMETRY_API_REQUEST_COUNT) ?? 0,
930
+ cli_version: VERSION,
931
+ node_version: process.versions.node,
932
+ platform: process.platform,
933
+ arch: process.arch,
934
+ flags_json: { names: sanitizedFlagNames(input.flags) },
935
+ ...serializeAdoption(input.adoption)
936
+ })
937
+ };
938
+ }
939
+ async function sendCliUsageTelemetry(input) {
940
+ try {
941
+ if (!input.apiKey || isTelemetryDisabled(input.flags)) {
942
+ return;
943
+ }
944
+ const request = buildCliUsageRequest({ ...input, apiKey: input.apiKey });
945
+ if (process.env[TELEMETRY_TRANSPORT_ENV] !== "inline" && spawnDetachedTelemetrySender(request)) {
946
+ return;
947
+ }
948
+ await sendInline(request);
949
+ } catch {}
950
+ }
831
951
 
832
952
  // src/update-check.ts
833
953
  import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
@@ -2081,46 +2201,46 @@ function exitCodesForCommand(command) {
2081
2201
  import { fileURLToPath } from "url";
2082
2202
  import { realpathSync } from "fs";
2083
2203
  async function runPromptsCommand(...args) {
2084
- return (await import("./prompts-kw5kzm39.js")).runPromptsCommand(...args);
2204
+ return (await import("./prompts-jg0stjfb.js")).runPromptsCommand(...args);
2085
2205
  }
2086
2206
  async function runSkillsCommand(...args) {
2087
- return (await import("./skills-sagxq9sc.js")).runSkillsCommand(...args);
2207
+ return (await import("./skills-gjesa81c.js")).runSkillsCommand(...args);
2088
2208
  }
2089
2209
  async function runFixCommand(...args) {
2090
- return (await import("./fix-91sr76gw.js")).runFixCommand(...args);
2210
+ return (await import("./fix-v8xka487.js")).runFixCommand(...args);
2091
2211
  }
2092
2212
  async function runFixesCommand(...args) {
2093
- return (await import("./fix-91sr76gw.js")).runFixesCommand(...args);
2213
+ return (await import("./fix-v8xka487.js")).runFixesCommand(...args);
2094
2214
  }
2095
2215
  async function runHarnessCommand(...args) {
2096
- return (await import("./harness-vm0xd80p.js")).runHarnessCommand(...args);
2216
+ return (await import("./harness-28wbzncq.js")).runHarnessCommand(...args);
2097
2217
  }
2098
2218
  async function runSyncCommand(...args) {
2099
- return (await import("./sync-xv04wnth.js")).runSyncCommand(...args);
2219
+ return (await import("./sync-7ts9psky.js")).runSyncCommand(...args);
2100
2220
  }
2101
2221
  async function runRegistryCommand(...args) {
2102
- return (await import("./registry-mbz65bjy.js")).runRegistryCommand(...args);
2222
+ return (await import("./registry-39xzetsc.js")).runRegistryCommand(...args);
2103
2223
  }
2104
2224
  async function runDoctorCommand(...args) {
2105
- return (await import("./doctor-grvx6xx0.js")).runDoctorCommand(...args);
2225
+ return (await import("./doctor-e2xrbpmp.js")).runDoctorCommand(...args);
2106
2226
  }
2107
2227
  async function runStatusCommand(...args) {
2108
- return (await import("./doctor-grvx6xx0.js")).runStatusCommand(...args);
2228
+ return (await import("./doctor-e2xrbpmp.js")).runStatusCommand(...args);
2109
2229
  }
2110
2230
  async function runAuthCommand(...args) {
2111
- return (await import("./profile-commands-2g5bjzj2.js")).runAuthCommand(...args);
2231
+ return (await import("./profile-commands-f5kysjrv.js")).runAuthCommand(...args);
2112
2232
  }
2113
2233
  async function runConfigCommand(...args) {
2114
- return (await import("./profile-commands-2g5bjzj2.js")).runConfigCommand(...args);
2234
+ return (await import("./profile-commands-f5kysjrv.js")).runConfigCommand(...args);
2115
2235
  }
2116
2236
  async function runProfilesCommand(...args) {
2117
- return (await import("./profile-commands-2g5bjzj2.js")).runProfilesCommand(...args);
2237
+ return (await import("./profile-commands-f5kysjrv.js")).runProfilesCommand(...args);
2118
2238
  }
2119
2239
  async function runAgentCommand(...args) {
2120
- return (await import("./agent-y47qgmf1.js")).runAgentCommand(...args);
2240
+ return (await import("./agent-a2xwfeeh.js")).runAgentCommand(...args);
2121
2241
  }
2122
2242
  async function runProductionCommand(...args) {
2123
- return (await import("./production-intelligence-mg3qp2dg.js")).runProductionCommand(...args);
2243
+ return (await import("./production-intelligence-0wqcvvxk.js")).runProductionCommand(...args);
2124
2244
  }
2125
2245
  function parseArgs(argv) {
2126
2246
  const args = argv.slice(2);
@@ -2246,6 +2366,7 @@ var META_SWITCHES = new Set([
2246
2366
  "no-telemetry",
2247
2367
  "no-update-check"
2248
2368
  ]);
2369
+ var AGENT_VALUE_COMMANDS = new Set(["harness", "sync"]);
2249
2370
  var COMMAND_BOOLEAN_FLAGS = {
2250
2371
  context: new Set(["all", "metadata-only"])
2251
2372
  };
@@ -2271,7 +2392,7 @@ function parseFlag(args, index, flags, beforeCommand, bareFlags, command = "") {
2271
2392
  return index;
2272
2393
  }
2273
2394
  const switchName = key.replace(/_/g, "-");
2274
- if (META_SWITCHES.has(switchName)) {
2395
+ if (META_SWITCHES.has(switchName) || switchName === "agent" && !AGENT_VALUE_COMMANDS.has(command)) {
2275
2396
  set(key, "true", true);
2276
2397
  return index;
2277
2398
  }
@@ -2376,7 +2497,9 @@ Commands:
2376
2497
  world-state <conversation_id> Get a trace's world state (slots/threads/events)
2377
2498
  context <conversation_id> Get windowed trace context (--metadata-only: summary + counts only)
2378
2499
  context <conversation_id> --all Whole transcript in order (first 500; --from=N --max-messages=N to continue)
2500
+ context <id>[@N] <id>[@N] ... Batch: up to 25 traces in one call (or --ids-from=-|<file>)
2379
2501
  audit <conversation_id|trace_id> Raw span audit (spans, hierarchy, orphans, duplicates)
2502
+ audit <id> <id> ... Batch audit: up to 25 ids in one call (or --ids-from=-|<file>)
2380
2503
  frustrations Frustration detections (same data as emotions --family=frustration)
2381
2504
  emotions Multi-family emotion detections (frustration, disapproval, sadness, confusion, anxiety, trust, positive)
2382
2505
  hallucinations Grounding detections: contradicted/verified outputs with rule breakdown
@@ -2825,7 +2948,7 @@ function noWorldStateWarnings(conversationId, isMissing) {
2825
2948
  return;
2826
2949
  return {
2827
2950
  warnings: [
2828
- `No world state for trace "${conversationId}": the trace may not exist in this tenant, or its world state has not been generated yet. Check the trace exists with: moda context ${conversationId} --metadata-only`
2951
+ `No world state for trace "${conversationId}": the trace may not exist in this tenant, or its world state has not been generated yet. Check the trace exists with: moda context ${shellArg(contextTarget(conversationId))} --metadata-only`
2829
2952
  ]
2830
2953
  };
2831
2954
  }
@@ -3112,7 +3235,8 @@ function recordSearchTelemetry(context, data) {
3112
3235
  context.recordTelemetry({
3113
3236
  search_mode_effective: SEARCH_MODES2.includes(effective) ? effective : undefined,
3114
3237
  result_count: results.length,
3115
- has_more: hasMore === true ? "yes" : hasMore === false ? "no" : "na"
3238
+ has_more: hasMore === true ? "yes" : hasMore === false ? "no" : "na",
3239
+ ...typeof record.degrade_reason === "string" && record.degrade_reason ? { degrade_reason: record.degrade_reason.slice(0, 64) } : {}
3116
3240
  });
3117
3241
  }
3118
3242
  function recordConversationsTelemetry(context, data) {
@@ -3550,6 +3674,7 @@ function processingDisabledWarning(data, family) {
3550
3674
  }
3551
3675
  var CONTEXT_USAGE = "Usage: moda context <conversation_id> [--msg-index=N (alias --message-index)] [--window=0-5 | --metadata-only]";
3552
3676
  var CONTEXT_ALL_USAGE = "Usage: moda context <conversation_id> --all [--from=N] [--max-messages=N]";
3677
+ var CONTEXT_BATCH_USAGE = `Usage: moda context <id>[@msg_index] <id>[@msg_index] ... | --ids-from=-|<file> [--window=0-5 | --metadata-only | --all [--from=N] [--max-messages=N]] (max ${BATCH_MAX_TARGETS} targets)`;
3553
3678
  var CONTEXT_FLAG_ALIASES = { "message-index": "msg-index" };
3554
3679
  var CONTEXT_MAX_WINDOW = 5;
3555
3680
  var EMPTY_ANCHOR_VALUES = new Set(["", "null", "undefined", "none"]);
@@ -3723,7 +3848,7 @@ async function readFullTranscript(conversationId, opts = {}) {
3723
3848
  if (next !== null) {
3724
3849
  const last = asNumber(returned[returned.length - 1]?.index) ?? next - 1;
3725
3850
  const nextMax = firstMissing !== null ? Math.min(pageSize, Math.max(kept * 2, 50)) : pageSize;
3726
- const continueWith = `moda context ${shellArg(conversationId)} --all --from=${next} --max-messages=${nextMax}`;
3851
+ const continueWith = `moda context ${shellArg(contextTarget(conversationId))} --all --from=${next} --max-messages=${nextMax}`;
3727
3852
  out.push(`Trace has ${total} messages; returned messages ${start}-${last}. ` + (firstMissing !== null ? `Stopped at ${kept} of the ${messages.length} messages read to stay under the agent output byte limit (--json has no limit). ` : "") + `Continue with: ${continueWith}`);
3728
3853
  nextCommands.push({
3729
3854
  command: continueWith,
@@ -3768,6 +3893,249 @@ async function readFullTranscript(conversationId, opts = {}) {
3768
3893
  }
3769
3894
  return build(low);
3770
3895
  }
3896
+ async function readContextItem(command, params, inputWarnings, fits) {
3897
+ if (params.all === true) {
3898
+ const full = await readFullTranscript(params.conversation_id, {
3899
+ from: params.from,
3900
+ maxMessages: params.max_messages,
3901
+ fits: fits ? (page) => fits(page.data, { warnings: page.warnings, nextCommands: page.nextCommands }) : undefined
3902
+ });
3903
+ const fullWarnings = [...inputWarnings, ...full.warnings];
3904
+ return {
3905
+ data: full.data,
3906
+ options: {
3907
+ ...fullWarnings.length > 0 ? { warnings: fullWarnings } : {},
3908
+ ...full.nextCommands.length > 0 ? { nextCommands: full.nextCommands } : {}
3909
+ }
3910
+ };
3911
+ }
3912
+ const query2 = new URLSearchParams;
3913
+ if (params.msg_index !== undefined)
3914
+ query2.set("msg_index", params.msg_index.toString());
3915
+ if (params.metadata_only === true)
3916
+ query2.set("metadata_only", "1");
3917
+ const window = params.window === undefined ? undefined : Math.min(params.window, CONTEXT_MAX_WINDOW);
3918
+ if (window !== undefined)
3919
+ query2.set("window", window.toString());
3920
+ const queryString = query2.toString() ? `?${query2.toString()}` : "";
3921
+ const contextPath = `/conversations/${encodeURIComponent(params.conversation_id)}/context`;
3922
+ const data = params.metadata_only === true ? await readContextMetadataOnly(contextPath, query2) : await callDataAPI(`${contextPath}${queryString}`);
3923
+ const ctxRecord = asRecord(data) ?? {};
3924
+ throwIfNotFound("trace", params.conversation_id, asNumber(ctxRecord.total_messages) === 0);
3925
+ const warnings = [...inputWarnings];
3926
+ const nextCommands = [];
3927
+ if (params.window !== undefined && params.window > CONTEXT_MAX_WINDOW) {
3928
+ const center = asNumber(asRecord(ctxRecord.context)?.center_index) ?? params.msg_index ?? 0;
3929
+ const span = Math.min(params.window * 2 + 1, CONTEXT_ALL_MAX_MESSAGES);
3930
+ const from = Math.max(0, center - Math.floor((span - 1) / 2));
3931
+ const wide = `moda context ${shellArg(contextTarget(params.conversation_id))} --all --from=${from} --max-messages=${span}`;
3932
+ warnings.push(`--window=${params.window} is above the maximum of ${CONTEXT_MAX_WINDOW}, so this shows ±${CONTEXT_MAX_WINDOW} messages. For a wider slice run: ${wide}`);
3933
+ nextCommands.push({ command: wide, purpose: `Read ±${params.window} messages around the anchor.`, mutability: "read", requires_approval: false });
3934
+ }
3935
+ return {
3936
+ data,
3937
+ options: {
3938
+ ...warnings.length > 0 ? { warnings } : {},
3939
+ ...nextCommands.length > 0 ? { nextCommands } : {}
3940
+ }
3941
+ };
3942
+ }
3943
+ var AUDIT_USAGE = "Usage: moda audit <conversation_id|trace_id> [--kind=auto|trace|conversation] [--include-raw] [--include-bodies] [--limit=N] [--cursor=<next_cursor>]";
3944
+ var AUDIT_BATCH_USAGE = `Usage: moda audit <id> <id> ... | --ids-from=-|<file> [--kind=auto|trace|conversation] [--include-raw] [--include-bodies] [--limit=N] (max ${BATCH_MAX_TARGETS} targets)`;
3945
+ async function readAuditItem(command, params, budget) {
3946
+ const query2 = new URLSearchParams;
3947
+ if (params.kind && params.kind !== "auto")
3948
+ query2.set("kind", params.kind);
3949
+ if (params.include_raw === true)
3950
+ query2.set("include_raw", "1");
3951
+ if (params.include_bodies === true)
3952
+ query2.set("include_bodies", "1");
3953
+ if (params.limit)
3954
+ query2.set("limit", params.limit.toString());
3955
+ if (params.cursor)
3956
+ query2.set("cursor", params.cursor);
3957
+ let maxBytes = budget?.maxBytes;
3958
+ let page = auditOutput(command, params, await fetchAudit(params.id, query2, maxBytes));
3959
+ while (budget && maxBytes !== undefined && maxBytes > AUDIT_MIN_PAGE_BYTES && !budget.fits(page.data, page.options)) {
3960
+ maxBytes = Math.max(AUDIT_MIN_PAGE_BYTES, Math.floor(maxBytes / 2));
3961
+ page = auditOutput(command, params, await fetchAudit(params.id, query2, maxBytes));
3962
+ }
3963
+ if (budget && !budget.fits(page.data, page.options)) {
3964
+ page.options.warnings = [
3965
+ ...page.options.warnings ?? [],
3966
+ "This page is a single ingest row larger than the agent output budget, so some of its spans are cut from this output. Rerun this command with --json (no byte limit) or a higher MODA_AGENT_MAX_OUTPUT_BYTES to see the whole row before following next_cursor."
3967
+ ];
3968
+ }
3969
+ return page;
3970
+ }
3971
+ var IDS_FROM_KEYS = ["ids-from", "ids_from"];
3972
+ function singleContextTarget(positional, flags) {
3973
+ if (positional === undefined)
3974
+ return [positional, flags];
3975
+ const target = parseBatchTarget(positional, true, CONTEXT_USAGE);
3976
+ if (target.msgIndex === undefined)
3977
+ return [target.id, flags];
3978
+ if (Object.keys(flags).some((key) => ["msg-index", "message-index"].includes(key.replace(/_/g, "-")))) {
3979
+ throw new CliInputError(`${JSON.stringify(positional)} already anchors at message ${target.msgIndex}; drop --msg-index, or pass {"id": "..."} if the id itself ends in @<digits>.`, CONTEXT_USAGE, "flag_conflict");
3980
+ }
3981
+ return [target.id, { ...flags, "msg-index": String(target.msgIndex) }];
3982
+ }
3983
+ function isBatchRead(positionals, flags) {
3984
+ return positionals.length > 1 || IDS_FROM_KEYS.some((key) => flags[key] !== undefined);
3985
+ }
3986
+ function splitIdsFrom(flags) {
3987
+ let idsFrom;
3988
+ const rest = {};
3989
+ for (const [key, value] of Object.entries(flags)) {
3990
+ if (IDS_FROM_KEYS.includes(key))
3991
+ idsFrom = value;
3992
+ else
3993
+ rest[key] = value;
3994
+ }
3995
+ return { idsFrom, rest };
3996
+ }
3997
+ function auditItemByteShare(count) {
3998
+ return Math.max(AUDIT_MIN_PAGE_BYTES, Math.floor((agentMaxOutputBytes() - AUDIT_AGENT_RESERVE_BYTES) / count));
3999
+ }
4000
+ var BATCH_ENVELOPE_RESERVE_BYTES = 4096;
4001
+ var BATCH_ENVELOPE_RESERVE_PER_TARGET_BYTES = 256;
4002
+ function contextItemByteShare(count) {
4003
+ const reserve = BATCH_ENVELOPE_RESERVE_BYTES + BATCH_ENVELOPE_RESERVE_PER_TARGET_BYTES * count;
4004
+ return Math.max(1, Math.floor((agentMaxOutputBytes() - reserve) / count));
4005
+ }
4006
+ function fitsShare(share) {
4007
+ return (data, options) => Buffer.byteLength(JSON.stringify({ data, ...options }) ?? "", "utf8") <= share;
4008
+ }
4009
+ function isBatchFatal(error) {
4010
+ const type = classifyCliError(error);
4011
+ return type === "auth_error" || type === "access_error" || error instanceof CliInputError;
4012
+ }
4013
+ async function readBatchItem(target, read) {
4014
+ try {
4015
+ const item = await read();
4016
+ return {
4017
+ target: target.raw,
4018
+ ok: true,
4019
+ data: item.data,
4020
+ ...item.options.warnings?.length ? { warnings: item.options.warnings } : {},
4021
+ ...item.options.nextCommands?.length ? { next_commands: item.options.nextCommands } : {}
4022
+ };
4023
+ } catch (error) {
4024
+ if (isBatchFatal(error))
4025
+ throw error;
4026
+ const agentError = errorToAgentError(error);
4027
+ const code = classifyCliError(error) === "api_not_found" ? "not_found" : agentError.code;
4028
+ return {
4029
+ target: target.raw,
4030
+ ok: false,
4031
+ error: {
4032
+ code,
4033
+ message: agentError.message,
4034
+ ...agentError.cause ? { cause: agentError.cause } : {},
4035
+ ...agentError.suggested_commands?.length ? { suggested_commands: agentError.suggested_commands } : {}
4036
+ }
4037
+ };
4038
+ }
4039
+ }
4040
+ function renderBatchFlags(flags) {
4041
+ return Object.entries(flags).map(([key, value]) => value === "true" ? `--${key}` : `--${key}=${shellArg(value)}`);
4042
+ }
4043
+ function writeBatchResult(command, context, targets, results, batchWarnings, flags) {
4044
+ const agentMode = context.output.mode === "agent" || context.output.mode === "agent-stream";
4045
+ const build = (kept2) => {
4046
+ const returned = results.slice(0, kept2);
4047
+ const remaining = targets.slice(kept2);
4048
+ const failed = returned.filter((result) => !result.ok);
4049
+ const allFailed = failed.length === returned.length;
4050
+ const warnings = [...batchWarnings];
4051
+ if (failed.length > 0 && failed.length < returned.length) {
4052
+ warnings.push(`${failed.length} of ${returned.length} targets failed: ` + failed.map((result) => `${result.target} (${result.error?.code ?? "error"})`).join(", ") + ".");
4053
+ }
4054
+ const nextCommands = [];
4055
+ if (remaining.length > 0) {
4056
+ const lines = remaining.map((target) => shellArg(target.raw)).join(" ");
4057
+ const continueWith = [`printf '%s\\n' ${lines} |`, `moda ${command}`, "--ids-from=-", ...renderBatchFlags(flags)].join(" ");
4058
+ warnings.push(`Returned ${kept2} of ${targets.length} targets to stay under the agent output byte limit (--json has no limit). Read the other ${remaining.length} with: ${continueWith}`);
4059
+ nextCommands.push({
4060
+ command: continueWith,
4061
+ purpose: `Read the remaining ${remaining.length} target(s) of this batch.`,
4062
+ mutability: "read",
4063
+ requires_approval: false
4064
+ });
4065
+ }
4066
+ return {
4067
+ data: {
4068
+ results: returned,
4069
+ requested: targets.length,
4070
+ returned: returned.length,
4071
+ succeeded: returned.length - failed.length,
4072
+ failed: failed.length,
4073
+ has_more: remaining.length > 0,
4074
+ remaining_targets: remaining.map((target) => target.raw)
4075
+ },
4076
+ options: {
4077
+ summary: `Read ${returned.length - failed.length} of ${targets.length} targets` + (failed.length > 0 ? ` (${failed.length} failed)` : "") + (remaining.length > 0 ? `; ${remaining.length} left for a follow-up call` : "") + ".",
4078
+ ...warnings.length > 0 ? { warnings } : {},
4079
+ ...nextCommands.length > 0 ? { nextCommands } : {},
4080
+ ...allFailed ? {
4081
+ status: "error",
4082
+ errors: returned.map((result) => ({
4083
+ code: result.error?.code ?? "unknown_error",
4084
+ message: clipText(`${result.target}: ${result.error?.message ?? "failed"}`, BATCH_ERROR_MESSAGE_CHARS),
4085
+ blocking: false
4086
+ }))
4087
+ } : failed.length > 0 ? { status: "degraded" } : {}
4088
+ }
4089
+ };
4090
+ };
4091
+ let kept = results.length;
4092
+ let page = build(kept);
4093
+ while (agentMode && kept > 1 && !agentEnvelopeFits(command, page.data, page.options)) {
4094
+ kept -= 1;
4095
+ page = build(kept);
4096
+ }
4097
+ const failedPage = page.options.status === "error";
4098
+ context.output.writeData(page.data, { ...page.options, ...failedPage ? { bypassQuiet: true } : {} });
4099
+ return failedPage ? 1 : 0;
4100
+ }
4101
+ var BATCH_ERROR_MESSAGE_CHARS = 300;
4102
+ function clipText(text, max) {
4103
+ return text.length <= max ? text : `${text.slice(0, max - 3)}...`;
4104
+ }
4105
+ async function runContextBatch(command, positionals, flags, context) {
4106
+ const { idsFrom, rest } = splitIdsFrom(flags);
4107
+ if (Object.keys(rest).some((key) => key.replace(/_/g, "-") === "conversation-id")) {
4108
+ throw new CliInputError("Batch reads take ids as positionals or --ids-from, not --conversation-id; drop --conversation-id.", CONTEXT_BATCH_USAGE, "flag_conflict");
4109
+ }
4110
+ const targets = await collectBatchTargets(positionals, idsFrom, { anchors: true, usage: CONTEXT_BATCH_USAGE, command });
4111
+ const { params: base, warnings: inputWarnings } = parseContextRequest(targets[0].id, rest);
4112
+ if ((base.all === true || base.metadata_only === true) && targets.some((target) => target.msgIndex !== undefined)) {
4113
+ throw new CliInputError(`${base.all === true ? "--all reads whole traces" : "--metadata-only reads no messages"}, so targets cannot carry an @msg_index anchor; drop the flag or the anchors.`, CONTEXT_BATCH_USAGE, "flag_conflict");
4114
+ }
4115
+ const agentMode = context.output.mode === "agent" || context.output.mode === "agent-stream";
4116
+ const share = agentMode ? contextItemByteShare(targets.length) : undefined;
4117
+ const results = await mapWithConcurrency(targets, BATCH_CONCURRENCY, (target) => readBatchItem(target, () => {
4118
+ const params = {
4119
+ ...base,
4120
+ conversation_id: target.id,
4121
+ ...target.msgIndex !== undefined ? { msg_index: target.msgIndex } : {}
4122
+ };
4123
+ return readContextItem(command, params, [], share !== undefined ? fitsShare(share) : undefined);
4124
+ }));
4125
+ return writeBatchResult(command, context, targets, results, inputWarnings, rest);
4126
+ }
4127
+ async function runAuditBatch(command, positionals, flags, context) {
4128
+ const { idsFrom, rest } = splitIdsFrom(flags);
4129
+ if (rest.cursor !== undefined) {
4130
+ throw new CliInputError("--cursor continues one trace, so it cannot be used with several ids; follow each item's next_commands instead.", AUDIT_BATCH_USAGE, "flag_conflict");
4131
+ }
4132
+ const targets = await collectBatchTargets(positionals, idsFrom, { anchors: false, usage: AUDIT_BATCH_USAGE, command });
4133
+ const base = parseCommandFlags(AuditSchema, flagsToArgs(rest, "id", targets[0].id), command, { positionalKey: "id" });
4134
+ const agentMode = context.output.mode === "agent" || context.output.mode === "agent-stream";
4135
+ const share = agentMode ? auditItemByteShare(targets.length) : undefined;
4136
+ const results = await mapWithConcurrency(targets, BATCH_CONCURRENCY, (target) => readBatchItem(target, () => readAuditItem(command, { ...base, id: target.id }, share !== undefined ? { maxBytes: share, fits: fitsShare(share) } : undefined)));
4137
+ return writeBatchResult(command, context, targets, results, [], rest);
4138
+ }
3771
4139
  async function runCommand(command, positional, flags, positionals = positional ? [positional] : [], context = createCommandContext({ command, positional, positionals, flags })) {
3772
4140
  assertHandParsedFlags(command, flags, positionals);
3773
4141
  switch (command) {
@@ -3988,81 +4356,28 @@ async function runCommand(command, positional, flags, positionals = positional ?
3988
4356
  break;
3989
4357
  }
3990
4358
  case "context": {
3991
- const { params, warnings: inputWarnings } = parseContextRequest(positional, flags);
3992
- if (params.all === true) {
3993
- const agentMode = context.output.mode === "agent" || context.output.mode === "agent-stream";
3994
- const full = await readFullTranscript(params.conversation_id, {
3995
- from: params.from,
3996
- maxMessages: params.max_messages,
3997
- fits: agentMode ? (page) => agentEnvelopeFits(command, page.data, { warnings: page.warnings, nextCommands: page.nextCommands }) : undefined
3998
- });
3999
- const fullWarnings = [...inputWarnings, ...full.warnings];
4000
- context.output.writeData(full.data, {
4001
- ...fullWarnings.length > 0 ? { warnings: fullWarnings } : {},
4002
- ...full.nextCommands.length > 0 ? { nextCommands: full.nextCommands } : {}
4003
- });
4004
- break;
4005
- }
4006
- const query2 = new URLSearchParams;
4007
- if (params.msg_index !== undefined)
4008
- query2.set("msg_index", params.msg_index.toString());
4009
- if (params.metadata_only === true)
4010
- query2.set("metadata_only", "1");
4011
- const window = params.window === undefined ? undefined : Math.min(params.window, CONTEXT_MAX_WINDOW);
4012
- if (window !== undefined)
4013
- query2.set("window", window.toString());
4014
- const queryString = query2.toString() ? `?${query2.toString()}` : "";
4015
- const contextPath = `/conversations/${encodeURIComponent(params.conversation_id)}/context`;
4016
- const data = params.metadata_only === true ? await readContextMetadataOnly(contextPath, query2) : await callDataAPI(`${contextPath}${queryString}`);
4017
- const ctxRecord = asRecord(data) ?? {};
4018
- throwIfNotFound("trace", params.conversation_id, asNumber(ctxRecord.total_messages) === 0);
4019
- const warnings = [...inputWarnings];
4020
- const nextCommands = [];
4021
- if (params.window !== undefined && params.window > CONTEXT_MAX_WINDOW) {
4022
- const center = asNumber(asRecord(ctxRecord.context)?.center_index) ?? params.msg_index ?? 0;
4023
- const span = Math.min(params.window * 2 + 1, CONTEXT_ALL_MAX_MESSAGES);
4024
- const from = Math.max(0, center - Math.floor((span - 1) / 2));
4025
- const wide = `moda context ${shellArg(params.conversation_id)} --all --from=${from} --max-messages=${span}`;
4026
- warnings.push(`--window=${params.window} is above the maximum of ${CONTEXT_MAX_WINDOW}, so this shows ±${CONTEXT_MAX_WINDOW} messages. For a wider slice run: ${wide}`);
4027
- nextCommands.push({ command: wide, purpose: `Read ±${params.window} messages around the anchor.`, mutability: "read", requires_approval: false });
4028
- }
4029
- context.output.writeData(data, {
4030
- ...warnings.length > 0 ? { warnings } : {},
4031
- ...nextCommands.length > 0 ? { nextCommands } : {}
4032
- });
4359
+ if (isBatchRead(positionals, flags))
4360
+ return runContextBatch(command, positionals, flags, context);
4361
+ const { params, warnings: inputWarnings } = parseContextRequest(...singleContextTarget(positional, flags));
4362
+ const agentMode = context.output.mode === "agent" || context.output.mode === "agent-stream";
4363
+ const item = await readContextItem(command, params, inputWarnings, agentMode ? (data, options) => agentEnvelopeFits(command, data, options) : undefined);
4364
+ context.output.writeData(item.data, item.options);
4033
4365
  break;
4034
4366
  }
4035
4367
  case "audit":
4036
4368
  case "trace": {
4369
+ if (isBatchRead(positionals, flags))
4370
+ return runAuditBatch(command, positionals, flags, context);
4037
4371
  if (!positional) {
4038
- throw new CliInputError("<conversation_id|trace_id> is required", "Usage: moda audit <conversation_id|trace_id> [--kind=auto|trace|conversation] [--include-raw] [--include-bodies] [--limit=N] [--cursor=<next_cursor>]");
4372
+ throw new CliInputError("<conversation_id|trace_id> is required", AUDIT_USAGE);
4039
4373
  }
4040
4374
  const args = flagsToArgs(flags, "id", positional);
4041
4375
  const params = parseCommandFlags(AuditSchema, args, command, { positionalKey: "id" });
4042
- const query2 = new URLSearchParams;
4043
- if (params.kind && params.kind !== "auto")
4044
- query2.set("kind", params.kind);
4045
- if (params.include_raw === true)
4046
- query2.set("include_raw", "1");
4047
- if (params.include_bodies === true)
4048
- query2.set("include_bodies", "1");
4049
- if (params.limit)
4050
- query2.set("limit", params.limit.toString());
4051
- if (params.cursor)
4052
- query2.set("cursor", params.cursor);
4053
4376
  const agentMode = context.output.mode === "agent" || context.output.mode === "agent-stream";
4054
- let maxBytes = agentMode ? Math.max(AUDIT_MIN_PAGE_BYTES, agentMaxOutputBytes() - AUDIT_AGENT_RESERVE_BYTES) : undefined;
4055
- let page = auditOutput(command, params, await fetchAudit(params.id, query2, maxBytes));
4056
- while (maxBytes !== undefined && maxBytes > AUDIT_MIN_PAGE_BYTES && !agentEnvelopeFits(command, page.data, page.options)) {
4057
- maxBytes = Math.max(AUDIT_MIN_PAGE_BYTES, Math.floor(maxBytes / 2));
4058
- page = auditOutput(command, params, await fetchAudit(params.id, query2, maxBytes));
4059
- }
4060
- if (maxBytes !== undefined && !agentEnvelopeFits(command, page.data, page.options)) {
4061
- page.options.warnings = [
4062
- ...page.options.warnings ?? [],
4063
- "This page is a single ingest row larger than the agent output budget, so some of its spans are cut from this output. Rerun this command with --json (no byte limit) or a higher MODA_AGENT_MAX_OUTPUT_BYTES to see the whole row before following next_cursor."
4064
- ];
4065
- }
4377
+ const page = await readAuditItem(command, params, agentMode ? {
4378
+ maxBytes: Math.max(AUDIT_MIN_PAGE_BYTES, agentMaxOutputBytes() - AUDIT_AGENT_RESERVE_BYTES),
4379
+ fits: (data, options) => agentEnvelopeFits(command, data, options)
4380
+ } : undefined);
4066
4381
  context.output.writeData(page.data, page.options);
4067
4382
  break;
4068
4383
  }
@@ -4677,6 +4992,13 @@ async function runCommand(command, positional, flags, positionals = positional ?
4677
4992
  function telemetryCommandName(definition) {
4678
4993
  return definition.telemetryCommand ?? definition.name;
4679
4994
  }
4995
+ var TELEMETRY_EXEMPT_COMMANDS = {};
4996
+ function telemetrySubcommandNames(definition) {
4997
+ return [
4998
+ ...definition.subcommands?.map((subcommand) => subcommand.name) ?? [],
4999
+ ...definition.telemetrySubcommands ?? []
5000
+ ];
5001
+ }
4680
5002
  var OFFLINE_PROMPTS_SUBCOMMANDS = new Set(["init", "status", "diff", "migrate"]);
4681
5003
  function legacyCommand(metadata) {
4682
5004
  return {
@@ -4771,9 +5093,9 @@ var commandRegistry = createCommandRegistry([
4771
5093
  mutability: "write",
4772
5094
  validateConfigBeforeRun: false,
4773
5095
  resetApiRequestCountBeforeRun: true,
4774
- telemetry: "result",
5096
+ telemetry: "result-and-error",
4775
5097
  handler: async (context) => {
4776
- const { runInit } = await import("./index-f6cydfxg.js");
5098
+ const { runInit } = await import("./index-ccdpy9ma.js");
4777
5099
  if (context.outputMode === "agent-stream") {
4778
5100
  context.output.writeEvent({
4779
5101
  event: "started",
@@ -4814,7 +5136,7 @@ var commandRegistry = createCommandRegistry([
4814
5136
  resetApiRequestCountBeforeRun: true,
4815
5137
  telemetry: "result-and-error",
4816
5138
  handler: async (context) => {
4817
- const { runProvision } = await import("./provision-rm0yc08f.js");
5139
+ const { runProvision } = await import("./provision-25bw5rd7.js");
4818
5140
  return runProvision(context, {
4819
5141
  resumeCommand: buildResumeCommand("provision", context.rawFlags)
4820
5142
  });
@@ -4829,7 +5151,7 @@ var commandRegistry = createCommandRegistry([
4829
5151
  mutability: "read",
4830
5152
  validateConfigBeforeRun: false,
4831
5153
  resetApiRequestCountBeforeRun: false,
4832
- telemetry: "none",
5154
+ telemetry: "result-and-error",
4833
5155
  handler: async (context) => {
4834
5156
  const manifest = buildManifest(commandRegistry.all());
4835
5157
  if (context.outputMode === "human") {
@@ -4936,7 +5258,7 @@ var commandRegistry = createCommandRegistry([
4936
5258
  mutability: "write",
4937
5259
  validateConfigBeforeRun: false,
4938
5260
  resetApiRequestCountBeforeRun: false,
4939
- telemetry: "none",
5261
+ telemetry: "result-and-error",
4940
5262
  handler: runAuthCommand
4941
5263
  },
4942
5264
  {
@@ -4948,7 +5270,7 @@ var commandRegistry = createCommandRegistry([
4948
5270
  mutability: "read",
4949
5271
  validateConfigBeforeRun: false,
4950
5272
  resetApiRequestCountBeforeRun: false,
4951
- telemetry: "none",
5273
+ telemetry: "result-and-error",
4952
5274
  handler: runStatusCommand
4953
5275
  },
4954
5276
  {
@@ -4961,7 +5283,7 @@ var commandRegistry = createCommandRegistry([
4961
5283
  mutability: "read",
4962
5284
  validateConfigBeforeRun: false,
4963
5285
  resetApiRequestCountBeforeRun: false,
4964
- telemetry: "none",
5286
+ telemetry: "result-and-error",
4965
5287
  handler: runDoctorCommand
4966
5288
  },
4967
5289
  {
@@ -4973,7 +5295,8 @@ var commandRegistry = createCommandRegistry([
4973
5295
  mutability: "write",
4974
5296
  validateConfigBeforeRun: false,
4975
5297
  resetApiRequestCountBeforeRun: false,
4976
- telemetry: "none",
5298
+ telemetry: "result-and-error",
5299
+ telemetrySubcommands: ["list", "use", "create", "doctor"],
4977
5300
  handler: runProfilesCommand
4978
5301
  },
4979
5302
  {
@@ -4985,7 +5308,8 @@ var commandRegistry = createCommandRegistry([
4985
5308
  mutability: "read",
4986
5309
  validateConfigBeforeRun: false,
4987
5310
  resetApiRequestCountBeforeRun: false,
4988
- telemetry: "none",
5311
+ telemetry: "result-and-error",
5312
+ telemetrySubcommands: ["show"],
4989
5313
  handler: runConfigCommand
4990
5314
  },
4991
5315
  {
@@ -5008,7 +5332,8 @@ var commandRegistry = createCommandRegistry([
5008
5332
  mutability: "write",
5009
5333
  validateConfigBeforeRun: false,
5010
5334
  resetApiRequestCountBeforeRun: false,
5011
- telemetry: "none",
5335
+ telemetry: "result-and-error",
5336
+ defaultSubcommand: "scan",
5012
5337
  handler: runHarnessCommand
5013
5338
  },
5014
5339
  {
@@ -5024,7 +5349,9 @@ var commandRegistry = createCommandRegistry([
5024
5349
  mutability: "read",
5025
5350
  validateConfigBeforeRun: false,
5026
5351
  resetApiRequestCountBeforeRun: false,
5027
- telemetry: "none",
5352
+ telemetry: "result-and-error",
5353
+ telemetrySubcommands: ["context", "next-action", "next-actions", "evidence", "investigate"],
5354
+ defaultSubcommand: "context",
5028
5355
  handler: runAgentCommand
5029
5356
  },
5030
5357
  {
@@ -5040,7 +5367,9 @@ var commandRegistry = createCommandRegistry([
5040
5367
  mutability: "write",
5041
5368
  validateConfigBeforeRun: false,
5042
5369
  resetApiRequestCountBeforeRun: false,
5043
- telemetry: "none",
5370
+ telemetry: "result-and-error",
5371
+ telemetrySubcommands: ["harness", "prompts", "skills"],
5372
+ defaultSubcommand: "harness",
5044
5373
  handler: runSyncCommand
5045
5374
  },
5046
5375
  {
@@ -5180,7 +5509,8 @@ var commandRegistry = createCommandRegistry([
5180
5509
  mutability: "write",
5181
5510
  validateConfigBeforeRun: false,
5182
5511
  resetApiRequestCountBeforeRun: false,
5183
- telemetry: "none",
5512
+ telemetry: "result-and-error",
5513
+ defaultSubcommand: "push",
5184
5514
  handler: runRegistryCommand
5185
5515
  },
5186
5516
  legacyCommand({
@@ -5270,7 +5600,9 @@ var commandRegistry = createCommandRegistry([
5270
5600
  "moda context <conversation_id> --msg-index=40 --window=0 # --message-index is an alias",
5271
5601
  "moda context <conversation_id> --metadata-only # summary + total_messages, no messages",
5272
5602
  "moda context <conversation_id> --all",
5273
- "moda context <conversation_id> --all --from=500 --max-messages=500"
5603
+ "moda context <conversation_id> --all --from=500 --max-messages=500",
5604
+ "moda context <id>@12 <id2>@3 <id3> --window=2 # batch: up to 25 targets, one envelope; id@N anchors at message N",
5605
+ "moda context --ids-from=ids.txt --window=1 # one target per line (id or id@N); --ids-from=- reads stdin"
5274
5606
  ],
5275
5607
  ...dataApiDefaults
5276
5608
  }),
@@ -5284,7 +5616,8 @@ var commandRegistry = createCommandRegistry([
5284
5616
  "moda audit <conversation_id> --include-raw",
5285
5617
  "moda audit <conversation_id> --include-bodies # keep prompt/response bodies (omitted by default; long strings truncated)",
5286
5618
  "moda audit <conversation_id> --limit=1000 # ingest rows to read (default 200, max 1000); warns when capped",
5287
- "moda audit <conversation_id> --cursor=<next_cursor> # next page of a capped audit"
5619
+ "moda audit <conversation_id> --cursor=<next_cursor> # next page of a capped audit",
5620
+ "moda audit <id1> <id2> <id3> # batch: up to 25 ids, one envelope (or --ids-from=-|<file>)"
5288
5621
  ],
5289
5622
  ...dataApiDefaults
5290
5623
  }),
@@ -5315,6 +5648,7 @@ var commandRegistry = createCommandRegistry([
5315
5648
  description: "Rank cross-signal Problems by root cause (what to fix first)",
5316
5649
  examples: ["moda problems", "moda problems --days-back=7 --limit=10", "moda problems remainder --family=emotion"],
5317
5650
  subcommands: PROBLEMS_SUBCOMMAND_HELP,
5651
+ defaultSubcommand: "list",
5318
5652
  ...dataApiDefaults
5319
5653
  }),
5320
5654
  legacyCommand({
@@ -5429,6 +5763,7 @@ var commandRegistry = createCommandRegistry([
5429
5763
  "moda signals activate <signal_id>"
5430
5764
  ],
5431
5765
  subcommands: SIGNALS_SUBCOMMAND_HELP,
5766
+ defaultSubcommand: "list",
5432
5767
  ...dataApiDefaults,
5433
5768
  mutability: "write"
5434
5769
  }),
@@ -5616,7 +5951,8 @@ var commandRegistry = createCommandRegistry([
5616
5951
  mutability: "write",
5617
5952
  validateConfigBeforeRun: (parsed) => !OFFLINE_PROMPTS_SUBCOMMANDS.has(parsed.positional ?? "status"),
5618
5953
  resetApiRequestCountBeforeRun: true,
5619
- telemetry: "result-and-error"
5954
+ telemetry: "result-and-error",
5955
+ defaultSubcommand: "status"
5620
5956
  }),
5621
5957
  {
5622
5958
  name: "skills",
@@ -5636,7 +5972,7 @@ var commandRegistry = createCommandRegistry([
5636
5972
  mutability: "write",
5637
5973
  validateConfigBeforeRun: false,
5638
5974
  resetApiRequestCountBeforeRun: false,
5639
- telemetry: "result",
5975
+ telemetry: "result-and-error",
5640
5976
  handler: async (context) => ({
5641
5977
  exitCode: await runSkillsCommand(context)
5642
5978
  })
@@ -5656,9 +5992,10 @@ var commandRegistry = createCommandRegistry([
5656
5992
  outputModes: ["human", "json", "agent"],
5657
5993
  mutability: "write",
5658
5994
  subcommands: FIXES_SUBCOMMAND_HELP,
5995
+ defaultSubcommand: "list",
5659
5996
  validateConfigBeforeRun: false,
5660
5997
  resetApiRequestCountBeforeRun: false,
5661
- telemetry: "result",
5998
+ telemetry: "result-and-error",
5662
5999
  handler: async (context) => ({
5663
6000
  exitCode: await runFixesCommand(context)
5664
6001
  })
@@ -5682,7 +6019,7 @@ var commandRegistry = createCommandRegistry([
5682
6019
  mutability: "write",
5683
6020
  validateConfigBeforeRun: false,
5684
6021
  resetApiRequestCountBeforeRun: false,
5685
- telemetry: "result",
6022
+ telemetry: "result-and-error",
5686
6023
  handler: async (context) => ({
5687
6024
  exitCode: await runFixCommand(context)
5688
6025
  })
@@ -5798,6 +6135,12 @@ function printAgentCliError(command, error, mode = "agent") {
5798
6135
  });
5799
6136
  output.writeError(error);
5800
6137
  }
6138
+ function existingFlagProfile(flags) {
6139
+ const name = flags.profile;
6140
+ if (!name || name === "true")
6141
+ return;
6142
+ return Object.hasOwn(loadProfileConfig({ env: process.env }).profiles, name) ? name : undefined;
6143
+ }
5801
6144
  async function dispatchParsedCommand(parsed, startedAt = Date.now()) {
5802
6145
  const previousProfileEnv = process.env.MODA_PROFILE;
5803
6146
  try {
@@ -5850,8 +6193,7 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
5850
6193
  const telemetryOptOut = telemetryDisabled || flags["no-telemetry"] !== undefined && flags["no-telemetry"] !== "false";
5851
6194
  if (commandDefinition && !telemetryOptOut && commandDefinition.telemetry === "result-and-error") {
5852
6195
  const telemetryCommand2 = telemetryCommandName(commandDefinition);
5853
- const flagProfile = commandFlags.profile && commandFlags.profile !== "true" ? commandFlags.profile : undefined;
5854
- const telemetryProfile = flagProfile && Object.hasOwn(loadProfileConfig({ env: process.env }).profiles, flagProfile) ? flagProfile : undefined;
6196
+ const telemetryProfile = existingFlagProfile(commandFlags);
5855
6197
  sendCliUsageTelemetry({
5856
6198
  apiKey: resolveApiKey({ profile: telemetryProfile }),
5857
6199
  profile: telemetryProfile,
@@ -5870,7 +6212,8 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
5870
6212
  outputMode: mode,
5871
6213
  recorded: {},
5872
6214
  skillVersion: process.env.MODA_SKILL_VERSION,
5873
- subcommands: commandDefinition.subcommands?.map((subcommand) => subcommand.name)
6215
+ subcommands: telemetrySubcommandNames(commandDefinition),
6216
+ defaultSubcommand: commandDefinition.defaultSubcommand
5874
6217
  })
5875
6218
  });
5876
6219
  }
@@ -5925,15 +6268,17 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
5925
6268
  });
5926
6269
  setActiveContext(context);
5927
6270
  const telemetryCommand = telemetryCommandName(definition);
5928
- const telemetrySubcommands = definition.subcommands?.map((subcommand) => subcommand.name);
6271
+ const telemetrySubcommands = telemetrySubcommandNames(definition);
5929
6272
  const needsConfig = typeof definition.validateConfigBeforeRun === "function" ? definition.validateConfigBeforeRun(parsed) : definition.validateConfigBeforeRun;
5930
6273
  if (needsConfig) {
5931
6274
  try {
5932
6275
  validateConfig();
5933
6276
  } catch (error) {
5934
6277
  if (!telemetryDisabled && definition.telemetry === "result-and-error") {
6278
+ const telemetryProfile = existingFlagProfile(commandFlags);
5935
6279
  sendCliUsageTelemetry({
5936
- apiKey: resolveApiKey(),
6280
+ apiKey: resolveApiKey({ profile: telemetryProfile }),
6281
+ profile: telemetryProfile,
5937
6282
  command: telemetryCommand,
5938
6283
  flags: commandFlags,
5939
6284
  status: "error",
@@ -5949,7 +6294,8 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
5949
6294
  outputMode: context.outputMode,
5950
6295
  recorded: context.getTelemetryMeta(),
5951
6296
  skillVersion: process.env.MODA_SKILL_VERSION,
5952
- subcommands: telemetrySubcommands
6297
+ subcommands: telemetrySubcommands,
6298
+ defaultSubcommand: definition.defaultSubcommand
5953
6299
  })
5954
6300
  });
5955
6301
  }
@@ -5967,8 +6313,10 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
5967
6313
  try {
5968
6314
  const result = await definition.handler(context);
5969
6315
  if (!telemetryDisabled && definition.telemetry !== "none") {
6316
+ const telemetryProfile = existingFlagProfile(commandFlags);
5970
6317
  sendCliUsageTelemetry({
5971
- apiKey: result.apiKey ?? resolveApiKey(),
6318
+ apiKey: result.apiKey ?? resolveApiKey({ profile: telemetryProfile }),
6319
+ profile: telemetryProfile,
5972
6320
  command: telemetryCommand,
5973
6321
  flags: commandFlags,
5974
6322
  status: result.exitCode === 0 ? "success" : "error",
@@ -5982,7 +6330,8 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
5982
6330
  outputMode: context.outputMode,
5983
6331
  recorded: context.getTelemetryMeta(),
5984
6332
  skillVersion: process.env.MODA_SKILL_VERSION,
5985
- subcommands: telemetrySubcommands
6333
+ subcommands: telemetrySubcommands,
6334
+ defaultSubcommand: definition.defaultSubcommand
5986
6335
  })
5987
6336
  });
5988
6337
  }
@@ -5993,8 +6342,10 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
5993
6342
  return finishRun(context, { kind: "completed", exitCode: result.exitCode });
5994
6343
  } catch (error) {
5995
6344
  if (!telemetryDisabled && definition.telemetry === "result-and-error") {
6345
+ const telemetryProfile = existingFlagProfile(commandFlags);
5996
6346
  sendCliUsageTelemetry({
5997
- apiKey: resolveApiKey(),
6347
+ apiKey: resolveApiKey({ profile: telemetryProfile }),
6348
+ profile: telemetryProfile,
5998
6349
  command: telemetryCommand,
5999
6350
  flags: commandFlags,
6000
6351
  status: "error",
@@ -6010,7 +6361,8 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
6010
6361
  outputMode: context.outputMode,
6011
6362
  recorded: context.getTelemetryMeta(),
6012
6363
  skillVersion: process.env.MODA_SKILL_VERSION,
6013
- subcommands: telemetrySubcommands
6364
+ subcommands: telemetrySubcommands,
6365
+ defaultSubcommand: definition.defaultSubcommand
6014
6366
  })
6015
6367
  });
6016
6368
  }
@@ -6062,6 +6414,7 @@ if (isMain) {
6062
6414
  });
6063
6415
  }
6064
6416
  export {
6417
+ telemetrySubcommandNames,
6065
6418
  telemetryCommandName,
6066
6419
  stripLoneSurrogates,
6067
6420
  searchOutcomeWarnings,
@@ -6085,6 +6438,7 @@ export {
6085
6438
  capProblemsBlocks,
6086
6439
  buildResumeCommand,
6087
6440
  auditCapStatus,
6441
+ TELEMETRY_EXEMPT_COMMANDS,
6088
6442
  TAIL_LIMITS,
6089
6443
  RAW_BOOLEAN_FLAGS,
6090
6444
  LEGACY_WINDOW_MAX_MESSAGES,