@moda-ai/cli 1.55.26 → 1.55.28

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 (44) hide show
  1. package/dist/{agent-nqmha8ck.js → agent-0w9rtdsw.js} +22 -16
  2. package/dist/cli-3n0gz4d0.js +17971 -0
  3. package/dist/{cli-b4740tnv.js → cli-3retgh64.js} +85 -1165
  4. package/dist/{cli-1mbb0ct0.js → cli-97jew729.js} +1 -1
  5. package/dist/{cli-sqsjd08w.js → cli-99p2jh28.js} +105 -893
  6. package/dist/{cli-k6q8dbpk.js → cli-9bgk5jeh.js} +8 -6
  7. package/dist/{cli-q6f6vrrr.js → cli-9bgnvth2.js} +5 -3
  8. package/dist/cli-9kfxkxmk.js +6994 -0
  9. package/dist/cli-cesds766.js +1516 -0
  10. package/dist/{cli-cdrvjva5.js → cli-dr6x0zv7.js} +28 -6
  11. package/dist/{cli-jtyvbd8d.js → cli-e23g9ywa.js} +1 -1
  12. package/dist/cli-fwpqghgc.js +569 -0
  13. package/dist/cli-k4tqwah4.js +89 -0
  14. package/dist/{cli-8tfk8qeb.js → cli-mg5zv4s6.js} +18 -15
  15. package/dist/{cli-jgfm7w1r.js → cli-n2hng3gv.js} +9 -6
  16. package/dist/cli-ns5fcnkz.js +341 -0
  17. package/dist/{cli-5g1tv80h.js → cli-ny48a8de.js} +12 -9
  18. package/dist/{cli-d577kq6h.js → cli-qpq84eee.js} +5220 -32715
  19. package/dist/cli-xq45etg1.js +1098 -0
  20. package/dist/cli-yf39avhh.js +754 -0
  21. package/dist/cli-yz8xcpyk.js +12 -0
  22. package/dist/cli.js +355 -283
  23. package/dist/doctor-k3ta6h2y.js +24 -0
  24. package/dist/{fix-crkwdkt4.js → fix-w5z02wt4.js} +47 -50
  25. package/dist/{harness-x3e7d68b.js → harness-7azmzytc.js} +15 -7
  26. package/dist/{harness-github-actions-fjhvhgpj.js → harness-github-actions-bv2qrnqb.js} +11 -5
  27. package/dist/harness-report-rd9c4e9v.js +54 -0
  28. package/dist/{index-2kf3fnnb.js → index-d1z50dsq.js} +45 -36
  29. package/dist/{production-intelligence-7n83c701.js → production-intelligence-wvsgjxth.js} +21 -18
  30. package/dist/{profile-commands-ct2t0bfr.js → profile-commands-h8evz9x0.js} +9 -5
  31. package/dist/prompt-attribution-1nytc9wj.js +148 -0
  32. package/dist/prompt-source-mcp.js +14 -7
  33. package/dist/prompt-sources-07tczyqa.js +19 -0
  34. package/dist/{prompts-92aqqb2k.js → prompts-6y9wfq5z.js} +8 -7
  35. package/dist/prompts-ab-ezrd63sk.js +70 -0
  36. package/dist/prompts-propose-2k3enm2q.js +255 -0
  37. package/dist/{provision-gn8raqpt.js → provision-y5bdbh4y.js} +9 -6
  38. package/dist/{registry-ex162j5y.js → registry-96aze5wp.js} +7 -4
  39. package/dist/{skills-2mbsj9bt.js → skills-j8865009.js} +7 -5
  40. package/dist/{sync-kghmmmk5.js → sync-ew7yvy0e.js} +16 -10
  41. package/package.json +1 -1
  42. package/skills/integration/index.json +2 -2
  43. package/dist/cli-bb7133m7.js +0 -144
  44. package/dist/doctor-w913fj4g.js +0 -22
package/dist/cli.js CHANGED
@@ -1,11 +1,31 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- MODA_INTELLIGENCE_V1_JSON_SCHEMA
4
- } from "./cli-bb7133m7.js";
3
+ BATCH_CONCURRENCY,
4
+ BATCH_MAX_TARGETS,
5
+ MODA_INTELLIGENCE_V1_JSON_SCHEMA,
6
+ asNumber,
7
+ asRecord,
8
+ asString,
9
+ collectBatchTargets,
10
+ compactProblemDossier,
11
+ contextTarget,
12
+ embeddedWindowSize,
13
+ frustrationsFromEmotions,
14
+ mapWithConcurrency,
15
+ parseBatchTarget,
16
+ trimToolFailureConversations,
17
+ withFrustrationAnchors,
18
+ withToolFailureAnchors,
19
+ withoutDetectionWindows
20
+ } from "./cli-fwpqghgc.js";
5
21
  import {
6
22
  createCommandContext,
7
- parseBooleanFlagValue
8
- } from "./cli-cdrvjva5.js";
23
+ envOptOutSet,
24
+ envSwitchedOff,
25
+ optOutFlagSet,
26
+ parseBooleanFlagValue,
27
+ withoutFlag
28
+ } from "./cli-dr6x0zv7.js";
9
29
  import {
10
30
  AuditSchema,
11
31
  COMMAND_FLAG_SPECS,
@@ -47,22 +67,14 @@ import {
47
67
  unknownSignalsSubcommandError,
48
68
  usageLine,
49
69
  writeDryRun
50
- } from "./cli-jgfm7w1r.js";
70
+ } from "./cli-n2hng3gv.js";
51
71
  import {
52
72
  ApiError,
53
73
  callControlAPI,
54
74
  callDataAPI
55
- } from "./cli-jtyvbd8d.js";
75
+ } from "./cli-e23g9ywa.js";
56
76
  import {
57
77
  AGENT_ERROR_CODES,
58
- BATCH_CONCURRENCY,
59
- BATCH_MAX_TARGETS,
60
- CliAccessError,
61
- CliAuthError,
62
- CliCancellationError,
63
- CliInputError,
64
- CliInputRequiredError,
65
- CliNotFoundError,
66
78
  EXIT_AUTH_REQUIRED,
67
79
  EXIT_CANCELLED,
68
80
  EXIT_DEGRADED,
@@ -74,46 +86,43 @@ import {
74
86
  VERSION,
75
87
  agentEnvelopeFits,
76
88
  agentMaxOutputBytes,
77
- apiErrorStatus,
78
89
  apiKeyHeaders,
79
- asNumber,
80
- asRecord,
81
- asString,
82
- attachInputDetails,
83
90
  canonicalCommandText,
84
- collectBatchTargets,
85
- compactProblemDossier,
86
- contextTarget,
87
91
  createCliOutput,
88
92
  embeddedTenantIdFromApiKey,
89
- embeddedWindowSize,
90
93
  errorToAgentError,
91
- frustrationsFromEmotions,
92
94
  getApiRequestCount,
93
95
  getModaDir,
94
- inputDetailsOf,
95
- isApiLikeError,
96
- isNetworkLikeError,
97
96
  isPlatformApiKey,
98
97
  loadProfileConfig,
99
- mapWithConcurrency,
100
- parseBatchTarget,
101
98
  resetApiRequestCount,
102
99
  resolveApiKey,
103
100
  resolveApiTenantId,
104
101
  resolveModaBaseUrl,
102
+ resolveModaBaseUrlStrict,
105
103
  resolveOutputMode,
106
104
  safeWriteStderr,
107
105
  safeWriteStdout,
108
106
  setAgentUpdateNotice,
109
107
  setPlatformTenantOverride,
110
- trimToolFailureConversations,
108
+ shellArg,
111
109
  validateConfig,
112
- wasOutputCancelled,
113
- withFrustrationAnchors,
114
- withToolFailureAnchors,
115
- withoutDetectionWindows
116
- } from "./cli-sqsjd08w.js";
110
+ wasOutputCancelled
111
+ } from "./cli-99p2jh28.js";
112
+ import {
113
+ CliAccessError,
114
+ CliAuthError,
115
+ CliCancellationError,
116
+ CliInputError,
117
+ CliInputRequiredError,
118
+ CliNotFoundError,
119
+ apiErrorStatus,
120
+ attachInputDetails,
121
+ inputDetailsOf,
122
+ isApiLikeError,
123
+ isNetworkLikeError
124
+ } from "./cli-k4tqwah4.js";
125
+ import"./cli-ns5fcnkz.js";
117
126
  import {
118
127
  __require
119
128
  } from "./cli-0v6na3yp.js";
