@moda-ai/cli 1.49.0 → 1.50.0
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/{cli-c64d2jrw.js → cli-7kbzqact.js} +1 -1
- package/dist/{cli-taf854xx.js → cli-h4k23fb0.js} +2 -2
- package/dist/{cli-6xndg2h4.js → cli-jqfm8dp4.js} +4 -4
- package/dist/{cli-m3bg9yyh.js → cli-x0x0n35w.js} +8 -9
- package/dist/{cli-bqhs6sk7.js → cli-xrs02c0t.js} +242 -59
- package/dist/cli.js +31 -47
- package/dist/{harness-4ypeg9dh.js → harness-7gr0xbtc.js} +2 -2
- package/dist/{harness-github-actions-dvq7spqh.js → harness-github-actions-q9kewzb6.js} +2 -2
- package/dist/{index-pdg9t77n.js → index-z0jpjcsm.js} +5 -5
- package/dist/prompt-source-mcp.js +2 -2
- package/dist/{provision-7fhbgk2d.js → provision-qkazpt0c.js} +3 -3
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/skills/moda-cli/SKILL.md +25 -13
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
authFetch,
|
|
3
3
|
getCachedLoginContext
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-7kbzqact.js";
|
|
5
5
|
import {
|
|
6
6
|
CliAccessError,
|
|
7
7
|
CliInputError,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
resolveTenantIdFromActiveProfile,
|
|
16
16
|
saveCliConfig,
|
|
17
17
|
writeSecretJsonFile
|
|
18
|
-
} from "./cli-
|
|
18
|
+
} from "./cli-xrs02c0t.js";
|
|
19
19
|
|
|
20
20
|
// src/init/tenant.ts
|
|
21
21
|
import { randomUUID } from "node:crypto";
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
resolvePromptSource,
|
|
14
14
|
safePromptEvidencePath,
|
|
15
15
|
scanHarness
|
|
16
|
-
} from "./cli-
|
|
16
|
+
} from "./cli-x0x0n35w.js";
|
|
17
17
|
import {
|
|
18
18
|
SKILL_SOURCE_HARNESS,
|
|
19
19
|
SKILL_SOURCE_INTEGRATION_BUNDLED,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
import {
|
|
27
27
|
isAuthSessionValid,
|
|
28
28
|
loadAuthSession
|
|
29
|
-
} from "./cli-
|
|
29
|
+
} from "./cli-7kbzqact.js";
|
|
30
30
|
import {
|
|
31
31
|
CliInputError,
|
|
32
32
|
EXIT_ERROR,
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
resolveTenantId,
|
|
46
46
|
secretFilePathFromRef,
|
|
47
47
|
validateConfig
|
|
48
|
-
} from "./cli-
|
|
48
|
+
} from "./cli-xrs02c0t.js";
|
|
49
49
|
import {
|
|
50
50
|
__commonJS,
|
|
51
51
|
__require,
|
|
@@ -6711,7 +6711,7 @@ async function runPromptSyncExclusive(flags, profileOptions, options) {
|
|
|
6711
6711
|
const analyzedDefinitions = new Map;
|
|
6712
6712
|
if (flags["no-analyze"] !== "true") {
|
|
6713
6713
|
options.onProgress?.("Analyzing prompt sources before sync.");
|
|
6714
|
-
const { analyzeHarnessPrompts } = await import("./harness-
|
|
6714
|
+
const { analyzeHarnessPrompts } = await import("./harness-7gr0xbtc.js");
|
|
6715
6715
|
const result = await analyzeHarnessPrompts({
|
|
6716
6716
|
rootDir: process.cwd(),
|
|
6717
6717
|
existing: established.flatMap((prompt) => prompt.sourceDefinition ? [prompt.sourceDefinition.source] : []),
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
resolveTenantId,
|
|
26
26
|
shouldInventoryFile,
|
|
27
27
|
stringOption
|
|
28
|
-
} from "./cli-
|
|
28
|
+
} from "./cli-xrs02c0t.js";
|
|
29
29
|
import {
|
|
30
30
|
__commonJS,
|
|
31
31
|
__require,
|
|
@@ -180210,7 +180210,7 @@ function citationExcerpt(rootDir, path, line) {
|
|
|
180210
180210
|
const selected = line ? lines[line - 1] : lines.find((candidate) => candidate.trim().length > 0);
|
|
180211
180211
|
if (!selected)
|
|
180212
180212
|
return {};
|
|
180213
|
-
return { excerpt: selected.trim()
|
|
180213
|
+
return { excerpt: selected.trim() };
|
|
180214
180214
|
} catch {
|
|
180215
180215
|
return {};
|
|
180216
180216
|
}
|
|
@@ -181065,7 +181065,6 @@ function enrichScanCaptureMetadata(graph) {
|
|
|
181065
181065
|
// src/harness-candidates.ts
|
|
181066
181066
|
import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
181067
181067
|
import { basename as basename3, dirname as dirname3, extname, resolve as resolve4 } from "node:path";
|
|
181068
|
-
var EXCERPT_MAX_CHARS = 240;
|
|
181069
181068
|
var MAX_CANDIDATES_PER_FILE_PER_SIGNAL = 20;
|
|
181070
181069
|
var MIN_PROMPT_LITERAL_CHARS = 160;
|
|
181071
181070
|
var CONFIDENCE_WEIGHT = {
|
|
@@ -181311,8 +181310,7 @@ function instructionScore(text) {
|
|
|
181311
181310
|
return score;
|
|
181312
181311
|
}
|
|
181313
181312
|
function normalizeExcerpt(text) {
|
|
181314
|
-
|
|
181315
|
-
return collapsed.length > EXCERPT_MAX_CHARS ? `${collapsed.slice(0, EXCERPT_MAX_CHARS - 1)}…` : collapsed;
|
|
181313
|
+
return text.replace(/\s+/g, " ").trim();
|
|
181316
181314
|
}
|
|
181317
181315
|
function buildLineIndex(text) {
|
|
181318
181316
|
const offsets = [0];
|
|
@@ -181423,7 +181421,7 @@ function detectPromptModule(file, out) {
|
|
|
181423
181421
|
`).length),
|
|
181424
181422
|
confidence: "medium",
|
|
181425
181423
|
signal: "prompt_module.name_hint",
|
|
181426
|
-
excerpt: normalizeExcerpt(file.text
|
|
181424
|
+
excerpt: normalizeExcerpt(file.text)
|
|
181427
181425
|
});
|
|
181428
181426
|
}
|
|
181429
181427
|
function detectPromptLiterals(file, out) {
|
|
@@ -181506,7 +181504,7 @@ function detectPromptFile(file, out) {
|
|
|
181506
181504
|
`).length),
|
|
181507
181505
|
confidence,
|
|
181508
181506
|
signal,
|
|
181509
|
-
excerpt: normalizeExcerpt(file.text
|
|
181507
|
+
excerpt: normalizeExcerpt(file.text)
|
|
181510
181508
|
});
|
|
181511
181509
|
}
|
|
181512
181510
|
function detectPromptLoaderReferences(file, filesByPath, out) {
|
|
@@ -184859,7 +184857,7 @@ async function runHarnessCommand(context) {
|
|
|
184859
184857
|
throw new CliInputError("Focused remote prompt analysis is not supported yet.", "Use local --analyst=claude|codex|cursor|local-scan, or drop --concern for a full remote report.");
|
|
184860
184858
|
}
|
|
184861
184859
|
if (context.flags["github-actions"] === "true") {
|
|
184862
|
-
const { runGithubActionsAnalyze } = await import("./harness-github-actions-
|
|
184860
|
+
const { runGithubActionsAnalyze } = await import("./harness-github-actions-q9kewzb6.js");
|
|
184863
184861
|
const result = await runGithubActionsAnalyze(rootDir, {
|
|
184864
184862
|
writeReport: (report2) => {
|
|
184865
184863
|
const normalized = normalizeHarnessReport(report2);
|
|
@@ -186605,6 +186603,7 @@ var CONCERN_CANDIDATE_KINDS = {
|
|
|
186605
186603
|
evals: ["model_config"]
|
|
186606
186604
|
};
|
|
186607
186605
|
var MAX_SEED_CANDIDATES_PER_KIND = 40;
|
|
186606
|
+
var MAX_INLINE_CANDIDATE_EXCERPT_CHARS = 500;
|
|
186608
186607
|
var MAX_SEED_READ_PLAN_FILES = 25;
|
|
186609
186608
|
var SEED_CANDIDATE_KIND_LABELS = {
|
|
186610
186609
|
llm_call_site: "LLM call sites",
|
|
@@ -186644,7 +186643,7 @@ function renderAnalystCandidateLines(report, concern) {
|
|
|
186644
186643
|
const shown = bucket.slice(0, MAX_SEED_CANDIDATES_PER_KIND);
|
|
186645
186644
|
lines.push(`${label} (${bucket.length}${bucket.length > shown.length ? `, showing ${shown.length}` : ""}):`);
|
|
186646
186645
|
for (const candidate of shown) {
|
|
186647
|
-
lines.push(`- ${candidate.path}:${candidate.startLine} [${candidate.signal}] ${candidate.excerpt}`);
|
|
186646
|
+
lines.push(candidate.endLine > candidate.startLine ? `- ${candidate.path}:${candidate.startLine}-${candidate.endLine} [${candidate.signal}] (multi-line span; read lines ${candidate.startLine}-${candidate.endLine} of the file)` : candidate.excerpt.length > MAX_INLINE_CANDIDATE_EXCERPT_CHARS ? `- ${candidate.path}:${candidate.startLine} [${candidate.signal}] (${candidate.excerpt.length}-character match; read line ${candidate.startLine} of the file)` : `- ${candidate.path}:${candidate.startLine} [${candidate.signal}] ${candidate.excerpt}`);
|
|
186648
186647
|
}
|
|
186649
186648
|
}
|
|
186650
186649
|
const readPlan = report.files.slice(0, MAX_SEED_READ_PLAN_FILES);
|
|
@@ -986,6 +986,9 @@ function packSnapshot(inputs, opts) {
|
|
|
986
986
|
}
|
|
987
987
|
// src/output.ts
|
|
988
988
|
import { randomUUID } from "node:crypto";
|
|
989
|
+
import { lstatSync, mkdirSync as mkdirSync2, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
990
|
+
import { tmpdir } from "node:os";
|
|
991
|
+
import { join as join2 } from "node:path";
|
|
989
992
|
var AGENT_SCHEMA_VERSION = "moda.agent.v1";
|
|
990
993
|
var AGENT_EVENT_SCHEMA_VERSION = "moda.agent_event.v1";
|
|
991
994
|
var FEEDBACK_TIP = 'Help us improve! If a result in this response looks wrong or is missing data, flag it: moda feedback "<describe what looked wrong>" [--category=...] [--conversation-id=... | --cluster-id=... | --tool-name=...]. Only submit genuine observations.';
|
|
@@ -1005,7 +1008,8 @@ var AGENT_ERROR_CODES = [
|
|
|
1005
1008
|
"command_error",
|
|
1006
1009
|
"access_denied",
|
|
1007
1010
|
"unknown_error",
|
|
1008
|
-
"cloud_unavailable"
|
|
1011
|
+
"cloud_unavailable",
|
|
1012
|
+
"output_error"
|
|
1009
1013
|
];
|
|
1010
1014
|
var FALLBACK_RUN_ID = randomUUID();
|
|
1011
1015
|
var fallbackSeq = 0;
|
|
@@ -1116,6 +1120,7 @@ function createCliOutput(options) {
|
|
|
1116
1120
|
seq: 0,
|
|
1117
1121
|
started: false,
|
|
1118
1122
|
terminal: false,
|
|
1123
|
+
outputError: false,
|
|
1119
1124
|
startedAt: Date.now(),
|
|
1120
1125
|
lastEventAt: Date.now()
|
|
1121
1126
|
};
|
|
@@ -1177,6 +1182,8 @@ function createCliOutput(options) {
|
|
|
1177
1182
|
if (state.terminal)
|
|
1178
1183
|
return;
|
|
1179
1184
|
const envelope = writeEnvelope(data, writeOptions);
|
|
1185
|
+
if (envelope.errors.some((error) => error.code === "output_error"))
|
|
1186
|
+
state.outputError = true;
|
|
1180
1187
|
if (options.mode === "agent-stream") {
|
|
1181
1188
|
ensureStarted();
|
|
1182
1189
|
emitEvent({
|
|
@@ -1272,6 +1279,9 @@ function createCliOutput(options) {
|
|
|
1272
1279
|
hasTerminalOutput() {
|
|
1273
1280
|
return state.terminal;
|
|
1274
1281
|
},
|
|
1282
|
+
hasOutputError() {
|
|
1283
|
+
return state.outputError;
|
|
1284
|
+
},
|
|
1275
1285
|
close() {
|
|
1276
1286
|
clearHeartbeat(state);
|
|
1277
1287
|
}
|
|
@@ -1281,41 +1291,198 @@ function createCliOutput(options) {
|
|
|
1281
1291
|
function createAgentEnvelope(options) {
|
|
1282
1292
|
const safeData = redactDeep(options.data);
|
|
1283
1293
|
const maxBytes = agentMaxOutputBytes();
|
|
1294
|
+
let fullOutput;
|
|
1295
|
+
let saveFailed = false;
|
|
1296
|
+
let envelopeTextSaveFailed = false;
|
|
1297
|
+
const writeFullOutput = options.persistFullOutput === false ? undefined : () => {
|
|
1298
|
+
fullOutput ??= { path: writeAgentFullOutput(options.command, safeData) };
|
|
1299
|
+
if (!fullOutput.path)
|
|
1300
|
+
saveFailed = true;
|
|
1301
|
+
return fullOutput.path;
|
|
1302
|
+
};
|
|
1303
|
+
let text = redactDeep({
|
|
1304
|
+
summary: normalizeSummary(options.summary, options.command, options.status, safeData),
|
|
1305
|
+
findings: options.findings ?? [],
|
|
1306
|
+
evidence_refs: options.evidenceRefs ?? [],
|
|
1307
|
+
recommended_actions: options.recommendedActions ?? [],
|
|
1308
|
+
next_commands: normalizeNextCommands(options.nextCommands ?? []),
|
|
1309
|
+
warnings: options.warnings ?? inferWarnings(safeData)
|
|
1310
|
+
});
|
|
1311
|
+
let moved;
|
|
1284
1312
|
const build = (bounded) => ({
|
|
1285
1313
|
schema_version: AGENT_SCHEMA_VERSION,
|
|
1286
1314
|
command: options.command,
|
|
1287
1315
|
status: options.status,
|
|
1288
1316
|
generated_at: new Date().toISOString(),
|
|
1289
1317
|
...options.profile ? { profile: options.profile } : {},
|
|
1290
|
-
summary:
|
|
1291
|
-
findings:
|
|
1292
|
-
evidence_refs:
|
|
1293
|
-
recommended_actions:
|
|
1294
|
-
next_commands:
|
|
1295
|
-
artifacts:
|
|
1318
|
+
summary: text.summary,
|
|
1319
|
+
findings: text.findings,
|
|
1320
|
+
evidence_refs: text.evidence_refs,
|
|
1321
|
+
recommended_actions: text.recommended_actions,
|
|
1322
|
+
next_commands: text.next_commands,
|
|
1323
|
+
artifacts: [
|
|
1324
|
+
...options.artifacts ?? [],
|
|
1325
|
+
...bounded.fullOutputPath ? [{ kind: "full_output", path: bounded.fullOutputPath, description: "Complete command output (the same JSON --json prints); data in this envelope was bounded." }] : [],
|
|
1326
|
+
...moved?.path ? [{ kind: "full_envelope_text", path: moved.path, description: "Whole envelope text (summary, findings, evidence_refs, actions, next_commands, warnings) before oversized fields were moved out of this envelope." }] : []
|
|
1327
|
+
],
|
|
1296
1328
|
warnings: [
|
|
1297
|
-
...
|
|
1298
|
-
...bounded.warning ? [bounded.warning] : []
|
|
1329
|
+
...text.warnings,
|
|
1330
|
+
...bounded.warning ? [bounded.warning] : [],
|
|
1331
|
+
...moved ? [movedTextWarning(moved)] : []
|
|
1299
1332
|
],
|
|
1300
1333
|
errors: options.errors ?? [],
|
|
1301
1334
|
data: bounded.data,
|
|
1302
1335
|
...options.meta ? { meta: options.meta } : {},
|
|
1303
|
-
...bounded.truncation ? { truncation:
|
|
1336
|
+
...bounded.truncation || moved ? { truncation: {
|
|
1337
|
+
...bounded.truncation ?? {},
|
|
1338
|
+
...moved ? { envelope_text: {
|
|
1339
|
+
reason: "agent_output_byte_limit",
|
|
1340
|
+
moved_fields: moved.fields,
|
|
1341
|
+
complete: false,
|
|
1342
|
+
...moved.whole ? { whole_text_moved: true } : {},
|
|
1343
|
+
...moved.path ? { full_envelope_path: moved.path } : {}
|
|
1344
|
+
} } : {}
|
|
1345
|
+
} } : {}
|
|
1304
1346
|
});
|
|
1305
|
-
|
|
1306
|
-
const
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1347
|
+
const sizeOf = (value) => Buffer.byteLength(JSON.stringify(value) ?? "", "utf8");
|
|
1348
|
+
const rebound = (current) => {
|
|
1349
|
+
const overhead = sizeOf(current) - sizeOf(current.data);
|
|
1350
|
+
return build(boundForAgent(safeData, Math.max(1024, maxBytes - overhead - 1024), { writeFullOutput }));
|
|
1351
|
+
};
|
|
1352
|
+
let envelope = build(boundForAgent(safeData, maxBytes, { writeFullOutput }));
|
|
1353
|
+
if (sizeOf(envelope) > maxBytes)
|
|
1354
|
+
envelope = rebound(envelope);
|
|
1355
|
+
if (sizeOf(envelope) > maxBytes && !saveFailed) {
|
|
1356
|
+
const original = text;
|
|
1357
|
+
const savedPath = options.persistFullOutput === false ? undefined : writeAgentFullOutput(`${options.command}-envelope`, original);
|
|
1358
|
+
if (options.persistFullOutput !== false && !savedPath) {
|
|
1359
|
+
saveFailed = true;
|
|
1360
|
+
envelopeTextSaveFailed = true;
|
|
1361
|
+
} else {
|
|
1362
|
+
const slots = envelopeTextSlots(original).sort((left, right) => right.bytes - left.bytes);
|
|
1363
|
+
text = structuredClone(original);
|
|
1364
|
+
moved = { path: savedPath, fields: [] };
|
|
1365
|
+
for (const slot of slots) {
|
|
1366
|
+
if (sizeOf(envelope) <= maxBytes)
|
|
1367
|
+
break;
|
|
1368
|
+
const pointer = movedTextPointer(slot.field, slot.text, savedPath);
|
|
1369
|
+
const added = Buffer.byteLength(JSON.stringify(pointer), "utf8") + 2 * movedFieldNameBytes(slot.field);
|
|
1370
|
+
if (added >= slot.bytes)
|
|
1371
|
+
continue;
|
|
1372
|
+
slot.set(text, pointer);
|
|
1373
|
+
moved.fields.push(slot.field);
|
|
1374
|
+
envelope = rebound(envelope);
|
|
1375
|
+
}
|
|
1376
|
+
if (moved.fields.length === 0)
|
|
1377
|
+
moved = undefined;
|
|
1378
|
+
envelope = rebound(envelope);
|
|
1379
|
+
if (sizeOf(envelope) > maxBytes) {
|
|
1380
|
+
text = {
|
|
1381
|
+
summary: { text: movedWholeTextPointer(savedPath), confidence: original.summary.confidence },
|
|
1382
|
+
findings: [],
|
|
1383
|
+
evidence_refs: [],
|
|
1384
|
+
recommended_actions: [],
|
|
1385
|
+
next_commands: [],
|
|
1386
|
+
warnings: []
|
|
1387
|
+
};
|
|
1388
|
+
moved = { path: savedPath, fields: ["*"], whole: true };
|
|
1389
|
+
envelope = rebound(envelope);
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
if (saveFailed) {
|
|
1394
|
+
envelope = {
|
|
1395
|
+
...envelope,
|
|
1396
|
+
status: "error",
|
|
1397
|
+
errors: [...envelope.errors, saveFailedError(maxBytes, envelopeTextSaveFailed, fullOutput?.path)]
|
|
1398
|
+
};
|
|
1310
1399
|
}
|
|
1311
1400
|
return redactDeep(envelope);
|
|
1312
1401
|
}
|
|
1402
|
+
function saveFailedError(maxBytes, envelopeTextSaveFailed, dataPath) {
|
|
1403
|
+
const where = "(MODA_AGENT_OUTPUT_DIR is unwritable or the disk is full)";
|
|
1404
|
+
const remedy = "Point MODA_AGENT_OUTPUT_DIR at a writable directory, rerun with --json (no byte limit), or narrow the query.";
|
|
1405
|
+
if (!envelopeTextSaveFailed) {
|
|
1406
|
+
return {
|
|
1407
|
+
code: "output_error",
|
|
1408
|
+
cause: "full_output_save_failed",
|
|
1409
|
+
message: `Output is over the ${maxBytes}-byte agent limit and the complete output could not be saved to a file ${where}, ` + `so nothing was moved out: this envelope holds the whole result, over the limit. ${remedy}`,
|
|
1410
|
+
blocking: false
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1413
|
+
const dataState = dataPath ? `data is NOT the whole result: it was bounded to fit, and the complete data was saved to ${dataPath} ` + "(truncation.data.full_output_path); read it in line ranges or with jq. " : "data is the whole result. ";
|
|
1414
|
+
return {
|
|
1415
|
+
code: "output_error",
|
|
1416
|
+
cause: "envelope_text_save_failed",
|
|
1417
|
+
message: `Output is over the ${maxBytes}-byte agent limit and the oversized envelope text (summary, findings, evidence_refs, ` + `recommended_actions, next_commands, warnings) could not be saved to a file ${where}, so that text was kept whole ` + `in this envelope, over the limit. ${dataState}${remedy}`,
|
|
1418
|
+
blocking: false
|
|
1419
|
+
};
|
|
1420
|
+
}
|
|
1421
|
+
function envelopeTextSlots(text) {
|
|
1422
|
+
const slots = [
|
|
1423
|
+
{ field: "summary.text", text: text.summary.text, set: (target, value) => {
|
|
1424
|
+
target.summary.text = value;
|
|
1425
|
+
} }
|
|
1426
|
+
];
|
|
1427
|
+
text.findings.forEach((finding, index) => {
|
|
1428
|
+
slots.push({ field: `findings[${index}].title`, text: finding.title, set: (target, value) => {
|
|
1429
|
+
target.findings[index].title = value;
|
|
1430
|
+
} });
|
|
1431
|
+
if (finding.description) {
|
|
1432
|
+
slots.push({ field: `findings[${index}].description`, text: finding.description, set: (target, value) => {
|
|
1433
|
+
target.findings[index].description = value;
|
|
1434
|
+
} });
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
1437
|
+
text.evidence_refs.forEach((ref, index) => {
|
|
1438
|
+
slots.push({ field: `evidence_refs[${index}].label`, text: ref.label, set: (target, value) => {
|
|
1439
|
+
target.evidence_refs[index].label = value;
|
|
1440
|
+
} });
|
|
1441
|
+
});
|
|
1442
|
+
text.recommended_actions.forEach((action, index) => {
|
|
1443
|
+
slots.push({ field: `recommended_actions[${index}].title`, text: action.title, set: (target, value) => {
|
|
1444
|
+
target.recommended_actions[index].title = value;
|
|
1445
|
+
} });
|
|
1446
|
+
if (action.rationale) {
|
|
1447
|
+
slots.push({ field: `recommended_actions[${index}].rationale`, text: action.rationale, set: (target, value) => {
|
|
1448
|
+
target.recommended_actions[index].rationale = value;
|
|
1449
|
+
} });
|
|
1450
|
+
}
|
|
1451
|
+
});
|
|
1452
|
+
text.next_commands.forEach((command, index) => {
|
|
1453
|
+
slots.push({ field: `next_commands[${index}].purpose`, text: command.purpose, set: (target, value) => {
|
|
1454
|
+
target.next_commands[index].purpose = value;
|
|
1455
|
+
} });
|
|
1456
|
+
});
|
|
1457
|
+
text.warnings.forEach((warning, index) => {
|
|
1458
|
+
slots.push({ field: `warnings[${index}]`, text: warning, set: (target, value) => {
|
|
1459
|
+
target.warnings[index] = value;
|
|
1460
|
+
} });
|
|
1461
|
+
});
|
|
1462
|
+
return slots.map((slot) => ({ ...slot, bytes: Buffer.byteLength(JSON.stringify(slot.text), "utf8") }));
|
|
1463
|
+
}
|
|
1464
|
+
function movedTextPointer(field, value, path) {
|
|
1465
|
+
const chars = Array.from(value).length;
|
|
1466
|
+
return path ? `[${chars} characters moved whole to ${path} at ${field}]` : `[${chars} characters over the agent byte limit; not saved. Rerun with --json or raise MODA_AGENT_MAX_OUTPUT_BYTES]`;
|
|
1467
|
+
}
|
|
1468
|
+
function movedFieldNameBytes(field) {
|
|
1469
|
+
return Buffer.byteLength(JSON.stringify(field), "utf8") + 2;
|
|
1470
|
+
}
|
|
1471
|
+
function movedWholeTextPointer(path) {
|
|
1472
|
+
return path ? `[Envelope text (summary, findings, evidence_refs, recommended_actions, next_commands, warnings) was over the agent byte limit and moved whole to ${path}]` : "[Envelope text was over the agent byte limit; not saved. Rerun with --json or raise MODA_AGENT_MAX_OUTPUT_BYTES]";
|
|
1473
|
+
}
|
|
1474
|
+
function movedTextWarning(moved) {
|
|
1475
|
+
if (moved.whole) {
|
|
1476
|
+
return "Envelope text outside data was over the agent byte limit even after moving its largest fields: all of it was moved whole " + (moved.path ? `to ${moved.path} (read it with jq)` : "(the file could not be saved; rerun with --json or raise MODA_AGENT_MAX_OUTPUT_BYTES)") + ".";
|
|
1477
|
+
}
|
|
1478
|
+
return `Envelope text outside data was over the agent byte limit: ${moved.fields.length} field(s) were moved whole ` + (moved.path ? `to ${moved.path} (same field paths; read it with jq)` : "(the file could not be saved; rerun with --json or raise MODA_AGENT_MAX_OUTPUT_BYTES)") + ` and replaced by pointers: ${moved.fields.join(", ")}.`;
|
|
1479
|
+
}
|
|
1313
1480
|
var AGENT_ENVELOPE_RESERVE_BYTES = 2048;
|
|
1314
1481
|
function agentEnvelopeFits(command, data, options = {}) {
|
|
1315
1482
|
const maxBytes = agentMaxOutputBytes() - AGENT_ENVELOPE_RESERVE_BYTES;
|
|
1316
1483
|
if (Buffer.byteLength(JSON.stringify(data) ?? "", "utf8") > maxBytes)
|
|
1317
1484
|
return false;
|
|
1318
|
-
const envelope = createAgentEnvelope({ command, status: "ok", data, ...options });
|
|
1485
|
+
const envelope = createAgentEnvelope({ command, status: "ok", data, ...options, persistFullOutput: false });
|
|
1319
1486
|
return !envelope.truncation && Buffer.byteLength(JSON.stringify(envelope), "utf8") <= maxBytes;
|
|
1320
1487
|
}
|
|
1321
1488
|
function errorWarnings(error) {
|
|
@@ -1559,41 +1726,61 @@ function inferWarnings(data) {
|
|
|
1559
1726
|
}
|
|
1560
1727
|
return [];
|
|
1561
1728
|
}
|
|
1562
|
-
var AGENT_MAX_STRING_CHARS = 2000;
|
|
1563
|
-
var PROTECTED_STRING_KEY = /(cursor|token|_id$|^id$|url$|href$|^key$|hash$)/i;
|
|
1564
1729
|
function agentMaxOutputBytes() {
|
|
1565
1730
|
return Number(process.env.MODA_AGENT_MAX_OUTPUT_BYTES ?? 200000);
|
|
1566
1731
|
}
|
|
1567
|
-
|
|
1732
|
+
var AGENT_FULL_OUTPUT_FILE = /-\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z-[0-9a-f]{8}\.json$/;
|
|
1733
|
+
function agentOutputRetentionMs() {
|
|
1734
|
+
const hours = Number(process.env.MODA_AGENT_OUTPUT_RETENTION_HOURS ?? 24);
|
|
1735
|
+
return (Number.isFinite(hours) && hours > 0 ? hours : 24) * 3600000;
|
|
1736
|
+
}
|
|
1737
|
+
function pruneAgentFullOutputs(dir, keep, now = Date.now()) {
|
|
1738
|
+
const cutoff = now - agentOutputRetentionMs();
|
|
1739
|
+
let names;
|
|
1740
|
+
try {
|
|
1741
|
+
names = readdirSync(dir);
|
|
1742
|
+
} catch {
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
for (const name of names) {
|
|
1746
|
+
if (!AGENT_FULL_OUTPUT_FILE.test(name))
|
|
1747
|
+
continue;
|
|
1748
|
+
const path = join2(dir, name);
|
|
1749
|
+
if (path === keep)
|
|
1750
|
+
continue;
|
|
1751
|
+
try {
|
|
1752
|
+
const stat = lstatSync(path);
|
|
1753
|
+
if (stat.isFile() && stat.mtimeMs < cutoff)
|
|
1754
|
+
unlinkSync(path);
|
|
1755
|
+
} catch {}
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
function writeAgentFullOutput(command, data) {
|
|
1759
|
+
try {
|
|
1760
|
+
const dir = process.env.MODA_AGENT_OUTPUT_DIR || join2(tmpdir(), "moda-agent-output");
|
|
1761
|
+
mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
1762
|
+
const slug = command.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "") || "output";
|
|
1763
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
1764
|
+
const path = join2(dir, `${slug}-${stamp}-${randomUUID().slice(0, 8)}.json`);
|
|
1765
|
+
writeFileSync2(path, `${JSON.stringify(data, null, 2)}
|
|
1766
|
+
`, { encoding: "utf8", mode: 384 });
|
|
1767
|
+
pruneAgentFullOutputs(dir, path);
|
|
1768
|
+
return path;
|
|
1769
|
+
} catch {
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
function boundForAgent(data, maxBytes = agentMaxOutputBytes(), options = {}) {
|
|
1568
1774
|
const sizeOf = (value) => Buffer.byteLength(JSON.stringify(value) ?? "", "utf8");
|
|
1569
1775
|
const serialized = JSON.stringify(data) ?? "";
|
|
1570
1776
|
const originalBytes = Buffer.byteLength(serialized, "utf8");
|
|
1571
1777
|
if (originalBytes <= maxBytes)
|
|
1572
1778
|
return { data };
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
return value;
|
|
1578
|
-
shortenedStrings += 1;
|
|
1579
|
-
return `${value.slice(0, limit)}… [truncated ${value.length - limit} chars]`;
|
|
1580
|
-
}
|
|
1581
|
-
if (Array.isArray(value))
|
|
1582
|
-
return value.map((item) => shorten(item, limit));
|
|
1583
|
-
if (value && typeof value === "object") {
|
|
1584
|
-
return Object.fromEntries(Object.entries(value).map(([entryKey, item]) => [entryKey, shorten(item, limit, entryKey)]));
|
|
1585
|
-
}
|
|
1586
|
-
return value;
|
|
1587
|
-
};
|
|
1588
|
-
let bounded = data;
|
|
1779
|
+
const fullOutputPath = options.writeFullOutput?.();
|
|
1780
|
+
if (options.writeFullOutput && !fullOutputPath)
|
|
1781
|
+
return { data, saveFailed: true };
|
|
1782
|
+
const bounded = JSON.parse(serialized);
|
|
1589
1783
|
let boundedBytes = originalBytes;
|
|
1590
|
-
for (const limit of [AGENT_MAX_STRING_CHARS, 500, 200]) {
|
|
1591
|
-
shortenedStrings = 0;
|
|
1592
|
-
bounded = shorten(data, limit);
|
|
1593
|
-
boundedBytes = sizeOf(bounded);
|
|
1594
|
-
if (boundedBytes <= maxBytes)
|
|
1595
|
-
break;
|
|
1596
|
-
}
|
|
1597
1784
|
const droppedItems = {};
|
|
1598
1785
|
const collectArrays = (value, path, out) => {
|
|
1599
1786
|
if (Array.isArray(value)) {
|
|
@@ -1630,39 +1817,35 @@ function boundForAgent(data, maxBytes = agentMaxOutputBytes()) {
|
|
|
1630
1817
|
boundedBytes = sizeOf(bounded);
|
|
1631
1818
|
}
|
|
1632
1819
|
const dropped = Object.entries(droppedItems);
|
|
1633
|
-
const
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
].filter(Boolean);
|
|
1637
|
-
const howToGetMore = "For complete results narrow the query (a smaller --limit, with --offset or --cursor paging where the command supports it), " + "rerun with --json (no byte limit), or raise MODA_AGENT_MAX_OUTPUT_BYTES.";
|
|
1820
|
+
const whereIsTheRest = fullOutputPath ? `The complete output (every item, no text shortened) is in ${fullOutputPath}; read it in line ranges or query it with jq. ` : "The complete output could not be saved to a file. ";
|
|
1821
|
+
const howToGetMore = whereIsTheRest + "Alternatively narrow the query (a smaller --limit, with --offset or --cursor paging where the command supports it), " + "rerun with --json (no byte limit), or raise MODA_AGENT_MAX_OUTPUT_BYTES.";
|
|
1822
|
+
const pathField = fullOutputPath ? { full_output_path: fullOutputPath } : {};
|
|
1638
1823
|
if (boundedBytes > maxBytes) {
|
|
1639
|
-
const stub = { truncated: true, original_bytes: originalBytes, max_bytes: maxBytes, preview: serialized.slice(0, Math.max(0, maxBytes - 256)) };
|
|
1640
|
-
for (let stubBytes = sizeOf(stub);stubBytes > maxBytes && stub.preview.length > 0; stubBytes = sizeOf(stub)) {
|
|
1641
|
-
stub.preview = stub.preview.slice(0, Math.max(0, stub.preview.length - (stubBytes - maxBytes) - 16));
|
|
1642
|
-
}
|
|
1643
1824
|
return {
|
|
1644
|
-
data:
|
|
1645
|
-
warning: `Output was ${originalBytes} bytes, over the ${maxBytes}-byte agent limit, and could not be reduced while keeping its structure; data is a
|
|
1825
|
+
data: { truncated: true, original_bytes: originalBytes, max_bytes: maxBytes, ...pathField },
|
|
1826
|
+
warning: `Output was ${originalBytes} bytes, over the ${maxBytes}-byte agent limit, and could not be reduced while keeping its structure; data is a pointer stub. ${howToGetMore}`,
|
|
1646
1827
|
truncation: {
|
|
1647
|
-
data: { original_bytes: originalBytes, max_bytes: maxBytes, reason: "agent_output_byte_limit", structure_preserved: false, complete: false }
|
|
1648
|
-
}
|
|
1828
|
+
data: { original_bytes: originalBytes, max_bytes: maxBytes, reason: "agent_output_byte_limit", structure_preserved: false, complete: false, ...pathField }
|
|
1829
|
+
},
|
|
1830
|
+
fullOutputPath
|
|
1649
1831
|
};
|
|
1650
1832
|
}
|
|
1651
1833
|
return {
|
|
1652
1834
|
data: bounded,
|
|
1653
|
-
warning: `Output was ${originalBytes} bytes, over the ${maxBytes}-byte agent limit: ${
|
|
1835
|
+
warning: `Output was ${originalBytes} bytes, over the ${maxBytes}-byte agent limit: ${dropped.map(([path, count]) => `dropped the last ${count} item(s) of data.${path}`).join("; ")}. ${howToGetMore}`,
|
|
1654
1836
|
truncation: {
|
|
1655
1837
|
data: {
|
|
1656
1838
|
original_bytes: originalBytes,
|
|
1657
1839
|
bounded_bytes: boundedBytes,
|
|
1658
1840
|
max_bytes: maxBytes,
|
|
1659
1841
|
reason: "agent_output_byte_limit",
|
|
1660
|
-
shortened_strings: shortenedStrings,
|
|
1661
1842
|
dropped_items: droppedItems,
|
|
1662
1843
|
structure_preserved: true,
|
|
1663
|
-
complete: false
|
|
1844
|
+
complete: false,
|
|
1845
|
+
...pathField
|
|
1664
1846
|
}
|
|
1665
|
-
}
|
|
1847
|
+
},
|
|
1848
|
+
fullOutputPath
|
|
1666
1849
|
};
|
|
1667
1850
|
}
|
|
1668
1851
|
function asRecord(value) {
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
runPromptsCommand,
|
|
9
9
|
runSkillsCommand,
|
|
10
10
|
runStatusCommand
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-jqfm8dp4.js";
|
|
12
12
|
import {
|
|
13
13
|
ApiError,
|
|
14
14
|
HARNESS_REPORT_APPROVAL_PATH,
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
terminalStyles,
|
|
38
38
|
unknownSignalsSubcommandError,
|
|
39
39
|
validateHarnessReport
|
|
40
|
-
} from "./cli-
|
|
40
|
+
} from "./cli-x0x0n35w.js";
|
|
41
41
|
import"./cli-ssfq84k5.js";
|
|
42
42
|
import {
|
|
43
43
|
authFetch,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
loadAuthSession,
|
|
47
47
|
login,
|
|
48
48
|
revokeCliSessionToken
|
|
49
|
-
} from "./cli-
|
|
49
|
+
} from "./cli-7kbzqact.js";
|
|
50
50
|
import {
|
|
51
51
|
AGENT_ERROR_CODES,
|
|
52
52
|
CliAccessError,
|
|
@@ -97,7 +97,7 @@ import {
|
|
|
97
97
|
validateConfig,
|
|
98
98
|
wasOutputCancelled,
|
|
99
99
|
writeSecretJsonFile
|
|
100
|
-
} from "./cli-
|
|
100
|
+
} from "./cli-xrs02c0t.js";
|
|
101
101
|
import {
|
|
102
102
|
__require
|
|
103
103
|
} from "./cli-0v6na3yp.js";
|
|
@@ -547,8 +547,16 @@ function buildFrustrationAnchor(row) {
|
|
|
547
547
|
if (firstQuote) {
|
|
548
548
|
signal = asString(firstQuote.signal);
|
|
549
549
|
const quote = asString(firstQuote.quote);
|
|
550
|
-
if (quote !== null)
|
|
551
|
-
|
|
550
|
+
if (quote !== null) {
|
|
551
|
+
let end = 0;
|
|
552
|
+
let points = 0;
|
|
553
|
+
for (const ch of quote) {
|
|
554
|
+
if (points++ === 200)
|
|
555
|
+
break;
|
|
556
|
+
end += ch.length;
|
|
557
|
+
}
|
|
558
|
+
quote_preview = quote.slice(0, end);
|
|
559
|
+
}
|
|
552
560
|
}
|
|
553
561
|
return {
|
|
554
562
|
kind: "frustration",
|
|
@@ -624,7 +632,6 @@ function withFrustrationAnchors(response) {
|
|
|
624
632
|
});
|
|
625
633
|
return { ...response, frustrations };
|
|
626
634
|
}
|
|
627
|
-
var TOOL_FAILURE_TEXT_LIMIT = 300;
|
|
628
635
|
var TOOL_FAILURE_CONTEXT_RADIUS = 2;
|
|
629
636
|
function shellWord(value) {
|
|
630
637
|
return /^[\w@%+=:,./-]+$/.test(value) ? value : `'${value.replace(/'/g, `'\\''`)}'`;
|
|
@@ -674,26 +681,6 @@ function trimToolFailureConversations(response, opts) {
|
|
|
674
681
|
});
|
|
675
682
|
return { ...response, examples };
|
|
676
683
|
}
|
|
677
|
-
function compactToolFailureExamples(response, maxChars = TOOL_FAILURE_TEXT_LIMIT) {
|
|
678
|
-
if (!Array.isArray(response.examples))
|
|
679
|
-
return { data: response, truncated: 0 };
|
|
680
|
-
let truncated = 0;
|
|
681
|
-
const cap = (value) => {
|
|
682
|
-
if (typeof value === "string") {
|
|
683
|
-
if (value.length <= maxChars)
|
|
684
|
-
return value;
|
|
685
|
-
truncated += 1;
|
|
686
|
-
return `${value.slice(0, maxChars)}… [truncated ${value.length - maxChars} chars]`;
|
|
687
|
-
}
|
|
688
|
-
if (Array.isArray(value))
|
|
689
|
-
return value.map(cap);
|
|
690
|
-
if (value && typeof value === "object") {
|
|
691
|
-
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, cap(child)]));
|
|
692
|
-
}
|
|
693
|
-
return value;
|
|
694
|
-
};
|
|
695
|
-
return { data: { ...response, examples: response.examples.map(cap) }, truncated };
|
|
696
|
-
}
|
|
697
684
|
function withToolFailureAnchors(response) {
|
|
698
685
|
if (!Array.isArray(response.examples))
|
|
699
686
|
return response;
|
|
@@ -5385,7 +5372,6 @@ var MODA_DIR = ".moda";
|
|
|
5385
5372
|
var HARNESS_PATH = join4(MODA_DIR, "harness.json");
|
|
5386
5373
|
var HARNESS_REPORT_MARKDOWN_PATH = join4(MODA_DIR, "HARNESS_REPORT.md");
|
|
5387
5374
|
var HARNESS_SUMMARY_PATH = join4(MODA_DIR, "HARNESS.md");
|
|
5388
|
-
var MAX_AGENT_EVIDENCE_BYTES = 24000;
|
|
5389
5375
|
async function runAgentCommand(context) {
|
|
5390
5376
|
const subcommand2 = context.positionals[0] ?? "context";
|
|
5391
5377
|
switch (subcommand2) {
|
|
@@ -5738,7 +5724,7 @@ function expandEvidenceRef(ref, loaded, cwd) {
|
|
|
5738
5724
|
label: artifact.description ?? artifact.path,
|
|
5739
5725
|
path: artifact.path
|
|
5740
5726
|
},
|
|
5741
|
-
value:
|
|
5727
|
+
value: readModaArtifact(cwd, artifact.path),
|
|
5742
5728
|
artifact
|
|
5743
5729
|
};
|
|
5744
5730
|
}
|
|
@@ -5769,11 +5755,11 @@ function readCitationExcerpt(cwd, citation) {
|
|
|
5769
5755
|
return citation.excerpt;
|
|
5770
5756
|
const text = readFileSync5(absolute, "utf8");
|
|
5771
5757
|
if (citation.line && citation.line > 0) {
|
|
5772
|
-
return text.split(/\r?\n/)[citation.line - 1]
|
|
5758
|
+
return text.split(/\r?\n/)[citation.line - 1] ?? citation.excerpt;
|
|
5773
5759
|
}
|
|
5774
|
-
return text
|
|
5760
|
+
return text;
|
|
5775
5761
|
}
|
|
5776
|
-
function
|
|
5762
|
+
function readModaArtifact(cwd, artifactPath) {
|
|
5777
5763
|
if (!artifactPath.startsWith(".moda/")) {
|
|
5778
5764
|
throw new CliInputError(`Artifact '${artifactPath}' is outside .moda and cannot be expanded directly.`, "Use a citation evidence ref for source-file evidence.");
|
|
5779
5765
|
}
|
|
@@ -5781,12 +5767,10 @@ function readBoundedModaArtifact(cwd, artifactPath) {
|
|
|
5781
5767
|
if (!absolute || !existsSync4(absolute))
|
|
5782
5768
|
throw missingEvidence(`artifact:${artifactPath}`);
|
|
5783
5769
|
const size = statSync2(absolute).size;
|
|
5784
|
-
const text = readFileSync5(absolute, "utf8");
|
|
5785
5770
|
return {
|
|
5786
5771
|
path: artifactPath,
|
|
5787
5772
|
bytes: size,
|
|
5788
|
-
|
|
5789
|
-
text: text.slice(0, MAX_AGENT_EVIDENCE_BYTES)
|
|
5773
|
+
text: readFileSync5(absolute, "utf8")
|
|
5790
5774
|
};
|
|
5791
5775
|
}
|
|
5792
5776
|
function safeResolve(cwd, path) {
|
|
@@ -7282,7 +7266,7 @@ function toolRows(data, scopedTool) {
|
|
|
7282
7266
|
function firstQuote(row) {
|
|
7283
7267
|
const quotes = Array.isArray(row?.user_quotes) ? row.user_quotes : [];
|
|
7284
7268
|
const first = asRecord(quotes[0]);
|
|
7285
|
-
return asString(first?.quote)
|
|
7269
|
+
return asString(first?.quote) ?? undefined;
|
|
7286
7270
|
}
|
|
7287
7271
|
function likelyToolLocation(toolName, hints) {
|
|
7288
7272
|
const normalized = normalizeKey(toolName);
|
|
@@ -7595,7 +7579,10 @@ async function finishRun(context, outcome) {
|
|
|
7595
7579
|
context.output.close();
|
|
7596
7580
|
if (wasOutputCancelled())
|
|
7597
7581
|
return EXIT_CANCELLED;
|
|
7598
|
-
|
|
7582
|
+
const exitCode = outcome.exitCode ?? EXIT_OK;
|
|
7583
|
+
if (context.output.hasOutputError() && (exitCode === EXIT_OK || exitCode === EXIT_DEGRADED))
|
|
7584
|
+
return EXIT_ERROR;
|
|
7585
|
+
return exitCode;
|
|
7599
7586
|
}
|
|
7600
7587
|
if (outcome.kind === "cancelled") {
|
|
7601
7588
|
context.output.writeCancelled(outcome.reason ?? "Command cancelled.");
|
|
@@ -7659,6 +7646,8 @@ function buildManifest(commands) {
|
|
|
7659
7646
|
"MODA_AUTH_TIMEOUT_MS",
|
|
7660
7647
|
"MODA_HEARTBEAT_MS",
|
|
7661
7648
|
"MODA_AGENT_MAX_OUTPUT_BYTES",
|
|
7649
|
+
"MODA_AGENT_OUTPUT_DIR",
|
|
7650
|
+
"MODA_AGENT_OUTPUT_RETENTION_HOURS",
|
|
7662
7651
|
"MODA_CLI_TELEMETRY",
|
|
7663
7652
|
"MODA_CLI_UPDATE_CHECK",
|
|
7664
7653
|
"MODA_CLI_TIPS"
|
|
@@ -7922,8 +7911,7 @@ Commands:
|
|
|
7922
7911
|
hallucinations Grounding detections: contradicted/verified outputs with rule breakdown
|
|
7923
7912
|
laziness Laziness detections per trace (repeated calls, premature handoffs, ...)
|
|
7924
7913
|
tool-failures Get tool failure overview
|
|
7925
|
-
tool-failure-detail <tool_name> Get per-tool failure detail (--limit=N examples, 1-20, default 5
|
|
7926
|
-
long example text is cut to 300 chars)
|
|
7914
|
+
tool-failure-detail <tool_name> Get per-tool failure detail (--limit=N examples, 1-20, default 5)
|
|
7927
7915
|
problems Rank cross-signal Problems by root cause (what to fix first)
|
|
7928
7916
|
problems remainder Signals no Problem explains yet (--family, --cursor)
|
|
7929
7917
|
problem-impact Live problem/use-case impact (--node-id, --problem-id, --mode, --days-back)
|
|
@@ -9531,11 +9519,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
9531
9519
|
trimmed = { ...trimmed, subtypes: ranked.slice(0, TOOL_FAILURE_AGENT_SUBTYPES), subtypes_total: subtypes.length };
|
|
9532
9520
|
out.push(`Showing the ${TOOL_FAILURE_AGENT_SUBTYPES} most frequent of ${subtypes.length} failure subtypes; --json lists all of them.`);
|
|
9533
9521
|
}
|
|
9534
|
-
|
|
9535
|
-
if (truncated > 0) {
|
|
9536
|
-
out.push(`${truncated} long text field(s) in examples were cut to ${TOOL_FAILURE_TEXT_LIMIT} characters to keep this output small. For the full text, run each example's \`context_command\` (\`moda context <conversation_id> --msg-index=<msg_index>\`).`);
|
|
9537
|
-
}
|
|
9538
|
-
return compacted;
|
|
9522
|
+
return trimmed;
|
|
9539
9523
|
});
|
|
9540
9524
|
break;
|
|
9541
9525
|
}
|
|
@@ -10163,7 +10147,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
10163
10147
|
resetApiRequestCountBeforeRun: true,
|
|
10164
10148
|
telemetry: "result",
|
|
10165
10149
|
handler: async (context) => {
|
|
10166
|
-
const { runInit } = await import("./index-
|
|
10150
|
+
const { runInit } = await import("./index-z0jpjcsm.js");
|
|
10167
10151
|
if (context.outputMode === "agent-stream") {
|
|
10168
10152
|
context.output.writeEvent({
|
|
10169
10153
|
event: "started",
|
|
@@ -10204,7 +10188,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
10204
10188
|
resetApiRequestCountBeforeRun: true,
|
|
10205
10189
|
telemetry: "result-and-error",
|
|
10206
10190
|
handler: async (context) => {
|
|
10207
|
-
const { runProvision } = await import("./provision-
|
|
10191
|
+
const { runProvision } = await import("./provision-qkazpt0c.js");
|
|
10208
10192
|
return runProvision(context, {
|
|
10209
10193
|
resumeCommand: buildResumeCommand("provision", context.rawFlags)
|
|
10210
10194
|
});
|
|
@@ -10701,7 +10685,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
10701
10685
|
}),
|
|
10702
10686
|
legacyCommand({
|
|
10703
10687
|
name: "tool-failure-detail",
|
|
10704
|
-
description: "Get per-tool failure detail (each example embeds its anchor ±2 messages
|
|
10688
|
+
description: "Get per-tool failure detail (each example embeds its anchor ±2 messages)",
|
|
10705
10689
|
examples: [
|
|
10706
10690
|
"moda tool-failure-detail search",
|
|
10707
10691
|
"moda tool-failure-detail search --compact # no embedded conversation (same as --include-window=false)",
|
|
@@ -42,8 +42,8 @@ import {
|
|
|
42
42
|
writeHarnessAnalyzeResult,
|
|
43
43
|
writeHarnessArtifacts,
|
|
44
44
|
writeHumanProgress
|
|
45
|
-
} from "./cli-
|
|
46
|
-
import"./cli-
|
|
45
|
+
} from "./cli-x0x0n35w.js";
|
|
46
|
+
import"./cli-xrs02c0t.js";
|
|
47
47
|
import"./cli-0v6na3yp.js";
|
|
48
48
|
export {
|
|
49
49
|
writeHumanProgress,
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
initPrompts,
|
|
4
4
|
runPromptSync,
|
|
5
5
|
runSkillSync
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-jqfm8dp4.js";
|
|
7
7
|
import {
|
|
8
8
|
codingAgentDisplayName,
|
|
9
9
|
describeCodingAgentEvent,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
runHarnessCommand,
|
|
23
23
|
startRemoteAnalyze,
|
|
24
24
|
stripAnsi
|
|
25
|
-
} from "./cli-
|
|
25
|
+
} from "./cli-x0x0n35w.js";
|
|
26
26
|
import {
|
|
27
27
|
bundledSkillsDir,
|
|
28
28
|
installIntegrationSkill,
|
|
@@ -34,14 +34,14 @@ import {
|
|
|
34
34
|
} from "./cli-ssfq84k5.js";
|
|
35
35
|
import {
|
|
36
36
|
selectTenantAndCreateKey
|
|
37
|
-
} from "./cli-
|
|
37
|
+
} from "./cli-h4k23fb0.js";
|
|
38
38
|
import {
|
|
39
39
|
ConnectCodeError,
|
|
40
40
|
connectWithCode,
|
|
41
41
|
loadAuthSession,
|
|
42
42
|
loadToken,
|
|
43
43
|
login
|
|
44
|
-
} from "./cli-
|
|
44
|
+
} from "./cli-7kbzqact.js";
|
|
45
45
|
import {
|
|
46
46
|
CliAuthError,
|
|
47
47
|
CliInputError,
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
createCommandContext,
|
|
50
50
|
resolveIngestUrl,
|
|
51
51
|
resolveModaBaseUrl
|
|
52
|
-
} from "./cli-
|
|
52
|
+
} from "./cli-xrs02c0t.js";
|
|
53
53
|
import"./cli-0v6na3yp.js";
|
|
54
54
|
|
|
55
55
|
// src/init/index.ts
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
selectTenantAndCreateKey
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-h4k23fb0.js";
|
|
4
4
|
import {
|
|
5
5
|
loadAuthSession
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-7kbzqact.js";
|
|
7
7
|
import {
|
|
8
8
|
CliAuthError,
|
|
9
9
|
resolveIngestUrl,
|
|
10
10
|
resolveModaBaseUrl,
|
|
11
11
|
stringOption
|
|
12
|
-
} from "./cli-
|
|
12
|
+
} from "./cli-xrs02c0t.js";
|
|
13
13
|
import"./cli-0v6na3yp.js";
|
|
14
14
|
|
|
15
15
|
// src/provision.ts
|
package/package.json
CHANGED
package/skills/moda-cli/SKILL.md
CHANGED
|
@@ -364,8 +364,8 @@ Fields an agent should read:
|
|
|
364
364
|
|
|
365
365
|
`errors[].code` is one of `input_error`, `api_error`, `network_error`,
|
|
366
366
|
`auth_required`, `input_required`, `cancelled`, `command_error`,
|
|
367
|
-
`access_denied`, `unknown_error`, or a documented domain
|
|
368
|
-
`cloud_unavailable`. `access_denied` (exit 1) is an access problem — no
|
|
367
|
+
`access_denied`, `output_error`, `unknown_error`, or a documented domain
|
|
368
|
+
code such as `cloud_unavailable`. `access_denied` (exit 1) is an access problem — no
|
|
369
369
|
organizations or an insufficient (viewer) role — distinct from `auth_required`
|
|
370
370
|
(exit 4, missing/expired credentials).
|
|
371
371
|
|
|
@@ -408,14 +408,26 @@ Treat an answer as degraded if **any** of these hold:
|
|
|
408
408
|
|
|
409
409
|
### Large outputs and unknown flags
|
|
410
410
|
|
|
411
|
-
- **Byte limit.** In `--agent` mode, envelopes over 200 KB
|
|
412
|
-
*without*
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
`
|
|
417
|
-
|
|
418
|
-
|
|
411
|
+
- **Byte limit.** In `--agent` mode, envelopes over 200 KB
|
|
412
|
+
(`MODA_AGENT_MAX_OUTPUT_BYTES`) are bounded *without* cutting any text or
|
|
413
|
+
breaking their shape: the complete output (the same JSON `--json` prints) is
|
|
414
|
+
written to a local file, and whole trailing list items are dropped from
|
|
415
|
+
`data`. `truncation.data.full_output_path` (also an `artifacts[]` entry of
|
|
416
|
+
kind `full_output`) is that file; read it in line ranges or with `jq`.
|
|
417
|
+
These files are pruned after 24 hours (`MODA_AGENT_OUTPUT_RETENTION_HOURS`).
|
|
418
|
+
`truncation.data` also says what was dropped (`dropped_items`,
|
|
419
|
+
`complete: false`). `data` is still normal JSON, so
|
|
420
|
+
`data.frustrations[0].conversation_id` keeps working. If even one item is
|
|
421
|
+
over budget, `data` is a stub `{ truncated, original_bytes, max_bytes,
|
|
422
|
+
full_output_path }`. If that file cannot be written (unwritable
|
|
423
|
+
`MODA_AGENT_OUTPUT_DIR`, full disk), nothing is dropped: the envelope keeps
|
|
424
|
+
the whole result over the limit with `status: "error"`, an `output_error`
|
|
425
|
+
(`cause: "full_output_save_failed"`), and exit `1`. If only the oversized
|
|
426
|
+
envelope text could not be saved (`cause: "envelope_text_save_failed"`),
|
|
427
|
+
that text stays whole, and the error message says whether `data` is whole
|
|
428
|
+
or bounded with its complete copy at `truncation.data.full_output_path`.
|
|
429
|
+
You can also page with a smaller `--limit` and
|
|
430
|
+
`--offset`, or rerun with `--json` (no byte limit).
|
|
419
431
|
- **Unknown flags fail.** A flag the command doesn't take (a typo, or a
|
|
420
432
|
filter it lacks) exits `1` with the valid flag list and a "did you mean",
|
|
421
433
|
instead of being silently ignored. Stray arguments on commands that take
|
|
@@ -746,9 +758,9 @@ Pass `--include-window` to attach a `window` field per row (instead of
|
|
|
746
758
|
(1–5, default `1`) is the half-width; `--window=1` ⇒ 3 messages total
|
|
747
759
|
(anchor ± 1).
|
|
748
760
|
|
|
749
|
-
Examples default to `--limit=5` (max 20).
|
|
750
|
-
|
|
751
|
-
|
|
761
|
+
Examples default to `--limit=5` (max 20). Example text is returned whole; if
|
|
762
|
+
the agent envelope goes over its byte limit, whole trailing examples are
|
|
763
|
+
dropped and `truncation.data.full_output_path` holds every example. Agent output lists the 20 most frequent
|
|
752
764
|
`subtypes` (`subtypes_total` has the full count); `--json` lists all.
|
|
753
765
|
|
|
754
766
|
### 7. Prompt management
|