@moda-ai/cli 1.55.27 → 1.55.29
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.
- package/dist/{agent-vp9prdma.js → agent-0w9rtdsw.js} +22 -16
- package/dist/cli-3n0gz4d0.js +17971 -0
- package/dist/{cli-q9nsvqqg.js → cli-3retgh64.js} +85 -1165
- package/dist/{cli-ccjfwzqx.js → cli-97jew729.js} +1 -1
- package/dist/{cli-r5pp7qny.js → cli-99p2jh28.js} +42 -456
- package/dist/{cli-0pkc8jhg.js → cli-9bgk5jeh.js} +8 -6
- package/dist/{cli-hmjdgxrn.js → cli-9bgnvth2.js} +5 -3
- package/dist/cli-9kfxkxmk.js +6994 -0
- package/dist/cli-cesds766.js +1516 -0
- package/dist/{cli-v8q7sd7g.js → cli-dr6x0zv7.js} +1 -1
- package/dist/{cli-pg5qfmqc.js → cli-e23g9ywa.js} +1 -1
- package/dist/{cli-vdkwkkp5.js → cli-fwpqghgc.js} +4 -2
- package/dist/cli-k4tqwah4.js +89 -0
- package/dist/{cli-6et4z504.js → cli-mg5zv4s6.js} +15 -13
- package/dist/{cli-wzds257x.js → cli-n2hng3gv.js} +6 -4
- package/dist/cli-ns5fcnkz.js +341 -0
- package/dist/{cli-4h0ave0f.js → cli-ny48a8de.js} +12 -9
- package/dist/{cli-qwgct6x7.js → cli-qpq84eee.js} +5220 -32716
- package/dist/cli-xq45etg1.js +1098 -0
- package/dist/cli-yf39avhh.js +754 -0
- package/dist/cli-yz8xcpyk.js +12 -0
- package/dist/cli.js +435 -192
- package/dist/doctor-k3ta6h2y.js +24 -0
- package/dist/{fix-75s9s0d6.js → fix-w5z02wt4.js} +8 -9
- package/dist/{harness-a7tb9a23.js → harness-7azmzytc.js} +15 -7
- package/dist/{harness-github-actions-6v4wydb8.js → harness-github-actions-bv2qrnqb.js} +11 -5
- package/dist/harness-report-rd9c4e9v.js +54 -0
- package/dist/{index-91bpc8g8.js → index-d1z50dsq.js} +41 -33
- package/dist/{production-intelligence-7nqddd4f.js → production-intelligence-wvsgjxth.js} +9 -6
- package/dist/{profile-commands-49yn02yg.js → profile-commands-h8evz9x0.js} +7 -4
- package/dist/prompt-attribution-1nytc9wj.js +148 -0
- package/dist/prompt-source-mcp.js +14 -7
- package/dist/prompt-sources-07tczyqa.js +19 -0
- package/dist/{prompts-17wyrst6.js → prompts-6y9wfq5z.js} +8 -7
- package/dist/prompts-ab-ezrd63sk.js +70 -0
- package/dist/prompts-propose-2k3enm2q.js +255 -0
- package/dist/{provision-bc3h68e1.js → provision-y5bdbh4y.js} +9 -6
- package/dist/{registry-fpzhjznj.js → registry-96aze5wp.js} +7 -4
- package/dist/{skills-ccdbqghj.js → skills-j8865009.js} +7 -5
- package/dist/{sync-hkxce5zh.js → sync-ew7yvy0e.js} +16 -10
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/dist/doctor-wmre3mr7.js +0 -22
package/dist/cli.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
withFrustrationAnchors,
|
|
18
18
|
withToolFailureAnchors,
|
|
19
19
|
withoutDetectionWindows
|
|
20
|
-
} from "./cli-
|
|
20
|
+
} from "./cli-fwpqghgc.js";
|
|
21
21
|
import {
|
|
22
22
|
createCommandContext,
|
|
23
23
|
envOptOutSet,
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
optOutFlagSet,
|
|
26
26
|
parseBooleanFlagValue,
|
|
27
27
|
withoutFlag
|
|
28
|
-
} from "./cli-
|
|
28
|
+
} from "./cli-dr6x0zv7.js";
|
|
29
29
|
import {
|
|
30
30
|
AuditSchema,
|
|
31
31
|
COMMAND_FLAG_SPECS,
|
|
@@ -67,20 +67,14 @@ import {
|
|
|
67
67
|
unknownSignalsSubcommandError,
|
|
68
68
|
usageLine,
|
|
69
69
|
writeDryRun
|
|
70
|
-
} from "./cli-
|
|
70
|
+
} from "./cli-n2hng3gv.js";
|
|
71
71
|
import {
|
|
72
72
|
ApiError,
|
|
73
73
|
callControlAPI,
|
|
74
74
|
callDataAPI
|
|
75
|
-
} from "./cli-
|
|
75
|
+
} from "./cli-e23g9ywa.js";
|
|
76
76
|
import {
|
|
77
77
|
AGENT_ERROR_CODES,
|
|
78
|
-
CliAccessError,
|
|
79
|
-
CliAuthError,
|
|
80
|
-
CliCancellationError,
|
|
81
|
-
CliInputError,
|
|
82
|
-
CliInputRequiredError,
|
|
83
|
-
CliNotFoundError,
|
|
84
78
|
EXIT_AUTH_REQUIRED,
|
|
85
79
|
EXIT_CANCELLED,
|
|
86
80
|
EXIT_DEGRADED,
|
|
@@ -92,18 +86,14 @@ import {
|
|
|
92
86
|
VERSION,
|
|
93
87
|
agentEnvelopeFits,
|
|
94
88
|
agentMaxOutputBytes,
|
|
95
|
-
apiErrorStatus,
|
|
96
89
|
apiKeyHeaders,
|
|
97
|
-
attachInputDetails,
|
|
98
90
|
canonicalCommandText,
|
|
99
91
|
createCliOutput,
|
|
100
92
|
embeddedTenantIdFromApiKey,
|
|
101
93
|
errorToAgentError,
|
|
94
|
+
getActiveProfile,
|
|
102
95
|
getApiRequestCount,
|
|
103
96
|
getModaDir,
|
|
104
|
-
inputDetailsOf,
|
|
105
|
-
isApiLikeError,
|
|
106
|
-
isNetworkLikeError,
|
|
107
97
|
isPlatformApiKey,
|
|
108
98
|
loadProfileConfig,
|
|
109
99
|
resetApiRequestCount,
|
|
@@ -119,13 +109,27 @@ import {
|
|
|
119
109
|
shellArg,
|
|
120
110
|
validateConfig,
|
|
121
111
|
wasOutputCancelled
|
|
122
|
-
} from "./cli-
|
|
112
|
+
} from "./cli-99p2jh28.js";
|
|
113
|
+
import {
|
|
114
|
+
CliAccessError,
|
|
115
|
+
CliAuthError,
|
|
116
|
+
CliCancellationError,
|
|
117
|
+
CliInputError,
|
|
118
|
+
CliInputRequiredError,
|
|
119
|
+
CliNotFoundError,
|
|
120
|
+
apiErrorStatus,
|
|
121
|
+
attachInputDetails,
|
|
122
|
+
inputDetailsOf,
|
|
123
|
+
isApiLikeError,
|
|
124
|
+
isNetworkLikeError
|
|
125
|
+
} from "./cli-k4tqwah4.js";
|
|
126
|
+
import"./cli-ns5fcnkz.js";
|
|
123
127
|
import {
|
|
124
128
|
__require
|
|
125
129
|
} from "./cli-0v6na3yp.js";
|
|
126
130
|
|
|
127
131
|
// src/cli.ts
|
|
128
|
-
import { randomUUID as
|
|
132
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
129
133
|
import { z } from "zod";
|
|
130
134
|
|
|
131
135
|
// src/replays.ts
|
|
@@ -384,10 +388,223 @@ function spawnDetachedNode(script, options = {}, spawnImpl = spawn) {
|
|
|
384
388
|
}
|
|
385
389
|
|
|
386
390
|
// src/telemetry.ts
|
|
387
|
-
import { randomUUID } from "node:crypto";
|
|
391
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
392
|
+
|
|
393
|
+
// src/telemetry-spool.ts
|
|
394
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
395
|
+
import {
|
|
396
|
+
closeSync,
|
|
397
|
+
constants as fsConstants,
|
|
398
|
+
fchmodSync,
|
|
399
|
+
mkdirSync,
|
|
400
|
+
openSync,
|
|
401
|
+
readFileSync,
|
|
402
|
+
renameSync,
|
|
403
|
+
rmSync,
|
|
404
|
+
statSync,
|
|
405
|
+
unlinkSync,
|
|
406
|
+
writeSync
|
|
407
|
+
} from "node:fs";
|
|
408
|
+
import { join } from "node:path";
|
|
409
|
+
var SPOOL_MAX_BYTES = 256 * 1024;
|
|
410
|
+
var FLUSH_MIN_EVENTS = 20;
|
|
411
|
+
var FLUSH_MAX_AGE_MS = 30000;
|
|
412
|
+
var SPOOL_MAX_EVENT_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
413
|
+
var FLUSH_LOCK_STALE_MS = 30000;
|
|
414
|
+
var MAX_BATCH_EVENTS = 50;
|
|
415
|
+
var SPOOL_LOCK_STALE_MS = 2000;
|
|
416
|
+
var SPOOL_LOCK_WAIT_MS = 200;
|
|
417
|
+
var SPOOL_FILE = "usage-spool.jsonl";
|
|
418
|
+
var LOCK_FILE = "flush.lock";
|
|
419
|
+
var SPOOL_LOCK_FILE = "spool.lock";
|
|
420
|
+
var O_NOFOLLOW = fsConstants.O_NOFOLLOW ?? 0;
|
|
421
|
+
function telemetrySpoolDir() {
|
|
422
|
+
return join(getModaDir(), "telemetry");
|
|
423
|
+
}
|
|
424
|
+
function keyFingerprint(apiKey) {
|
|
425
|
+
return createHash("sha256").update(`moda-cli-usage-spool\x00${apiKey}`).digest("hex").slice(0, 16);
|
|
426
|
+
}
|
|
427
|
+
function ensureDir(dir) {
|
|
428
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
429
|
+
}
|
|
430
|
+
function appendLines(path, text) {
|
|
431
|
+
const fd = openSync(path, fsConstants.O_WRONLY | fsConstants.O_APPEND | fsConstants.O_CREAT | O_NOFOLLOW, 384);
|
|
432
|
+
try {
|
|
433
|
+
try {
|
|
434
|
+
fchmodSync(fd, 384);
|
|
435
|
+
} catch {}
|
|
436
|
+
writeSync(fd, text);
|
|
437
|
+
} finally {
|
|
438
|
+
closeSync(fd);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function sleepSync(ms) {
|
|
442
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
443
|
+
}
|
|
444
|
+
function createLockFile(path, staleMs, now) {
|
|
445
|
+
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
446
|
+
try {
|
|
447
|
+
const fd = openSync(path, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL | O_NOFOLLOW, 384);
|
|
448
|
+
try {
|
|
449
|
+
writeSync(fd, String(process.pid));
|
|
450
|
+
} finally {
|
|
451
|
+
closeSync(fd);
|
|
452
|
+
}
|
|
453
|
+
return true;
|
|
454
|
+
} catch (error) {
|
|
455
|
+
if (error.code !== "EEXIST")
|
|
456
|
+
return false;
|
|
457
|
+
try {
|
|
458
|
+
if (now - statSync(path).mtimeMs < staleMs)
|
|
459
|
+
return false;
|
|
460
|
+
unlinkSync(path);
|
|
461
|
+
} catch {}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
466
|
+
function withSpoolLock(dir, fn) {
|
|
467
|
+
const path = join(dir, SPOOL_LOCK_FILE);
|
|
468
|
+
const deadline = Date.now() + SPOOL_LOCK_WAIT_MS;
|
|
469
|
+
while (!createLockFile(path, SPOOL_LOCK_STALE_MS, Date.now())) {
|
|
470
|
+
if (Date.now() >= deadline)
|
|
471
|
+
throw new Error("telemetry spool is locked");
|
|
472
|
+
sleepSync(5);
|
|
473
|
+
}
|
|
474
|
+
try {
|
|
475
|
+
return fn();
|
|
476
|
+
} finally {
|
|
477
|
+
try {
|
|
478
|
+
unlinkSync(path);
|
|
479
|
+
} catch {}
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
function fileSize(path) {
|
|
483
|
+
try {
|
|
484
|
+
return statSync(path).size;
|
|
485
|
+
} catch {
|
|
486
|
+
return 0;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
function parseEntries(text) {
|
|
490
|
+
const entries = [];
|
|
491
|
+
for (const line of text.split(`
|
|
492
|
+
`)) {
|
|
493
|
+
if (!line)
|
|
494
|
+
continue;
|
|
495
|
+
try {
|
|
496
|
+
const entry = JSON.parse(line);
|
|
497
|
+
if (entry && entry.v === 1 && typeof entry.url === "string" && typeof entry.profile === "string" && typeof entry.key === "string" && typeof entry.t === "number" && entry.event && typeof entry.event === "object") {
|
|
498
|
+
entries.push(entry);
|
|
499
|
+
}
|
|
500
|
+
} catch {}
|
|
501
|
+
}
|
|
502
|
+
return entries;
|
|
503
|
+
}
|
|
504
|
+
function sameGroup(a, b) {
|
|
505
|
+
return a.url === b.url && a.profile === b.profile && a.key === b.key;
|
|
506
|
+
}
|
|
507
|
+
function appendSpoolEntry(entry, dir = telemetrySpoolDir()) {
|
|
508
|
+
ensureDir(dir);
|
|
509
|
+
const path = join(dir, SPOOL_FILE);
|
|
510
|
+
const line = `${JSON.stringify(entry)}
|
|
511
|
+
`;
|
|
512
|
+
return withSpoolLock(dir, () => {
|
|
513
|
+
if (fileSize(path) + Buffer.byteLength(line) > SPOOL_MAX_BYTES)
|
|
514
|
+
return false;
|
|
515
|
+
appendLines(path, line);
|
|
516
|
+
return true;
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
function readSpool(dir = telemetrySpoolDir()) {
|
|
520
|
+
try {
|
|
521
|
+
return parseEntries(readFileSync(join(dir, SPOOL_FILE), "utf8"));
|
|
522
|
+
} catch {
|
|
523
|
+
return [];
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
function discardSpool(dir = telemetrySpoolDir()) {
|
|
527
|
+
try {
|
|
528
|
+
rmSync(join(dir, SPOOL_FILE), { force: true });
|
|
529
|
+
} catch {}
|
|
530
|
+
}
|
|
531
|
+
function flushDue(entries, group, now) {
|
|
532
|
+
let count = 0;
|
|
533
|
+
for (const entry of entries) {
|
|
534
|
+
if (!sameGroup(entry, group))
|
|
535
|
+
continue;
|
|
536
|
+
count += 1;
|
|
537
|
+
if (count >= FLUSH_MIN_EVENTS || now - entry.t >= FLUSH_MAX_AGE_MS)
|
|
538
|
+
return true;
|
|
539
|
+
}
|
|
540
|
+
return false;
|
|
541
|
+
}
|
|
542
|
+
function acquireFlushLock(dir = telemetrySpoolDir(), now = Date.now()) {
|
|
543
|
+
ensureDir(dir);
|
|
544
|
+
const path = join(dir, LOCK_FILE);
|
|
545
|
+
return createLockFile(path, FLUSH_LOCK_STALE_MS, now) ? path : undefined;
|
|
546
|
+
}
|
|
547
|
+
function releaseFlushLock(path) {
|
|
548
|
+
if (!path)
|
|
549
|
+
return;
|
|
550
|
+
try {
|
|
551
|
+
unlinkSync(path);
|
|
552
|
+
} catch {}
|
|
553
|
+
}
|
|
554
|
+
function claimSpoolGroup(group, dir = telemetrySpoolDir(), now = Date.now(), limit = Number.POSITIVE_INFINITY) {
|
|
555
|
+
try {
|
|
556
|
+
return withSpoolLock(dir, () => claimLocked(group, dir, now, limit));
|
|
557
|
+
} catch {
|
|
558
|
+
return [];
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
function claimLocked(group, dir, now, limit) {
|
|
562
|
+
const path = join(dir, SPOOL_FILE);
|
|
563
|
+
const claim = join(dir, `${SPOOL_FILE}.${process.pid}.${randomUUID()}.claim`);
|
|
564
|
+
try {
|
|
565
|
+
renameSync(path, claim);
|
|
566
|
+
} catch {
|
|
567
|
+
return [];
|
|
568
|
+
}
|
|
569
|
+
let entries = [];
|
|
570
|
+
try {
|
|
571
|
+
entries = parseEntries(readFileSync(claim, "utf8"));
|
|
572
|
+
} catch {} finally {
|
|
573
|
+
rmSync(claim, { force: true });
|
|
574
|
+
}
|
|
575
|
+
const mine = [];
|
|
576
|
+
const others = [];
|
|
577
|
+
for (const entry of entries) {
|
|
578
|
+
const age = now - entry.t;
|
|
579
|
+
if (age > SPOOL_MAX_EVENT_AGE_MS || age < -FLUSH_LOCK_STALE_MS)
|
|
580
|
+
continue;
|
|
581
|
+
(sameGroup(entry, group) && mine.length < limit ? mine : others).push(entry);
|
|
582
|
+
}
|
|
583
|
+
if (others.length > 0) {
|
|
584
|
+
try {
|
|
585
|
+
const text = others.map((entry) => `${JSON.stringify(entry)}
|
|
586
|
+
`).join("");
|
|
587
|
+
if (fileSize(path) + Buffer.byteLength(text) <= SPOOL_MAX_BYTES)
|
|
588
|
+
appendLines(path, text);
|
|
589
|
+
} catch {}
|
|
590
|
+
}
|
|
591
|
+
return mine;
|
|
592
|
+
}
|
|
593
|
+
function batchBodies(entries, now = Date.now()) {
|
|
594
|
+
const bodies = [];
|
|
595
|
+
for (let start = 0;start < entries.length; start += MAX_BATCH_EVENTS) {
|
|
596
|
+
const events = entries.slice(start, start + MAX_BATCH_EVENTS).map((entry) => ({ ...entry.event, age_ms: Math.min(SPOOL_MAX_EVENT_AGE_MS, Math.max(0, Math.round(now - entry.t))) }));
|
|
597
|
+
bodies.push(JSON.stringify(events));
|
|
598
|
+
}
|
|
599
|
+
return bodies;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// src/telemetry.ts
|
|
388
603
|
var INLINE_TELEMETRY_TIMEOUT_MS = 500;
|
|
389
604
|
var DETACHED_TELEMETRY_TIMEOUT_MS = 5000;
|
|
390
|
-
var
|
|
605
|
+
var DETACHED_TELEMETRY_HARD_STOP_MS = 20000;
|
|
606
|
+
var MAX_FLUSH_BATCHES = Math.floor(DETACHED_TELEMETRY_HARD_STOP_MS / (2 * DETACHED_TELEMETRY_TIMEOUT_MS));
|
|
607
|
+
var INVOCATION_ID = randomUUID2();
|
|
391
608
|
var TELEMETRY_FLAG = "no-telemetry";
|
|
392
609
|
var TELEMETRY_TRANSPORT_ENV = "MODA_CLI_TELEMETRY_TRANSPORT";
|
|
393
610
|
var MAX_TELEMETRY_DURATION_MS = 86400000;
|
|
@@ -557,48 +774,103 @@ function safeCode(value) {
|
|
|
557
774
|
var TELEMETRY_SENDER_SCRIPT = [
|
|
558
775
|
"try {",
|
|
559
776
|
" let raw = '';",
|
|
560
|
-
|
|
561
|
-
" const
|
|
777
|
+
" let lock;",
|
|
778
|
+
" const release = () => { if (typeof lock === 'string') { try { require('node:fs').unlinkSync(lock); } catch {} lock = undefined; } };",
|
|
779
|
+
` const quit = setTimeout(() => { release(); process.exit(0); }, ${DETACHED_TELEMETRY_HARD_STOP_MS});`,
|
|
780
|
+
" const done = () => { release(); clearTimeout(quit); };",
|
|
781
|
+
" const post = (r, body) => new Promise((resolve) => {",
|
|
782
|
+
" try {",
|
|
783
|
+
" const u = new URL(r.url);",
|
|
784
|
+
" const lib = require(u.protocol === 'https:' ? 'node:https' : 'node:http');",
|
|
785
|
+
" const headers = Object.assign({}, r.headers, { 'Content-Length': Buffer.byteLength(body) });",
|
|
786
|
+
` const req = lib.request(u, { method: 'POST', headers, agent: false, timeout: ${DETACHED_TELEMETRY_TIMEOUT_MS} }, (res) => {`,
|
|
787
|
+
" res.on('error', () => resolve(0));",
|
|
788
|
+
" res.on('end', () => resolve(res.statusCode || 0));",
|
|
789
|
+
" res.resume();",
|
|
790
|
+
" });",
|
|
791
|
+
" req.on('timeout', () => req.destroy());",
|
|
792
|
+
" req.on('error', () => resolve(0));",
|
|
793
|
+
" req.end(body);",
|
|
794
|
+
" } catch { resolve(0); }",
|
|
795
|
+
" });",
|
|
796
|
+
" const run = async (requests) => {",
|
|
797
|
+
" for (const r of requests) {",
|
|
798
|
+
" if (!r || typeof r.url !== 'string' || typeof r.body !== 'string' || !r.headers || typeof r.headers !== 'object') continue;",
|
|
799
|
+
" const status = await post(r, r.body);",
|
|
800
|
+
" if (status !== 400 || r.body[0] !== '[') continue;",
|
|
801
|
+
" let events = [];",
|
|
802
|
+
" try { events = JSON.parse(r.body); } catch {}",
|
|
803
|
+
" await Promise.all((Array.isArray(events) ? events : []).map((event) => post(r, JSON.stringify(event))));",
|
|
804
|
+
" }",
|
|
805
|
+
" };",
|
|
562
806
|
" process.stdin.setEncoding('utf8');",
|
|
563
807
|
" process.stdin.on('error', () => {});",
|
|
564
808
|
" process.stdin.on('data', (chunk) => { raw += chunk; });",
|
|
565
809
|
" process.stdin.on('end', () => {",
|
|
566
|
-
"
|
|
567
|
-
"
|
|
568
|
-
"
|
|
569
|
-
"
|
|
570
|
-
"
|
|
571
|
-
|
|
572
|
-
" fetch(r.url, { method: 'POST', headers: r.headers, body: r.body, signal: c.signal })",
|
|
573
|
-
" .then((res) => (res.body && res.body.cancel ? res.body.cancel() : undefined))",
|
|
574
|
-
" .catch(() => {})",
|
|
575
|
-
" .finally(() => { clearTimeout(t); done(); });",
|
|
576
|
-
" } catch { done(); }",
|
|
810
|
+
" let job = null;",
|
|
811
|
+
" try { job = raw ? JSON.parse(raw) : null; } catch {}",
|
|
812
|
+
" raw = '';",
|
|
813
|
+
" if (job && typeof job.lock === 'string') lock = job.lock;",
|
|
814
|
+
" const requests = job && Array.isArray(job.requests) ? job.requests : [];",
|
|
815
|
+
" run(requests).catch(() => {}).finally(done);",
|
|
577
816
|
" });",
|
|
578
817
|
"} catch {}"
|
|
579
818
|
].join(`
|
|
580
819
|
`);
|
|
581
|
-
function spawnDetachedTelemetrySender(
|
|
582
|
-
return spawnDetachedNode(TELEMETRY_SENDER_SCRIPT, { stdin: JSON.stringify(
|
|
820
|
+
function spawnDetachedTelemetrySender(job, spawnImpl = spawn2) {
|
|
821
|
+
return spawnDetachedNode(TELEMETRY_SENDER_SCRIPT, { stdin: JSON.stringify(job), dropEnv: ["MODA_API_KEY"] }, spawnImpl);
|
|
822
|
+
}
|
|
823
|
+
async function sendTelemetryJobInline(job) {
|
|
824
|
+
try {
|
|
825
|
+
for (const pending of job.requests)
|
|
826
|
+
await sendInline(pending);
|
|
827
|
+
} finally {
|
|
828
|
+
releaseFlushLock(job.lock);
|
|
829
|
+
}
|
|
583
830
|
}
|
|
584
831
|
async function sendInline(request) {
|
|
832
|
+
const status = await postInline(request);
|
|
833
|
+
if (status !== 400 || !request.body.startsWith("["))
|
|
834
|
+
return;
|
|
835
|
+
let events = [];
|
|
836
|
+
try {
|
|
837
|
+
events = JSON.parse(request.body);
|
|
838
|
+
} catch {}
|
|
839
|
+
if (!Array.isArray(events))
|
|
840
|
+
return;
|
|
841
|
+
await Promise.all(events.map((event) => postInline({ ...request, body: JSON.stringify(event) })));
|
|
842
|
+
}
|
|
843
|
+
async function postInline(request) {
|
|
585
844
|
const controller = new AbortController;
|
|
586
845
|
const timeout = setTimeout(() => controller.abort(), INLINE_TELEMETRY_TIMEOUT_MS);
|
|
587
846
|
if (typeof timeout.unref === "function") {
|
|
588
847
|
timeout.unref();
|
|
589
848
|
}
|
|
590
849
|
try {
|
|
591
|
-
await fetch(request.url, {
|
|
850
|
+
const response = await fetch(request.url, {
|
|
592
851
|
method: "POST",
|
|
593
852
|
headers: request.headers,
|
|
594
853
|
body: request.body,
|
|
595
854
|
signal: controller.signal
|
|
596
855
|
});
|
|
597
|
-
|
|
856
|
+
return response.status;
|
|
857
|
+
} catch {
|
|
858
|
+
return 0;
|
|
859
|
+
} finally {
|
|
598
860
|
clearTimeout(timeout);
|
|
599
861
|
}
|
|
600
862
|
}
|
|
601
|
-
function
|
|
863
|
+
function usageRequest(baseUrl, apiKey, body) {
|
|
864
|
+
return {
|
|
865
|
+
url: `${baseUrl}/api/v1/data/cli-usage`,
|
|
866
|
+
headers: {
|
|
867
|
+
...apiKeyHeaders(apiKey),
|
|
868
|
+
"Content-Type": "application/json"
|
|
869
|
+
},
|
|
870
|
+
body
|
|
871
|
+
};
|
|
872
|
+
}
|
|
873
|
+
function buildCliUsageEvent(input) {
|
|
602
874
|
const baseUrl = resolveModaBaseUrlStrict(input.profile ? { profile: input.profile } : {});
|
|
603
875
|
if (!baseUrl)
|
|
604
876
|
return;
|
|
@@ -610,12 +882,8 @@ function buildCliUsageRequest(input) {
|
|
|
610
882
|
delete adoption[key];
|
|
611
883
|
}
|
|
612
884
|
return {
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
...apiKeyHeaders(input.apiKey),
|
|
616
|
-
"Content-Type": "application/json"
|
|
617
|
-
},
|
|
618
|
-
body: JSON.stringify({
|
|
885
|
+
baseUrl,
|
|
886
|
+
event: {
|
|
619
887
|
invocation_id: INVOCATION_ID,
|
|
620
888
|
command: safeCode(input.command.slice(0, 64)) ?? "unknown",
|
|
621
889
|
status: input.status,
|
|
@@ -634,27 +902,79 @@ function buildCliUsageRequest(input) {
|
|
|
634
902
|
...((alias) => alias ? { legacy_alias: alias } : {})(safeCode(sanitizeReasonCode(input.legacyAlias?.replace(/ /g, ":"), 64)))
|
|
635
903
|
},
|
|
636
904
|
...adoption
|
|
637
|
-
}
|
|
905
|
+
}
|
|
638
906
|
};
|
|
639
907
|
}
|
|
908
|
+
function telemetryProfileName(profile) {
|
|
909
|
+
try {
|
|
910
|
+
return getActiveProfile(profile ? { profile } : {}).name;
|
|
911
|
+
} catch {
|
|
912
|
+
return "";
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
function queueCliUsageEvent(request, group, event, now) {
|
|
916
|
+
const dir = telemetrySpoolDir();
|
|
917
|
+
const entry = { v: 1, ...group, t: now, event };
|
|
918
|
+
let unspooled = [];
|
|
919
|
+
try {
|
|
920
|
+
if (!appendSpoolEntry(entry, dir))
|
|
921
|
+
unspooled = [entry];
|
|
922
|
+
} catch {
|
|
923
|
+
return { requests: [request] };
|
|
924
|
+
}
|
|
925
|
+
const due = unspooled.length > 0 || envOptOutSet(process.env.CI) || flushDue(readSpool(dir), group, now);
|
|
926
|
+
if (!due)
|
|
927
|
+
return;
|
|
928
|
+
const lock = acquireFlushLock(dir, now);
|
|
929
|
+
if (!lock)
|
|
930
|
+
return unspooled.length > 0 ? { requests: [request] } : undefined;
|
|
931
|
+
const limit = MAX_FLUSH_BATCHES * MAX_BATCH_EVENTS - unspooled.length;
|
|
932
|
+
const entries = [...claimSpoolGroup(group, dir, now, limit), ...unspooled];
|
|
933
|
+
if (entries.length === 0) {
|
|
934
|
+
releaseFlushLock(lock);
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
return {
|
|
938
|
+
requests: batchBodies(entries, now).map((body) => ({ url: request.url, headers: request.headers, body })),
|
|
939
|
+
lock
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
function discardSpoolOnEnvOptOut() {
|
|
943
|
+
if (!isTelemetryDisabled({}))
|
|
944
|
+
return false;
|
|
945
|
+
discardSpool();
|
|
946
|
+
return true;
|
|
947
|
+
}
|
|
640
948
|
async function sendCliUsageTelemetry(input) {
|
|
641
949
|
try {
|
|
950
|
+
if (discardSpoolOnEnvOptOut())
|
|
951
|
+
return;
|
|
642
952
|
if (!input.apiKey || isTelemetryDisabled(input.flags)) {
|
|
643
953
|
return;
|
|
644
954
|
}
|
|
645
|
-
const
|
|
646
|
-
if (!
|
|
955
|
+
const built = buildCliUsageEvent(input);
|
|
956
|
+
if (!built)
|
|
647
957
|
return;
|
|
648
|
-
|
|
958
|
+
const request = usageRequest(built.baseUrl, input.apiKey, JSON.stringify(built.event));
|
|
959
|
+
if (process.env[TELEMETRY_TRANSPORT_ENV] === "inline") {
|
|
960
|
+
await sendInline(request);
|
|
649
961
|
return;
|
|
650
962
|
}
|
|
651
|
-
|
|
963
|
+
const group = {
|
|
964
|
+
url: built.baseUrl,
|
|
965
|
+
profile: telemetryProfileName(input.profile),
|
|
966
|
+
key: keyFingerprint(input.apiKey)
|
|
967
|
+
};
|
|
968
|
+
const job = queueCliUsageEvent(request, group, built.event, Date.now());
|
|
969
|
+
if (!job || spawnDetachedTelemetrySender(job))
|
|
970
|
+
return;
|
|
971
|
+
await sendTelemetryJobInline(job);
|
|
652
972
|
} catch {}
|
|
653
973
|
}
|
|
654
974
|
|
|
655
975
|
// src/update-check.ts
|
|
656
|
-
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
657
|
-
import { join } from "node:path";
|
|
976
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync } from "node:fs";
|
|
977
|
+
import { join as join2 } from "node:path";
|
|
658
978
|
var UPDATE_CHECK_FLAG = "no-update-check";
|
|
659
979
|
var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
660
980
|
var REGISTRY_TIMEOUT_MS = 1500;
|
|
@@ -667,11 +987,11 @@ function isUpdateCheckDisabled(flags, env = process.env) {
|
|
|
667
987
|
return optOutFlagSet(flags, UPDATE_CHECK_FLAG) || envSwitchedOff(env.MODA_CLI_UPDATE_CHECK) || envOptOutSet(env.DO_NOT_TRACK) || envOptOutSet(env.CI);
|
|
668
988
|
}
|
|
669
989
|
function cachePath(options = {}) {
|
|
670
|
-
return
|
|
990
|
+
return join2(getModaDir(options), "update-check.json");
|
|
671
991
|
}
|
|
672
992
|
function readCache(options = {}) {
|
|
673
993
|
try {
|
|
674
|
-
const parsed = JSON.parse(
|
|
994
|
+
const parsed = JSON.parse(readFileSync2(cachePath(options), "utf8"));
|
|
675
995
|
if (parsed && typeof parsed === "object" && typeof parsed.checked_at === "number" && typeof parsed.latest === "string") {
|
|
676
996
|
return parsed;
|
|
677
997
|
}
|
|
@@ -680,7 +1000,7 @@ function readCache(options = {}) {
|
|
|
680
1000
|
}
|
|
681
1001
|
function writeCache(cache, options = {}) {
|
|
682
1002
|
try {
|
|
683
|
-
|
|
1003
|
+
mkdirSync2(getModaDir(options), { recursive: true });
|
|
684
1004
|
writeFileSync(cachePath(options), `${JSON.stringify(cache, null, 2)}
|
|
685
1005
|
`, "utf8");
|
|
686
1006
|
} catch {}
|
|
@@ -2639,46 +2959,46 @@ function leafManifestFields(leaf, commands) {
|
|
|
2639
2959
|
import { fileURLToPath } from "url";
|
|
2640
2960
|
import { realpathSync } from "fs";
|
|
2641
2961
|
async function runPromptsCommand(...args) {
|
|
2642
|
-
return (await import("./prompts-
|
|
2962
|
+
return (await import("./prompts-6y9wfq5z.js")).runPromptsCommand(...args);
|
|
2643
2963
|
}
|
|
2644
2964
|
async function runSkillsCommand(...args) {
|
|
2645
|
-
return (await import("./skills-
|
|
2965
|
+
return (await import("./skills-j8865009.js")).runSkillsCommand(...args);
|
|
2646
2966
|
}
|
|
2647
2967
|
async function runFixCommand(...args) {
|
|
2648
|
-
return (await import("./fix-
|
|
2968
|
+
return (await import("./fix-w5z02wt4.js")).runFixCommand(...args);
|
|
2649
2969
|
}
|
|
2650
2970
|
async function runFixesCommand(...args) {
|
|
2651
|
-
return (await import("./fix-
|
|
2971
|
+
return (await import("./fix-w5z02wt4.js")).runFixesCommand(...args);
|
|
2652
2972
|
}
|
|
2653
2973
|
async function runHarnessCommand(...args) {
|
|
2654
|
-
return (await import("./harness-
|
|
2974
|
+
return (await import("./harness-7azmzytc.js")).runHarnessCommand(...args);
|
|
2655
2975
|
}
|
|
2656
2976
|
async function runSyncCommand(...args) {
|
|
2657
|
-
return (await import("./sync-
|
|
2977
|
+
return (await import("./sync-ew7yvy0e.js")).runSyncCommand(...args);
|
|
2658
2978
|
}
|
|
2659
2979
|
async function runRegistryCommand(...args) {
|
|
2660
|
-
return (await import("./registry-
|
|
2980
|
+
return (await import("./registry-96aze5wp.js")).runRegistryCommand(...args);
|
|
2661
2981
|
}
|
|
2662
2982
|
async function runDoctorCommand(...args) {
|
|
2663
|
-
return (await import("./doctor-
|
|
2983
|
+
return (await import("./doctor-k3ta6h2y.js")).runDoctorCommand(...args);
|
|
2664
2984
|
}
|
|
2665
2985
|
async function runStatusCommand(...args) {
|
|
2666
|
-
return (await import("./doctor-
|
|
2986
|
+
return (await import("./doctor-k3ta6h2y.js")).runStatusCommand(...args);
|
|
2667
2987
|
}
|
|
2668
2988
|
async function runAuthCommand(...args) {
|
|
2669
|
-
return (await import("./profile-commands-
|
|
2989
|
+
return (await import("./profile-commands-h8evz9x0.js")).runAuthCommand(...args);
|
|
2670
2990
|
}
|
|
2671
2991
|
async function runConfigCommand(...args) {
|
|
2672
|
-
return (await import("./profile-commands-
|
|
2992
|
+
return (await import("./profile-commands-h8evz9x0.js")).runConfigCommand(...args);
|
|
2673
2993
|
}
|
|
2674
2994
|
async function runProfilesCommand(...args) {
|
|
2675
|
-
return (await import("./profile-commands-
|
|
2995
|
+
return (await import("./profile-commands-h8evz9x0.js")).runProfilesCommand(...args);
|
|
2676
2996
|
}
|
|
2677
2997
|
async function runAgentCommand(...args) {
|
|
2678
|
-
return (await import("./agent-
|
|
2998
|
+
return (await import("./agent-0w9rtdsw.js")).runAgentCommand(...args);
|
|
2679
2999
|
}
|
|
2680
3000
|
async function runProductionCommand(...args) {
|
|
2681
|
-
return (await import("./production-intelligence-
|
|
3001
|
+
return (await import("./production-intelligence-wvsgjxth.js")).runProductionCommand(...args);
|
|
2682
3002
|
}
|
|
2683
3003
|
function parseArgs(argv) {
|
|
2684
3004
|
const args = argv.slice(2);
|
|
@@ -3376,23 +3696,21 @@ function noWorldStateWarnings(conversationId, isMissing) {
|
|
|
3376
3696
|
}
|
|
3377
3697
|
var AUDIT_DEFAULT_LIMIT = 200;
|
|
3378
3698
|
var AUDIT_MAX_LIMIT = 1000;
|
|
3379
|
-
function auditCapStatus(data
|
|
3699
|
+
function auditCapStatus(data) {
|
|
3380
3700
|
const record = asRecord(data);
|
|
3381
3701
|
if (!record)
|
|
3382
3702
|
return null;
|
|
3383
3703
|
const summary = asRecord(record.summary) ?? {};
|
|
3384
3704
|
const rows = (asNumber(summary.ingest_rows) ?? (Array.isArray(record.ingest) ? record.ingest.length : 0)) + (asNumber(record.parse_errors) ?? 0);
|
|
3385
3705
|
const spans = asNumber(summary.total_spans) ?? (Array.isArray(record.spans) ? record.spans.length : 0);
|
|
3386
|
-
const
|
|
3706
|
+
const rowsCapped = record.has_more === true || summary.has_more === true;
|
|
3387
3707
|
const spansCapped = summary.truncated === true || record.truncated === true;
|
|
3388
|
-
const serverSaid = typeof record.has_more === "boolean" || typeof summary.has_more === "boolean";
|
|
3389
|
-
const rowsCapped = hasMore || !serverSaid && rows >= limit;
|
|
3390
3708
|
if (!rowsCapped && !spansCapped)
|
|
3391
3709
|
return null;
|
|
3392
3710
|
const reason = typeof summary.truncated_reason === "string" ? summary.truncated_reason : null;
|
|
3393
3711
|
const cursorValue = summary.next_cursor ?? record.next_cursor;
|
|
3394
3712
|
const nextCursor = typeof cursorValue === "string" && cursorValue ? cursorValue : null;
|
|
3395
|
-
return { rowsCapped, spansCapped,
|
|
3713
|
+
return { rowsCapped, spansCapped, rows, spans, reason, nextCursor };
|
|
3396
3714
|
}
|
|
3397
3715
|
var AUDIT_AGENT_RESERVE_BYTES = 16384;
|
|
3398
3716
|
function auditMaxBytes(budgetBytes) {
|
|
@@ -3463,7 +3781,7 @@ function auditOutput(command, params, data, keep) {
|
|
|
3463
3781
|
}
|
|
3464
3782
|
};
|
|
3465
3783
|
}
|
|
3466
|
-
const capped = auditCapStatus(data
|
|
3784
|
+
const capped = auditCapStatus(data);
|
|
3467
3785
|
if (!capped || !record) {
|
|
3468
3786
|
return {
|
|
3469
3787
|
data: record ? { ...record, truncated: false, has_more: false, next_cursor: null } : data,
|
|
@@ -3488,7 +3806,7 @@ function auditOutput(command, params, data, keep) {
|
|
|
3488
3806
|
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.`);
|
|
3489
3807
|
} else if (capped.rowsCapped) {
|
|
3490
3808
|
const bigger = Math.min(AUDIT_MAX_LIMIT, limit * 5);
|
|
3491
|
-
warnings.push(`Spans were capped: read ${capped.rows} ingest row(s), the --limit=${limit} maximum, so this trace
|
|
3809
|
+
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)}.`));
|
|
3492
3810
|
if (limit < AUDIT_MAX_LIMIT && !params.cursor && !sliced) {
|
|
3493
3811
|
nextCommands.push({ command: auditFlags([`--limit=${bigger}`]), purpose: "Read more ingest rows of this trace.", mutability: "read", requires_approval: false });
|
|
3494
3812
|
}
|
|
@@ -4257,8 +4575,18 @@ var CONTEXT_BUDGET_BYTES_PER_FIRST_PAGE_MESSAGE = 480;
|
|
|
4257
4575
|
function jsonByteLength(value) {
|
|
4258
4576
|
return Buffer.byteLength(JSON.stringify(value) ?? "", "utf8");
|
|
4259
4577
|
}
|
|
4260
|
-
|
|
4261
|
-
|
|
4578
|
+
function largestFittingCount(max, fits) {
|
|
4579
|
+
let low = 1;
|
|
4580
|
+
let high = Math.max(1, max);
|
|
4581
|
+
while (low < high) {
|
|
4582
|
+
const mid = Math.ceil((low + high) / 2);
|
|
4583
|
+
if (fits(mid))
|
|
4584
|
+
low = mid;
|
|
4585
|
+
else
|
|
4586
|
+
high = mid - 1;
|
|
4587
|
+
}
|
|
4588
|
+
return low;
|
|
4589
|
+
}
|
|
4262
4590
|
var LONE_SURROGATE = /[\ud800-\udbff](?![\udc00-\udfff])|(?<![\ud800-\udbff])[\udc00-\udfff]/g;
|
|
4263
4591
|
function stripLoneSurrogates(value) {
|
|
4264
4592
|
if (typeof value === "string")
|
|
@@ -4270,13 +4598,6 @@ function stripLoneSurrogates(value) {
|
|
|
4270
4598
|
}
|
|
4271
4599
|
return value;
|
|
4272
4600
|
}
|
|
4273
|
-
function isUnknownRangeParamsError(error) {
|
|
4274
|
-
const e = error;
|
|
4275
|
-
if (e?.statusCode !== 400)
|
|
4276
|
-
return false;
|
|
4277
|
-
const text = `${typeof e.responseBody === "string" ? e.responseBody : ""} ${typeof e.message === "string" ? e.message : ""}`;
|
|
4278
|
-
return /property (from|count) should not exist/i.test(text);
|
|
4279
|
-
}
|
|
4280
4601
|
function pageMessages(page) {
|
|
4281
4602
|
const messages = asRecord(page.context)?.messages ?? page.messages;
|
|
4282
4603
|
return (Array.isArray(messages) ? messages : []).map((m) => asRecord(m) ?? {});
|
|
@@ -4286,13 +4607,11 @@ async function readFullTranscript(conversationId, opts = {}) {
|
|
|
4286
4607
|
const start = opts.from ?? 0;
|
|
4287
4608
|
const requested = opts.maxMessages ?? FULL_TRANSCRIPT_DEFAULT_MAX_MESSAGES;
|
|
4288
4609
|
const path = `/conversations/${encodeURIComponent(conversationId)}/context`;
|
|
4289
|
-
const warnings = [];
|
|
4290
4610
|
const messages = [];
|
|
4291
4611
|
let total = 0;
|
|
4292
4612
|
let summary = null;
|
|
4293
4613
|
let ordering;
|
|
4294
4614
|
let nextFrom = null;
|
|
4295
|
-
let legacy = false;
|
|
4296
4615
|
let cursor = start;
|
|
4297
4616
|
let readBytes = 0;
|
|
4298
4617
|
const byteBudget = opts.fits ? opts.maxBytes : undefined;
|
|
@@ -4303,22 +4622,13 @@ async function readFullTranscript(conversationId, opts = {}) {
|
|
|
4303
4622
|
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));
|
|
4304
4623
|
count = Math.max(1, Math.min(count, estimate));
|
|
4305
4624
|
}
|
|
4306
|
-
|
|
4307
|
-
try {
|
|
4308
|
-
page = asRecord(await callDataAPI(`${path}?from=${cursor}&count=${count}`)) ?? {};
|
|
4309
|
-
} catch (error) {
|
|
4310
|
-
if (cursor === start && isUnknownRangeParamsError(error)) {
|
|
4311
|
-
legacy = true;
|
|
4312
|
-
break;
|
|
4313
|
-
}
|
|
4314
|
-
throw error;
|
|
4315
|
-
}
|
|
4625
|
+
const page = asRecord(await callDataAPI(`${path}?from=${cursor}&count=${count}`)) ?? {};
|
|
4316
4626
|
if (cursor === start) {
|
|
4317
4627
|
total = asNumber(page.total_messages) ?? 0;
|
|
4318
|
-
summary = page.summary ?? null;
|
|
4319
|
-
ordering = asRecord(page.ordering) ?? undefined;
|
|
4628
|
+
summary = stripLoneSurrogates(page.summary ?? null);
|
|
4629
|
+
ordering = stripLoneSurrogates(asRecord(page.ordering) ?? undefined);
|
|
4320
4630
|
}
|
|
4321
|
-
const batch = pageMessages(page);
|
|
4631
|
+
const batch = stripLoneSurrogates(pageMessages(page));
|
|
4322
4632
|
messages.push(...batch);
|
|
4323
4633
|
if (byteBudget !== undefined)
|
|
4324
4634
|
readBytes += batch.reduce((sum, message) => sum + jsonByteLength(message) + 1, 0);
|
|
@@ -4330,46 +4640,13 @@ async function readFullTranscript(conversationId, opts = {}) {
|
|
|
4330
4640
|
break;
|
|
4331
4641
|
cursor = nextFrom;
|
|
4332
4642
|
}
|
|
4333
|
-
if (legacy) {
|
|
4334
|
-
const limit = Math.min(requested, LEGACY_WINDOW_MAX_MESSAGES);
|
|
4335
|
-
const window = 5;
|
|
4336
|
-
const span = window * 2 + 1;
|
|
4337
|
-
const byIndex = new Map;
|
|
4338
|
-
for (let center = start + window;; center += span) {
|
|
4339
|
-
const page = asRecord(await callDataAPI(`${path}?msg_index=${center}&window=${window}`)) ?? {};
|
|
4340
|
-
if (center === start + window) {
|
|
4341
|
-
total = asNumber(page.total_messages) ?? 0;
|
|
4342
|
-
summary = page.summary ?? null;
|
|
4343
|
-
}
|
|
4344
|
-
for (const message of pageMessages(page)) {
|
|
4345
|
-
const index = asNumber(message.index);
|
|
4346
|
-
if (index !== null && index !== undefined && index >= start && index < start + limit)
|
|
4347
|
-
byIndex.set(index, message);
|
|
4348
|
-
}
|
|
4349
|
-
if (center + window + 1 >= Math.min(total, start + limit))
|
|
4350
|
-
break;
|
|
4351
|
-
}
|
|
4352
|
-
messages.push(...[...byIndex.entries()].sort(([a], [b]) => a - b).map(([, message]) => message));
|
|
4353
|
-
const end = start + messages.length;
|
|
4354
|
-
nextFrom = end < total && messages.length > 0 ? end : null;
|
|
4355
|
-
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.`);
|
|
4356
|
-
}
|
|
4357
4643
|
throwIfNotFound("trace", conversationId, total === 0);
|
|
4358
|
-
const pageSize =
|
|
4644
|
+
const pageSize = requested;
|
|
4359
4645
|
const tied = asNumber(ordering?.tied_timestamp_messages) ?? 0;
|
|
4360
4646
|
const synthetic = asNumber(ordering?.synthetic_timestamp_messages) ?? 0;
|
|
4361
|
-
const atCap = (value) => {
|
|
4362
|
-
const text = typeof value === "string" ? value : value === undefined || value === null ? "" : JSON.stringify(value);
|
|
4363
|
-
return text.length >= CONTEXT_MESSAGE_TRUNCATE_CHARS;
|
|
4364
|
-
};
|
|
4365
|
-
const isTruncated = (record) => {
|
|
4366
|
-
const toolCalls = Array.isArray(record.tool_calls) ? record.tool_calls : [];
|
|
4367
|
-
const toolResults = Array.isArray(record.tool_results) ? record.tool_results : [];
|
|
4368
|
-
return atCap(record.content) || toolCalls.some((call) => atCap(asRecord(call)?.input)) || toolResults.some((result) => atCap(asRecord(result)?.content));
|
|
4369
|
-
};
|
|
4370
4647
|
const build = (kept) => {
|
|
4371
4648
|
const returned = messages.slice(0, kept);
|
|
4372
|
-
const out = [
|
|
4649
|
+
const out = [];
|
|
4373
4650
|
if (total > 0 && start >= total) {
|
|
4374
4651
|
out.push(`--from=${start} is past the end of this trace (${total} messages, indexes 0-${total - 1}).`);
|
|
4375
4652
|
}
|
|
@@ -4391,12 +4668,9 @@ async function readFullTranscript(conversationId, opts = {}) {
|
|
|
4391
4668
|
if (tied > 0 || synthetic > 0) {
|
|
4392
4669
|
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` : ""}.`);
|
|
4393
4670
|
}
|
|
4394
|
-
if (legacy && returned.some(isTruncated)) {
|
|
4395
|
-
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).`);
|
|
4396
|
-
}
|
|
4397
4671
|
return {
|
|
4398
|
-
data:
|
|
4399
|
-
conversation_id: conversationId,
|
|
4672
|
+
data: {
|
|
4673
|
+
conversation_id: stripLoneSurrogates(conversationId),
|
|
4400
4674
|
total_messages: total,
|
|
4401
4675
|
from: start,
|
|
4402
4676
|
returned: returned.length,
|
|
@@ -4405,7 +4679,7 @@ async function readFullTranscript(conversationId, opts = {}) {
|
|
|
4405
4679
|
summary,
|
|
4406
4680
|
...ordering ? { ordering } : {},
|
|
4407
4681
|
messages: returned
|
|
4408
|
-
}
|
|
4682
|
+
},
|
|
4409
4683
|
warnings: out,
|
|
4410
4684
|
nextCommands
|
|
4411
4685
|
};
|
|
@@ -4413,18 +4687,10 @@ async function readFullTranscript(conversationId, opts = {}) {
|
|
|
4413
4687
|
const full = build(messages.length);
|
|
4414
4688
|
if (!opts.fits || messages.length <= 1 || opts.fits(full))
|
|
4415
4689
|
return full;
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
while (low < high) {
|
|
4419
|
-
const mid = Math.ceil((low + high) / 2);
|
|
4420
|
-
if (opts.fits(build(mid)))
|
|
4421
|
-
low = mid;
|
|
4422
|
-
else
|
|
4423
|
-
high = mid - 1;
|
|
4424
|
-
}
|
|
4425
|
-
return build(low);
|
|
4690
|
+
const fits = opts.fits;
|
|
4691
|
+
return build(largestFittingCount(messages.length - 1, (kept) => fits(build(kept))));
|
|
4426
4692
|
}
|
|
4427
|
-
async function readContextItem(
|
|
4693
|
+
async function readContextItem(params, inputWarnings, budget) {
|
|
4428
4694
|
const fits = budget?.fits;
|
|
4429
4695
|
if (params.all === true) {
|
|
4430
4696
|
const full = await readFullTranscript(params.conversation_id, {
|
|
@@ -4533,17 +4799,10 @@ function trimContextWindow(conversationId, record, requestedAnchor, fits) {
|
|
|
4533
4799
|
};
|
|
4534
4800
|
return { data, warnings, nextCommands };
|
|
4535
4801
|
};
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
const page = build(mid);
|
|
4541
|
-
if (fits(page.data, page.warnings, page.nextCommands))
|
|
4542
|
-
low = mid;
|
|
4543
|
-
else
|
|
4544
|
-
high = mid - 1;
|
|
4545
|
-
}
|
|
4546
|
-
return build(low);
|
|
4802
|
+
return build(largestFittingCount(order.length, (kept) => {
|
|
4803
|
+
const page = build(kept);
|
|
4804
|
+
return fits(page.data, page.warnings, page.nextCommands);
|
|
4805
|
+
}));
|
|
4547
4806
|
}
|
|
4548
4807
|
var AUDIT_USAGE = "Usage: moda traces spans <conversation_id|trace_id> [--kind=auto|trace|conversation] [--include-raw] [--include-bodies] [--limit=N] [--cursor=<next_cursor>]";
|
|
4549
4808
|
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)`;
|
|
@@ -4569,16 +4828,10 @@ async function readAuditItem(command, params, budget) {
|
|
|
4569
4828
|
const available = (Array.isArray(spans) ? spans.length : 0) - (params.span_offset ?? 0);
|
|
4570
4829
|
if (available <= 0)
|
|
4571
4830
|
return whole;
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
const page2 = auditOutput(command, params, raw, mid);
|
|
4577
|
-
if (budget.fits(page2.data, page2.options))
|
|
4578
|
-
low = mid;
|
|
4579
|
-
else
|
|
4580
|
-
high = mid - 1;
|
|
4581
|
-
}
|
|
4831
|
+
const low = largestFittingCount(available, (keep) => {
|
|
4832
|
+
const page2 = auditOutput(command, params, raw, keep);
|
|
4833
|
+
return budget.fits(page2.data, page2.options);
|
|
4834
|
+
});
|
|
4582
4835
|
const page = auditOutput(command, params, raw, low);
|
|
4583
4836
|
if (low === 1 && !budget.fits(page.data, page.options)) {
|
|
4584
4837
|
page.options.warnings = [
|
|
@@ -4661,7 +4914,7 @@ async function readBatchTargets(targets, agentMode, read) {
|
|
|
4661
4914
|
});
|
|
4662
4915
|
}
|
|
4663
4916
|
function fitsShare(share) {
|
|
4664
|
-
return (data, options) =>
|
|
4917
|
+
return (data, options) => jsonByteLength({ data, ...options }) <= share;
|
|
4665
4918
|
}
|
|
4666
4919
|
function isBatchFatal(error) {
|
|
4667
4920
|
const type = classifyCliError(error);
|
|
@@ -4776,7 +5029,7 @@ async function runContextBatch(command, positionals, flags, context) {
|
|
|
4776
5029
|
conversation_id: target.id,
|
|
4777
5030
|
...target.msgIndex !== undefined ? { msg_index: target.msgIndex } : {}
|
|
4778
5031
|
};
|
|
4779
|
-
return withAnchorHint(target, () => readContextItem(
|
|
5032
|
+
return withAnchorHint(target, () => readContextItem(params, [], budget));
|
|
4780
5033
|
});
|
|
4781
5034
|
return writeBatchResult(command, context, targets, results, inputWarnings, rest);
|
|
4782
5035
|
}
|
|
@@ -4983,16 +5236,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4983
5236
|
return agentEnvelopeFits(command, page2.data, page2.options);
|
|
4984
5237
|
};
|
|
4985
5238
|
if (agentMode && kept > 1 && !fitsAgent(kept)) {
|
|
4986
|
-
|
|
4987
|
-
let high = kept - 1;
|
|
4988
|
-
while (low < high) {
|
|
4989
|
-
const mid = Math.ceil((low + high) / 2);
|
|
4990
|
-
if (fitsAgent(mid))
|
|
4991
|
-
low = mid;
|
|
4992
|
-
else
|
|
4993
|
-
high = mid - 1;
|
|
4994
|
-
}
|
|
4995
|
-
kept = low;
|
|
5239
|
+
kept = largestFittingCount(kept - 1, fitsAgent);
|
|
4996
5240
|
}
|
|
4997
5241
|
const page = write(kept);
|
|
4998
5242
|
recordSearchTelemetry(context, page.data);
|
|
@@ -5054,7 +5298,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5054
5298
|
return runContextBatch(command, positionals, flags, context);
|
|
5055
5299
|
const { params, warnings: inputWarnings } = parseContextRequest(...singleContextTarget(positional, flags));
|
|
5056
5300
|
const agentMode = context.output.mode === "agent" || context.output.mode === "agent-stream";
|
|
5057
|
-
const read = () => readContextItem(
|
|
5301
|
+
const read = () => readContextItem(params, inputWarnings, agentMode ? { fits: (data, options) => agentEnvelopeFits(command, data, options), maxBytes: agentMaxOutputBytes() } : undefined);
|
|
5058
5302
|
const item = positional === undefined ? await read() : await withAnchorHint(parseBatchTarget(positional, true, CONTEXT_USAGE), read);
|
|
5059
5303
|
context.output.writeData(item.data, item.options);
|
|
5060
5304
|
break;
|
|
@@ -5518,7 +5762,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5518
5762
|
}
|
|
5519
5763
|
const data = await callDataAPI(reviewPath, {
|
|
5520
5764
|
method: "POST",
|
|
5521
|
-
body: JSON.stringify({ ...reviewBody, request_nonce:
|
|
5765
|
+
body: JSON.stringify({ ...reviewBody, request_nonce: randomUUID3() }),
|
|
5522
5766
|
headers: { "Content-Type": "application/json" }
|
|
5523
5767
|
});
|
|
5524
5768
|
context.output.writeData(data);
|
|
@@ -5611,7 +5855,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5611
5855
|
});
|
|
5612
5856
|
break;
|
|
5613
5857
|
}
|
|
5614
|
-
const sentBody = request.body && request.nonce ? { ...request.body, request_nonce:
|
|
5858
|
+
const sentBody = request.body && request.nonce ? { ...request.body, request_nonce: randomUUID3() } : request.body;
|
|
5615
5859
|
const data = await callDataAPI(request.path, {
|
|
5616
5860
|
method: request.method,
|
|
5617
5861
|
...sentBody ? { body: JSON.stringify(sentBody), headers: { "Content-Type": "application/json" } } : {}
|
|
@@ -5767,7 +6011,6 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5767
6011
|
function telemetryCommandName(definition) {
|
|
5768
6012
|
return definition.telemetryCommand ?? definition.name;
|
|
5769
6013
|
}
|
|
5770
|
-
var TELEMETRY_EXEMPT_COMMANDS = {};
|
|
5771
6014
|
function telemetrySubcommandNames(definition) {
|
|
5772
6015
|
return [
|
|
5773
6016
|
...definition.subcommands?.map((subcommand) => subcommand.name) ?? [],
|
|
@@ -5900,7 +6143,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
5900
6143
|
resetApiRequestCountBeforeRun: true,
|
|
5901
6144
|
telemetry: "result-and-error",
|
|
5902
6145
|
handler: async (context) => {
|
|
5903
|
-
const { runInit } = await import("./index-
|
|
6146
|
+
const { runInit } = await import("./index-d1z50dsq.js");
|
|
5904
6147
|
if (context.outputMode === "agent-stream") {
|
|
5905
6148
|
context.output.writeEvent({
|
|
5906
6149
|
event: "started",
|
|
@@ -5950,7 +6193,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
5950
6193
|
resetApiRequestCountBeforeRun: true,
|
|
5951
6194
|
telemetry: "result-and-error",
|
|
5952
6195
|
handler: async (context) => {
|
|
5953
|
-
const { runProvision } = await import("./provision-
|
|
6196
|
+
const { runProvision } = await import("./provision-y5bdbh4y.js");
|
|
5954
6197
|
return runProvision(context, {
|
|
5955
6198
|
resumeCommand: buildResumeCommand("provision", context.rawFlags)
|
|
5956
6199
|
});
|
|
@@ -7174,6 +7417,8 @@ async function dispatchParsedCommandInner(typedParsed, startedAt) {
|
|
|
7174
7417
|
const switchError = normalizeBooleanFlags(flags);
|
|
7175
7418
|
const typedFlags = stripUpdateCheckFlag(stripTelemetryFlag(flags));
|
|
7176
7419
|
const telemetryDisabled = isTelemetryDisabled(flags);
|
|
7420
|
+
if (telemetryDisabled)
|
|
7421
|
+
discardSpoolOnEnvOptOut();
|
|
7177
7422
|
const updateCheckDisabled = isUpdateCheckDisabled(flags);
|
|
7178
7423
|
if (command === "--version" || command === "-V" || flags.version === "true") {
|
|
7179
7424
|
console.log(`moda-cli ${VERSION}`);
|
|
@@ -7479,7 +7724,6 @@ export {
|
|
|
7479
7724
|
trimContextWindow,
|
|
7480
7725
|
telemetrySubcommandNames,
|
|
7481
7726
|
telemetryCommandName,
|
|
7482
|
-
stripLoneSurrogates,
|
|
7483
7727
|
searchOutcomeWarnings,
|
|
7484
7728
|
searchDegradeWarning,
|
|
7485
7729
|
searchCoverageWarnings,
|
|
@@ -7490,6 +7734,7 @@ export {
|
|
|
7490
7734
|
parseCommandFlags,
|
|
7491
7735
|
parseArgs,
|
|
7492
7736
|
normalizeBooleanFlags,
|
|
7737
|
+
largestFittingCount,
|
|
7493
7738
|
initFlagsForContext,
|
|
7494
7739
|
globalFlagHelpLines,
|
|
7495
7740
|
flagsToArgs,
|
|
@@ -7506,10 +7751,8 @@ export {
|
|
|
7506
7751
|
canonicalFlagKey,
|
|
7507
7752
|
buildResumeCommand,
|
|
7508
7753
|
auditCapStatus,
|
|
7509
|
-
TELEMETRY_EXEMPT_COMMANDS,
|
|
7510
7754
|
TAIL_LIMITS,
|
|
7511
7755
|
RAW_BOOLEAN_FLAGS,
|
|
7512
|
-
LEGACY_WINDOW_MAX_MESSAGES,
|
|
7513
7756
|
FULL_TRANSCRIPT_DEFAULT_MAX_MESSAGES,
|
|
7514
7757
|
CliInputError,
|
|
7515
7758
|
CONTEXT_MAX_WINDOW,
|