@@ -302,16 +311,91 @@ async function runReplaysCommand(context) {
302
311
  }
303
312
 
304
313
  // src/telemetry.ts
314
+ import { spawn as spawn2 } from "node:child_process";
315
+
316
+ // src/detached.ts
305
317
  import { spawn } from "node:child_process";
318
+ var INSPECTOR_VALUE_OPTIONS = new Set(["--inspect-port", "--debug-port", "--inspect-publish-uid"]);
319
+ function nodeOptionTokens(nodeOptions) {
320
+ const tokens = [];
321
+ let start = -1;
322
+ let quoted = false;
323
+ for (let i = 0;i < nodeOptions.length; i += 1) {
324
+ const ch = nodeOptions[i];
325
+ if (start === -1) {
326
+ if (/\s/.test(ch))
327
+ continue;
328
+ start = i;
329
+ }
330
+ if (quoted && ch === "\\") {
331
+ i += 1;
332
+ } else if (ch === '"') {
333
+ quoted = !quoted;
334
+ } else if (!quoted && /\s/.test(ch)) {
335
+ tokens.push(nodeOptions.slice(start, i));
336
+ start = -1;
337
+ }
338
+ }
339
+ if (start !== -1)
340
+ tokens.push(nodeOptions.slice(start));
341
+ return tokens;
342
+ }
343
+ function withoutInspectorOptions(nodeOptions) {
344
+ const tokens = nodeOptionTokens(nodeOptions);
345
+ const kept = [];
346
+ for (let i = 0;i < tokens.length; i += 1) {
347
+ const name = tokens[i].split("=")[0];
348
+ if (!name.startsWith("--inspect") && name !== "--debug-port") {
349
+ kept.push(tokens[i]);
350
+ continue;
351
+ }
352
+ if (INSPECTOR_VALUE_OPTIONS.has(tokens[i]) && tokens[i + 1] && !tokens[i + 1].startsWith("-"))
353
+ i += 1;
354
+ }
355
+ return kept.join(" ");
356
+ }
357
+ function spawnDetachedNode(script, options = {}, spawnImpl = spawn) {
358
+ try {
359
+ const env = { ...process.env, ...options.env };
360
+ for (const key of options.dropEnv ?? [])
361
+ delete env[key];
362
+ if (env.NODE_OPTIONS?.includes("--inspect")) {
363
+ const kept = withoutInspectorOptions(env.NODE_OPTIONS);
364
+ if (kept)
365
+ env.NODE_OPTIONS = kept;
366
+ else
367
+ delete env.NODE_OPTIONS;
368
+ }
369
+ const child = spawnImpl(process.execPath, ["-e", script], {
370
+ detached: true,
371
+ stdio: [options.stdin === undefined ? "ignore" : "pipe", "ignore", "ignore"],
372
+ windowsHide: true,
373
+ env
374
+ });
375
+ child.on("error", () => {});
376
+ if (child.pid === undefined)
377
+ return false;
378
+ if (options.stdin !== undefined && child.stdin) {
379
+ child.stdin.on("error", () => {});
380
+ child.stdin.end(options.stdin);
381
+ }
382
+ child.unref();
383
+ return true;
384
+ } catch {
385
+ return false;
386
+ }
387
+ }
388
+
389
+ // src/telemetry.ts
306
390
  import { randomUUID } from "node:crypto";
307
391
  var INLINE_TELEMETRY_TIMEOUT_MS = 500;
308
392
  var DETACHED_TELEMETRY_TIMEOUT_MS = 5000;
309
393
  var INVOCATION_ID = randomUUID();
310
394
  var TELEMETRY_FLAG = "no-telemetry";
311
- var TELEMETRY_REQUEST_ENV = "MODA_CLI_TELEMETRY_REQUEST";
312
395
  var TELEMETRY_TRANSPORT_ENV = "MODA_CLI_TELEMETRY_TRANSPORT";
313
396
  var MAX_TELEMETRY_DURATION_MS = 86400000;
314
397
  var MAX_TELEMETRY_API_REQUEST_COUNT = 1e6;
