@moda-ai/cli 1.55.37 → 1.55.39
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-4pyeecf7.js → agent-bhe95ae8.js} +8 -8
- package/dist/{cli-nqgyz74b.js → cli-1vqq24qh.js} +1 -1
- package/dist/{cli-nzx7rqjs.js → cli-2h2nvq6w.js} +1 -1
- package/dist/{cli-w3ckvma5.js → cli-39617gab.js} +3 -3
- package/dist/{cli-ef9eagsc.js → cli-4hkesrkq.js} +1 -1
- package/dist/{cli-wh83c3ss.js → cli-6gtgm2gx.js} +4 -4
- package/dist/{cli-xkcy9wns.js → cli-as4c1xwm.js} +5 -5
- package/dist/{cli-x605txan.js → cli-c7vj8tq1.js} +5 -5
- package/dist/{cli-4d92a450.js → cli-jkza0bj6.js} +1 -1
- package/dist/{cli-npkb08xt.js → cli-jmbt1hf9.js} +8 -8
- package/dist/{cli-cdx6yd7m.js → cli-k9se46y4.js} +81 -10
- package/dist/{cli-cr44672e.js → cli-msgp78ag.js} +5 -5
- package/dist/{cli-gjzr7jq5.js → cli-ptm7pwqg.js} +1 -1
- package/dist/{cli-s72pph9c.js → cli-qzag917n.js} +1 -1
- package/dist/{cli-wg6e2a1g.js → cli-wr6f0kyw.js} +70 -20
- package/dist/cli.js +436 -60
- package/dist/{doctor-w8z3wj1e.js → doctor-3v20hc26.js} +7 -7
- package/dist/{fix-667fyx00.js → fix-s3zkjt69.js} +4 -4
- package/dist/{harness-github-actions-7s41s1vg.js → harness-github-actions-mcy21e4d.js} +5 -5
- package/dist/{harness-fb0083ap.js → harness-n4569wbm.js} +5 -5
- package/dist/{index-4w5szrnw.js → index-2qm3h7v2.js} +11 -11
- package/dist/{production-intelligence-v2wq2aqv.js → production-intelligence-z2cad1hv.js} +61 -4
- package/dist/{profile-commands-3hw4trwk.js → profile-commands-7ck1tqfv.js} +3 -3
- package/dist/{prompt-attribution-g7md8hzc.js → prompt-attribution-dm50am6e.js} +5 -5
- package/dist/prompt-source-mcp.js +5 -5
- package/dist/{prompts-ab-59r52mxw.js → prompts-ab-9e0dsmce.js} +7 -7
- package/dist/{prompts-90v9eg2k.js → prompts-p9hhxx0c.js} +5 -5
- package/dist/{prompts-propose-cbenbk8w.js → prompts-propose-91qrjpd0.js} +7 -7
- package/dist/{provision-8c4s6vgg.js → provision-x4wkyw60.js} +5 -5
- package/dist/{registry-qvjyvbk8.js → registry-nq8qsqtv.js} +3 -3
- package/dist/{skills-z7w5x7jj.js → skills-rk2pmwx8.js} +5 -5
- package/dist/{sync-r32tgpar.js → sync-xxbfjcz5.js} +7 -7
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/skills/moda-cli/SKILL.md +4 -2
- package/skills/moda-cli/references/commands.md +3 -2
- package/skills/moda-cli/references/dashboard-parity.md +5 -0
- package/skills/moda-cli/references/detections.md +53 -0
- package/skills/moda-cli/references/production-intelligence.md +1 -1
package/dist/cli.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
withFrustrationAnchors,
|
|
21
21
|
withToolFailureAnchors,
|
|
22
22
|
withoutDetectionWindows
|
|
23
|
-
} from "./cli-
|
|
23
|
+
} from "./cli-1vqq24qh.js";
|
|
24
24
|
import {
|
|
25
25
|
createCommandContext,
|
|
26
26
|
envOptOutSet,
|
|
@@ -28,17 +28,21 @@ import {
|
|
|
28
28
|
optOutFlagSet,
|
|
29
29
|
parseBooleanFlagValue,
|
|
30
30
|
withoutFlag
|
|
31
|
-
} from "./cli-
|
|
31
|
+
} from "./cli-jkza0bj6.js";
|
|
32
32
|
import {
|
|
33
33
|
AuditSchema,
|
|
34
|
+
BOOK_PROBLEM_SORTS,
|
|
34
35
|
COMMAND_FLAG_SPECS,
|
|
35
36
|
DETECTION_VERDICTS,
|
|
37
|
+
DREAM_PROBLEM_SORTS,
|
|
36
38
|
DetectionReviewSchema,
|
|
37
39
|
EMOTION_FAMILIES,
|
|
38
40
|
FALSE_POSITIVE_KINDS,
|
|
39
41
|
FEEDBACK_USAGE,
|
|
40
42
|
FalsePositiveSchema,
|
|
41
43
|
LAZINESS_FAMILIES,
|
|
44
|
+
PROBLEMS_DEFAULT_LIMIT,
|
|
45
|
+
PROBLEMS_MAX_LIMIT,
|
|
42
46
|
PROBLEM_FEEDBACK_ACTIONS,
|
|
43
47
|
ProblemFeedbackSchema,
|
|
44
48
|
ProblemImpactSchema,
|
|
@@ -47,6 +51,7 @@ import {
|
|
|
47
51
|
SIGNALS_MANAGEMENT_SUBCOMMANDS,
|
|
48
52
|
SignalLabelSchema,
|
|
49
53
|
StepScoresSchema,
|
|
54
|
+
TRACE_GRAIN_FLAGS,
|
|
50
55
|
UUID_RE,
|
|
51
56
|
assertFlags,
|
|
52
57
|
assertPositionals,
|
|
@@ -70,12 +75,12 @@ import {
|
|
|
70
75
|
unknownSignalsSubcommandError,
|
|
71
76
|
usageLine,
|
|
72
77
|
writeDryRun
|
|
73
|
-
} from "./cli-
|
|
78
|
+
} from "./cli-k9se46y4.js";
|
|
74
79
|
import {
|
|
75
80
|
ApiError,
|
|
76
81
|
callControlAPI,
|
|
77
82
|
callDataAPI
|
|
78
|
-
} from "./cli-
|
|
83
|
+
} from "./cli-qzag917n.js";
|
|
79
84
|
import {
|
|
80
85
|
AGENT_ERROR_CODES,
|
|
81
86
|
EXIT_AUTH_REQUIRED,
|
|
@@ -112,7 +117,7 @@ import {
|
|
|
112
117
|
shellArg,
|
|
113
118
|
validateConfig,
|
|
114
119
|
wasOutputCancelled
|
|
115
|
-
} from "./cli-
|
|
120
|
+
} from "./cli-wr6f0kyw.js";
|
|
116
121
|
import {
|
|
117
122
|
CliAccessError,
|
|
118
123
|
CliAuthError,
|
|
@@ -1155,8 +1160,8 @@ var CANONICAL_LEAVES = [
|
|
|
1155
1160
|
path: "problems list",
|
|
1156
1161
|
args: "",
|
|
1157
1162
|
handler: "problems",
|
|
1158
|
-
summary: "
|
|
1159
|
-
examples: ["moda problems list", "moda problems list --days-back=7 --
|
|
1163
|
+
summary: "The Problems the dashboard shows, ranked (the dream grouping when published, else the Book)",
|
|
1164
|
+
examples: ["moda problems list", "moda problems list --sort=users --limit=20", "moda problems list --view=book --days-back=7 --offset=10 --list-version=<list_version>"]
|
|
1160
1165
|
},
|
|
1161
1166
|
{
|
|
1162
1167
|
noun: "problems",
|
|
@@ -1164,8 +1169,8 @@ var CANONICAL_LEAVES = [
|
|
|
1164
1169
|
path: "problems get",
|
|
1165
1170
|
args: "<problem_id>",
|
|
1166
1171
|
handler: "problem",
|
|
1167
|
-
summary: "One Problem: dossier,
|
|
1168
|
-
examples: ["moda problems get <problem_id>", "moda problems get <problem_id> --evidence --limit=10", "moda problems get <problem_id> --traces --family=tool_failure"]
|
|
1172
|
+
summary: "One Problem: dossier, its --evidence/--reports/--traces/--feedback pages, or --view=dream",
|
|
1173
|
+
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"]
|
|
1169
1174
|
},
|
|
1170
1175
|
{
|
|
1171
1176
|
noun: "problems",
|
|
@@ -2981,46 +2986,46 @@ function leafManifestFields(leaf, commands) {
|
|
|
2981
2986
|
import { fileURLToPath } from "url";
|
|
2982
2987
|
import { realpathSync } from "fs";
|
|
2983
2988
|
async function runPromptsCommand(...args) {
|
|
2984
|
-
return (await import("./prompts-
|
|
2989
|
+
return (await import("./prompts-p9hhxx0c.js")).runPromptsCommand(...args);
|
|
2985
2990
|
}
|
|
2986
2991
|
async function runSkillsCommand(...args) {
|
|
2987
|
-
return (await import("./skills-
|
|
2992
|
+
return (await import("./skills-rk2pmwx8.js")).runSkillsCommand(...args);
|
|
2988
2993
|
}
|
|
2989
2994
|
async function runFixCommand(...args) {
|
|
2990
|
-
return (await import("./fix-
|
|
2995
|
+
return (await import("./fix-s3zkjt69.js")).runFixCommand(...args);
|
|
2991
2996
|
}
|
|
2992
2997
|
async function runFixesCommand(...args) {
|
|
2993
|
-
return (await import("./fix-
|
|
2998
|
+
return (await import("./fix-s3zkjt69.js")).runFixesCommand(...args);
|
|
2994
2999
|
}
|
|
2995
3000
|
async function runHarnessCommand(...args) {
|
|
2996
|
-
return (await import("./harness-
|
|
3001
|
+
return (await import("./harness-n4569wbm.js")).runHarnessCommand(...args);
|
|
2997
3002
|
}
|
|
2998
3003
|
async function runSyncCommand(...args) {
|
|
2999
|
-
return (await import("./sync-
|
|
3004
|
+
return (await import("./sync-xxbfjcz5.js")).runSyncCommand(...args);
|
|
3000
3005
|
}
|
|
3001
3006
|
async function runRegistryCommand(...args) {
|
|
3002
|
-
return (await import("./registry-
|
|
3007
|
+
return (await import("./registry-nq8qsqtv.js")).runRegistryCommand(...args);
|
|
3003
3008
|
}
|
|
3004
3009
|
async function runDoctorCommand(...args) {
|
|
3005
|
-
return (await import("./doctor-
|
|
3010
|
+
return (await import("./doctor-3v20hc26.js")).runDoctorCommand(...args);
|
|
3006
3011
|
}
|
|
3007
3012
|
async function runStatusCommand(...args) {
|
|
3008
|
-
return (await import("./doctor-
|
|
3013
|
+
return (await import("./doctor-3v20hc26.js")).runStatusCommand(...args);
|
|
3009
3014
|
}
|
|
3010
3015
|
async function runAuthCommand(...args) {
|
|
3011
|
-
return (await import("./profile-commands-
|
|
3016
|
+
return (await import("./profile-commands-7ck1tqfv.js")).runAuthCommand(...args);
|
|
3012
3017
|
}
|
|
3013
3018
|
async function runConfigCommand(...args) {
|
|
3014
|
-
return (await import("./profile-commands-
|
|
3019
|
+
return (await import("./profile-commands-7ck1tqfv.js")).runConfigCommand(...args);
|
|
3015
3020
|
}
|
|
3016
3021
|
async function runProfilesCommand(...args) {
|
|
3017
|
-
return (await import("./profile-commands-
|
|
3022
|
+
return (await import("./profile-commands-7ck1tqfv.js")).runProfilesCommand(...args);
|
|
3018
3023
|
}
|
|
3019
3024
|
async function runAgentCommand(...args) {
|
|
3020
|
-
return (await import("./agent-
|
|
3025
|
+
return (await import("./agent-bhe95ae8.js")).runAgentCommand(...args);
|
|
3021
3026
|
}
|
|
3022
3027
|
async function runProductionCommand(...args) {
|
|
3023
|
-
return (await import("./production-intelligence-
|
|
3028
|
+
return (await import("./production-intelligence-z2cad1hv.js")).runProductionCommand(...args);
|
|
3024
3029
|
}
|
|
3025
3030
|
function parseArgs(argv) {
|
|
3026
3031
|
const args = argv.slice(2);
|
|
@@ -3675,7 +3680,7 @@ var TOOL_FAILURE_DETAIL_DEFAULT_LIMIT = 5;
|
|
|
3675
3680
|
var TOOL_FAILURE_AGENT_SUBTYPES = 20;
|
|
3676
3681
|
var TOOL_FAILURE_CATALOG_LINKS = 3;
|
|
3677
3682
|
var TOOL_CATALOG_DEFAULT_LIMIT = 25;
|
|
3678
|
-
async function printWithOptionalWindows(enriched, listKey, includeWindow, windowSize, output, warnings, finalize, nextCommands = []) {
|
|
3683
|
+
async function printWithOptionalWindows(enriched, listKey, includeWindow, windowSize, output, warnings, finalize, nextCommands = [], summary) {
|
|
3679
3684
|
const allWarnings = [...warnings ?? []];
|
|
3680
3685
|
let data = enriched;
|
|
3681
3686
|
if (includeWindow) {
|
|
@@ -3686,6 +3691,7 @@ async function printWithOptionalWindows(enriched, listKey, includeWindow, window
|
|
|
3686
3691
|
if (finalize)
|
|
3687
3692
|
data = finalize(data, allWarnings);
|
|
3688
3693
|
const options = {
|
|
3694
|
+
...summary ? { summary } : {},
|
|
3689
3695
|
...allWarnings.length > 0 ? { warnings: allWarnings } : {},
|
|
3690
3696
|
...nextCommands.length > 0 ? { nextCommands } : {}
|
|
3691
3697
|
};
|
|
@@ -4144,7 +4150,7 @@ var WINDOW_FLAG_HINTS = {
|
|
|
4144
4150
|
var COMMAND_FLAG_HINTS = {
|
|
4145
4151
|
problems: {
|
|
4146
4152
|
family: "'moda problems' ranks every family together. To filter by family use 'moda problems unexplained --family=<family>' (signals no Problem explains yet) or 'moda problems get <problem_id> --traces --family=<family>' (one Problem's traces).",
|
|
4147
|
-
cursor: "'moda problems'
|
|
4153
|
+
cursor: "'moda problems list' pages with --offset=<next_offset> --list-version=<list_version>; 'moda problems unexplained --cursor=<next_cursor>' pages the unexplained signals."
|
|
4148
4154
|
}
|
|
4149
4155
|
};
|
|
4150
4156
|
function parseCommandFlags(schema, args, command, options = {}) {
|
|
@@ -4519,6 +4525,260 @@ async function runProblemsRemainder(flags, context) {
|
|
|
4519
4525
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
4520
4526
|
context.output.writeData(await callDataAPI(`/problems/remainder${queryString}`));
|
|
4521
4527
|
}
|
|
4528
|
+
var isDreamOnlySort = (sort) => sort === "severity" || sort === "silent";
|
|
4529
|
+
var isBookOnlySort = (sort) => sort === "signals" || sort === "problems" || (sort?.startsWith("signal:") ?? false);
|
|
4530
|
+
function problemsListCommand(params, view, page, daysGiven) {
|
|
4531
|
+
const parts = ["moda problems list", `--view=${view}`];
|
|
4532
|
+
if (daysGiven && params.days_back !== undefined)
|
|
4533
|
+
parts.push(`--days-back=${params.days_back}`);
|
|
4534
|
+
parts.push(`--limit=${params.limit ?? PROBLEMS_DEFAULT_LIMIT}`);
|
|
4535
|
+
if (params.sort)
|
|
4536
|
+
parts.push(`--sort=${shellArg(params.sort)}`);
|
|
4537
|
+
if (params.dir)
|
|
4538
|
+
parts.push(`--dir=${params.dir}`);
|
|
4539
|
+
if (params.cohort)
|
|
4540
|
+
parts.push(`--cohort=${shellArg(params.cohort)}`);
|
|
4541
|
+
parts.push(`--offset=${page.offset}`, `--list-version=${page.listVersion}`);
|
|
4542
|
+
return parts.join(" ");
|
|
4543
|
+
}
|
|
4544
|
+
function listVersionWarning(params, served) {
|
|
4545
|
+
if (!params.list_version || typeof served !== "string" || served === params.list_version)
|
|
4546
|
+
return [];
|
|
4547
|
+
return [
|
|
4548
|
+
`The list changed since --list-version=${params.list_version} was read (this page is list_version=${served}). Offsets of the two lists do not line up: restart from the first page (drop --offset and --list-version).`
|
|
4549
|
+
];
|
|
4550
|
+
}
|
|
4551
|
+
function hierarchyForPage(payload) {
|
|
4552
|
+
const hierarchy = asRecord(payload.hierarchy);
|
|
4553
|
+
if (!hierarchy || !Array.isArray(hierarchy.macros))
|
|
4554
|
+
return payload;
|
|
4555
|
+
const shown = new Set([...Array.isArray(payload.problems) ? payload.problems : [], ...Array.isArray(payload.untrusted) ? payload.untrusted : []].map((row) => asRecord(row)?.problem_id).filter((id) => typeof id === "string"));
|
|
4556
|
+
const macros = hierarchy.macros.map((macro) => {
|
|
4557
|
+
const record = asRecord(macro);
|
|
4558
|
+
if (!record || !Array.isArray(record.children))
|
|
4559
|
+
return macro;
|
|
4560
|
+
return { ...record, children: record.children.filter((id) => typeof id === "string" && shown.has(id)) };
|
|
4561
|
+
});
|
|
4562
|
+
return { ...payload, hierarchy: { ...hierarchy, macros, children_listed: "this page only; child_count is the full size" } };
|
|
4563
|
+
}
|
|
4564
|
+
async function runProblemsList(flags, context, command) {
|
|
4565
|
+
const args = flagsToArgs(flags);
|
|
4566
|
+
const params = parseSpecFlags("problems", args, command);
|
|
4567
|
+
const view = params.view ?? "auto";
|
|
4568
|
+
const daysGiven = args.days_back !== undefined;
|
|
4569
|
+
const limit = params.limit ?? PROBLEMS_DEFAULT_LIMIT;
|
|
4570
|
+
const offset = params.offset ?? 0;
|
|
4571
|
+
if (view === "book" && isDreamOnlySort(params.sort)) {
|
|
4572
|
+
throw new CliInputError(`--sort=${params.sort} orders the dream view; the Book sorts by ${BOOK_PROBLEM_SORTS.join(", ")} or signal:<family>.`);
|
|
4573
|
+
}
|
|
4574
|
+
if (view === "dream" && isBookOnlySort(params.sort)) {
|
|
4575
|
+
throw new CliInputError(`--sort=${params.sort} orders the Book; the dream view sorts by rank, ${DREAM_PROBLEM_SORTS.join(", ")}.`);
|
|
4576
|
+
}
|
|
4577
|
+
if (params.list_version && params.offset === undefined) {
|
|
4578
|
+
throw new CliInputError("--list-version pages a list: pass it with the --offset of the next page (next_offset).");
|
|
4579
|
+
}
|
|
4580
|
+
if (view !== "book") {
|
|
4581
|
+
const query3 = new URLSearchParams;
|
|
4582
|
+
if (daysGiven && params.days_back !== undefined)
|
|
4583
|
+
query3.set("days_back", String(params.days_back));
|
|
4584
|
+
if (params.cohort)
|
|
4585
|
+
query3.set("cohort", params.cohort);
|
|
4586
|
+
const bookOnly = isBookOnlySort(params.sort);
|
|
4587
|
+
query3.set("limit", String(bookOnly ? 1 : limit));
|
|
4588
|
+
if (!bookOnly) {
|
|
4589
|
+
if (offset > 0)
|
|
4590
|
+
query3.set("offset", String(offset));
|
|
4591
|
+
if (params.list_version)
|
|
4592
|
+
query3.set("list_version", params.list_version);
|
|
4593
|
+
if (params.sort && params.sort !== "rank")
|
|
4594
|
+
query3.set("sort", params.sort);
|
|
4595
|
+
if (params.dir)
|
|
4596
|
+
query3.set("dir", params.dir);
|
|
4597
|
+
}
|
|
4598
|
+
const dream = asRecord(await callDataAPI(`/problems/dream?${query3.toString()}`)) ?? {};
|
|
4599
|
+
if (dream.available === true) {
|
|
4600
|
+
if (bookOnly) {
|
|
4601
|
+
throw new CliInputError(`This tenant's dashboard shows the dream grouping of its Problems, which --sort=${params.sort} does not order.`, `Use --sort=rank|${DREAM_PROBLEM_SORTS.join("|")} for the dream view, or --view=book --sort=${params.sort} for the Book's ranked list.`);
|
|
4602
|
+
}
|
|
4603
|
+
writeDreamProblemsList(context, params, dream, { offset, limit, daysGiven });
|
|
4604
|
+
return;
|
|
4605
|
+
}
|
|
4606
|
+
if (view === "dream") {
|
|
4607
|
+
context.output.writeData({ available: false, view: "dream", dashboard_url: `${MODA_BASE_URL}/dashboard/problems` }, {
|
|
4608
|
+
warnings: ["This tenant has no dream grouping published; the dashboard shows the Book. List it with: moda problems list --view=book"],
|
|
4609
|
+
nextCommands: [{ command: "moda problems list --view=book", purpose: "List the Book's ranked Problems (what the dashboard shows for this tenant).", mutability: "read", requires_approval: false }]
|
|
4610
|
+
});
|
|
4611
|
+
return;
|
|
4612
|
+
}
|
|
4613
|
+
}
|
|
4614
|
+
if (isDreamOnlySort(params.sort)) {
|
|
4615
|
+
throw new CliInputError(`This tenant has no dream grouping published, so its Problems are the Book's ranked list, which --sort=${params.sort} does not order.`, `Use --sort=${BOOK_PROBLEM_SORTS.join("|")} or signal:<family>.`);
|
|
4616
|
+
}
|
|
4617
|
+
const query2 = new URLSearchParams;
|
|
4618
|
+
query2.set("days_back", String(params.days_back ?? 30));
|
|
4619
|
+
query2.set("limit", String(limit));
|
|
4620
|
+
if (offset > 0)
|
|
4621
|
+
query2.set("offset", String(offset));
|
|
4622
|
+
if (params.list_version)
|
|
4623
|
+
query2.set("list_version", params.list_version);
|
|
4624
|
+
if (params.sort)
|
|
4625
|
+
query2.set("sort", params.sort);
|
|
4626
|
+
if (params.dir)
|
|
4627
|
+
query2.set("dir", params.dir);
|
|
4628
|
+
if (params.cohort)
|
|
4629
|
+
query2.set("cohort", params.cohort);
|
|
4630
|
+
const data = await callDataAPI(`/problems?${query2.toString()}`);
|
|
4631
|
+
const { payload: capped, truncated } = capProblemsBlocks(asRecord(data) ?? {}, limit);
|
|
4632
|
+
const agentMode = context.output.mode === "agent" || context.output.mode === "agent-stream";
|
|
4633
|
+
const payload = agentMode ? hierarchyForPage(capped) : capped;
|
|
4634
|
+
const problems = Array.isArray(payload.problems) ? payload.problems : [];
|
|
4635
|
+
const untrusted = Array.isArray(payload.untrusted) ? payload.untrusted : [];
|
|
4636
|
+
const nextOffset = typeof payload.next_offset === "number" ? payload.next_offset : null;
|
|
4637
|
+
const listVersion = typeof payload.list_version === "string" ? payload.list_version : undefined;
|
|
4638
|
+
const withLink = {
|
|
4639
|
+
view: "book",
|
|
4640
|
+
...payload,
|
|
4641
|
+
pagination: {
|
|
4642
|
+
offset,
|
|
4643
|
+
limit,
|
|
4644
|
+
returned: problems.length,
|
|
4645
|
+
untrusted_returned: untrusted.length,
|
|
4646
|
+
has_more: nextOffset !== null,
|
|
4647
|
+
next_offset: nextOffset,
|
|
4648
|
+
...listVersion ? { list_version: listVersion } : {}
|
|
4649
|
+
},
|
|
4650
|
+
...truncated ? { truncated } : {},
|
|
4651
|
+
dashboard_url: `${MODA_BASE_URL}/dashboard/problems`
|
|
4652
|
+
};
|
|
4653
|
+
const nextCommands = [];
|
|
4654
|
+
if (nextOffset !== null && listVersion) {
|
|
4655
|
+
nextCommands.push({
|
|
4656
|
+
command: problemsListCommand(params, "book", { offset: nextOffset, listVersion }, daysGiven),
|
|
4657
|
+
purpose: `Read the next page of the Book (problems and untrusted from row ${nextOffset}).`,
|
|
4658
|
+
mutability: "read",
|
|
4659
|
+
requires_approval: false,
|
|
4660
|
+
nextPage: true
|
|
4661
|
+
});
|
|
4662
|
+
}
|
|
4663
|
+
const top = asRecord(problems[0]) ?? asRecord(untrusted[0]);
|
|
4664
|
+
if (typeof top?.problem_id === "string") {
|
|
4665
|
+
nextCommands.push({ command: `moda problems get ${shellArg(top.problem_id)}`, purpose: "Open the first Problem on this page.", mutability: "read", requires_approval: false });
|
|
4666
|
+
}
|
|
4667
|
+
const warnings = [
|
|
4668
|
+
...serverWarnings(payload),
|
|
4669
|
+
...listVersionWarning(params, listVersion),
|
|
4670
|
+
...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.`] : []
|
|
4671
|
+
];
|
|
4672
|
+
context.output.writeData(withLink, {
|
|
4673
|
+
...warnings.length > 0 ? { warnings } : {},
|
|
4674
|
+
...nextCommands.length > 0 ? { nextCommands } : {}
|
|
4675
|
+
});
|
|
4676
|
+
}
|
|
4677
|
+
function writeDreamProblemsList(context, params, dream, page) {
|
|
4678
|
+
const problems = Array.isArray(dream.problems) ? dream.problems : [];
|
|
4679
|
+
const nextOffset = typeof dream.next_offset === "number" ? dream.next_offset : null;
|
|
4680
|
+
const listVersion = typeof dream.list_version === "string" ? dream.list_version : undefined;
|
|
4681
|
+
const run = asRecord(dream.run);
|
|
4682
|
+
const { offset: _offset, limit: _limit, next_offset: _next, list_version: _version, ...rest } = dream;
|
|
4683
|
+
const data = {
|
|
4684
|
+
...rest,
|
|
4685
|
+
pagination: {
|
|
4686
|
+
offset: page.offset,
|
|
4687
|
+
limit: page.limit,
|
|
4688
|
+
returned: problems.length,
|
|
4689
|
+
total: asNumber(asRecord(dream.summary)?.problems) ?? null,
|
|
4690
|
+
has_more: nextOffset !== null,
|
|
4691
|
+
next_offset: nextOffset,
|
|
4692
|
+
...listVersion ? { list_version: listVersion } : {}
|
|
4693
|
+
},
|
|
4694
|
+
dashboard_url: `${MODA_BASE_URL}/dashboard/problems`
|
|
4695
|
+
};
|
|
4696
|
+
const nextCommands = [];
|
|
4697
|
+
if (nextOffset !== null && listVersion) {
|
|
4698
|
+
nextCommands.push({
|
|
4699
|
+
command: problemsListCommand(params, "dream", { offset: nextOffset, listVersion }, page.daysGiven),
|
|
4700
|
+
purpose: `Read the next page of the dream grouping (from row ${nextOffset}).`,
|
|
4701
|
+
mutability: "read",
|
|
4702
|
+
requires_approval: false,
|
|
4703
|
+
nextPage: true
|
|
4704
|
+
});
|
|
4705
|
+
}
|
|
4706
|
+
const top = asRecord(problems[0]);
|
|
4707
|
+
if (typeof top?.problem_id === "string") {
|
|
4708
|
+
const id = shellArg(top.problem_id);
|
|
4709
|
+
nextCommands.push({ command: `moda problems get ${id} --view=dream`, purpose: "Open the first Problem as the dashboard shows it: definition, severity and its most serious incidents.", mutability: "read", requires_approval: false }, { command: `moda problems get ${id} --evidence`, purpose: "Page the evidence behind it (dream problem ids are Book ids).", mutability: "read", requires_approval: false });
|
|
4710
|
+
}
|
|
4711
|
+
const windowHours = asNumber(run?.window_hours);
|
|
4712
|
+
const warnings = [
|
|
4713
|
+
"This tenant's dashboard shows the dream grouping of its Problems, so this is that list, in the dashboard table's order. The Book's ranked list is --view=book.",
|
|
4714
|
+
...!page.daysGiven && windowHours !== undefined ? [`Counts cover the dream run's window (${windowHours} hours), the dashboard's default range; pass --days-back to choose another.`] : [],
|
|
4715
|
+
...listVersionWarning(params, listVersion)
|
|
4716
|
+
];
|
|
4717
|
+
context.output.writeData(data, { warnings, ...nextCommands.length > 0 ? { nextCommands } : {} });
|
|
4718
|
+
}
|
|
4719
|
+
var DREAM_INCIDENTS_DEFAULT_LIMIT = 3;
|
|
4720
|
+
async function runDreamProblem(params, context, command) {
|
|
4721
|
+
const others = ["evidence", "reports", "traces", "conversations", "feedback", "full"].filter((key) => params[key] === true);
|
|
4722
|
+
if (others.length > 0) {
|
|
4723
|
+
throw new CliInputError(`--view=dream is its own page; it does not combine with ${others.map((key) => `--${key === "conversations" ? "traces" : key}`).join(", ")}.`, `Usage: moda problems get <problem_id> --view=dream [--limit=N] [--offset=N] [--days-back=N], or drop --view=dream for the dossier and its pages.`);
|
|
4724
|
+
}
|
|
4725
|
+
rejectInapplicableFlags(command, params, ["cursor", "family", "door"], "to --view=dream; it pages incidents with --limit and --offset");
|
|
4726
|
+
if (!UUID_RE.test(params.id)) {
|
|
4727
|
+
throw new CliInputError(`--view=dream requires a canonical problem UUID; got "${params.id}". Run \`moda problems list\` to list problem ids.`);
|
|
4728
|
+
}
|
|
4729
|
+
const limit = params.limit ?? DREAM_INCIDENTS_DEFAULT_LIMIT;
|
|
4730
|
+
const offset = params.offset ?? 0;
|
|
4731
|
+
const query2 = new URLSearchParams({ limit: String(limit) });
|
|
4732
|
+
if (offset > 0)
|
|
4733
|
+
query2.set("offset", String(offset));
|
|
4734
|
+
if (params.days_back !== undefined)
|
|
4735
|
+
query2.set("days_back", String(params.days_back));
|
|
4736
|
+
const id = shellArg(params.id);
|
|
4737
|
+
const data = asRecord(await callDataAPI(`/problems/dream/${encodeURIComponent(params.id)}?${query2.toString()}`).catch((error) => {
|
|
4738
|
+
if (error instanceof ApiError && error.statusCode === 404) {
|
|
4739
|
+
throwIfNotFound("problem", params.id, true, `Problem "${params.id}" is not in this tenant's dream grouping; read its dossier with: moda problems get ${id}`);
|
|
4740
|
+
}
|
|
4741
|
+
throw error;
|
|
4742
|
+
})) ?? {};
|
|
4743
|
+
if (data.available !== true) {
|
|
4744
|
+
context.output.writeData({ available: false, view: "dream", problem_id: params.id }, {
|
|
4745
|
+
warnings: [`This tenant has no dream grouping published; read the problem's dossier with: moda problems get ${id}`],
|
|
4746
|
+
nextCommands: [{ command: `moda problems get ${id}`, purpose: "Read the dossier (what the dashboard shows for this tenant).", mutability: "read", requires_approval: false }]
|
|
4747
|
+
});
|
|
4748
|
+
return;
|
|
4749
|
+
}
|
|
4750
|
+
const incidents = Array.isArray(data.incidents) ? data.incidents : [];
|
|
4751
|
+
const nextOffset = typeof data.next_offset === "number" ? data.next_offset : null;
|
|
4752
|
+
const { offset: _offset, limit: _limit, next_offset: _next, ...rest } = data;
|
|
4753
|
+
const nextCommands = [];
|
|
4754
|
+
if (nextOffset !== null) {
|
|
4755
|
+
const days = params.days_back !== undefined ? ` --days-back=${params.days_back}` : "";
|
|
4756
|
+
nextCommands.push({
|
|
4757
|
+
command: `moda problems get ${id} --view=dream --limit=${limit} --offset=${nextOffset}${days}`,
|
|
4758
|
+
purpose: `Read the next incidents of this problem (from incident ${nextOffset}).`,
|
|
4759
|
+
mutability: "read",
|
|
4760
|
+
requires_approval: false,
|
|
4761
|
+
nextPage: true
|
|
4762
|
+
});
|
|
4763
|
+
}
|
|
4764
|
+
const first = asRecord(incidents[0]);
|
|
4765
|
+
if (typeof first?.conversation_id === "string") {
|
|
4766
|
+
nextCommands.push({ command: `moda traces get ${shellArg(first.conversation_id)}`, purpose: "Open the trace of its most serious incident.", mutability: "read", requires_approval: false });
|
|
4767
|
+
}
|
|
4768
|
+
nextCommands.push({ command: `moda problems get ${id} --evidence`, purpose: "Page the Book evidence behind the same problem (dream ids are Book ids).", mutability: "read", requires_approval: false });
|
|
4769
|
+
context.output.writeData({
|
|
4770
|
+
...rest,
|
|
4771
|
+
pagination: {
|
|
4772
|
+
offset,
|
|
4773
|
+
limit,
|
|
4774
|
+
returned: incidents.length,
|
|
4775
|
+
total: asNumber(data.incidents_total) ?? null,
|
|
4776
|
+
has_more: nextOffset !== null,
|
|
4777
|
+
next_offset: nextOffset
|
|
4778
|
+
},
|
|
4779
|
+
dashboard_url: `${MODA_BASE_URL}/dashboard/problems/${encodeURIComponent(params.id)}`
|
|
4780
|
+
}, { nextCommands });
|
|
4781
|
+
}
|
|
4522
4782
|
function processingDisabledWarning(data, family) {
|
|
4523
4783
|
const processing = asRecord(asRecord(data)?.processing);
|
|
4524
4784
|
const label = family === "emotion" ? "Emotion" : "Frustration";
|
|
@@ -4535,6 +4795,91 @@ function processingDisabledWarning(data, family) {
|
|
|
4535
4795
|
`${family === "emotion" ? "Emotion" : "Frustration"} analysis is disabled for this tenant (${setting} = false), ` + "so zero results do NOT mean users are not frustrated. Enable it in Settings → Account → Signal processing; " + "only traces ingested after enabling are analyzed."
|
|
4536
4796
|
];
|
|
4537
4797
|
}
|
|
4798
|
+
function readsPerTrace(command, params, perRowScopes) {
|
|
4799
|
+
const filters = TRACE_GRAIN_FLAGS[command].filter((key) => params[key] !== undefined);
|
|
4800
|
+
const grain = params.group_by;
|
|
4801
|
+
if (grain !== undefined && grain !== "trace" && filters.length > 0) {
|
|
4802
|
+
rejectInapplicableFlags(command, params, filters, `with --group-by=${grain}; they filter the per-trace list (--group-by=trace)`);
|
|
4803
|
+
}
|
|
4804
|
+
const perTrace = grain === "trace" || filters.length > 0;
|
|
4805
|
+
if (perTrace) {
|
|
4806
|
+
rejectInapplicableFlags(command, params, perRowScopes, "to the per-trace list (--group-by=trace, or a filter that implies it); drop --group-by and the trace filters to use them");
|
|
4807
|
+
}
|
|
4808
|
+
return perTrace;
|
|
4809
|
+
}
|
|
4810
|
+
function setTraceFilters(query2, params, keys) {
|
|
4811
|
+
query2.set("group_by", "trace");
|
|
4812
|
+
for (const key of keys) {
|
|
4813
|
+
const value = params[key];
|
|
4814
|
+
if (value === undefined)
|
|
4815
|
+
continue;
|
|
4816
|
+
if (key === "signal")
|
|
4817
|
+
query2.set("signals", String(value).split(",").map((part) => part.trim()).join(","));
|
|
4818
|
+
else
|
|
4819
|
+
query2.set(key, String(value));
|
|
4820
|
+
}
|
|
4821
|
+
}
|
|
4822
|
+
function countingSummary(data) {
|
|
4823
|
+
const record = asRecord(data);
|
|
4824
|
+
const counting = asString(record?.counting);
|
|
4825
|
+
const total = asNumber(asRecord(record?.pagination)?.total);
|
|
4826
|
+
if (!counting || total === null)
|
|
4827
|
+
return;
|
|
4828
|
+
switch (counting) {
|
|
4829
|
+
case "per_trace":
|
|
4830
|
+
return `${total} trace(s) match. Counting: per trace, as the dashboard counts (pagination.total = traces).`;
|
|
4831
|
+
case "per_detection":
|
|
4832
|
+
return `${total} detection(s) match. Counting: per detection (one row per trace and family), not per trace; add --group-by=trace for the dashboard's per-trace count.`;
|
|
4833
|
+
case "per_message":
|
|
4834
|
+
return `${total} message detection(s) match. Counting: per scored message, not per trace; add --group-by=trace for the dashboard's per-trace count.`;
|
|
4835
|
+
default:
|
|
4836
|
+
return;
|
|
4837
|
+
}
|
|
4838
|
+
}
|
|
4839
|
+
function traceStateWarnings(data) {
|
|
4840
|
+
const record = asRecord(data);
|
|
4841
|
+
if (asString(record?.trace_state) === "unavailable") {
|
|
4842
|
+
return ["Trace processing state could not be read, so processing_status is null on every row; do not read missing detections as clean."];
|
|
4843
|
+
}
|
|
4844
|
+
const rows = Array.isArray(record?.conversations) ? record.conversations.map(asRecord) : [];
|
|
4845
|
+
const pending = rows.filter((row) => asString(row?.processing_status) === "pending").length;
|
|
4846
|
+
const errored = rows.filter((row) => asString(row?.error_message)).length;
|
|
4847
|
+
const warnings = [];
|
|
4848
|
+
if (pending > 0) {
|
|
4849
|
+
warnings.push(`${pending} of ${rows.length} trace(s) on this page are not fully processed yet (processing_status=pending), so their detections may be incomplete; missing detections do not mean they are clean.`);
|
|
4850
|
+
}
|
|
4851
|
+
if (errored > 0) {
|
|
4852
|
+
warnings.push(`${errored} trace(s) on this page have a processing error (error_message); their detections may be missing.`);
|
|
4853
|
+
}
|
|
4854
|
+
return warnings;
|
|
4855
|
+
}
|
|
4856
|
+
function singleTraceStateWarnings(value) {
|
|
4857
|
+
const traceState = asRecord(value);
|
|
4858
|
+
const warnings = [];
|
|
4859
|
+
if (asString(traceState?.processing_status) === "pending") {
|
|
4860
|
+
warnings.push("This trace is not fully processed yet (trace_state.processing_status=pending), so its detections may be incomplete; missing detections do not mean it is clean.");
|
|
4861
|
+
}
|
|
4862
|
+
if (asString(traceState?.error_message)) {
|
|
4863
|
+
warnings.push("This trace has a processing error (trace_state.error_message); its detections may be missing.");
|
|
4864
|
+
}
|
|
4865
|
+
return warnings;
|
|
4866
|
+
}
|
|
4867
|
+
function customSignalProcessingWarning(data, rows) {
|
|
4868
|
+
const record = asRecord(data);
|
|
4869
|
+
const processing = asRecord(record?.processing);
|
|
4870
|
+
const list = record?.[rows];
|
|
4871
|
+
if (!processing || !Array.isArray(list) || list.length > 0)
|
|
4872
|
+
return [];
|
|
4873
|
+
if (processing.enabled === false) {
|
|
4874
|
+
return [
|
|
4875
|
+
"Custom-signal judging is disabled for this tenant (signals.custom_signals = false), so no hits does NOT mean the traces are clean. " + "Enable it in Settings → Account → Signal processing; only conversations judged after enabling get hits."
|
|
4876
|
+
];
|
|
4877
|
+
}
|
|
4878
|
+
if (processing.enabled === null) {
|
|
4879
|
+
return ["Could not confirm whether custom-signal judging is enabled for this tenant, so treat no hits with caution."];
|
|
4880
|
+
}
|
|
4881
|
+
return [];
|
|
4882
|
+
}
|
|
4538
4883
|
var CONTEXT_USAGE = "Usage: moda traces get <conversation_id> [--msg-index=N (alias --message-index)] [--window=0-5 | --metadata-only]";
|
|
4539
4884
|
var CONTEXT_ALL_USAGE = "Usage: moda traces get <conversation_id> --all [--from=N] [--max-messages=N]";
|
|
4540
4885
|
var CONTEXT_BATCH_USAGE = `Usage: moda traces get <id>[@msg_index] <id>[@msg_index] ... | --ids-from=-|<file> [--window=0-5 | --metadata-only | --all [--from=N] [--max-messages=N]] (max ${BATCH_MAX_TARGETS} targets)`;
|
|
@@ -4640,6 +4985,7 @@ async function readFullTranscript(conversationId, opts = {}) {
|
|
|
4640
4985
|
let total = 0;
|
|
4641
4986
|
let summary = null;
|
|
4642
4987
|
let ordering;
|
|
4988
|
+
let traceState;
|
|
4643
4989
|
let nextFrom = null;
|
|
4644
4990
|
let cursor = start;
|
|
4645
4991
|
let readBytes = 0;
|
|
@@ -4656,6 +5002,7 @@ async function readFullTranscript(conversationId, opts = {}) {
|
|
|
4656
5002
|
total = asNumber(page.total_messages) ?? 0;
|
|
4657
5003
|
summary = stripLoneSurrogates(page.summary ?? null);
|
|
4658
5004
|
ordering = stripLoneSurrogates(asRecord(page.ordering) ?? undefined);
|
|
5005
|
+
traceState = page.trace_state;
|
|
4659
5006
|
}
|
|
4660
5007
|
const batch = stripLoneSurrogates(pageMessages(page));
|
|
4661
5008
|
messages.push(...batch);
|
|
@@ -4707,6 +5054,7 @@ async function readFullTranscript(conversationId, opts = {}) {
|
|
|
4707
5054
|
next_from: next,
|
|
4708
5055
|
summary,
|
|
4709
5056
|
...ordering ? { ordering } : {},
|
|
5057
|
+
...traceState !== undefined ? { trace_state: traceState } : {},
|
|
4710
5058
|
messages: returned
|
|
4711
5059
|
},
|
|
4712
5060
|
warnings: out,
|
|
@@ -4728,7 +5076,7 @@ async function readContextItem(params, inputWarnings, budget) {
|
|
|
4728
5076
|
fits: fits ? (page) => fits(page.data, { warnings: page.warnings, nextCommands: page.nextCommands }) : undefined,
|
|
4729
5077
|
maxBytes: budget?.maxBytes
|
|
4730
5078
|
});
|
|
4731
|
-
const fullWarnings = [...inputWarnings, ...full.warnings];
|
|
5079
|
+
const fullWarnings = [...inputWarnings, ...singleTraceStateWarnings(asRecord(full.data)?.trace_state), ...full.warnings];
|
|
4732
5080
|
return {
|
|
4733
5081
|
data: full.data,
|
|
4734
5082
|
options: {
|
|
@@ -4750,7 +5098,7 @@ async function readContextItem(params, inputWarnings, budget) {
|
|
|
4750
5098
|
const data = params.metadata_only === true ? await readContextMetadataOnly(contextPath, query2) : await callDataAPI(`${contextPath}${queryString}`);
|
|
4751
5099
|
const ctxRecord = asRecord(data) ?? {};
|
|
4752
5100
|
throwIfNotFound("trace", params.conversation_id, asNumber(ctxRecord.total_messages) === 0);
|
|
4753
|
-
const warnings = [...inputWarnings];
|
|
5101
|
+
const warnings = [...inputWarnings, ...singleTraceStateWarnings(ctxRecord.trace_state)];
|
|
4754
5102
|
const nextCommands = [];
|
|
4755
5103
|
if (params.window !== undefined && params.window > CONTEXT_MAX_WINDOW) {
|
|
4756
5104
|
const center = asNumber(asRecord(ctxRecord.context)?.center_index) ?? params.msg_index ?? 0;
|
|
@@ -5189,6 +5537,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5189
5537
|
searchWarnings.push("--sort=slowest: no trace in this page has a known duration (synthetic timestamps), so the order is not by duration. Use --sort=longest (message count) instead.");
|
|
5190
5538
|
}
|
|
5191
5539
|
}
|
|
5540
|
+
searchWarnings.push(...traceStateWarnings(data));
|
|
5192
5541
|
const writeOptions = searchWarnings.length > 0 ? { warnings: searchWarnings } : undefined;
|
|
5193
5542
|
if (params.include_world_state === true) {
|
|
5194
5543
|
const enriched = asRecord(data) ?? {};
|
|
@@ -5356,6 +5705,15 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5356
5705
|
query2.set("limit", params.limit.toString());
|
|
5357
5706
|
if (params.offset !== undefined)
|
|
5358
5707
|
query2.set("offset", params.offset.toString());
|
|
5708
|
+
if (readsPerTrace("frustrations", params, ["user_id", "conversation_id", "include_window"])) {
|
|
5709
|
+
query2.set("family", "frustration");
|
|
5710
|
+
setTraceFilters(query2, params, TRACE_GRAIN_FLAGS.frustrations);
|
|
5711
|
+
const data2 = await callDataAPI(`/emotions?${query2.toString()}`);
|
|
5712
|
+
const warnings = processingDisabledWarning(data2, "frustration");
|
|
5713
|
+
const summary = countingSummary(data2);
|
|
5714
|
+
context.output.writeData(data2, { ...summary ? { summary } : {}, ...warnings.length > 0 ? { warnings } : {} });
|
|
5715
|
+
break;
|
|
5716
|
+
}
|
|
5359
5717
|
if (params.user_id)
|
|
5360
5718
|
query2.set("user_id", params.user_id);
|
|
5361
5719
|
if (params.conversation_id)
|
|
@@ -5367,7 +5725,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5367
5725
|
query2.set("include_context", "0");
|
|
5368
5726
|
const data = frustrationsFromEmotions(await callDataAPI(`/emotions?${query2.toString()}`));
|
|
5369
5727
|
const anchored = withFrustrationAnchors(data);
|
|
5370
|
-
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);
|
|
5728
|
+
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));
|
|
5371
5729
|
break;
|
|
5372
5730
|
}
|
|
5373
5731
|
case "tool-failures": {
|
|
@@ -5565,25 +5923,9 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5565
5923
|
break;
|
|
5566
5924
|
}
|
|
5567
5925
|
if (positional) {
|
|
5568
|
-
throw new CliInputError(`Unknown problems subcommand '${positional}'.`, "Usage: moda problems [--days-back=N] [--limit=N] | moda problems unexplained [--family=F] [--days-back=N] [--limit=N] [--cursor=TOKEN]. For one Problem use 'moda problems get <id>'.");
|
|
5926
|
+
throw new CliInputError(`Unknown problems subcommand '${positional}'.`, "Usage: moda problems list [--view=auto|book|dream] [--days-back=N] [--limit=N] [--offset=N --list-version=V] [--sort=S] [--cohort=REF] | moda problems unexplained [--family=F] [--days-back=N] [--limit=N] [--cursor=TOKEN]. For one Problem use 'moda problems get <id>'.");
|
|
5569
5927
|
}
|
|
5570
|
-
|
|
5571
|
-
const params = parseSpecFlags("problems", args, command);
|
|
5572
|
-
const query2 = new URLSearchParams;
|
|
5573
|
-
if (params.days_back)
|
|
5574
|
-
query2.set("days_back", params.days_back.toString());
|
|
5575
|
-
if (params.limit)
|
|
5576
|
-
query2.set("limit", params.limit.toString());
|
|
5577
|
-
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
5578
|
-
const data = await callDataAPI(`/problems${queryString}`);
|
|
5579
|
-
const { payload, truncated } = capProblemsBlocks(asRecord(data) ?? {}, params.limit ?? 25);
|
|
5580
|
-
const withLink = {
|
|
5581
|
-
...payload,
|
|
5582
|
-
...truncated ? { truncated } : {},
|
|
5583
|
-
dashboard_url: `${MODA_BASE_URL}/dashboard/problems`
|
|
5584
|
-
};
|
|
5585
|
-
const warnings = [...serverWarnings(payload), ...truncated ? [`--limit=${params.limit ?? 25} also capped ${Object.entries(truncated).map(([block, count]) => `${block} (${count} more)`).join(", ")}; raise --limit (max 25) or open dashboard_url for the rest.`] : []];
|
|
5586
|
-
context.output.writeData(withLink, warnings.length > 0 ? { warnings } : undefined);
|
|
5928
|
+
await runProblemsList(flags, context, command);
|
|
5587
5929
|
break;
|
|
5588
5930
|
}
|
|
5589
5931
|
case "problem": {
|
|
@@ -5596,6 +5938,11 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5596
5938
|
}
|
|
5597
5939
|
const args = flagsToArgs(flags, "id", positional);
|
|
5598
5940
|
const params = parseSpecFlags("problem", args, command);
|
|
5941
|
+
if (params.view === "dream") {
|
|
5942
|
+
await runDreamProblem(params, context, command);
|
|
5943
|
+
break;
|
|
5944
|
+
}
|
|
5945
|
+
rejectInapplicableFlags(command, params, ["offset", "days_back"], "without --view=dream; the dossier pages page with --limit and --cursor");
|
|
5599
5946
|
const traceView = params.traces === true || params.conversations === true;
|
|
5600
5947
|
const views = ["evidence", "reports", "conversations", "feedback"].filter((view2) => view2 === "conversations" ? traceView : params[view2] === true);
|
|
5601
5948
|
if (views.length > 1) {
|
|
@@ -5803,7 +6150,8 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5803
6150
|
query2.set("offset", params.offset.toString());
|
|
5804
6151
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
5805
6152
|
const data = await callDataAPI(`/custom-signals/${id}/detections${queryString}`);
|
|
5806
|
-
|
|
6153
|
+
const warnings = customSignalProcessingWarning(data, "detections");
|
|
6154
|
+
context.output.writeData(data, warnings.length > 0 ? { warnings } : undefined);
|
|
5807
6155
|
break;
|
|
5808
6156
|
}
|
|
5809
6157
|
case "trace-signals": {
|
|
@@ -5811,7 +6159,8 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5811
6159
|
throw new CliInputError("<conversation_id> is required", "Usage: moda detections list --family=custom_signal --conversation-id=<conversation_id>");
|
|
5812
6160
|
}
|
|
5813
6161
|
const data = await callDataAPI(`/conversations/${encodeURIComponent(positional)}/custom-signals`);
|
|
5814
|
-
|
|
6162
|
+
const warnings = customSignalProcessingWarning(data, "detections");
|
|
6163
|
+
context.output.writeData(data, warnings.length > 0 ? { warnings } : undefined);
|
|
5815
6164
|
break;
|
|
5816
6165
|
}
|
|
5817
6166
|
case "signal-label": {
|
|
@@ -6029,6 +6378,14 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6029
6378
|
query2.set("offset", params.offset.toString());
|
|
6030
6379
|
if (params.family)
|
|
6031
6380
|
query2.set("family", params.family);
|
|
6381
|
+
if (readsPerTrace("emotions", params, ["user_id", "conversation_id", "include_window"])) {
|
|
6382
|
+
setTraceFilters(query2, params, TRACE_GRAIN_FLAGS.emotions);
|
|
6383
|
+
const data2 = await callDataAPI(`/emotions?${query2.toString()}`);
|
|
6384
|
+
const warnings = processingDisabledWarning(data2, "emotion");
|
|
6385
|
+
const summary2 = countingSummary(data2);
|
|
6386
|
+
context.output.writeData(data2, { ...summary2 ? { summary: summary2 } : {}, ...warnings.length > 0 ? { warnings } : {} });
|
|
6387
|
+
break;
|
|
6388
|
+
}
|
|
6032
6389
|
if (params.user_id)
|
|
6033
6390
|
query2.set("user_id", params.user_id);
|
|
6034
6391
|
if (params.conversation_id)
|
|
@@ -6041,7 +6398,8 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6041
6398
|
const processingWarnings = processingDisabledWarning(raw, "emotion");
|
|
6042
6399
|
const record = asRecord(raw);
|
|
6043
6400
|
const data = agentMode && params.include_window !== true && record ? withoutDetectionWindows(record, "detections", "conversation_context") : raw;
|
|
6044
|
-
|
|
6401
|
+
const summary = countingSummary(data);
|
|
6402
|
+
context.output.writeData(data, summary || processingWarnings.length > 0 ? { ...summary ? { summary } : {}, ...processingWarnings.length > 0 ? { warnings: processingWarnings } : {} } : undefined);
|
|
6045
6403
|
break;
|
|
6046
6404
|
}
|
|
6047
6405
|
case "laziness": {
|
|
@@ -6058,9 +6416,21 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6058
6416
|
query2.set("conversation_id", params.conversation_id);
|
|
6059
6417
|
if (params.family)
|
|
6060
6418
|
query2.set("family", params.family);
|
|
6419
|
+
if (params.conversation_id) {
|
|
6420
|
+
rejectInapplicableFlags(command, params, ["search", "status", "sort", "order"], "to one trace's detections (--conversation-id); they filter and order the trace list");
|
|
6421
|
+
}
|
|
6422
|
+
if (params.search)
|
|
6423
|
+
query2.set("search", params.search);
|
|
6424
|
+
if (params.status)
|
|
6425
|
+
query2.set("status", params.status);
|
|
6426
|
+
if (params.sort)
|
|
6427
|
+
query2.set("sort", params.sort);
|
|
6428
|
+
if (params.order)
|
|
6429
|
+
query2.set("order", params.order);
|
|
6061
6430
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
6062
6431
|
const data = await callDataAPI(`/laziness${queryString}`);
|
|
6063
|
-
|
|
6432
|
+
const summary = countingSummary(data);
|
|
6433
|
+
context.output.writeData(data, summary ? { summary } : undefined);
|
|
6064
6434
|
break;
|
|
6065
6435
|
}
|
|
6066
6436
|
case "hallucinations": {
|
|
@@ -6073,13 +6443,18 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6073
6443
|
query2.set("limit", params.limit.toString());
|
|
6074
6444
|
if (params.offset !== undefined)
|
|
6075
6445
|
query2.set("offset", params.offset.toString());
|
|
6076
|
-
if (params
|
|
6077
|
-
query2
|
|
6078
|
-
|
|
6079
|
-
|
|
6446
|
+
if (readsPerTrace("hallucinations", params, ["conversation_id", "kind"])) {
|
|
6447
|
+
setTraceFilters(query2, params, TRACE_GRAIN_FLAGS.hallucinations);
|
|
6448
|
+
} else {
|
|
6449
|
+
if (params.conversation_id)
|
|
6450
|
+
query2.set("conversation_id", params.conversation_id);
|
|
6451
|
+
if (params.kind)
|
|
6452
|
+
query2.set("kind", params.kind);
|
|
6453
|
+
}
|
|
6080
6454
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
6081
6455
|
const data = await callDataAPI(`/hallucinations${queryString}`);
|
|
6082
|
-
|
|
6456
|
+
const summary = countingSummary(data);
|
|
6457
|
+
context.output.writeData(data, summary ? { summary } : undefined);
|
|
6083
6458
|
break;
|
|
6084
6459
|
}
|
|
6085
6460
|
case "step-scores": {
|
|
@@ -6268,7 +6643,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
6268
6643
|
resetApiRequestCountBeforeRun: true,
|
|
6269
6644
|
telemetry: "result-and-error",
|
|
6270
6645
|
handler: async (context) => {
|
|
6271
|
-
const { runInit } = await import("./index-
|
|
6646
|
+
const { runInit } = await import("./index-2qm3h7v2.js");
|
|
6272
6647
|
if (context.outputMode === "agent-stream") {
|
|
6273
6648
|
context.output.writeEvent({
|
|
6274
6649
|
event: "started",
|
|
@@ -6318,7 +6693,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
6318
6693
|
resetApiRequestCountBeforeRun: true,
|
|
6319
6694
|
telemetry: "result-and-error",
|
|
6320
6695
|
handler: async (context) => {
|
|
6321
|
-
const { runProvision } = await import("./provision-
|
|
6696
|
+
const { runProvision } = await import("./provision-x4wkyw60.js");
|
|
6322
6697
|
return runProvision(context, {
|
|
6323
6698
|
resumeCommand: buildResumeCommand("provision", context.rawFlags)
|
|
6324
6699
|
});
|
|
@@ -6834,7 +7209,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
6834
7209
|
legacyCommand({
|
|
6835
7210
|
name: "problems",
|
|
6836
7211
|
description: "Rank cross-signal Problems by root cause (what to fix first)",
|
|
6837
|
-
examples: ["moda problems list", "moda problems list --
|
|
7212
|
+
examples: ["moda problems list", "moda problems list --view=book --sort=users --limit=20", "moda problems get <problem_id> --view=dream", "moda problems get <problem_id> --evidence", "moda problems unexplained --family=emotion"],
|
|
6838
7213
|
subcommands: treeSubcommandHelp("problems"),
|
|
6839
7214
|
defaultSubcommand: "list",
|
|
6840
7215
|
...dataApiDefaults
|
|
@@ -6856,14 +7231,15 @@ var commandRegistry = createCommandRegistry([
|
|
|
6856
7231
|
}),
|
|
6857
7232
|
legacyCommand({
|
|
6858
7233
|
name: "problem",
|
|
6859
|
-
description: "Open one Problem: dossier,
|
|
7234
|
+
description: "Open one Problem: dossier, --evidence/--reports/--traces/--feedback pages (--conversations is a legacy alias of --traces), or --view=dream",
|
|
6860
7235
|
examples: [
|
|
6861
7236
|
"moda problems get <problem_id>",
|
|
6862
7237
|
"moda problems get <problem_id> --full # whole dossier (agent output defaults to a compact one)",
|
|
6863
7238
|
"moda problems get <problem_id> --evidence --limit=10",
|
|
6864
7239
|
"moda problems get <problem_id> --reports",
|
|
6865
7240
|
"moda problems get <problem_id> --traces --family=tool_failure",
|
|
6866
|
-
"moda problems get <problem_id> --feedback"
|
|
7241
|
+
"moda problems get <problem_id> --feedback",
|
|
7242
|
+
"moda problems get <problem_id> --view=dream --limit=3 --offset=3 # the dream page: definition, severity, incidents"
|
|
6867
7243
|
],
|
|
6868
7244
|
...dataApiDefaults
|
|
6869
7245
|
}),
|