@moda-ai/cli 1.55.41 → 1.55.43
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-ck6y31n2.js → agent-x1gwrrvd.js} +6 -5
- package/dist/{cli-xddtv3yn.js → cli-5fhqfx04.js} +1 -39
- package/dist/{cli-gt3yq1y5.js → cli-5y9tj6cb.js} +183 -1
- package/dist/{cli-f1jfrqgf.js → cli-9a0a3v13.js} +234 -17
- package/dist/cli-e0kbye4s.js +39 -0
- package/dist/{cli-ypqwcf9n.js → cli-fpd1pfvt.js} +2 -2
- package/dist/{cli-a8nxbtpk.js → cli-h62j4jn7.js} +2 -2
- package/dist/{cli-4tg0hkbz.js → cli-k5drmy8r.js} +7 -7
- package/dist/{cli-azage7s0.js → cli-s1w5phms.js} +3 -3
- package/dist/{cli-7bn406mt.js → cli-stfpr2ct.js} +2 -2
- package/dist/cli.js +224 -52
- package/dist/{doctor-p8sp6cbk.js → doctor-wrgajgev.js} +5 -4
- package/dist/{fix-0r974yge.js → fix-7aajsdbf.js} +1 -1
- package/dist/{harness-72ejenza.js → harness-1rn1hqzz.js} +4 -3
- package/dist/{harness-github-actions-2qc4gg2w.js → harness-github-actions-m95qvgbs.js} +4 -3
- package/dist/{index-w7v472w4.js → index-svfzq5rb.js} +7 -6
- package/dist/{production-intelligence-e5vsc6cw.js → production-intelligence-7jvfdz6b.js} +22 -5
- package/dist/{prompt-attribution-3987hhqz.js → prompt-attribution-hc6mcvee.js} +4 -3
- package/dist/prompt-source-mcp.js +4 -3
- package/dist/{prompts-ab-gmd10n5d.js → prompts-ab-ws66335h.js} +5 -4
- package/dist/{prompts-propose-q626zmm4.js → prompts-propose-a9m0p9nr.js} +5 -4
- package/dist/{prompts-ysm9ra72.js → prompts-xe5bgbx8.js} +4 -3
- package/dist/{provision-cya5rpxa.js → provision-a9kkfvp7.js} +2 -1
- package/dist/{registry-7xz09ry0.js → registry-j2dsfh6v.js} +1 -1
- package/dist/{skills-x6yszxxn.js → skills-vveagdwe.js} +4 -3
- package/dist/{sync-trjzvam9.js → sync-yy3fgnxe.js} +6 -5
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/skills/moda-cli/SKILL.md +4 -1
- package/skills/moda-cli/references/commands.md +8 -3
- package/skills/moda-cli/references/dashboard-parity.md +7 -2
- package/skills/moda-cli/references/detections.md +20 -0
- package/skills/moda-cli/references/production-intelligence.md +48 -0
package/dist/cli.js
CHANGED
|
@@ -6,34 +6,41 @@ import {
|
|
|
6
6
|
asNumber,
|
|
7
7
|
asRecord,
|
|
8
8
|
asString,
|
|
9
|
+
assertCompareScope,
|
|
9
10
|
collectBatchTargets,
|
|
10
11
|
compactProblemDossier,
|
|
11
12
|
contextTarget,
|
|
12
13
|
embeddedWindowSize,
|
|
13
14
|
frustrationsFromEmotions,
|
|
15
|
+
loadFamilyCompare,
|
|
14
16
|
mapWithConcurrency,
|
|
15
17
|
parseBatchTarget,
|
|
16
18
|
parseTargetLines,
|
|
19
|
+
problemTrendSummary,
|
|
17
20
|
readIdsFrom,
|
|
18
21
|
shapeToolCatalogDetail,
|
|
19
22
|
toolCatalogGetCommand,
|
|
20
23
|
toolFailureExamplesCommand,
|
|
21
24
|
trimToolFailureConversations,
|
|
22
25
|
withFrustrationAnchors,
|
|
26
|
+
withSummaryCompare,
|
|
23
27
|
withToolFailureAnchors,
|
|
24
28
|
withoutDetectionWindows
|
|
25
|
-
} from "./cli-
|
|
29
|
+
} from "./cli-5y9tj6cb.js";
|
|
30
|
+
import {
|
|
31
|
+
createCommandContext
|
|
32
|
+
} from "./cli-5fhqfx04.js";
|
|
26
33
|
import {
|
|
27
|
-
createCommandContext,
|
|
28
34
|
envOptOutSet,
|
|
29
35
|
envSwitchedOff,
|
|
30
36
|
optOutFlagSet,
|
|
31
37
|
parseBooleanFlagValue,
|
|
32
38
|
withoutFlag
|
|
33
|
-
} from "./cli-
|
|
39
|
+
} from "./cli-e0kbye4s.js";
|
|
34
40
|
import {
|
|
35
41
|
AuditSchema,
|
|
36
42
|
BOOK_PROBLEM_SORTS,
|
|
43
|
+
CLUSTER_COHORT_TIME_RANGES,
|
|
37
44
|
COMMAND_FLAG_SPECS,
|
|
38
45
|
DETECTION_VERDICTS,
|
|
39
46
|
DREAM_PROBLEM_SORTS,
|
|
@@ -68,6 +75,7 @@ import {
|
|
|
68
75
|
kebabFlag,
|
|
69
76
|
manifestFlagFields,
|
|
70
77
|
renderFlagHelp,
|
|
78
|
+
runCohortCommand,
|
|
71
79
|
runProblemReopenCommand,
|
|
72
80
|
runSignalsManagementCommand,
|
|
73
81
|
runUserCommand,
|
|
@@ -79,7 +87,7 @@ import {
|
|
|
79
87
|
unknownSignalsSubcommandError,
|
|
80
88
|
usageLine,
|
|
81
89
|
writeDryRun
|
|
82
|
-
} from "./cli-
|
|
90
|
+
} from "./cli-9a0a3v13.js";
|
|
83
91
|
import {
|
|
84
92
|
ApiError,
|
|
85
93
|
callControlAPI,
|
|
@@ -1355,7 +1363,7 @@ var CANONICAL_LEAVES = [
|
|
|
1355
1363
|
args: "<problem_id>",
|
|
1356
1364
|
handler: "problem",
|
|
1357
1365
|
summary: "One Problem: dossier, its --evidence/--reports/--traces/--feedback pages, or --view=dream",
|
|
1358
|
-
examples: ["moda problems get <problem_id>", "moda problems get <problem_id> --view=dream", "moda problems get <problem_id> --evidence --limit=10", "moda problems get <problem_id> --traces --family=tool_failure"]
|
|
1366
|
+
examples: ["moda problems get <problem_id>", "moda problems get <problem_id> --view=dream", "moda problems get <problem_id> --evidence --limit=10", "moda problems get <problem_id> --traces --family=tool_failure", "moda problems get <problem_id> --trend --days-back=14"]
|
|
1359
1367
|
},
|
|
1360
1368
|
{
|
|
1361
1369
|
noun: "problems",
|
|
@@ -1423,7 +1431,8 @@ var CANONICAL_LEAVES = [
|
|
|
1423
1431
|
"moda detections list --family=frustration --limit=10",
|
|
1424
1432
|
"moda detections list --family=emotion:confusion --days-back=14",
|
|
1425
1433
|
"moda detections list --family=hallucination --kind=contradicted",
|
|
1426
|
-
"moda detections list --family=custom_signal --signal-id=<signal_id>"
|
|
1434
|
+
"moda detections list --family=custom_signal --signal-id=<signal_id>",
|
|
1435
|
+
"moda detections list --family=frustration --compare --days-back=7"
|
|
1427
1436
|
]
|
|
1428
1437
|
},
|
|
1429
1438
|
{
|
|
@@ -1453,6 +1462,69 @@ var CANONICAL_LEAVES = [
|
|
|
1453
1462
|
summary: "One tool: calls, recorded schema and payload fields, usage over time, top failure categories",
|
|
1454
1463
|
examples: ["moda tools get <tool_name>", "moda tools get <tool_name> --days-back=30 --full"]
|
|
1455
1464
|
},
|
|
1465
|
+
{
|
|
1466
|
+
noun: "cohorts",
|
|
1467
|
+
verb: "list",
|
|
1468
|
+
path: "cohorts list",
|
|
1469
|
+
args: "",
|
|
1470
|
+
handler: "cohort-list",
|
|
1471
|
+
summary: "Built-in and saved user cohorts with their refs and definitions (the dashboard Users page)",
|
|
1472
|
+
examples: ["moda cohorts list", "moda cohorts list --include-archived"]
|
|
1473
|
+
},
|
|
1474
|
+
{
|
|
1475
|
+
noun: "cohorts",
|
|
1476
|
+
verb: "get",
|
|
1477
|
+
path: "cohorts get",
|
|
1478
|
+
args: "<ref>",
|
|
1479
|
+
handler: "cohort-get",
|
|
1480
|
+
summary: "One cohort: name, definition and revision (ref: builtin:<key> or a saved cohort id)",
|
|
1481
|
+
examples: ["moda cohorts get builtin:power_users", "moda cohorts get <cohort_id>"]
|
|
1482
|
+
},
|
|
1483
|
+
{
|
|
1484
|
+
noun: "cohorts",
|
|
1485
|
+
verb: "fields",
|
|
1486
|
+
path: "cohorts fields",
|
|
1487
|
+
args: "",
|
|
1488
|
+
handler: "cohort-fields",
|
|
1489
|
+
summary: "The fields and operators a cohort definition can use",
|
|
1490
|
+
examples: ["moda cohorts fields"]
|
|
1491
|
+
},
|
|
1492
|
+
{
|
|
1493
|
+
noun: "cohorts",
|
|
1494
|
+
verb: "preview",
|
|
1495
|
+
path: "cohorts preview",
|
|
1496
|
+
args: "",
|
|
1497
|
+
handler: "cohort-preview",
|
|
1498
|
+
summary: "Member count and a sample of users for an unsaved definition",
|
|
1499
|
+
examples: ["moda cohorts preview --file=cohort.json", `moda cohorts preview --definition='{"version":1,"window":"30d","where":{"field":"tool_failure_count","op":"gte","value":3}}'`]
|
|
1500
|
+
},
|
|
1501
|
+
{
|
|
1502
|
+
noun: "cohorts",
|
|
1503
|
+
verb: "compare",
|
|
1504
|
+
path: "cohorts compare",
|
|
1505
|
+
args: "<cohort_a> <cohort_b>",
|
|
1506
|
+
handler: "cohort-compare",
|
|
1507
|
+
summary: "Two cohorts side by side: size, health, top topics and failure mix",
|
|
1508
|
+
examples: ["moda cohorts compare builtin:new_this_week builtin:power_users --days=30"]
|
|
1509
|
+
},
|
|
1510
|
+
{
|
|
1511
|
+
noun: "cohorts",
|
|
1512
|
+
verb: "create",
|
|
1513
|
+
path: "cohorts create",
|
|
1514
|
+
args: "",
|
|
1515
|
+
handler: "cohort-create",
|
|
1516
|
+
summary: "Save a cohort from a definition (write; --dry-run prints the request)",
|
|
1517
|
+
examples: ['moda cohorts create --name="Enterprise" --file=cohort.json --dry-run']
|
|
1518
|
+
},
|
|
1519
|
+
{
|
|
1520
|
+
noun: "cohorts",
|
|
1521
|
+
verb: "update",
|
|
1522
|
+
path: "cohorts update",
|
|
1523
|
+
args: "<cohort_id>",
|
|
1524
|
+
handler: "cohort-update",
|
|
1525
|
+
summary: "Edit a saved cohort: name, definition, description, pin, color (write; --dry-run)",
|
|
1526
|
+
examples: ['moda cohorts update <cohort_id> --file=cohort.json --note="exclude trials" --dry-run']
|
|
1527
|
+
},
|
|
1456
1528
|
{
|
|
1457
1529
|
noun: "review",
|
|
1458
1530
|
verb: "",
|
|
@@ -1486,12 +1558,13 @@ var CANONICAL_LEAVES = [
|
|
|
1486
1558
|
examples: ["moda skills push --dry-run", "moda skills push"]
|
|
1487
1559
|
}
|
|
1488
1560
|
];
|
|
1489
|
-
var CANONICAL_NOUNS = ["traces", "problems", "detections", "tools", "review", "reviews", "skills"];
|
|
1561
|
+
var CANONICAL_NOUNS = ["traces", "problems", "detections", "tools", "cohorts", "review", "reviews", "skills"];
|
|
1490
1562
|
var NOUN_SUMMARIES = {
|
|
1491
1563
|
traces: "Traces (agent runs): list, search, read, findings, world state, raw spans",
|
|
1492
1564
|
problems: "Problems ranked by root cause, their evidence, impact and lifecycle",
|
|
1493
1565
|
detections: "Detections of every family, and the tool failure leaderboard",
|
|
1494
1566
|
tools: "The Tool catalog: every tool with calls and success rate, and one tool's schema, usage and failure categories",
|
|
1567
|
+
cohorts: "User cohorts: list, read, preview and compare them, and save or edit one; scope lists with --cohort",
|
|
1495
1568
|
review: "Mark a detection a false positive, correct, or clear the mark",
|
|
1496
1569
|
reviews: "List false-positive marks and detection reviews",
|
|
1497
1570
|
skills: "Generate, pull, push, and install agent skills"
|
|
@@ -3175,31 +3248,31 @@ function leafManifestFields(leaf, commands) {
|
|
|
3175
3248
|
import { fileURLToPath } from "url";
|
|
3176
3249
|
import { realpathSync } from "fs";
|
|
3177
3250
|
async function runPromptsCommand(...args) {
|
|
3178
|
-
return (await import("./prompts-
|
|
3251
|
+
return (await import("./prompts-xe5bgbx8.js")).runPromptsCommand(...args);
|
|
3179
3252
|
}
|
|
3180
3253
|
async function runSkillsCommand(...args) {
|
|
3181
|
-
return (await import("./skills-
|
|
3254
|
+
return (await import("./skills-vveagdwe.js")).runSkillsCommand(...args);
|
|
3182
3255
|
}
|
|
3183
3256
|
async function runFixCommand(...args) {
|
|
3184
|
-
return (await import("./fix-
|
|
3257
|
+
return (await import("./fix-7aajsdbf.js")).runFixCommand(...args);
|
|
3185
3258
|
}
|
|
3186
3259
|
async function runFixesCommand(...args) {
|
|
3187
|
-
return (await import("./fix-
|
|
3260
|
+
return (await import("./fix-7aajsdbf.js")).runFixesCommand(...args);
|
|
3188
3261
|
}
|
|
3189
3262
|
async function runHarnessCommand(...args) {
|
|
3190
|
-
return (await import("./harness-
|
|
3263
|
+
return (await import("./harness-1rn1hqzz.js")).runHarnessCommand(...args);
|
|
3191
3264
|
}
|
|
3192
3265
|
async function runSyncCommand(...args) {
|
|
3193
|
-
return (await import("./sync-
|
|
3266
|
+
return (await import("./sync-yy3fgnxe.js")).runSyncCommand(...args);
|
|
3194
3267
|
}
|
|
3195
3268
|
async function runRegistryCommand(...args) {
|
|
3196
|
-
return (await import("./registry-
|
|
3269
|
+
return (await import("./registry-j2dsfh6v.js")).runRegistryCommand(...args);
|
|
3197
3270
|
}
|
|
3198
3271
|
async function runDoctorCommand(...args) {
|
|
3199
|
-
return (await import("./doctor-
|
|
3272
|
+
return (await import("./doctor-wrgajgev.js")).runDoctorCommand(...args);
|
|
3200
3273
|
}
|
|
3201
3274
|
async function runStatusCommand(...args) {
|
|
3202
|
-
return (await import("./doctor-
|
|
3275
|
+
return (await import("./doctor-wrgajgev.js")).runStatusCommand(...args);
|
|
3203
3276
|
}
|
|
3204
3277
|
async function runAuthCommand(...args) {
|
|
3205
3278
|
return (await import("./profile-commands-se9947c1.js")).runAuthCommand(...args);
|
|
@@ -3211,10 +3284,10 @@ async function runProfilesCommand(...args) {
|
|
|
3211
3284
|
return (await import("./profile-commands-se9947c1.js")).runProfilesCommand(...args);
|
|
3212
3285
|
}
|
|
3213
3286
|
async function runAgentCommand(...args) {
|
|
3214
|
-
return (await import("./agent-
|
|
3287
|
+
return (await import("./agent-x1gwrrvd.js")).runAgentCommand(...args);
|
|
3215
3288
|
}
|
|
3216
3289
|
async function runProductionCommand(...args) {
|
|
3217
|
-
return (await import("./production-intelligence-
|
|
3290
|
+
return (await import("./production-intelligence-7jvfdz6b.js")).runProductionCommand(...args);
|
|
3218
3291
|
}
|
|
3219
3292
|
function parseArgs(argv) {
|
|
3220
3293
|
const args = argv.slice(2);
|
|
@@ -3515,6 +3588,7 @@ Production data:
|
|
|
3515
3588
|
clusters Browse or search topic clusters
|
|
3516
3589
|
cluster-traces <node_id> List traces in a cluster
|
|
3517
3590
|
users / user <user_id> End users with health and activity (the dashboard Users page)
|
|
3591
|
+
cohorts list|get|compare User cohorts; --cohort=<ref> scopes problems, traces, detections, clusters
|
|
3518
3592
|
tail Live-tail new traces/detections as NDJSON (one line per item)
|
|
3519
3593
|
|
|
3520
3594
|
Traces, Problems, detections, tools and review (moda <noun> --help lists the verbs):
|
|
@@ -4858,10 +4932,7 @@ async function runProblemsList(flags, context, command) {
|
|
|
4858
4932
|
...listVersionWarning(params, listVersion),
|
|
4859
4933
|
...truncated ? [`--limit=${limit} also capped ${Object.entries(truncated).map(([block, count]) => `${block} (${count} more)`).join(", ")}; raise --limit (max ${PROBLEMS_MAX_LIMIT}) or open dashboard_url for the rest.`] : []
|
|
4860
4934
|
];
|
|
4861
|
-
context.output.writeData(withLink, {
|
|
4862
|
-
...warnings.length > 0 ? { warnings } : {},
|
|
4863
|
-
...nextCommands.length > 0 ? { nextCommands } : {}
|
|
4864
|
-
});
|
|
4935
|
+
context.output.writeData(withLink, withCohortScope(params.cohort, payload, { warnings, nextCommands }));
|
|
4865
4936
|
}
|
|
4866
4937
|
function writeDreamProblemsList(context, params, dream, page) {
|
|
4867
4938
|
const problems = Array.isArray(dream.problems) ? dream.problems : [];
|
|
@@ -4903,7 +4974,7 @@ function writeDreamProblemsList(context, params, dream, page) {
|
|
|
4903
4974
|
...!page.daysGiven && windowHours !== undefined ? [`Counts cover the dream run's window (${windowHours} hours), the dashboard's default range; pass --days-back to choose another.`] : [],
|
|
4904
4975
|
...listVersionWarning(params, listVersion)
|
|
4905
4976
|
];
|
|
4906
|
-
context.output.writeData(data, { warnings, ...
|
|
4977
|
+
context.output.writeData(data, { warnings, ...withCohortScope(params.cohort, dream, { warnings, nextCommands }) });
|
|
4907
4978
|
}
|
|
4908
4979
|
var DREAM_INCIDENTS_DEFAULT_LIMIT = 3;
|
|
4909
4980
|
async function runDreamProblem(params, context, command) {
|
|
@@ -5008,6 +5079,27 @@ function setTraceFilters(query2, params, keys) {
|
|
|
5008
5079
|
query2.set(key, String(value));
|
|
5009
5080
|
}
|
|
5010
5081
|
}
|
|
5082
|
+
function cohortScope(cohort, data) {
|
|
5083
|
+
if (!cohort || cohort === "all")
|
|
5084
|
+
return { warnings: [] };
|
|
5085
|
+
if (asString(asRecord(data)?.cohort) !== cohort) {
|
|
5086
|
+
return {
|
|
5087
|
+
warnings: [`--cohort=${cohort} was sent, but the response does not confirm the cohort scope, so these results may cover every user.`]
|
|
5088
|
+
};
|
|
5089
|
+
}
|
|
5090
|
+
return { line: `Scoped to cohort ${cohort}: only its members' traces count (moda cohorts get ${shellArg(cohort)} shows who is in it).`, warnings: [] };
|
|
5091
|
+
}
|
|
5092
|
+
function withCohortScope(cohort, data, options = {}) {
|
|
5093
|
+
const scope = cohortScope(cohort, data);
|
|
5094
|
+
const summary = [options.summary, scope.line].filter(Boolean).join(" ");
|
|
5095
|
+
const warnings = [...options.warnings ?? [], ...scope.warnings];
|
|
5096
|
+
const merged = {
|
|
5097
|
+
...summary ? { summary } : {},
|
|
5098
|
+
...warnings.length > 0 ? { warnings } : {},
|
|
5099
|
+
...options.nextCommands && options.nextCommands.length > 0 ? { nextCommands: options.nextCommands } : {}
|
|
5100
|
+
};
|
|
5101
|
+
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
5102
|
+
}
|
|
5011
5103
|
function countingSummary(data) {
|
|
5012
5104
|
const record = asRecord(data);
|
|
5013
5105
|
const counting = asString(record?.counting);
|
|
@@ -5702,8 +5794,11 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5702
5794
|
case "clusters": {
|
|
5703
5795
|
const args = flagsToArgs(flags);
|
|
5704
5796
|
const params = parseSpecFlags("clusters", args, command);
|
|
5797
|
+
if (params.cohort && params.cohort !== "all" && params.time_range && !CLUSTER_COHORT_TIME_RANGES.includes(params.time_range)) {
|
|
5798
|
+
throw new CliInputError(`--cohort reads the Topics tree windows, so --time-range must be ${CLUSTER_COHORT_TIME_RANGES.join(", ")} (got ${params.time_range}). Nothing was sent.`);
|
|
5799
|
+
}
|
|
5705
5800
|
if (params.search !== undefined || params.node_id !== undefined) {
|
|
5706
|
-
rejectInapplicableFlags(command, params, ["parent_id", "time_range"], "to a cluster search (--search/--node-id); they page the cluster hierarchy");
|
|
5801
|
+
rejectInapplicableFlags(command, params, params.cohort ? ["parent_id"] : ["parent_id", "time_range"], "to a cluster search (--search/--node-id); they page the cluster hierarchy");
|
|
5707
5802
|
const query3 = new URLSearchParams;
|
|
5708
5803
|
if (params.search !== undefined)
|
|
5709
5804
|
query3.set("q", params.search);
|
|
@@ -5713,11 +5808,15 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5713
5808
|
query3.set("mode", params.mode);
|
|
5714
5809
|
if (params.limit)
|
|
5715
5810
|
query3.set("limit", params.limit.toString());
|
|
5811
|
+
if (params.cohort)
|
|
5812
|
+
query3.set("cohort", params.cohort);
|
|
5813
|
+
if (params.cohort && params.time_range)
|
|
5814
|
+
query3.set("time_range", params.time_range);
|
|
5716
5815
|
const data2 = await callDataAPI(`/task-clusters/search?${query3.toString()}`);
|
|
5717
5816
|
const record = asRecord(data2) ?? {};
|
|
5718
5817
|
const matches = Array.isArray(record.matches) ? record.matches : [];
|
|
5719
|
-
const warnings = params.node_id !== undefined && matches.length === 0 ? [`No cluster matched node id "${params.node_id}" for this search. ${NOT_FOUND_HINTS.cluster}`] : [];
|
|
5720
|
-
context.output.writeData(data2,
|
|
5818
|
+
const warnings = params.node_id !== undefined && matches.length === 0 ? [`No cluster matched node id "${params.node_id}" for this search${params.cohort ? " within the cohort" : ""}. ${NOT_FOUND_HINTS.cluster}`] : [];
|
|
5819
|
+
context.output.writeData(data2, withCohortScope(params.cohort, data2, { warnings }));
|
|
5721
5820
|
break;
|
|
5722
5821
|
}
|
|
5723
5822
|
rejectInapplicableFlags(command, params, ["mode", "limit"], "without --search or --node-id; they shape a cluster search");
|
|
@@ -5726,9 +5825,11 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5726
5825
|
query2.set("parent_id", params.parent_id);
|
|
5727
5826
|
if (params.time_range)
|
|
5728
5827
|
query2.set("time_range", params.time_range);
|
|
5828
|
+
if (params.cohort)
|
|
5829
|
+
query2.set("cohort", params.cohort);
|
|
5729
5830
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
5730
5831
|
const data = await callDataAPI(`/clusters${queryString}`);
|
|
5731
|
-
context.output.writeData(data);
|
|
5832
|
+
context.output.writeData(data, withCohortScope(params.cohort, data));
|
|
5732
5833
|
break;
|
|
5733
5834
|
}
|
|
5734
5835
|
case "cluster-traces":
|
|
@@ -5775,6 +5876,8 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5775
5876
|
query2.set("outcome", params.outcome);
|
|
5776
5877
|
if (params.sort)
|
|
5777
5878
|
query2.set("sort_by", params.sort);
|
|
5879
|
+
if (params.cohort)
|
|
5880
|
+
query2.set("cohort", params.cohort);
|
|
5778
5881
|
if (params.limit)
|
|
5779
5882
|
query2.set("limit", params.limit.toString());
|
|
5780
5883
|
if (params.offset !== undefined)
|
|
@@ -5800,7 +5903,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5800
5903
|
}
|
|
5801
5904
|
}
|
|
5802
5905
|
searchWarnings.push(...traceStateWarnings(data));
|
|
5803
|
-
const writeOptions =
|
|
5906
|
+
const writeOptions = withCohortScope(params.cohort, raw, { warnings: searchWarnings });
|
|
5804
5907
|
if (params.include_world_state === true) {
|
|
5805
5908
|
const enriched = asRecord(data) ?? {};
|
|
5806
5909
|
const list = Array.isArray(enriched.conversations) ? enriched.conversations : [];
|
|
@@ -5962,6 +6065,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5962
6065
|
case "frustrations": {
|
|
5963
6066
|
const args = flagsToArgs(flags);
|
|
5964
6067
|
const params = parseSpecFlags("frustrations", args, command);
|
|
6068
|
+
const compare = params.compare === true ? await loadFamilyCompare("frustrations", params) : undefined;
|
|
5965
6069
|
const query2 = new URLSearchParams;
|
|
5966
6070
|
if (params.days_back)
|
|
5967
6071
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -5972,10 +6076,9 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5972
6076
|
if (readsPerTrace("frustrations", params, ["user_id", "conversation_id", "conversation_ids", "ids_from", "include_window"])) {
|
|
5973
6077
|
query2.set("family", "frustration");
|
|
5974
6078
|
setTraceFilters(query2, params, TRACE_GRAIN_FLAGS.frustrations);
|
|
5975
|
-
const data2 = await callDataAPI(`/emotions?${query2.toString()}`);
|
|
6079
|
+
const data2 = withSummaryCompare(await callDataAPI(`/emotions?${query2.toString()}`), compare);
|
|
5976
6080
|
const warnings = processingDisabledWarning(data2, "frustration");
|
|
5977
|
-
|
|
5978
|
-
context.output.writeData(data2, { ...summary ? { summary } : {}, ...warnings.length > 0 ? { warnings } : {} });
|
|
6081
|
+
context.output.writeData(data2, withCohortScope(params.cohort, data2, { summary: countingSummary(data2), warnings }));
|
|
5979
6082
|
break;
|
|
5980
6083
|
}
|
|
5981
6084
|
if (params.user_id)
|
|
@@ -5991,22 +6094,33 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5991
6094
|
if (agentMode && !includeWindow)
|
|
5992
6095
|
query2.set("include_context", "0");
|
|
5993
6096
|
const data = frustrationsFromEmotions(await callDataAPI(`/emotions?${query2.toString()}`));
|
|
5994
|
-
const anchored = withFrustrationAnchors(data);
|
|
6097
|
+
const anchored = withSummaryCompare(withFrustrationAnchors(data), compare);
|
|
5995
6098
|
await printWithOptionalWindows(agentMode && !includeWindow ? withoutDetectionWindows(anchored, "frustrations", "conversation") : anchored, "frustrations", includeWindow, params.window ?? 1, context.output, processingDisabledWarning(data, "frustration"), agentMode && includeWindow ? (payload) => withoutRepeatedFrustrationWindow(payload) : undefined, [], countingSummary(data));
|
|
5996
6099
|
break;
|
|
5997
6100
|
}
|
|
5998
6101
|
case "tool-failures": {
|
|
5999
6102
|
const args = flagsToArgs(flags);
|
|
6000
6103
|
const params = parseSpecFlags("tool-failures", args, command);
|
|
6001
|
-
const
|
|
6002
|
-
|
|
6104
|
+
const tfQuery = new URLSearchParams;
|
|
6105
|
+
if (params.days_back)
|
|
6106
|
+
tfQuery.set("days_back", String(params.days_back));
|
|
6107
|
+
if (params.cohort)
|
|
6108
|
+
tfQuery.set("cohort", params.cohort);
|
|
6109
|
+
const queryString = tfQuery.toString() ? `?${tfQuery.toString()}` : "";
|
|
6110
|
+
if (params.compare === true)
|
|
6111
|
+
assertCompareScope("tool-failures", params);
|
|
6112
|
+
const [listed, compare] = await Promise.all([
|
|
6113
|
+
callDataAPI(`/tool-failures${queryString}`),
|
|
6114
|
+
params.compare === true ? loadFamilyCompare("tool-failures", params) : Promise.resolve(undefined)
|
|
6115
|
+
]);
|
|
6116
|
+
const data = withSummaryCompare(listed, compare);
|
|
6003
6117
|
const daysBack = params.days_back ?? 7;
|
|
6004
6118
|
const failing = (Array.isArray(asRecord(data)?.tools) ? asRecord(data).tools : []).map((row) => asString(asRecord(row)?.tool_name)).filter((name) => Boolean(name)).slice(0, TOOL_FAILURE_CATALOG_LINKS);
|
|
6005
6119
|
const nextCommands = failing.flatMap((name, index) => [
|
|
6006
6120
|
...index === 0 ? [{ command: toolFailureExamplesCommand(name, daysBack), purpose: `Read failure examples of ${name}, the tool with the most failures.`, mutability: "read", requires_approval: false }] : [],
|
|
6007
6121
|
{ command: toolCatalogGetCommand(name, daysBack), purpose: `Calls, recorded schema, usage over time and failure categories of ${name}.`, mutability: "read", requires_approval: false }
|
|
6008
6122
|
]);
|
|
6009
|
-
context.output.writeData(data,
|
|
6123
|
+
context.output.writeData(data, withCohortScope(params.cohort, data, { nextCommands }));
|
|
6010
6124
|
break;
|
|
6011
6125
|
}
|
|
6012
6126
|
case "tool-catalog": {
|
|
@@ -6205,11 +6319,21 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6205
6319
|
}
|
|
6206
6320
|
const args = flagsToArgs(flags, "id", positional);
|
|
6207
6321
|
const params = parseSpecFlags("problem", args, command);
|
|
6322
|
+
if (params.trend === true) {
|
|
6323
|
+
rejectInapplicableFlags(command, params, ["evidence", "reports", "traces", "conversations", "feedback", "full", "limit", "cursor", "family", "door", "view", "offset"], "with --trend; it reads the Problem's per-day history (only --days-back applies)");
|
|
6324
|
+
const query3 = params.days_back ? `?days_back=${params.days_back}` : "";
|
|
6325
|
+
const data2 = await callDataAPI(`/problems/${encodeURIComponent(params.id)}/history${query3}`);
|
|
6326
|
+
context.output.writeData(data2, {
|
|
6327
|
+
summary: problemTrendSummary(data2),
|
|
6328
|
+
nextCommands: [{ command: `moda problems get ${shellArg(params.id)}`, purpose: "Open the Problem dossier.", mutability: "read", requires_approval: false }]
|
|
6329
|
+
});
|
|
6330
|
+
break;
|
|
6331
|
+
}
|
|
6208
6332
|
if (params.view === "dream") {
|
|
6209
6333
|
await runDreamProblem(params, context, command);
|
|
6210
6334
|
break;
|
|
6211
6335
|
}
|
|
6212
|
-
rejectInapplicableFlags(command, params, ["offset", "days_back"], "without --view=dream; the dossier pages page with --limit and --cursor");
|
|
6336
|
+
rejectInapplicableFlags(command, params, ["offset", "days_back"], "without --view=dream or --trend; the dossier pages page with --limit and --cursor");
|
|
6213
6337
|
const traceView = params.traces === true || params.conversations === true;
|
|
6214
6338
|
const views = ["evidence", "reports", "conversations", "feedback"].filter((view2) => view2 === "conversations" ? traceView : params[view2] === true);
|
|
6215
6339
|
if (views.length > 1) {
|
|
@@ -6403,7 +6527,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6403
6527
|
const params = parseSpecFlags("signal", args, command);
|
|
6404
6528
|
const id = encodeURIComponent(params.id);
|
|
6405
6529
|
if (params.detections !== true) {
|
|
6406
|
-
rejectInapplicableFlags(command, params, ["days_back", "limit", "offset"], "to the signal summary; they page its hits (--detections)");
|
|
6530
|
+
rejectInapplicableFlags(command, params, ["days_back", "limit", "offset", "cohort"], "to the signal summary; they page its hits (--detections)");
|
|
6407
6531
|
const data2 = await callDataAPI(`/custom-signals/${id}`);
|
|
6408
6532
|
context.output.writeData(data2);
|
|
6409
6533
|
break;
|
|
@@ -6415,10 +6539,12 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6415
6539
|
query2.set("limit", params.limit.toString());
|
|
6416
6540
|
if (params.offset !== undefined)
|
|
6417
6541
|
query2.set("offset", params.offset.toString());
|
|
6542
|
+
if (params.cohort)
|
|
6543
|
+
query2.set("cohort", params.cohort);
|
|
6418
6544
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
6419
6545
|
const data = await callDataAPI(`/custom-signals/${id}/detections${queryString}`);
|
|
6420
6546
|
const warnings = customSignalProcessingWarning(data, "detections");
|
|
6421
|
-
context.output.writeData(data,
|
|
6547
|
+
context.output.writeData(data, withCohortScope(params.cohort, data, { warnings }));
|
|
6422
6548
|
break;
|
|
6423
6549
|
}
|
|
6424
6550
|
case "trace-signals": {
|
|
@@ -6636,6 +6762,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6636
6762
|
case "emotions": {
|
|
6637
6763
|
const args = flagsToArgs(flags);
|
|
6638
6764
|
const params = parseSpecFlags("emotions", args, command);
|
|
6765
|
+
const compare = params.compare === true ? await loadFamilyCompare("emotions", params) : undefined;
|
|
6639
6766
|
const query2 = new URLSearchParams;
|
|
6640
6767
|
if (params.days_back)
|
|
6641
6768
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -6647,10 +6774,9 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6647
6774
|
query2.set("family", params.family);
|
|
6648
6775
|
if (readsPerTrace("emotions", params, ["user_id", "conversation_id", "conversation_ids", "ids_from", "include_window"])) {
|
|
6649
6776
|
setTraceFilters(query2, params, TRACE_GRAIN_FLAGS.emotions);
|
|
6650
|
-
const data2 = await callDataAPI(`/emotions?${query2.toString()}`);
|
|
6777
|
+
const data2 = withSummaryCompare(await callDataAPI(`/emotions?${query2.toString()}`), compare);
|
|
6651
6778
|
const warnings = processingDisabledWarning(data2, "emotion");
|
|
6652
|
-
|
|
6653
|
-
context.output.writeData(data2, { ...summary2 ? { summary: summary2 } : {}, ...warnings.length > 0 ? { warnings } : {} });
|
|
6779
|
+
context.output.writeData(data2, withCohortScope(params.cohort, data2, { summary: countingSummary(data2), warnings }));
|
|
6654
6780
|
break;
|
|
6655
6781
|
}
|
|
6656
6782
|
if (params.user_id)
|
|
@@ -6664,7 +6790,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6664
6790
|
if (agentMode && params.include_window !== true)
|
|
6665
6791
|
query2.set("include_context", "0");
|
|
6666
6792
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
6667
|
-
const raw = await callDataAPI(`/emotions${queryString}`);
|
|
6793
|
+
const raw = withSummaryCompare(await callDataAPI(`/emotions${queryString}`), compare);
|
|
6668
6794
|
const processingWarnings = processingDisabledWarning(raw, "emotion");
|
|
6669
6795
|
const record = asRecord(raw);
|
|
6670
6796
|
const data = agentMode && params.include_window !== true && record ? withoutDetectionWindows(record, "detections", "conversation_context") : raw;
|
|
@@ -6690,8 +6816,10 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6690
6816
|
if (params.family)
|
|
6691
6817
|
query2.set("family", params.family);
|
|
6692
6818
|
if (params.conversation_id) {
|
|
6693
|
-
rejectInapplicableFlags(command, params, ["search", "status", "sort", "order"], "to one trace's detections (--conversation-id); they filter and order the trace list");
|
|
6819
|
+
rejectInapplicableFlags(command, params, ["search", "status", "sort", "order", "cohort"], "to one trace's detections (--conversation-id); they filter and order the trace list");
|
|
6694
6820
|
}
|
|
6821
|
+
if (params.cohort)
|
|
6822
|
+
query2.set("cohort", params.cohort);
|
|
6695
6823
|
if (params.search)
|
|
6696
6824
|
query2.set("search", params.search);
|
|
6697
6825
|
if (params.status)
|
|
@@ -6701,9 +6829,14 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6701
6829
|
if (params.order)
|
|
6702
6830
|
query2.set("order", params.order);
|
|
6703
6831
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6832
|
+
if (params.compare === true)
|
|
6833
|
+
assertCompareScope("laziness", params);
|
|
6834
|
+
const [listed, compare] = await Promise.all([
|
|
6835
|
+
callDataAPI(`/laziness${queryString}`),
|
|
6836
|
+
params.compare === true ? loadFamilyCompare("laziness", params) : Promise.resolve(undefined)
|
|
6837
|
+
]);
|
|
6838
|
+
const data = withSummaryCompare(listed, compare);
|
|
6839
|
+
context.output.writeData(data, withCohortScope(params.cohort, data, { summary: countingSummary(data) }));
|
|
6707
6840
|
break;
|
|
6708
6841
|
}
|
|
6709
6842
|
case "hallucinations": {
|
|
@@ -6728,9 +6861,14 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6728
6861
|
query2.set("kind", params.kind);
|
|
6729
6862
|
}
|
|
6730
6863
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6864
|
+
if (params.compare === true)
|
|
6865
|
+
assertCompareScope("hallucinations", params);
|
|
6866
|
+
const [listed, compare] = await Promise.all([
|
|
6867
|
+
callDataAPI(`/hallucinations${queryString}`),
|
|
6868
|
+
params.compare === true ? loadFamilyCompare("hallucinations", params) : Promise.resolve(undefined)
|
|
6869
|
+
]);
|
|
6870
|
+
const data = withSummaryCompare(listed, compare);
|
|
6871
|
+
context.output.writeData(data, withCohortScope(params.cohort, data, { summary: countingSummary(data) }));
|
|
6734
6872
|
break;
|
|
6735
6873
|
}
|
|
6736
6874
|
case "step-scores": {
|
|
@@ -6919,7 +7057,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
6919
7057
|
resetApiRequestCountBeforeRun: true,
|
|
6920
7058
|
telemetry: "result-and-error",
|
|
6921
7059
|
handler: async (context) => {
|
|
6922
|
-
const { runInit } = await import("./index-
|
|
7060
|
+
const { runInit } = await import("./index-svfzq5rb.js");
|
|
6923
7061
|
if (context.outputMode === "agent-stream") {
|
|
6924
7062
|
context.output.writeEvent({
|
|
6925
7063
|
event: "started",
|
|
@@ -6969,7 +7107,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
6969
7107
|
resetApiRequestCountBeforeRun: true,
|
|
6970
7108
|
telemetry: "result-and-error",
|
|
6971
7109
|
handler: async (context) => {
|
|
6972
|
-
const { runProvision } = await import("./provision-
|
|
7110
|
+
const { runProvision } = await import("./provision-a9kkfvp7.js");
|
|
6973
7111
|
return runProvision(context, {
|
|
6974
7112
|
resumeCommand: buildResumeCommand("provision", context.rawFlags)
|
|
6975
7113
|
});
|
|
@@ -7233,6 +7371,40 @@ var commandRegistry = createCommandRegistry([
|
|
|
7233
7371
|
telemetry: "result-and-error",
|
|
7234
7372
|
handler: runUserCommand
|
|
7235
7373
|
},
|
|
7374
|
+
{
|
|
7375
|
+
name: "cohorts",
|
|
7376
|
+
description: NOUN_SUMMARIES.cohorts,
|
|
7377
|
+
examples: [...leavesOf("cohorts").flatMap((leaf) => leaf.examples.slice(0, 1))],
|
|
7378
|
+
subcommands: treeSubcommandHelp("cohorts"),
|
|
7379
|
+
auth: "api-key",
|
|
7380
|
+
outputModes: ["human", "json", "agent"],
|
|
7381
|
+
mutability: "write",
|
|
7382
|
+
validateConfigBeforeRun: false,
|
|
7383
|
+
resetApiRequestCountBeforeRun: false,
|
|
7384
|
+
telemetry: "result-and-error",
|
|
7385
|
+
handler: canonicalNounHandler
|
|
7386
|
+
},
|
|
7387
|
+
...[
|
|
7388
|
+
["cohort-list", "Built-in and saved user cohorts", "read"],
|
|
7389
|
+
["cohort-get", "One cohort: name, definition and revision", "read"],
|
|
7390
|
+
["cohort-fields", "The fields and operators a cohort definition can use", "read"],
|
|
7391
|
+
["cohort-preview", "Member count and sample users for an unsaved definition", "read"],
|
|
7392
|
+
["cohort-compare", "Two cohorts side by side: size, health, top topics, failure mix", "read"],
|
|
7393
|
+
["cohort-create", "Save a cohort from a definition", "write"],
|
|
7394
|
+
["cohort-update", "Edit a saved cohort", "write"]
|
|
7395
|
+
].map(([name, description, mutability]) => ({
|
|
7396
|
+
name,
|
|
7397
|
+
description,
|
|
7398
|
+
examples: [...CANONICAL_LEAVES.find((leaf) => leaf.handler === name)?.examples ?? []],
|
|
7399
|
+
hidden: true,
|
|
7400
|
+
auth: "api-key",
|
|
7401
|
+
outputModes: ["human", "json", "agent"],
|
|
7402
|
+
mutability,
|
|
7403
|
+
validateConfigBeforeRun: false,
|
|
7404
|
+
resetApiRequestCountBeforeRun: false,
|
|
7405
|
+
telemetry: "result-and-error",
|
|
7406
|
+
handler: runCohortCommand
|
|
7407
|
+
})),
|
|
7236
7408
|
{
|
|
7237
7409
|
name: "replays",
|
|
7238
7410
|
description: "Read replay results: sets, run history, per-seed verdicts, and playout transcripts",
|
|
@@ -7349,7 +7521,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
7349
7521
|
legacyCommand({
|
|
7350
7522
|
name: "overview",
|
|
7351
7523
|
description: "Harness health briefing from production data",
|
|
7352
|
-
examples: ["moda overview --days-back=30", "moda --agent overview"],
|
|
7524
|
+
examples: ["moda overview --days-back=30", "moda --agent overview", "moda overview --compare --since=2026-10-17T14:00:00Z # after a deploy against the same span before it", "moda overview --series --days-back=14"],
|
|
7353
7525
|
...dataApiDefaults
|
|
7354
7526
|
}),
|
|
7355
7527
|
legacyCommand({
|
|
@@ -3,13 +3,14 @@ import {
|
|
|
3
3
|
promptsDiscoveredCheck,
|
|
4
4
|
runDoctorCommand,
|
|
5
5
|
runStatusCommand
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-h62j4jn7.js";
|
|
7
7
|
import"./cli-pmzh2qjy.js";
|
|
8
|
-
import"./cli-
|
|
8
|
+
import"./cli-k5drmy8r.js";
|
|
9
9
|
import"./cli-mm48br00.js";
|
|
10
10
|
import"./cli-xq45etg1.js";
|
|
11
|
-
import"./cli-
|
|
12
|
-
import"./cli-
|
|
11
|
+
import"./cli-5fhqfx04.js";
|
|
12
|
+
import"./cli-e0kbye4s.js";
|
|
13
|
+
import"./cli-9a0a3v13.js";
|
|
13
14
|
import"./cli-0xc5htv7.js";
|
|
14
15
|
import"./cli-t0pb7qbs.js";
|
|
15
16
|
import"./cli-k4tqwah4.js";
|
|
@@ -40,15 +40,16 @@ import {
|
|
|
40
40
|
writeHarnessAnalyzeResult,
|
|
41
41
|
writeHarnessArtifacts,
|
|
42
42
|
writeHumanProgress
|
|
43
|
-
} from "./cli-
|
|
43
|
+
} from "./cli-s1w5phms.js";
|
|
44
44
|
import"./cli-xq45etg1.js";
|
|
45
45
|
import"./cli-97fnztpy.js";
|
|
46
46
|
import {
|
|
47
47
|
HARNESS_ANALYZE_CONCERNS
|
|
48
48
|
} from "./cli-cesds766.js";
|
|
49
49
|
import"./cli-qpq84eee.js";
|
|
50
|
-
import"./cli-
|
|
51
|
-
import"./cli-
|
|
50
|
+
import"./cli-5fhqfx04.js";
|
|
51
|
+
import"./cli-e0kbye4s.js";
|
|
52
|
+
import"./cli-9a0a3v13.js";
|
|
52
53
|
import"./cli-0xc5htv7.js";
|
|
53
54
|
import"./cli-t0pb7qbs.js";
|
|
54
55
|
import"./cli-k4tqwah4.js";
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildSourceSnapshot
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-s1w5phms.js";
|
|
4
4
|
import"./cli-xq45etg1.js";
|
|
5
5
|
import"./cli-97fnztpy.js";
|
|
6
6
|
import"./cli-cesds766.js";
|
|
7
7
|
import"./cli-qpq84eee.js";
|
|
8
|
-
import"./cli-
|
|
9
|
-
import"./cli-
|
|
8
|
+
import"./cli-5fhqfx04.js";
|
|
9
|
+
import"./cli-e0kbye4s.js";
|
|
10
|
+
import"./cli-9a0a3v13.js";
|
|
10
11
|
import"./cli-0xc5htv7.js";
|
|
11
12
|
import {
|
|
12
13
|
recordApiRequest
|