398
+ var MAX_UNKNOWN_FLAG_COUNT = 1000;
315
399
  var SEARCH_SURFACE_BY_COMMAND = {
316
400
  search: "message",
317
401
  conversations: "conversation",
@@ -413,11 +497,10 @@ function serializeAdoption(adoption) {
413
497
  return out;
414
498
  }
415
499
  function stripTelemetryFlag(flags) {
416
- const { [TELEMETRY_FLAG]: _drop, ...rest } = flags;
417
- return rest;
500
+ return withoutFlag(flags, TELEMETRY_FLAG);
418
501
  }
419
- function isTelemetryDisabled(flags) {
420
- return flags[TELEMETRY_FLAG] === "true" || process.env.MODA_CLI_TELEMETRY === "0" || process.env.DO_NOT_TRACK === "1";
502
+ function isTelemetryDisabled(flags, env = process.env) {
503
+ return optOutFlagSet(flags, TELEMETRY_FLAG) || envSwitchedOff(env.MODA_CLI_TELEMETRY) || envOptOutSet(env.DO_NOT_TRACK);
421
504
  }
422
505
  var VALIDATION_REASON_MAX = 128;
423
506
  var DEGRADE_REASON_MAX = 64;
@@ -428,88 +511,78 @@ function sanitizeReasonCode(reason, max) {
428
511
  function sanitizeValidationReason(reason) {
429
512
  return sanitizeReasonCode(reason, VALIDATION_REASON_MAX);
430
513
  }
431
- function sanitizedFlagNames(flags) {
432
- return Object.keys(stripTelemetryFlag(flags)).sort();
514
+ var MAX_FLAG_NAMES = 50;
515
+ var FLAG_NAME_RE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
516
+ var SECRET_PATTERNS = [
517
+ /moda_sk_/i,
518
+ /(?:^|[^A-Za-z0-9])sk-[A-Za-z0-9_-]{8,}/,
519
+ /(?:^|[^A-Za-z0-9])(?:sk|pk|rk)_(?:live|test)_/i,
520
+ /gh[pousr]_[A-Za-z0-9]{16,}/,
521
+ /github_pat_/i,
522
+ /xox[abprs]-/i,
523
+ /AKIA[0-9A-Z]{16}/,
524
+ /eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/,
525
+ /-----BEGIN [A-Z ]*PRIVATE KEY/,
526
+ /[^\s@]+@[^\s@]+\.[A-Za-z]{2,}/,
527
+ /[A-Za-z0-9+/=]{32,}/
528
+ ];
529
+ function looksSecret(value) {
530
+ return SECRET_PATTERNS.some((pattern) => pattern.test(value));
531
+ }
532
+ function reportedFlagNames(flags, acceptedFlags = new Set) {
533
+ const names = new Set;
534
+ let unknownCount = 0;
535
+ for (const key of Object.keys(stripTelemetryFlag(flags))) {
536
+ if (acceptedFlags.has(key.replace(/_/g, "-")) && FLAG_NAME_RE.test(key) && !looksSecret(key))
537
+ names.add(key);
538
+ else
539
+ unknownCount += 1;
540
+ }
541
+ const sorted = [...names].sort();
542
+ return { names: sorted.slice(0, MAX_FLAG_NAMES), unknownCount: unknownCount + Math.max(0, sorted.length - MAX_FLAG_NAMES) };
543
+ }
544
+ function reportedValidationReason(reason, knownFlags = new Set) {
545
+ let code = reason;
546
+ const unknownFlag = code ? /^unknown_flag:(.*)$/s.exec(code) : null;
547
+ if (unknownFlag) {
548
+ const name = unknownFlag[1].replace(/_/g, "-");
549
+ code = knownFlags.has(name) && FLAG_NAME_RE.test(name) ? `unknown_flag:${name}` : "unknown_flag";
550
+ }
551
+ const cleaned = sanitizeValidationReason(code);
552
+ if (!cleaned || !looksSecret(cleaned))
553
+ return cleaned;
554
+ const head = cleaned.split(":")[0];
555
+ return head && !looksSecret(head) ? head : undefined;
556
+ }
557
+ function safeCode(value) {
558
+ return value && !looksSecret(value) ? value : undefined;
433
559
  }
434
560
  var TELEMETRY_SENDER_SCRIPT = [
435
561
  "try {",
436
- ` const raw = process.env.${TELEMETRY_REQUEST_ENV};`,
437
- ` delete process.env.${TELEMETRY_REQUEST_ENV};`,
438
- " const r = raw ? JSON.parse(raw) : null;",
439
- " if (r && typeof r.url === 'string' && typeof fetch === 'function') {",
440
- " const c = new AbortController();",
441
- ` const t = setTimeout(() => c.abort(), ${DETACHED_TELEMETRY_TIMEOUT_MS});`,
442
- " fetch(r.url, { method: 'POST', headers: r.headers, body: r.body, signal: c.signal })",
443
- " .then((res) => (res.body && res.body.cancel ? res.body.cancel() : undefined))",
444
- " .catch(() => {})",
445
- " .finally(() => clearTimeout(t));",
446
- " }",
562
+ " let raw = '';",
563
+ ` const quit = setTimeout(() => process.exit(0), ${DETACHED_TELEMETRY_TIMEOUT_MS + 1000});`,
564
+ " const done = () => clearTimeout(quit);",
565
+ " process.stdin.setEncoding('utf8');",
566
+ " process.stdin.on('error', () => {});",
567
+ " process.stdin.on('data', (chunk) => { raw += chunk; });",
568
+ " process.stdin.on('end', () => {",
569
+ " try {",
570
+ " const r = raw ? JSON.parse(raw) : null;",
571
+ " raw = '';",
572
+ " if (!r || typeof r.url !== 'string' || typeof fetch !== 'function') return done();",
573
+ " const c = new AbortController();",
574
+ ` const t = setTimeout(() => c.abort(), ${DETACHED_TELEMETRY_TIMEOUT_MS});`,
575
+ " fetch(r.url, { method: 'POST', headers: r.headers, body: r.body, signal: c.signal })",
576
+ " .then((res) => (res.body && res.body.cancel ? res.body.cancel() : undefined))",
577
+ " .catch(() => {})",
578
+ " .finally(() => { clearTimeout(t); done(); });",
579
+ " } catch { done(); }",
580
+ " });",
447
581
  "} catch {}"
448
582
  ].join(`
449
583
  `);
450
- var INSPECTOR_VALUE_OPTIONS = new Set(["--inspect-port", "--debug-port", "--inspect-publish-uid"]);
451
- function nodeOptionTokens(nodeOptions) {
452
- const tokens = [];
453
- let start = -1;
454
- let quoted = false;
455
- for (let i = 0;i < nodeOptions.length; i += 1) {
456
- const ch = nodeOptions[i];
457
- if (start === -1) {
458
- if (/\s/.test(ch))
459
- continue;
460
- start = i;
461
- }
462
- if (quoted && ch === "\\") {
463
- i += 1;
464
- } else if (ch === '"') {
465
- quoted = !quoted;
466
- } else if (!quoted && /\s/.test(ch)) {
467
- tokens.push(nodeOptions.slice(start, i));
468
- start = -1;
469
- }
470
- }
471
- if (start !== -1)
472
- tokens.push(nodeOptions.slice(start));
473
- return tokens;
474
- }
475
- function withoutInspectorOptions(nodeOptions) {
476
- const tokens = nodeOptionTokens(nodeOptions);
477
- const kept = [];
478
- for (let i = 0;i < tokens.length; i += 1) {
479
- const name = tokens[i].split("=")[0];
480
- if (!name.startsWith("--inspect") && name !== "--debug-port") {
481
- kept.push(tokens[i]);
482
- continue;
483
- }
484
- if (INSPECTOR_VALUE_OPTIONS.has(tokens[i]) && tokens[i + 1] && !tokens[i + 1].startsWith("-"))
485
- i += 1;
486
- }
487
- return kept.join(" ");
488
- }
489
- function spawnDetachedTelemetrySender(request, spawnImpl = spawn) {
490
- try {
491
- const env = { ...process.env, [TELEMETRY_REQUEST_ENV]: JSON.stringify(request) };
492
- if (env.NODE_OPTIONS?.includes("--inspect")) {
493
- const kept = withoutInspectorOptions(env.NODE_OPTIONS);
494
- if (kept)
495
- env.NODE_OPTIONS = kept;
496
- else
497
- delete env.NODE_OPTIONS;
498
- }
499
- const child = spawnImpl(process.execPath, ["-e", TELEMETRY_SENDER_SCRIPT], {
500
- detached: true,
501
- stdio: "ignore",
502
- windowsHide: true,
503
- env
504
- });
505
- child.on("error", () => {});
506
- if (child.pid === undefined)
507
- return false;
508
- child.unref();
509
- return true;
510
- } catch {
511
- return false;
512
- }
584
+ function spawnDetachedTelemetrySender(request, spawnImpl = spawn2) {
585
+ return spawnDetachedNode(TELEMETRY_SENDER_SCRIPT, { stdin: JSON.stringify(request), dropEnv: ["MODA_API_KEY"] }, spawnImpl);
513
586
  }
514
587
  async function sendInline(request) {
515
588
  const controller = new AbortController;
@@ -529,16 +602,25 @@ async function sendInline(request) {
529
602
  }
530
603
  }
531
604
  function buildCliUsageRequest(input) {
532
- const validationReason = sanitizeValidationReason(input.validationReason);
605
+ const baseUrl = resolveModaBaseUrlStrict(input.profile ? { profile: input.profile } : {});
606
+ if (!baseUrl)
607
+ return;
608
+ const validationReason = reportedValidationReason(input.validationReason, input.knownFlags);
609
+ const flagNames = reportedFlagNames(input.flags, input.acceptedFlags);
610
+ const adoption = serializeAdoption(input.adoption);
611
+ for (const key of ["subcommand", "degrade_reason", "skill_version"]) {
612
+ if (typeof adoption[key] === "string" && looksSecret(adoption[key]))
613
+ delete adoption[key];
614
+ }
533
615
  return {
534
- url: `${resolveModaBaseUrl({ profile: input.profile })}/api/v1/data/cli-usage`,
616
+ url: `${baseUrl}/api/v1/data/cli-usage`,
535
617
  headers: {
536
618
  ...apiKeyHeaders(input.apiKey),
537
619
  "Content-Type": "application/json"
538
620
  },
539
621
  body: JSON.stringify({
540
622
  invocation_id: INVOCATION_ID,
541
- command: input.command.slice(0, 64),
623
+ command: safeCode(input.command.slice(0, 64)) ?? "unknown",
542
624
  status: input.status,
543
625
  error_type: input.errorType,
544
626
  ...validationReason ? { validation_reason: validationReason } : {},
@@ -550,10 +632,11 @@ function buildCliUsageRequest(input) {
550
632
  platform: process.platform,
551
633
  arch: process.arch,
552
634
  flags_json: {
553
- names: sanitizedFlagNames(input.flags),
554
- ...((alias) => alias ? { legacy_alias: alias } : {})(sanitizeReasonCode(input.legacyAlias?.replace(/ /g, ":"), 64))
635
+ names: flagNames.names,
636
+ ...flagNames.unknownCount > 0 ? { unknown_count: Math.min(flagNames.unknownCount, MAX_UNKNOWN_FLAG_COUNT) } : {},
637
+ ...((alias) => alias ? { legacy_alias: alias } : {})(safeCode(sanitizeReasonCode(input.legacyAlias?.replace(/ /g, ":"), 64)))
555
638
  },
556
- ...serializeAdoption(input.adoption)
639
+ ...adoption
557
640
  })
558
641
  };
559
642
  }
@@ -563,6 +646,8 @@ async function sendCliUsageTelemetry(input) {
563
646
  return;
564
647
  }
565
648
  const request = buildCliUsageRequest({ ...input, apiKey: input.apiKey });
649
+ if (!request)
650
+ return;
566
651
  if (process.env[TELEMETRY_TRANSPORT_ENV] !== "inline" && spawnDetachedTelemetrySender(request)) {
567
652
  return;
568
653
  }
@@ -579,11 +664,10 @@ var REGISTRY_TIMEOUT_MS = 1500;
579
664
  var REGISTRY_LATEST_URL = "https://registry.npmjs.org/@moda-ai/cli/latest";
580
665
  var SEMVER_RE = /^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/;
581
666
  function stripUpdateCheckFlag(flags) {
582
- const { [UPDATE_CHECK_FLAG]: _drop, ...rest } = flags;
583
- return rest;
667
+ return withoutFlag(flags, UPDATE_CHECK_FLAG);
584
668
  }
585
669
  function isUpdateCheckDisabled(flags, env = process.env) {
586
- return flags[UPDATE_CHECK_FLAG] === "true" || env.MODA_CLI_UPDATE_CHECK === "0" || env.DO_NOT_TRACK === "1" || env.CI !== undefined && env.CI !== "" && env.CI !== "false" && env.CI !== "0";
670
+ return optOutFlagSet(flags, UPDATE_CHECK_FLAG) || envSwitchedOff(env.MODA_CLI_UPDATE_CHECK) || envOptOutSet(env.DO_NOT_TRACK) || envOptOutSet(env.CI);
587
671
  }
588
672
  function cachePath(options = {}) {
589
673
  return join(getModaDir(options), "update-check.json");
@@ -616,9 +700,39 @@ function isNewerVersion(candidate, current) {
616
700
  }
617
701
  return false;
618
702
  }
619
- async function startUpdateCheck(options = {}, now = Date.now()) {
703
+ var UPDATE_CHECK_URL_ENV = "MODA_CLI_UPDATE_CHECK_URL";
704
+ var UPDATE_CHECK_CACHE_ENV = "MODA_CLI_UPDATE_CHECK_CACHE";
705
+ var DETACHED_REGISTRY_TIMEOUT_MS = 1e4;
706
+ var UPDATE_CHECK_SCRIPT = [
707
+ "try {",
708
+ ` const url = process.env.${UPDATE_CHECK_URL_ENV};`,
709
+ ` const path = process.env.${UPDATE_CHECK_CACHE_ENV};`,
710
+ ` const semver = new RegExp(${JSON.stringify(SEMVER_RE.source)});`,
711
+ " if (url && path && typeof fetch === 'function') {",
712
+ " const c = new AbortController();",
713
+ ` const t = setTimeout(() => c.abort(), ${DETACHED_REGISTRY_TIMEOUT_MS});`,
714
+ " fetch(url, { headers: { Accept: 'application/json' }, signal: c.signal })",
715
+ " .then((res) => (res.ok ? res.json() : null))",
716
+ " .then((body) => {",
717
+ " if (body && typeof body.version === 'string' && semver.test(body.version)) {",
718
+ " require('fs').writeFileSync(path, JSON.stringify({ checked_at: Date.now(), latest: body.version }, null, 2) + '\\n', 'utf8');",
719
+ " }",
720
+ " })",
721
+ " .catch(() => {})",
722
+ " .finally(() => clearTimeout(t));",
723
+ " }",
724
+ "} catch {}"
725
+ ].join(`
726
+ `);
727
+ async function startUpdateCheck(options = {}, now = Date.now(), mode = {}) {
620
728
  const cache = readCache(options);
621
- if (cache && now - cache.checked_at < CHECK_INTERVAL_MS) {
729
+ if (cache && cache.checked_at <= now && now - cache.checked_at < CHECK_INTERVAL_MS) {
730
+ return;
731
+ }
732
+ const known = cache && SEMVER_RE.test(cache.latest) ? cache.latest : "";
733
+ writeCache({ checked_at: now, latest: known }, options);
734
+ if (mode.detached) {
735
+ spawnDetachedNode(UPDATE_CHECK_SCRIPT, { env: { [UPDATE_CHECK_URL_ENV]: REGISTRY_LATEST_URL, [UPDATE_CHECK_CACHE_ENV]: cachePath(options) }, dropEnv: ["MODA_API_KEY"] }, mode.spawnImpl);
622
736
  return;
623
737
  }
624
738
  const controller = new AbortController;
@@ -643,16 +757,16 @@ async function startUpdateCheck(options = {}, now = Date.now()) {
643
757
  }
644
758
  function getAvailableUpdate(options = {}) {
645
759
  const cache = readCache(options);
646
- return cache && isNewerVersion(cache.latest, VERSION) ? cache.latest : undefined;
760
+ return cache && SEMVER_RE.test(cache.latest) && isNewerVersion(cache.latest, VERSION) ? cache.latest : undefined;
647
761
  }
648
762
  function getUpdateNotice(options = {}) {
649
- const cache = readCache(options);
650
- if (!cache || !isNewerVersion(cache.latest, VERSION)) {
763
+ const latest = getAvailableUpdate(options);
764
+ if (!latest) {
651
765
  return;
652
766
  }
653
767
  return [
654
768
  "",
655
- `Update available: moda-cli ${VERSION} → ${cache.latest}`,
769
+ `Update available: moda-cli ${VERSION} → ${latest}`,
656
770
  "Run `npm install -g @moda-ai/cli@latest` to update."
657
771
  ].join(`
658
772
  `);
@@ -2528,46 +2642,46 @@ function leafManifestFields(leaf, commands) {
2528
2642
  import { fileURLToPath } from "url";
2529
2643
  import { realpathSync } from "fs";
2530
2644
  async function runPromptsCommand(...args) {
2531
- return (await import("./prompts-92aqqb2k.js")).runPromptsCommand(...args);
2645
+ return (await import("./prompts-6y9wfq5z.js")).runPromptsCommand(...args);
2532
2646
  }
2533
2647
  async function runSkillsCommand(...args) {
2534
- return (await import("./skills-2mbsj9bt.js")).runSkillsCommand(...args);
2648
+ return (await import("./skills-j8865009.js")).runSkillsCommand(...args);
2535
2649
  }
2536
2650
  async function runFixCommand(...args) {
2537
- return (await import("./fix-crkwdkt4.js")).runFixCommand(...args);
2651
+ return (await import("./fix-w5z02wt4.js")).runFixCommand(...args);
2538
2652
  }
2539
2653
  async function runFixesCommand(...args) {
2540
- return (await import("./fix-crkwdkt4.js")).runFixesCommand(...args);
2654
+ return (await import("./fix-w5z02wt4.js")).runFixesCommand(...args);
2541
2655
  }
2542
2656
  async function runHarnessCommand(...args) {
2543
- return (await import("./harness-x3e7d68b.js")).runHarnessCommand(...args);
2657
+ return (await import("./harness-7azmzytc.js")).runHarnessCommand(...args);
2544
2658
  }
2545
2659
  async function runSyncCommand(...args) {
2546
- return (await import("./sync-kghmmmk5.js")).runSyncCommand(...args);
2660
+ return (await import("./sync-ew7yvy0e.js")).runSyncCommand(...args);
2547
2661
  }
2548
2662
  async function runRegistryCommand(...args) {
2549
- return (await import("./registry-ex162j5y.js")).runRegistryCommand(...args);
2663
+ return (await import("./registry-96aze5wp.js")).runRegistryCommand(...args);
2550
2664
  }
2551
2665
  async function runDoctorCommand(...args) {
2552
- return (await import("./doctor-w913fj4g.js")).runDoctorCommand(...args);
2666
+ return (await import("./doctor-k3ta6h2y.js")).runDoctorCommand(...args);
2553
2667
  }
2554
2668
  async function runStatusCommand(...args) {
2555
- return (await import("./doctor-w913fj4g.js")).runStatusCommand(...args);
2669
+ return (await import("./doctor-k3ta6h2y.js")).runStatusCommand(...args);
2556
2670
  }
2557
2671
  async function runAuthCommand(...args) {
2558
- return (await import("./profile-commands-ct2t0bfr.js")).runAuthCommand(...args);
2672
+ return (await import("./profile-commands-h8evz9x0.js")).runAuthCommand(...args);
2559
2673
  }
2560
2674
  async function runConfigCommand(...args) {
2561
- return (await import("./profile-commands-ct2t0bfr.js")).runConfigCommand(...args);
2675
+ return (await import("./profile-commands-h8evz9x0.js")).runConfigCommand(...args);
2562
2676
  }
2563
2677
  async function runProfilesCommand(...args) {
2564
- return (await import("./profile-commands-ct2t0bfr.js")).runProfilesCommand(...args);
2678
+ return (await import("./profile-commands-h8evz9x0.js")).runProfilesCommand(...args);
2565
2679
  }
2566
2680
  async function runAgentCommand(...args) {
2567
- return (await import("./agent-nqmha8ck.js")).runAgentCommand(...args);
2681
+ return (await import("./agent-0w9rtdsw.js")).runAgentCommand(...args);
2568
2682
  }
2569
2683
  async function runProductionCommand(...args) {
2570
- return (await import("./production-intelligence-7n83c701.js")).runProductionCommand(...args);
2684
+ return (await import("./production-intelligence-wvsgjxth.js")).runProductionCommand(...args);
2571
2685
  }
2572
2686
  function parseArgs(argv) {
2573
2687
  const args = argv.slice(2);
@@ -3265,23 +3379,21 @@ function noWorldStateWarnings(conversationId, isMissing) {
3265
3379
  }
3266
3380
  var AUDIT_DEFAULT_LIMIT = 200;
3267
3381
  var AUDIT_MAX_LIMIT = 1000;
3268
- function auditCapStatus(data, limit) {
3382
+ function auditCapStatus(data) {
3269
3383
  const record = asRecord(data);
3270
3384
  if (!record)
3271
3385
  return null;
3272
3386
  const summary = asRecord(record.summary) ?? {};
3273
3387
  const rows = (asNumber(summary.ingest_rows) ?? (Array.isArray(record.ingest) ? record.ingest.length : 0)) + (asNumber(record.parse_errors) ?? 0);
3274
3388
  const spans = asNumber(summary.total_spans) ?? (Array.isArray(record.spans) ? record.spans.length : 0);
3275
- const hasMore = record.has_more === true || summary.has_more === true;
3389
+ const rowsCapped = record.has_more === true || summary.has_more === true;
3276
3390
  const spansCapped = summary.truncated === true || record.truncated === true;
3277
- const serverSaid = typeof record.has_more === "boolean" || typeof summary.has_more === "boolean";
3278
- const rowsCapped = hasMore || !serverSaid && rows >= limit;
3279
3391
  if (!rowsCapped && !spansCapped)
3280
3392
  return null;
3281
3393
  const reason = typeof summary.truncated_reason === "string" ? summary.truncated_reason : null;
3282
3394
  const cursorValue = summary.next_cursor ?? record.next_cursor;
3283
3395
  const nextCursor = typeof cursorValue === "string" && cursorValue ? cursorValue : null;
3284
- return { rowsCapped, spansCapped, hasMoreKnown: hasMore, rows, spans, reason, nextCursor };
3396
+ return { rowsCapped, spansCapped, rows, spans, reason, nextCursor };
3285
3397
  }
3286
3398
  var AUDIT_AGENT_RESERVE_BYTES = 16384;
3287
3399
  function auditMaxBytes(budgetBytes) {
@@ -3326,7 +3438,7 @@ function auditOutput(command, params, data, keep) {
3326
3438
  if (partial && record) {
3327
3439
  const continueWith = auditFlags([
3328
3440
  params.limit ? `--limit=${params.limit}` : "",
3329
- params.cursor ? `--cursor=${params.cursor}` : "",
3441
+ params.cursor ? `--cursor=${shellArg(params.cursor)}` : "",
3330
3442
  params.page_bytes ? `--page-bytes=${params.page_bytes}` : "",
3331
3443
  `--span-offset=${end}`
3332
3444
  ]);
@@ -3352,7 +3464,7 @@ function auditOutput(command, params, data, keep) {
3352
3464
  }
3353
3465
  };
3354
3466
  }
3355
- const capped = auditCapStatus(data, limit);
3467
+ const capped = auditCapStatus(data);
3356
3468
  if (!capped || !record) {
3357
3469
  return {
3358
3470
  data: record ? { ...record, truncated: false, has_more: false, next_cursor: null } : data,
@@ -3365,7 +3477,7 @@ function auditOutput(command, params, data, keep) {
3365
3477
  const nextCommands = [];
3366
3478
  if (capped.nextCursor) {
3367
3479
  nextCommands.push({
3368
- command: auditFlags([params.limit ? `--limit=${params.limit}` : "", `--cursor=${capped.nextCursor}`]),
3480
+ command: auditFlags([params.limit ? `--limit=${params.limit}` : "", `--cursor=${shellArg(capped.nextCursor)}`]),
3369
3481
  purpose: "Read the next page of ingest rows of this trace.",
3370
3482
  mutability: "read",
3371
3483
  requires_approval: false
@@ -3377,7 +3489,7 @@ function auditOutput(command, params, data, keep) {
3377
3489
  warnings.push(`Spans were capped: the page reached the server's per-page span cap after ${capped.rows} ingest row(s), so this trace has more spans than the ${shownText}. Continue with the next_cursor page. Orphan/duplicate analysis covers this page only.`);
3378
3490
  } else if (capped.rowsCapped) {
3379
3491
  const bigger = Math.min(AUDIT_MAX_LIMIT, limit * 5);
3380
- warnings.push(`Spans were capped: read ${capped.rows} ingest row(s), the --limit=${limit} maximum, so this trace ${capped.hasMoreKnown ? "has" : "may have"} more spans than the ${shownText}. ` + (capped.nextCursor ? "Page on with the next_cursor command, or " : "") + (limit < AUDIT_MAX_LIMIT ? `${capped.nextCursor ? "rerun" : "Rerun"} with --limit=${bigger} (max ${AUDIT_MAX_LIMIT}), or ${perTrace}.` : capped.nextCursor ? `${perTrace}.` : `${perTrace[0].toUpperCase()}${perTrace.slice(1)}.`));
3492
+ warnings.push(`Spans were capped: read ${capped.rows} ingest row(s), the --limit=${limit} maximum, so this trace has more spans than the ${shownText}. ` + (capped.nextCursor ? "Page on with the next_cursor command, or " : "") + (limit < AUDIT_MAX_LIMIT ? `${capped.nextCursor ? "rerun" : "Rerun"} with --limit=${bigger} (max ${AUDIT_MAX_LIMIT}), or ${perTrace}.` : capped.nextCursor ? `${perTrace}.` : `${perTrace[0].toUpperCase()}${perTrace.slice(1)}.`));
3381
3493
  if (limit < AUDIT_MAX_LIMIT && !params.cursor && !sliced) {
3382
3494
  nextCommands.push({ command: auditFlags([`--limit=${bigger}`]), purpose: "Read more ingest rows of this trace.", mutability: "read", requires_approval: false });
3383
3495
  }
@@ -3767,13 +3879,6 @@ function specParseOptions(spec) {
3767
3879
  ...spec.flagAliases ? { flagAliases: spec.flagAliases } : {}
3768
3880
  };
3769
3881
  }
3770
- function shellArg(value) {
3771
- if (/^[A-Za-z0-9_.,:@%+\/=-]+$/.test(value))
3772
- return value;
3773
- if (!/["$`\\!]/.test(value))
3774
- return `"${value}"`;
3775
- return `'${value.replace(/'/g, `'\\''`)}'`;
3776
- }
3777
3882
  function semanticIndexCoverage(coverage) {
3778
3883
  const ratio = asRecord(asRecord(coverage)?.semantic_index)?.coverage_ratio;
3779
3884
  if (typeof ratio !== "number" || !Number.isFinite(ratio) || ratio < 0 || ratio > 1)
@@ -4153,8 +4258,18 @@ var CONTEXT_BUDGET_BYTES_PER_FIRST_PAGE_MESSAGE = 480;
4153
4258
  function jsonByteLength(value) {
4154
4259
  return Buffer.byteLength(JSON.stringify(value) ?? "", "utf8");
4155
4260
  }
4156
- var LEGACY_WINDOW_MAX_MESSAGES = 100;
4157
- var CONTEXT_MESSAGE_TRUNCATE_CHARS = 500;
4261
+ function largestFittingCount(max, fits) {
4262
+ let low = 1;
4263
+ let high = Math.max(1, max);
4264
+ while (low < high) {
4265
+ const mid = Math.ceil((low + high) / 2);
4266
+ if (fits(mid))
4267
+ low = mid;
4268
+ else
4269
+ high = mid - 1;
4270
+ }
4271
+ return low;
4272
+ }
4158
4273
  var LONE_SURROGATE = /[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/g;
4159
4274
  function stripLoneSurrogates(value) {
4160
4275
  if (typeof value === "string")
@@ -4166,13 +4281,6 @@ function stripLoneSurrogates(value) {
4166
4281
  }
4167
4282
  return value;
4168
4283
  }
4169
- function isUnknownRangeParamsError(error) {
4170
- const e = error;
4171
- if (e?.statusCode !== 400)
4172
- return false;
4173
- const text = `${typeof e.responseBody === "string" ? e.responseBody : ""} ${typeof e.message === "string" ? e.message : ""}`;
4174
- return /property (from|count) should not exist/i.test(text);
4175
- }
4176
4284
  function pageMessages(page) {
4177
4285
  const messages = asRecord(page.context)?.messages ?? page.messages;
4178
4286
  return (Array.isArray(messages) ? messages : []).map((m) => asRecord(m) ?? {});
@@ -4182,13 +4290,11 @@ async function readFullTranscript(conversationId, opts = {}) {
4182
4290
  const start = opts.from ?? 0;
4183
4291
  const requested = opts.maxMessages ?? FULL_TRANSCRIPT_DEFAULT_MAX_MESSAGES;
4184
4292
  const path = `/conversations/${encodeURIComponent(conversationId)}/context`;
4185
- const warnings = [];
4186
4293
  const messages = [];
4187
4294
  let total = 0;
4188
4295
  let summary = null;
4189
4296
  let ordering;
4190
4297
  let nextFrom = null;
4191
- let legacy = false;
4192
4298
  let cursor = start;
4193
4299
  let readBytes = 0;
4194
4300
  const byteBudget = opts.fits ? opts.maxBytes : undefined;
@@ -4199,22 +4305,13 @@ async function readFullTranscript(conversationId, opts = {}) {
4199
4305
  const estimate = average > 0 ? Math.ceil(Math.max(0, byteBudget - readBytes) / average) + 1 : Math.max(1, Math.floor(byteBudget / CONTEXT_BUDGET_BYTES_PER_FIRST_PAGE_MESSAGE));
4200
4306
  count = Math.max(1, Math.min(count, estimate));
4201
4307
  }
4202
- let page;
4203
- try {
4204
- page = asRecord(await callDataAPI(`${path}?from=${cursor}&count=${count}`)) ?? {};
4205
- } catch (error) {
4206
- if (cursor === start && isUnknownRangeParamsError(error)) {
4207
- legacy = true;
4208
- break;
4209
- }
4210
- throw error;
4211
- }
4308
+ const page = asRecord(await callDataAPI(`${path}?from=${cursor}&count=${count}`)) ?? {};
4212
4309
  if (cursor === start) {
4213
4310
  total = asNumber(page.total_messages) ?? 0;
4214
- summary = page.summary ?? null;
4215
- ordering = asRecord(page.ordering) ?? undefined;
4311
+ summary = stripLoneSurrogates(page.summary ?? null);
4312
+ ordering = stripLoneSurrogates(asRecord(page.ordering) ?? undefined);
4216
4313
  }
4217
- const batch = pageMessages(page);
4314
+ const batch = stripLoneSurrogates(pageMessages(page));
4218
4315
  messages.push(...batch);
4219
4316
  if (byteBudget !== undefined)
4220
4317
  readBytes += batch.reduce((sum, message) => sum + jsonByteLength(message) + 1, 0);
@@ -4226,46 +4323,13 @@ async function readFullTranscript(conversationId, opts = {}) {
4226
4323
  break;
4227
4324
  cursor = nextFrom;
4228
4325
  }
4229
- if (legacy) {
4230
- const limit = Math.min(requested, LEGACY_WINDOW_MAX_MESSAGES);
4231
- const window = 5;
4232
- const span = window * 2 + 1;
4233
- const byIndex = new Map;
4234
- for (let center = start + window;; center += span) {
4235
- const page = asRecord(await callDataAPI(`${path}?msg_index=${center}&window=${window}`)) ?? {};
4236
- if (center === start + window) {
4237
- total = asNumber(page.total_messages) ?? 0;
4238
- summary = page.summary ?? null;
4239
- }
4240
- for (const message of pageMessages(page)) {
4241
- const index = asNumber(message.index);
4242
- if (index !== null && index !== undefined && index >= start && index < start + limit)
4243
- byIndex.set(index, message);
4244
- }
4245
- if (center + window + 1 >= Math.min(total, start + limit))
4246
- break;
4247
- }
4248
- messages.push(...[...byIndex.entries()].sort(([a], [b]) => a - b).map(([, message]) => message));
4249
- const end = start + messages.length;
4250
- nextFrom = end < total && messages.length > 0 ? end : null;
4251
- warnings.push(`This Moda server has no range reads for context (older backend), so --all fell back to windowed paging and stopped at ${LEGACY_WINDOW_MAX_MESSAGES} messages to keep it cheap.`);
4252
- }
4253
4326
  throwIfNotFound("trace", conversationId, total === 0);
4254
- const pageSize = legacy ? LEGACY_WINDOW_MAX_MESSAGES : requested;
4327
+ const pageSize = requested;
4255
4328
  const tied = asNumber(ordering?.tied_timestamp_messages) ?? 0;
4256
4329
  const synthetic = asNumber(ordering?.synthetic_timestamp_messages) ?? 0;
4257
- const atCap = (value) => {
4258
- const text = typeof value === "string" ? value : value === undefined || value === null ? "" : JSON.stringify(value);
4259
- return text.length >= CONTEXT_MESSAGE_TRUNCATE_CHARS;
4260
- };
4261
- const isTruncated = (record) => {
4262
- const toolCalls = Array.isArray(record.tool_calls) ? record.tool_calls : [];
4263
- const toolResults = Array.isArray(record.tool_results) ? record.tool_results : [];
4264
- return atCap(record.content) || toolCalls.some((call) => atCap(asRecord(call)?.input)) || toolResults.some((result) => atCap(asRecord(result)?.content));
4265
- };
4266
4330
  const build = (kept) => {
4267
4331
  const returned = messages.slice(0, kept);
4268
- const out = [...warnings];
4332
+ const out = [];
4269
4333
  if (total > 0 && start >= total) {
4270
4334
  out.push(`--from=${start} is past the end of this trace (${total} messages, indexes 0-${total - 1}).`);
4271
4335
  }
@@ -4287,12 +4351,9 @@ async function readFullTranscript(conversationId, opts = {}) {
4287
4351
  if (tied > 0 || synthetic > 0) {
4288
4352
  out.push(`Message order may not be chronological: ${tied} of ${total} messages share a timestamp with another message (ordered by id, not time)${synthetic > 0 ? ` and ${synthetic} carry a synthetic pre-2022 timestamp` : ""}.`);
4289
4353
  }
4290
- if (legacy && returned.some(isTruncated)) {
4291
- out.push(`This Moda server is older and truncates message text, tool-call inputs and tool results longer than ${CONTEXT_MESSAGE_TRUNCATE_CHARS} characters. For full content (prompts, tool arguments/results) use \`moda traces spans <conversation_id> --include-bodies\` (or \`--include-raw\` for the verbatim events).`);
4292
- }
4293
4354
  return {
4294
- data: stripLoneSurrogates({
4295
- conversation_id: conversationId,
4355
+ data: {
4356
+ conversation_id: stripLoneSurrogates(conversationId),
4296
4357
  total_messages: total,
4297
4358
  from: start,
4298
4359
  returned: returned.length,
@@ -4301,7 +4362,7 @@ async function readFullTranscript(conversationId, opts = {}) {
4301
4362
  summary,
4302
4363
  ...ordering ? { ordering } : {},
4303
4364
  messages: returned
4304
- }),
4365
+ },
4305
4366
  warnings: out,
4306
4367
  nextCommands
4307
4368
  };
@@ -4309,18 +4370,10 @@ async function readFullTranscript(conversationId, opts = {}) {
4309
4370
  const full = build(messages.length);
4310
4371
  if (!opts.fits || messages.length <= 1 || opts.fits(full))
4311
4372
  return full;
4312
- let low = 1;
4313
- let high = messages.length - 1;
4314
- while (low < high) {
4315
- const mid = Math.ceil((low + high) / 2);
4316
- if (opts.fits(build(mid)))
4317
- low = mid;
4318
- else
4319
- high = mid - 1;
4320
- }
4321
- return build(low);
4373
+ const fits = opts.fits;
4374
+ return build(largestFittingCount(messages.length - 1, (kept) => fits(build(kept))));
4322
4375
  }
4323
- async function readContextItem(command, params, inputWarnings, budget) {
4376
+ async function readContextItem(params, inputWarnings, budget) {
4324
4377
  const fits = budget?.fits;
4325
4378
  if (params.all === true) {
4326
4379
  const full = await readFullTranscript(params.conversation_id, {
@@ -4429,17 +4482,10 @@ function trimContextWindow(conversationId, record, requestedAnchor, fits) {
4429
4482
  };
4430
4483
  return { data, warnings, nextCommands };
4431
4484
  };
4432
- let low = 1;
4433
- let high = order.length;
4434
- while (low < high) {
4435
- const mid = Math.ceil((low + high) / 2);
4436
- const page = build(mid);
4437
- if (fits(page.data, page.warnings, page.nextCommands))
4438
- low = mid;
4439
- else
4440
- high = mid - 1;
4441
- }
4442
- return build(low);
4485
+ return build(largestFittingCount(order.length, (kept) => {
4486
+ const page = build(kept);
4487
+ return fits(page.data, page.warnings, page.nextCommands);
4488
+ }));
4443
4489
  }
4444
4490
  var AUDIT_USAGE = "Usage: moda traces spans <conversation_id|trace_id> [--kind=auto|trace|conversation] [--include-raw] [--include-bodies] [--limit=N] [--cursor=<next_cursor>]";
4445
4491
  var AUDIT_BATCH_USAGE = `Usage: moda traces spans <id> <id> ... | --ids-from=-|<file> [--kind=auto|trace|conversation] [--include-raw] [--include-bodies] [--limit=N] (max ${BATCH_MAX_TARGETS} targets)`;
@@ -4465,16 +4511,10 @@ async function readAuditItem(command, params, budget) {
4465
4511
  const available = (Array.isArray(spans) ? spans.length : 0) - (params.span_offset ?? 0);
4466
4512
  if (available <= 0)
4467
4513
  return whole;
4468
- let low = 1;
4469
- let high = available;
4470
- while (low < high) {
4471
- const mid = Math.ceil((low + high) / 2);
4472
- const page2 = auditOutput(command, params, raw, mid);
4473
- if (budget.fits(page2.data, page2.options))
4474
- low = mid;
4475
- else
4476
- high = mid - 1;
4477
- }
4514
+ const low = largestFittingCount(available, (keep) => {
4515
+ const page2 = auditOutput(command, params, raw, keep);
4516
+ return budget.fits(page2.data, page2.options);
4517
+ });
4478
4518
  const page = auditOutput(command, params, raw, low);
4479
4519
  if (low === 1 && !budget.fits(page.data, page.options)) {
4480
4520
  page.options.warnings = [
@@ -4557,7 +4597,7 @@ async function readBatchTargets(targets, agentMode, read) {
4557
4597
  });
4558
4598
  }
4559
4599
  function fitsShare(share) {
4560
- return (data, options) => Buffer.byteLength(JSON.stringify({ data, ...options }) ?? "", "utf8") <= share;
4600
+ return (data, options) => jsonByteLength({ data, ...options }) <= share;
4561
4601
  }
4562
4602
  function isBatchFatal(error) {
4563
4603
  const type = classifyCliError(error);
@@ -4672,7 +4712,7 @@ async function runContextBatch(command, positionals, flags, context) {
4672
4712
  conversation_id: target.id,
4673
4713
  ...target.msgIndex !== undefined ? { msg_index: target.msgIndex } : {}
4674
4714
  };
4675
- return withAnchorHint(target, () => readContextItem(command, params, [], budget));
4715
+ return withAnchorHint(target, () => readContextItem(params, [], budget));
4676
4716
  });
4677
4717
  return writeBatchResult(command, context, targets, results, inputWarnings, rest);
4678
4718
  }
@@ -4879,16 +4919,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
4879
4919
  return agentEnvelopeFits(command, page2.data, page2.options);
4880
4920
  };
4881
4921
  if (agentMode && kept > 1 && !fitsAgent(kept)) {
4882
- let low = 1;
4883
- let high = kept - 1;
4884
- while (low < high) {
4885
- const mid = Math.ceil((low + high) / 2);
4886
- if (fitsAgent(mid))
4887
- low = mid;
4888
- else
4889
- high = mid - 1;
4890
- }
4891
- kept = low;
4922
+ kept = largestFittingCount(kept - 1, fitsAgent);
4892
4923
  }
4893
4924
  const page = write(kept);
4894
4925
  recordSearchTelemetry(context, page.data);
@@ -4950,7 +4981,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
4950
4981
  return runContextBatch(command, positionals, flags, context);
4951
4982
  const { params, warnings: inputWarnings } = parseContextRequest(...singleContextTarget(positional, flags));
4952
4983
  const agentMode = context.output.mode === "agent" || context.output.mode === "agent-stream";
4953
- const read = () => readContextItem(command, params, inputWarnings, agentMode ? { fits: (data, options) => agentEnvelopeFits(command, data, options), maxBytes: agentMaxOutputBytes() } : undefined);
4984
+ const read = () => readContextItem(params, inputWarnings, agentMode ? { fits: (data, options) => agentEnvelopeFits(command, data, options), maxBytes: agentMaxOutputBytes() } : undefined);
4954
4985
  const item = positional === undefined ? await read() : await withAnchorHint(parseBatchTarget(positional, true, CONTEXT_USAGE), read);
4955
4986
  context.output.writeData(item.data, item.options);
4956
4987
  break;
@@ -5239,10 +5270,10 @@ async function runCommand(command, positional, flags, positionals = positional ?
5239
5270
  });
5240
5271
  const link = asRecord(data)?.link;
5241
5272
  const summary = describeLinearLink(link);
5242
- const nextCommands = link ? [] : [`moda problems link ${positional}`];
5273
+ const nextCommands = link ? [] : [`moda problems link ${shellArg(positional)}`];
5243
5274
  if (context.outputMode === "human" && !context.quiet) {
5244
5275
  safeWriteStderr(link ? `${summary}
5245
- ` : `${summary} File one with: moda problems link ${positional}
5276
+ ` : `${summary} File one with: moda problems link ${shellArg(positional)}
5246
5277
  `);
5247
5278
  }
5248
5279
  context.output.writeData(data, { summary, nextCommands });
@@ -5663,7 +5694,6 @@ async function runCommand(command, positional, flags, positionals = positional ?
5663
5694
  function telemetryCommandName(definition) {
5664
5695
  return definition.telemetryCommand ?? definition.name;
5665
5696
  }
5666
- var TELEMETRY_EXEMPT_COMMANDS = {};
5667
5697
  function telemetrySubcommandNames(definition) {
5668
5698
  return [
5669
5699
  ...definition.subcommands?.map((subcommand) => subcommand.name) ?? [],
@@ -5796,7 +5826,7 @@ var commandRegistry = createCommandRegistry([
5796
5826
  resetApiRequestCountBeforeRun: true,
5797
5827
  telemetry: "result-and-error",
5798
5828
  handler: async (context) => {
5799
- const { runInit } = await import("./index-2kf3fnnb.js");
5829
+ const { runInit } = await import("./index-d1z50dsq.js");
5800
5830
  if (context.outputMode === "agent-stream") {
5801
5831
  context.output.writeEvent({
5802
5832
  event: "started",
@@ -5846,7 +5876,7 @@ var commandRegistry = createCommandRegistry([
5846
5876
  resetApiRequestCountBeforeRun: true,
5847
5877
  telemetry: "result-and-error",
5848
5878
  handler: async (context) => {
5849
- const { runProvision } = await import("./provision-gn8raqpt.js");
5879
+ const { runProvision } = await import("./provision-y5bdbh4y.js");
5850
5880
  return runProvision(context, {
5851
5881
  resumeCommand: buildResumeCommand("provision", context.rawFlags)
5852
5882
  });
@@ -6923,6 +6953,46 @@ function printAgentCliError(command, error, mode = "agent") {
6923
6953
  });
6924
6954
  output.writeError(error);
6925
6955
  }
6956
+ function flagNamesInLabel(label) {
6957
+ return [...label.matchAll(/--([A-Za-z0-9][A-Za-z0-9-]*)/g)].map((match) => match[1]);
6958
+ }
6959
+ function specFlagNamesDeep(spec) {
6960
+ if (!spec)
6961
+ return [];
6962
+ return [...specFlagNames(spec), ...Object.values(spec.subcommands ?? {}).flatMap((sub) => specFlagNames(sub))];
6963
+ }
6964
+ function telemetryAcceptedFlags(definition, route) {
6965
+ const names = new Set([...GLOBAL_FLAG_NAMES, ...GLOBAL_BOOLEAN_FLAGS]);
6966
+ const add = (list) => {
6967
+ for (const name of list)
6968
+ names.add(name);
6969
+ };
6970
+ if (definition) {
6971
+ add(specFlagNamesDeep(flagSpecFor(definition.name)));
6972
+ for (const flag of definition.documentedFlags ?? [])
6973
+ add(flagNamesInLabel(flag.name));
6974
+ for (const sub of definition.subcommands ?? [])
6975
+ for (const flag of sub.flags ?? [])
6976
+ add(flagNamesInLabel(flag.name));
6977
+ }
6978
+ if (route) {
6979
+ add(route.allowedFlags ?? []);
6980
+ add(Object.keys(route.flagAliases ?? {}));
6981
+ add(specFlagNamesDeep(leafFlagSpec(route.leaf)));
6982
+ }
6983
+ return names;
6984
+ }
6985
+ var knownFlagNames;
6986
+ function telemetryKnownFlags() {
6987
+ if (!knownFlagNames) {
6988
+ knownFlagNames = new Set(RAW_BOOLEAN_FLAGS);
6989
+ for (const definition of commandRegistry.all()) {
6990
+ for (const name of telemetryAcceptedFlags(definition, undefined))
6991
+ knownFlagNames.add(name);
6992
+ }
6993
+ }
6994
+ return knownFlagNames;
6995
+ }
6926
6996
  function existingFlagProfile(flags) {
6927
6997
  const name = flags.profile;
6928
6998
  if (!name || name === "true")
@@ -7095,6 +7165,8 @@ async function dispatchParsedCommandInner(typedParsed, startedAt) {
7095
7165
  if (!handlerTelemetry)
7096
7166
  return;
7097
7167
  const telemetryProfile = existingFlagProfile(typedFlags);
7168
+ if (typedFlags.profile !== undefined && telemetryProfile === undefined)
7169
+ return;
7098
7170
  const adoption = buildSearchAdoptionTelemetry({
7099
7171
  command: handlerTelemetry,
7100
7172
  positional: parsed.positional,
@@ -7122,12 +7194,14 @@ async function dispatchParsedCommandInner(typedParsed, startedAt) {
7122
7194
  durationMs: Date.now() - startedAt,
7123
7195
  apiRequestCount: input.apiRequestCount,
7124
7196
  adoption,
7125
- ...identity2?.legacyAlias ? { legacyAlias: identity2.legacyAlias } : {}
7197
+ ...identity2?.legacyAlias ? { legacyAlias: identity2.legacyAlias } : {},
7198
+ acceptedFlags: telemetryAcceptedFlags(definition2, route),
7199
+ knownFlags: telemetryKnownFlags()
7126
7200
  });
7127
7201
  };
7128
7202
  const failEarly = (error, commandDefinition, identity2) => {
7129
7203
  const mode = outputModeFor();
7130
- const telemetryOptOut = telemetryDisabled || flags["no-telemetry"] !== undefined && flags["no-telemetry"] !== "false";
7204
+ const telemetryOptOut = telemetryDisabled || optOutFlagSet(flags, "no-telemetry", false);
7131
7205
  const reports = commandDefinition ? commandDefinition.telemetry === "result-and-error" : identity2 !== undefined;
7132
7206
  if (reports && !telemetryOptOut) {
7133
7207
  reportUsage({
@@ -7179,7 +7253,7 @@ async function dispatchParsedCommandInner(typedParsed, startedAt) {
7179
7253
  const known = Object.keys(loadProfileConfig({ env: process.env }).profiles);
7180
7254
  if (!known.includes(requestedProfile)) {
7181
7255
  const source = commandFlags.profile ? `--profile=${requestedProfile}` : `MODA_PROFILE=${requestedProfile}`;
7182
- return failEarly(new CliInputError(`Moda profile '${requestedProfile}' does not exist (from ${source}), so nothing was run.`, `Known profiles: ${known.join(", ")}. Create it with 'moda profiles create ${requestedProfile}' or fix the name.`, "unknown_profile"), definition, identity);
7256
+ return failEarly(new CliInputError(`Moda profile '${requestedProfile}' does not exist (from ${source}), so nothing was run.`, `Known profiles: ${known.join(", ")}. Create it with 'moda profiles create ${shellArg(requestedProfile)}' or fix the name.`, "unknown_profile"), definition, identity);
7183
7257
  }
7184
7258
  if (commandFlags.profile)
7185
7259
  process.env.MODA_PROFILE = commandFlags.profile;
@@ -7188,7 +7262,7 @@ async function dispatchParsedCommandInner(typedParsed, startedAt) {
7188
7262
  commandFlags.agent = "true";
7189
7263
  }
7190
7264
  if (!updateCheckDisabled) {
7191
- startUpdateCheck();
7265
+ startUpdateCheck({}, Date.now(), { detached: outputModeFor() !== "human" });
7192
7266
  setAgentUpdateNotice(() => {
7193
7267
  const latest = getAvailableUpdate();
7194
7268
  return latest ? `moda-cli ${VERSION} is out of date (latest ${latest}); commands and flags may differ from the docs. Update: npm install -g @moda-ai/cli@latest` : undefined;
@@ -7331,7 +7405,6 @@ export {
7331
7405
  trimContextWindow,
7332
7406
  telemetrySubcommandNames,
7333
7407
  telemetryCommandName,
7334
- stripLoneSurrogates,
7335
7408
  searchOutcomeWarnings,
7336
7409
  searchDegradeWarning,
7337
7410
  searchCoverageWarnings,
@@ -7342,6 +7415,7 @@ export {
7342
7415
  parseCommandFlags,
7343
7416
  parseArgs,
7344
7417
  normalizeBooleanFlags,
7418
+ largestFittingCount,
7345
7419
  initFlagsForContext,
7346
7420
  globalFlagHelpLines,
7347
7421
  flagsToArgs,
@@ -7358,10 +7432,8 @@ export {
7358
7432
  canonicalFlagKey,
7359
7433
  buildResumeCommand,
7360
7434
  auditCapStatus,
7361
- TELEMETRY_EXEMPT_COMMANDS,
7362
7435
  TAIL_LIMITS,
7363
7436
  RAW_BOOLEAN_FLAGS,
7364
- LEGACY_WINDOW_MAX_MESSAGES,
7365
7437
  FULL_TRANSCRIPT_DEFAULT_MAX_MESSAGES,
7366
7438
  CliInputError,
7367
7439
  CONTEXT_MAX_WINDOW,