@moda-ai/cli 1.55.41 → 1.55.42
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-86hghww1.js} +4 -4
- package/dist/{cli-f1jfrqgf.js → cli-4sy4tytm.js} +218 -15
- package/dist/{cli-4tg0hkbz.js → cli-he8csgsr.js} +6 -6
- package/dist/{cli-ypqwcf9n.js → cli-hjm9151g.js} +2 -2
- package/dist/{cli-7bn406mt.js → cli-mxfyq5nq.js} +1 -1
- package/dist/{cli-a8nxbtpk.js → cli-srwzar82.js} +2 -2
- package/dist/{cli-azage7s0.js → cli-vwpbspr5.js} +2 -2
- package/dist/cli.js +171 -36
- package/dist/{doctor-p8sp6cbk.js → doctor-c05njdv8.js} +3 -3
- package/dist/{fix-0r974yge.js → fix-aghp304m.js} +1 -1
- package/dist/{harness-github-actions-2qc4gg2w.js → harness-github-actions-112503xs.js} +2 -2
- package/dist/{harness-72ejenza.js → harness-vabp33ak.js} +2 -2
- package/dist/{index-w7v472w4.js → index-dtxvvcq2.js} +5 -5
- package/dist/{prompt-attribution-3987hhqz.js → prompt-attribution-pbns1ya3.js} +2 -2
- package/dist/prompt-source-mcp.js +2 -2
- package/dist/{prompts-ab-gmd10n5d.js → prompts-ab-f5qrvpkt.js} +3 -3
- package/dist/{prompts-propose-q626zmm4.js → prompts-propose-jg2j41wx.js} +3 -3
- package/dist/{prompts-ysm9ra72.js → prompts-qppk0mhp.js} +2 -2
- package/dist/{registry-7xz09ry0.js → registry-8a1940sr.js} +1 -1
- package/dist/{skills-x6yszxxn.js → skills-sh93b156.js} +2 -2
- package/dist/{sync-trjzvam9.js → sync-0pp1c8hs.js} +4 -4
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/skills/moda-cli/SKILL.md +2 -1
- package/skills/moda-cli/references/commands.md +4 -1
- package/skills/moda-cli/references/dashboard-parity.md +4 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildDoctorReport
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-srwzar82.js";
|
|
4
4
|
import"./cli-pmzh2qjy.js";
|
|
5
|
-
import"./cli-
|
|
5
|
+
import"./cli-he8csgsr.js";
|
|
6
6
|
import"./cli-mm48br00.js";
|
|
7
7
|
import {
|
|
8
8
|
readHarnessSyncState
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
validateHarnessReport
|
|
17
17
|
} from "./cli-cesds766.js";
|
|
18
18
|
import"./cli-xddtv3yn.js";
|
|
19
|
-
import"./cli-
|
|
19
|
+
import"./cli-4sy4tytm.js";
|
|
20
20
|
import"./cli-0xc5htv7.js";
|
|
21
21
|
import {
|
|
22
22
|
resolveApiKey,
|
|
@@ -94,7 +94,7 @@ async function buildAgentContext(context) {
|
|
|
94
94
|
const graph = readHarnessGraphIfPresent(context.cwd);
|
|
95
95
|
const reportState = readHarnessReportState(context.cwd);
|
|
96
96
|
const syncState = readHarnessSyncState(context.cwd);
|
|
97
|
-
const harness = graph ? await import("./harness-
|
|
97
|
+
const harness = graph ? await import("./harness-vabp33ak.js") : undefined;
|
|
98
98
|
const topFindings = doctor.checks.filter((check) => check.status === "fail" || check.status === "warning").slice(0, 12).map(checkToFinding);
|
|
99
99
|
const evidenceRefs = [
|
|
100
100
|
...doctor.checks.map(checkToEvidenceRef),
|
|
@@ -36,6 +36,10 @@ var daysBackFlag = (fallback) => {
|
|
|
36
36
|
var ISO_BOUND_MESSAGE = "must be an ISO 8601 date (2026-10-07) or datetime (2026-10-07T14:30:00Z)";
|
|
37
37
|
var ISO_BOUND = /^\d{4}-\d{2}-\d{2}(?:[Tt ]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?(?:[Zz]|[+-]\d{2}:?\d{2})?)?$/;
|
|
38
38
|
var isoBoundFlag = () => z.string().trim().regex(ISO_BOUND, ISO_BOUND_MESSAGE).optional();
|
|
39
|
+
var COHORT_REF = /^(all|builtin:[a-z_]{1,64}|[a-z_]{1,64}|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;
|
|
40
|
+
var COHORT_REF_MESSAGE = "must be builtin:<key> or a saved cohort id (see moda cohorts list)";
|
|
41
|
+
var cohortFlag = (description) => z.string().regex(COHORT_REF, COHORT_REF_MESSAGE).optional().describe(description);
|
|
42
|
+
var CLUSTER_COHORT_TIME_RANGES = ["all", "3d", "7d", "30d"];
|
|
39
43
|
var OverviewSchema = z.object({
|
|
40
44
|
days_back: daysBackFlag(7)
|
|
41
45
|
});
|
|
@@ -45,7 +49,8 @@ var ClustersSchema = z.object({
|
|
|
45
49
|
search: z.string().min(2).max(200).optional().describe("Find clusters by name or meaning"),
|
|
46
50
|
node_id: z.string().min(1).max(512).optional().describe("Resolve one cluster node by id (deep link)"),
|
|
47
51
|
mode: z.enum(["fuzzy", "semantic", "hybrid"]).optional().describe("Cluster search mode (server default hybrid)"),
|
|
48
|
-
limit: z.number().int().min(1).max(50).optional().describe("Maximum clusters to return (with --search/--node-id)")
|
|
52
|
+
limit: z.number().int().min(1).max(50).optional().describe("Maximum clusters to return (with --search/--node-id)"),
|
|
53
|
+
cohort: cohortFlag("Only the clusters this cohort's users reach, with its segment counts (builtin:<key> or a saved cohort id); --time-range all|3d|7d|30d")
|
|
49
54
|
});
|
|
50
55
|
var ClusterConversationsSchema = z.object({
|
|
51
56
|
node_id: z.string().describe("Cluster node id (from moda clusters)"),
|
|
@@ -64,6 +69,7 @@ var ConversationsSchema = z.object({
|
|
|
64
69
|
outcome: z.enum(["any", "positive", "negative"]).default("any").optional().describe("Filter by trace outcome (trajectory + frustration)"),
|
|
65
70
|
include_world_state: boolFlag().describe("Attach each result's world-state summary"),
|
|
66
71
|
sort: z.enum(["recent", "longest", "slowest"]).optional().describe("recent = newest activity, longest = most messages, slowest = longest span"),
|
|
72
|
+
cohort: cohortFlag("Only traces of this cohort's current members (builtin:<key> or a saved cohort id)"),
|
|
67
73
|
limit: z.number().int().min(1).max(100).default(20).optional().describe("Maximum traces to return"),
|
|
68
74
|
offset: z.number().int().min(0).default(0).optional().describe("Number of traces to skip")
|
|
69
75
|
});
|
|
@@ -124,12 +130,13 @@ var emotionTraceFilters = {
|
|
|
124
130
|
trajectory: z.enum(EMOTION_TRAJECTORIES).optional().describe("How the emotion moved over the trace; needs --group-by=trace"),
|
|
125
131
|
signal: emotionSignalsFlag(),
|
|
126
132
|
sort: z.enum(EMOTION_TRACE_SORTS).optional().describe("Trace order (default score); needs --group-by=trace"),
|
|
127
|
-
order: z.enum(SORT_ORDERS).optional().describe("Sort direction (default desc); needs --group-by=trace")
|
|
133
|
+
order: z.enum(SORT_ORDERS).optional().describe("Sort direction (default desc); needs --group-by=trace"),
|
|
134
|
+
cohort: cohortFlag("Only traces of this cohort's members, summary included (builtin:<key> or a saved cohort id); implies --group-by=trace")
|
|
128
135
|
};
|
|
129
136
|
var TRACE_GRAIN_FLAGS = {
|
|
130
|
-
emotions: ["search", "status", "elicitor", "trajectory", "signal", "sort", "order"],
|
|
131
|
-
frustrations: ["search", "status", "elicitor", "trajectory", "signal", "sort", "order"],
|
|
132
|
-
hallucinations: ["search", "status", "rule", "source", "sort", "order"]
|
|
137
|
+
emotions: ["search", "status", "elicitor", "trajectory", "signal", "sort", "order", "cohort"],
|
|
138
|
+
frustrations: ["search", "status", "elicitor", "trajectory", "signal", "sort", "order", "cohort"],
|
|
139
|
+
hallucinations: ["search", "status", "rule", "source", "sort", "order", "cohort"]
|
|
133
140
|
};
|
|
134
141
|
var MAX_CONVERSATION_IDS_FILTER = 50;
|
|
135
142
|
var conversationIdsFlag = () => z.string().min(1).max(MAX_CONVERSATION_IDS_FILTER * 257).optional().describe(`Scope everything to several trace IDs, comma-separated (up to ${MAX_CONVERSATION_IDS_FILTER}; or --ids-from)`);
|
|
@@ -147,14 +154,14 @@ var FrustrationsSchema = z.object({
|
|
|
147
154
|
ids_from: idsFromFilterFlag()
|
|
148
155
|
});
|
|
149
156
|
var ToolFailuresSchema = z.object({
|
|
150
|
-
days_back: daysBackFlag(7)
|
|
157
|
+
days_back: daysBackFlag(7),
|
|
158
|
+
cohort: cohortFlag("The dashboard Tool Failures leaderboard for this cohort's traces (builtin:<key> or a saved cohort id)")
|
|
151
159
|
});
|
|
152
160
|
var PROBLEM_LIST_VIEWS = ["auto", "book", "dream"];
|
|
153
161
|
var BOOK_PROBLEM_SORTS = ["rank", "users", "signals", "problems"];
|
|
154
162
|
var DREAM_PROBLEM_SORTS = ["severity", "users", "silent"];
|
|
155
163
|
var PROBLEMS_MAX_LIMIT = 200;
|
|
156
164
|
var PROBLEMS_DEFAULT_LIMIT = 10;
|
|
157
|
-
var COHORT_REF = /^(all|builtin:[a-z_]{1,64}|[a-z_]{1,64}|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;
|
|
158
165
|
var ProblemsSchema = z.object({
|
|
159
166
|
view: z.enum(PROBLEM_LIST_VIEWS).default("auto").optional().describe("auto: what the dashboard shows (the dream grouping when published, else the Book); book or dream to force one"),
|
|
160
167
|
days_back: daysBackFlag().describe("Whole days to look back (Book default 30; the dream view defaults to its run window)"),
|
|
@@ -163,7 +170,7 @@ var ProblemsSchema = z.object({
|
|
|
163
170
|
list_version: z.string().regex(/^[0-9a-f]{1,64}$/, "must be the list_version of a previous page").optional().describe("list_version of the first page, passed with every later --offset"),
|
|
164
171
|
sort: z.string().regex(/^(rank|severity|users|signals|problems|silent|signal:[a-z_]{1,64})$/, "must be rank, severity, users, silent (dream), signals, problems or signal:<family> (Book)").optional().describe("Order: rank (default), users; dream: severity, silent; Book: signals, problems, signal:<family>"),
|
|
165
172
|
dir: z.enum(["desc", "asc"]).optional().describe("Sort direction (default desc)"),
|
|
166
|
-
cohort:
|
|
173
|
+
cohort: cohortFlag("Only the Problems this cohort hit (builtin:<key> or a saved cohort id), with its counts")
|
|
167
174
|
});
|
|
168
175
|
var REMAINDER_FAMILIES = [
|
|
169
176
|
"tool_failure",
|
|
@@ -248,7 +255,8 @@ var SignalSchema = z.object({
|
|
|
248
255
|
detections: boolFlag().describe("List recent hits instead of the summary"),
|
|
249
256
|
days_back: daysBackFlag(),
|
|
250
257
|
limit: z.number().int().min(1).max(20).optional().describe("Hits page size (server default 10)"),
|
|
251
|
-
offset: z.number().int().min(0).max(1e4).optional().describe("Number of hits to skip")
|
|
258
|
+
offset: z.number().int().min(0).max(1e4).optional().describe("Number of hits to skip"),
|
|
259
|
+
cohort: cohortFlag("Only hits on traces of this cohort's members (builtin:<key> or a saved cohort id); with --detections")
|
|
252
260
|
});
|
|
253
261
|
var SIGNAL_LABELS = ["fits", "does_not_fit"];
|
|
254
262
|
var SignalLabelSchema = z.object({
|
|
@@ -342,7 +350,8 @@ var HallucinationsSchema = z.object({
|
|
|
342
350
|
rule: z.string().trim().min(1).max(200).optional().describe("One rule_id from summary.rule_breakdown; scopes the summary too; needs --group-by=trace"),
|
|
343
351
|
source: z.enum(HALLUCINATION_SOURCES).optional().describe("Only detections from this source; needs --group-by=trace"),
|
|
344
352
|
sort: z.enum(HALLUCINATION_TRACE_SORTS).optional().describe("Trace order (default contradicted_count); needs --group-by=trace"),
|
|
345
|
-
order: z.enum(SORT_ORDERS).optional().describe("Sort direction (default desc); needs --group-by=trace")
|
|
353
|
+
order: z.enum(SORT_ORDERS).optional().describe("Sort direction (default desc); needs --group-by=trace"),
|
|
354
|
+
cohort: cohortFlag("Only traces of this cohort's members, summary included (builtin:<key> or a saved cohort id); implies --group-by=trace")
|
|
346
355
|
});
|
|
347
356
|
var LAZINESS_FAMILIES = [
|
|
348
357
|
"omission_comment",
|
|
@@ -377,7 +386,8 @@ var LazinessSchema = z.object({
|
|
|
377
386
|
search: z.string().trim().min(1).max(200).optional().describe("Trace ID substring"),
|
|
378
387
|
status: z.enum(["all", "strong"]).optional().describe("all (default), or strong: traces with a high-confidence detection"),
|
|
379
388
|
sort: z.enum(LAZINESS_TRACE_SORTS).optional().describe("Trace order (default detections_count)"),
|
|
380
|
-
order: z.enum(SORT_ORDERS).optional().describe("Sort direction (default desc)")
|
|
389
|
+
order: z.enum(SORT_ORDERS).optional().describe("Sort direction (default desc)"),
|
|
390
|
+
cohort: cohortFlag("Only traces of this cohort's members (builtin:<key> or a saved cohort id); not with --conversation-id")
|
|
381
391
|
});
|
|
382
392
|
var StepScoresSchema = z.object({
|
|
383
393
|
conversation_id: z.string().min(1).describe("Trace ID")
|
|
@@ -489,7 +499,7 @@ var UsersSchema = z.object({
|
|
|
489
499
|
page_size: z.number().int().min(1).optional().describe("Users per page"),
|
|
490
500
|
limit: z.number().int().min(1).optional().describe("Alias of --page-size"),
|
|
491
501
|
search: z.string().optional().describe("Match user id or name"),
|
|
492
|
-
cohort:
|
|
502
|
+
cohort: cohortFlag(`Only users in this cohort: builtin:<key>, a saved cohort id, or a built-in key (${USER_COHORTS.filter((key) => key !== "all").join(", ")})`),
|
|
493
503
|
sort: z.enum(USER_SORTS).optional().describe("Sort field"),
|
|
494
504
|
order: z.enum(["asc", "desc"]).optional().describe("Sort order"),
|
|
495
505
|
health_status: z.string().optional().describe(`Comma-separated health states (${USER_HEALTH.join(", ")})`),
|
|
@@ -510,6 +520,52 @@ var ProblemReopenSchema = z.object({
|
|
|
510
520
|
reason: z.string().max(500).optional().describe("Why it is being reopened"),
|
|
511
521
|
dry_run: boolFlag().describe("Print the request and send nothing")
|
|
512
522
|
});
|
|
523
|
+
var COHORT_COLORS = ["neutral", "blue", "green", "amber", "red", "violet"];
|
|
524
|
+
var COHORT_COMPARE_DAYS = ["7", "30", "90"];
|
|
525
|
+
var cohortTenant = () => z.string().optional().describe("Tenant to read; must match the API key's tenant");
|
|
526
|
+
var cohortRef = (description) => z.string().regex(COHORT_REF, COHORT_REF_MESSAGE).describe(description);
|
|
527
|
+
var cohortDefinitionFlags = {
|
|
528
|
+
definition: z.string().optional().describe("Cohort definition (DSL v1) as inline JSON; see moda cohorts fields"),
|
|
529
|
+
file: z.string().optional().describe("JSON file with the definition, or a body with a definition key")
|
|
530
|
+
};
|
|
531
|
+
var CohortsListSchema = z.object({
|
|
532
|
+
include_archived: boolFlag().describe("Also list archived saved cohorts"),
|
|
533
|
+
tenant_id: cohortTenant()
|
|
534
|
+
});
|
|
535
|
+
var CohortGetSchema = z.object({
|
|
536
|
+
ref: cohortRef("builtin:<key> or a saved cohort id"),
|
|
537
|
+
tenant_id: cohortTenant()
|
|
538
|
+
});
|
|
539
|
+
var CohortFieldsSchema = z.object({
|
|
540
|
+
tenant_id: cohortTenant()
|
|
541
|
+
});
|
|
542
|
+
var CohortPreviewSchema = z.object({
|
|
543
|
+
...cohortDefinitionFlags,
|
|
544
|
+
tenant_id: cohortTenant()
|
|
545
|
+
});
|
|
546
|
+
var CohortCompareSchema = z.object({
|
|
547
|
+
a: cohortRef("First cohort: builtin:<key> or a saved cohort id"),
|
|
548
|
+
b: cohortRef("Second cohort: builtin:<key> or a saved cohort id"),
|
|
549
|
+
days: z.enum(COHORT_COMPARE_DAYS).optional().describe("Window for top topics and failure mix (server default 30)"),
|
|
550
|
+
tenant_id: cohortTenant()
|
|
551
|
+
});
|
|
552
|
+
var cohortFieldFlags = {
|
|
553
|
+
name: z.string().max(120).optional().describe("Cohort name"),
|
|
554
|
+
description: z.string().max(2000).optional().describe("Cohort description"),
|
|
555
|
+
...cohortDefinitionFlags,
|
|
556
|
+
pinned: boolFlag().describe("Pin the cohort on the Users page"),
|
|
557
|
+
color: z.enum(COHORT_COLORS).optional().describe("Pill color")
|
|
558
|
+
};
|
|
559
|
+
var CohortCreateSchema = z.object({
|
|
560
|
+
...cohortFieldFlags,
|
|
561
|
+
tenant_id: cohortTenant()
|
|
562
|
+
});
|
|
563
|
+
var CohortUpdateSchema = z.object({
|
|
564
|
+
id: z.string().regex(UUID_RE, "must be a saved cohort id (UUID); built-in cohorts cannot be edited").describe("Saved cohort id"),
|
|
565
|
+
...cohortFieldFlags,
|
|
566
|
+
note: z.string().max(500).optional().describe("Why it changed (kept with the revision)"),
|
|
567
|
+
tenant_id: cohortTenant()
|
|
568
|
+
});
|
|
513
569
|
|
|
514
570
|
// ../../packages/database/src/agent-feedback.ts
|
|
515
571
|
var FEEDBACK_CATEGORIES = [
|
|
@@ -716,7 +772,18 @@ var COMMAND_FLAG_SPECS = {
|
|
|
716
772
|
positionals: [{ name: "note", key: "note", required: true, variadic: true, alsoFlag: true }]
|
|
717
773
|
},
|
|
718
774
|
users: { schema: UsersSchema, handParsed: true },
|
|
719
|
-
user: { schema: UserSchema, handParsed: true, positionals: [{ name: "user_id", key: "user_id", required: true }] }
|
|
775
|
+
user: { schema: UserSchema, handParsed: true, positionals: [{ name: "user_id", key: "user_id", required: true }] },
|
|
776
|
+
"cohort-list": { schema: CohortsListSchema, handParsed: true },
|
|
777
|
+
"cohort-get": { schema: CohortGetSchema, handParsed: true, positionals: [{ name: "ref", key: "ref", required: true }] },
|
|
778
|
+
"cohort-fields": { schema: CohortFieldsSchema, handParsed: true },
|
|
779
|
+
"cohort-preview": { schema: CohortPreviewSchema, handParsed: true },
|
|
780
|
+
"cohort-compare": {
|
|
781
|
+
schema: CohortCompareSchema,
|
|
782
|
+
handParsed: true,
|
|
783
|
+
positionals: [{ name: "cohort_a", key: "a", required: true }, { name: "cohort_b", key: "b", required: true }]
|
|
784
|
+
},
|
|
785
|
+
"cohort-create": { schema: CohortCreateSchema, extra: DRY_RUN, handParsed: true },
|
|
786
|
+
"cohort-update": { schema: CohortUpdateSchema, extra: DRY_RUN, handParsed: true, positionals: [{ name: "cohort_id", key: "id", required: true }] }
|
|
720
787
|
};
|
|
721
788
|
function flagSpecFor(command) {
|
|
722
789
|
return Object.hasOwn(COMMAND_FLAG_SPECS, command) ? COMMAND_FLAG_SPECS[command] : undefined;
|
|
@@ -1063,6 +1130,14 @@ function oneOf(name, value, allowed) {
|
|
|
1063
1130
|
}
|
|
1064
1131
|
return value;
|
|
1065
1132
|
}
|
|
1133
|
+
function cohortRefFlag(value) {
|
|
1134
|
+
if (value === undefined)
|
|
1135
|
+
return;
|
|
1136
|
+
if (!COHORT_REF.test(value)) {
|
|
1137
|
+
throw new CliInputError(`--cohort must be builtin:<key> or a saved cohort id (got '${value}').`, "List the refs with `moda cohorts list`.");
|
|
1138
|
+
}
|
|
1139
|
+
return value;
|
|
1140
|
+
}
|
|
1066
1141
|
function csv(value) {
|
|
1067
1142
|
if (value === undefined)
|
|
1068
1143
|
return;
|
|
@@ -1116,7 +1191,7 @@ async function runUsersCommand(context) {
|
|
|
1116
1191
|
page: flags.page,
|
|
1117
1192
|
pageSize: flags["page-size"] ?? flags.limit,
|
|
1118
1193
|
search: flags.search,
|
|
1119
|
-
cohort:
|
|
1194
|
+
cohort: cohortRefFlag(flags.cohort),
|
|
1120
1195
|
sortBy: oneOf("sort", flags.sort, USER_SORTS),
|
|
1121
1196
|
sortOrder: oneOf("order", flags.order, ["asc", "desc"]),
|
|
1122
1197
|
healthStatus: csv(flags["health-status"])?.map((value) => oneOf("health-status", value, HEALTH)).join(","),
|
|
@@ -1146,6 +1221,134 @@ async function runUserCommand(context) {
|
|
|
1146
1221
|
await send(context, "control", "GET", `/tenants/${encodeURIComponent(tenantId)}/users/${encodeURIComponent(userId)}${suffix}`);
|
|
1147
1222
|
return { exitCode: 0 };
|
|
1148
1223
|
}
|
|
1224
|
+
var COHORT_DEFINITION_HINT = 'A definition is {"version":1,"window":"24h|7d|30d|90d","where":{...}}; `moda cohorts fields` lists the fields and operators.';
|
|
1225
|
+
function cohortsBase(context) {
|
|
1226
|
+
return `/tenants/${encodeURIComponent(requireTenant(context))}/cohorts`;
|
|
1227
|
+
}
|
|
1228
|
+
function cohortRefArg(value, what, usage) {
|
|
1229
|
+
if (!value)
|
|
1230
|
+
throw new CliInputError(`${what} is required.`, `Usage: ${usage}`);
|
|
1231
|
+
if (!COHORT_REF.test(value)) {
|
|
1232
|
+
throw new CliInputError(`${what} must be builtin:<key> or a saved cohort id (got '${value}').`, "List the refs with `moda cohorts list`.");
|
|
1233
|
+
}
|
|
1234
|
+
return value;
|
|
1235
|
+
}
|
|
1236
|
+
function cohortBodyInput(flags, cwd) {
|
|
1237
|
+
const fromFile = readBodyFile(flags, cwd);
|
|
1238
|
+
const body = Object.keys(fromFile).length === 0 ? {} : ("definition" in fromFile) ? fromFile : { definition: fromFile };
|
|
1239
|
+
if (flags.definition !== undefined) {
|
|
1240
|
+
let parsed;
|
|
1241
|
+
try {
|
|
1242
|
+
parsed = JSON.parse(flags.definition);
|
|
1243
|
+
} catch (error) {
|
|
1244
|
+
throw new CliInputError(`--definition is not valid JSON: ${error instanceof Error ? error.message : String(error)}`, COHORT_DEFINITION_HINT);
|
|
1245
|
+
}
|
|
1246
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
1247
|
+
throw new CliInputError("--definition must be a JSON object.", COHORT_DEFINITION_HINT);
|
|
1248
|
+
body.definition = parsed;
|
|
1249
|
+
}
|
|
1250
|
+
if (body.definition !== undefined && (!body.definition || typeof body.definition !== "object" || Array.isArray(body.definition))) {
|
|
1251
|
+
throw new CliInputError("The cohort definition must be a JSON object.", COHORT_DEFINITION_HINT);
|
|
1252
|
+
}
|
|
1253
|
+
return body;
|
|
1254
|
+
}
|
|
1255
|
+
function cohortFieldBody(flags, cwd) {
|
|
1256
|
+
const pinned = flags.pinned === undefined ? undefined : oneOf("pinned", flags.pinned, ["true", "false", "1", "0", "yes", "no"]);
|
|
1257
|
+
return {
|
|
1258
|
+
...cohortBodyInput(flags, cwd),
|
|
1259
|
+
...compact({
|
|
1260
|
+
name: flags.name,
|
|
1261
|
+
description: flags.description,
|
|
1262
|
+
pinned: pinned === undefined ? undefined : ["true", "1", "yes"].includes(pinned),
|
|
1263
|
+
color: oneOf("color", flags.color, COHORT_COLORS)
|
|
1264
|
+
})
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
var COHORT_COMMANDS = {
|
|
1268
|
+
"cohort-list": { path: "cohorts list", usage: "moda cohorts list [--include-archived]" },
|
|
1269
|
+
"cohort-get": { path: "cohorts get", usage: "moda cohorts get <ref>" },
|
|
1270
|
+
"cohort-fields": { path: "cohorts fields", usage: "moda cohorts fields" },
|
|
1271
|
+
"cohort-preview": { path: "cohorts preview", usage: "moda cohorts preview --file=<path> | --definition=<json>" },
|
|
1272
|
+
"cohort-compare": { path: "cohorts compare", usage: "moda cohorts compare <cohort_a> <cohort_b> [--days=7|30|90]" },
|
|
1273
|
+
"cohort-create": { path: "cohorts create", usage: "moda cohorts create --name=NAME --file=<path>|--definition=<json> [--description --pinned --color] [--dry-run]" },
|
|
1274
|
+
"cohort-update": { path: "cohorts update", usage: "moda cohorts update <cohort_id> [--name --description --file|--definition --pinned --color --note] [--dry-run]" }
|
|
1275
|
+
};
|
|
1276
|
+
async function runCohortCommand(context) {
|
|
1277
|
+
const flags = context.flags;
|
|
1278
|
+
const command = COHORT_COMMANDS[context.command];
|
|
1279
|
+
if (!command)
|
|
1280
|
+
throw new CliInputError(`Unknown cohorts command '${context.command}'.`, "Run 'moda cohorts --help'.");
|
|
1281
|
+
const spec = flagSpecFor(context.command);
|
|
1282
|
+
assertFlags(command.path, flags, spec ? specFlagNames(spec) : []);
|
|
1283
|
+
assertPositionals(command.path, context.positionals, spec?.positionals?.length ?? 0, command.usage);
|
|
1284
|
+
const [first, second] = context.positionals;
|
|
1285
|
+
switch (context.command) {
|
|
1286
|
+
case "cohort-list": {
|
|
1287
|
+
requireKey(context);
|
|
1288
|
+
const archived = flags["include-archived"];
|
|
1289
|
+
const query = archived !== undefined && archived !== "false" && archived !== "0" ? "?includeArchived=1" : "";
|
|
1290
|
+
await send(context, "control", "GET", `${cohortsBase(context)}${query}`);
|
|
1291
|
+
return { exitCode: 0 };
|
|
1292
|
+
}
|
|
1293
|
+
case "cohort-get": {
|
|
1294
|
+
const ref = cohortRefArg(first, "<ref>", "moda cohorts get <ref>");
|
|
1295
|
+
requireKey(context);
|
|
1296
|
+
await send(context, "control", "GET", `${cohortsBase(context)}/${encodeURIComponent(ref)}`);
|
|
1297
|
+
return { exitCode: 0 };
|
|
1298
|
+
}
|
|
1299
|
+
case "cohort-fields": {
|
|
1300
|
+
requireKey(context);
|
|
1301
|
+
await send(context, "control", "GET", `${cohortsBase(context)}/fields`);
|
|
1302
|
+
return { exitCode: 0 };
|
|
1303
|
+
}
|
|
1304
|
+
case "cohort-preview": {
|
|
1305
|
+
const { definition } = cohortBodyInput(flags, context.cwd);
|
|
1306
|
+
if (definition === undefined)
|
|
1307
|
+
throw new CliInputError("Pass the definition with --file=<path> or --definition=<json>.", COHORT_DEFINITION_HINT);
|
|
1308
|
+
requireKey(context);
|
|
1309
|
+
const data = await callControlAPI(`${cohortsBase(context)}/preview`, { method: "POST", body: JSON.stringify({ definition }) }, profileOptions(context));
|
|
1310
|
+
context.output.writeData(data ?? {});
|
|
1311
|
+
return { exitCode: 0 };
|
|
1312
|
+
}
|
|
1313
|
+
case "cohort-compare": {
|
|
1314
|
+
const usage = "moda cohorts compare <cohort_a> <cohort_b> [--days=7|30|90]";
|
|
1315
|
+
const a = cohortRefArg(first, "<cohort_a>", usage);
|
|
1316
|
+
const b = cohortRefArg(second, "<cohort_b>", usage);
|
|
1317
|
+
const days = oneOf("days", flags.days, COHORT_COMPARE_DAYS);
|
|
1318
|
+
requireKey(context);
|
|
1319
|
+
const query = new URLSearchParams(compact({ a, b, days }));
|
|
1320
|
+
await send(context, "control", "GET", `${cohortsBase(context)}/compare?${query.toString()}`);
|
|
1321
|
+
return { exitCode: 0 };
|
|
1322
|
+
}
|
|
1323
|
+
case "cohort-create": {
|
|
1324
|
+
const body = cohortFieldBody(flags, context.cwd);
|
|
1325
|
+
const missing = ["name", "definition"].filter((field) => body[field] === undefined);
|
|
1326
|
+
if (missing.length > 0) {
|
|
1327
|
+
throw new CliInputError(`Missing ${missing.join(" and ")} for cohorts create, so nothing was sent.`, `Pass --name and --file=<definition.json> (or --definition=<json>). ${COHORT_DEFINITION_HINT} Check the members first with \`moda cohorts preview\`.`);
|
|
1328
|
+
}
|
|
1329
|
+
requireKey(context);
|
|
1330
|
+
await send(context, "control", "POST", cohortsBase(context), body);
|
|
1331
|
+
return { exitCode: 0 };
|
|
1332
|
+
}
|
|
1333
|
+
case "cohort-update": {
|
|
1334
|
+
const usage = "moda cohorts update <cohort_id> [--name --description --file|--definition --pinned --color --note] [--dry-run]";
|
|
1335
|
+
if (!first)
|
|
1336
|
+
throw new CliInputError("<cohort_id> is required.", `Usage: ${usage}`);
|
|
1337
|
+
if (!UUID_RE2.test(first)) {
|
|
1338
|
+
throw new CliInputError(`<cohort_id> must be a saved cohort id (UUID), got '${first}'. Built-in cohorts cannot be edited.`, "List saved cohorts with `moda cohorts list`.");
|
|
1339
|
+
}
|
|
1340
|
+
const body = { ...cohortFieldBody(flags, context.cwd), ...compact({ note: flags.note }) };
|
|
1341
|
+
if (Object.keys(body).filter((key) => key !== "note").length === 0) {
|
|
1342
|
+
throw new CliInputError("Nothing to update, so nothing was sent: pass at least one of --name, --description, --file/--definition, --pinned or --color.", `Usage: ${usage}`);
|
|
1343
|
+
}
|
|
1344
|
+
requireKey(context);
|
|
1345
|
+
await send(context, "control", "PATCH", `${cohortsBase(context)}/${encodeURIComponent(first)}`, body);
|
|
1346
|
+
return { exitCode: 0 };
|
|
1347
|
+
}
|
|
1348
|
+
default:
|
|
1349
|
+
throw new CliInputError(`Unknown cohorts command '${context.command}'.`, "Run 'moda cohorts --help'.");
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1149
1352
|
async function runProblemReopenCommand(context) {
|
|
1150
1353
|
assertFlags("problem-reopen", context.flags, specFlagNames(COMMAND_FLAG_SPECS["problem-reopen"]));
|
|
1151
1354
|
assertPositionals("problem-reopen", context.positionals, 1, "moda problems reopen <problem_id> [--reason=TEXT]");
|
|
@@ -1447,4 +1650,4 @@ function unknownSignalsSubcommandError(sub, args = []) {
|
|
|
1447
1650
|
${SIGNAL_USAGE}`);
|
|
1448
1651
|
}
|
|
1449
1652
|
|
|
1450
|
-
export { TRACE_GRAIN_FLAGS, MAX_CONVERSATION_IDS_FILTER, BOOK_PROBLEM_SORTS, DREAM_PROBLEM_SORTS, PROBLEMS_MAX_LIMIT, PROBLEMS_DEFAULT_LIMIT, ProblemsRemainderSchema, UUID_RE, ProblemImpactSchema, PROBLEM_FEEDBACK_ACTIONS, ProblemFeedbackSchema, ProblemLinearFileSchema, SignalLabelSchema, DETECTION_VERDICTS, DetectionReviewSchema, FALSE_POSITIVE_KINDS, FalsePositiveSchema, EMOTION_FAMILIES, LAZINESS_FAMILIES, StepScoresSchema, AuditSchema, TraceFindingsSchema, FEEDBACK_USAGE, isFeedbackRefFlag, buildFeedbackRequest, writeDryRun, COMMAND_FLAG_SPECS, flagSpecFor, kebabFlag, schemaShape, describeField, specFlagKeys, specFlagNames, describeSpecFlags, closestMatches, usageLine, renderFlagHelp, subcommandHelpFlags, manifestFlagFields, requireTenant, assertFlags, assertPositionals, runUsersCommand, runUserCommand, runProblemReopenCommand, runSignalsManagementCommand, SIGNALS_MANAGEMENT_SUBCOMMANDS, unknownSignalsSubcommandError };
|
|
1653
|
+
export { CLUSTER_COHORT_TIME_RANGES, TRACE_GRAIN_FLAGS, MAX_CONVERSATION_IDS_FILTER, BOOK_PROBLEM_SORTS, DREAM_PROBLEM_SORTS, PROBLEMS_MAX_LIMIT, PROBLEMS_DEFAULT_LIMIT, ProblemsRemainderSchema, UUID_RE, ProblemImpactSchema, PROBLEM_FEEDBACK_ACTIONS, ProblemFeedbackSchema, ProblemLinearFileSchema, SignalLabelSchema, DETECTION_VERDICTS, DetectionReviewSchema, FALSE_POSITIVE_KINDS, FalsePositiveSchema, EMOTION_FAMILIES, LAZINESS_FAMILIES, StepScoresSchema, AuditSchema, TraceFindingsSchema, FEEDBACK_USAGE, isFeedbackRefFlag, buildFeedbackRequest, writeDryRun, COMMAND_FLAG_SPECS, flagSpecFor, kebabFlag, schemaShape, describeField, specFlagKeys, specFlagNames, describeSpecFlags, closestMatches, usageLine, renderFlagHelp, subcommandHelpFlags, manifestFlagFields, requireTenant, assertFlags, assertPositionals, runUsersCommand, runUserCommand, runCohortCommand, runProblemReopenCommand, runSignalsManagementCommand, SIGNALS_MANAGEMENT_SUBCOMMANDS, unknownSignalsSubcommandError };
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
assertFlags,
|
|
10
10
|
assertPositionals
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-4sy4tytm.js";
|
|
12
12
|
import {
|
|
13
13
|
callControlAPI
|
|
14
14
|
} from "./cli-0xc5htv7.js";
|
|
@@ -5725,9 +5725,9 @@ async function runPromptsCommand(input, legacyFlags, legacyProfileOptions) {
|
|
|
5725
5725
|
await promotePrompt(positionals, flags, profileOptions, context);
|
|
5726
5726
|
break;
|
|
5727
5727
|
case "ab":
|
|
5728
|
-
return (await import("./prompts-ab-
|
|
5728
|
+
return (await import("./prompts-ab-f5qrvpkt.js")).runPromptAb(flags, profileOptions, context);
|
|
5729
5729
|
case "propose":
|
|
5730
|
-
await (await import("./prompts-propose-
|
|
5730
|
+
await (await import("./prompts-propose-jg2j41wx.js")).runPromptPropose(positionals, flags, profileOptions, context);
|
|
5731
5731
|
break;
|
|
5732
5732
|
case "list":
|
|
5733
5733
|
case "show":
|
|
@@ -5830,7 +5830,7 @@ async function runPromptSyncExclusive(flags, profileOptions, options) {
|
|
|
5830
5830
|
const analyzedDefinitions = new Map;
|
|
5831
5831
|
if (flags["no-analyze"] !== "true") {
|
|
5832
5832
|
options.onProgress?.("Analyzing prompt sources before sync.");
|
|
5833
|
-
const { analyzeHarnessPrompts } = await import("./harness-
|
|
5833
|
+
const { analyzeHarnessPrompts } = await import("./harness-vabp33ak.js");
|
|
5834
5834
|
const result = await analyzeHarnessPrompts({
|
|
5835
5835
|
rootDir: process.cwd(),
|
|
5836
5836
|
existing: established.flatMap((prompt) => prompt.sourceDefinition ? [prompt.sourceDefinition.source] : []),
|
|
@@ -5858,7 +5858,7 @@ async function runPromptSyncExclusive(flags, profileOptions, options) {
|
|
|
5858
5858
|
const mergedSources = mergePromptSources(manifest.sources, extraSources);
|
|
5859
5859
|
const manifestUpdate = stableJson(mergedSources) === stableJson(mergePromptSources(manifest.sources, [])) ? undefined : $stringify({ version: 2, prompt_paths: manifest.promptPaths, sources: mergedSources });
|
|
5860
5860
|
const prompts = await discoverPrompts(extraSources);
|
|
5861
|
-
const { checkPromptAttribution } = await import("./prompt-attribution-
|
|
5861
|
+
const { checkPromptAttribution } = await import("./prompt-attribution-pbns1ya3.js");
|
|
5862
5862
|
const attribution = checkPromptAttribution(process.cwd(), prompts.map((prompt) => prompt.key));
|
|
5863
5863
|
const brokenAttribution = attribution.references.filter((reference) => reference.status === "missing");
|
|
5864
5864
|
if (brokenAttribution.length) {
|
|
@@ -6164,7 +6164,7 @@ async function migratePromptManifest(options = {}) {
|
|
|
6164
6164
|
let addedSources = [];
|
|
6165
6165
|
let pendingSources = [];
|
|
6166
6166
|
if (options.discover) {
|
|
6167
|
-
const { analyzeHarnessPrompts } = await import("./harness-
|
|
6167
|
+
const { analyzeHarnessPrompts } = await import("./harness-vabp33ak.js");
|
|
6168
6168
|
const result = await analyzeHarnessPrompts({
|
|
6169
6169
|
rootDir: root,
|
|
6170
6170
|
existing: manifest.sources,
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
parsePromptFileForAb,
|
|
5
5
|
readPromptLock,
|
|
6
6
|
runPromptSync
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-he8csgsr.js";
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_POLL_INTERVAL_MS,
|
|
10
10
|
DEFAULT_WAIT_TIMEOUT_MS,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "./cli-daqkdnm1.js";
|
|
13
13
|
import {
|
|
14
14
|
UUID_RE
|
|
15
|
-
} from "./cli-
|
|
15
|
+
} from "./cli-4sy4tytm.js";
|
|
16
16
|
import {
|
|
17
17
|
callControlAPI,
|
|
18
18
|
callDataAPI
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./cli-pmzh2qjy.js";
|
|
5
5
|
import {
|
|
6
6
|
inspectPromptManifest
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-he8csgsr.js";
|
|
8
8
|
import {
|
|
9
9
|
readHarnessSyncState,
|
|
10
10
|
renderDoctorHuman,
|
|
@@ -376,7 +376,7 @@ async function harnessCurrentCheck(cwd, manifestPath, manifestExists, tenantId)
|
|
|
376
376
|
};
|
|
377
377
|
}
|
|
378
378
|
try {
|
|
379
|
-
const { scanHarness } = await import("./harness-
|
|
379
|
+
const { scanHarness } = await import("./harness-vabp33ak.js");
|
|
380
380
|
const current = scanHarness({
|
|
381
381
|
rootDir: cwd,
|
|
382
382
|
scannerVersion: "doctor",
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
assertFlags,
|
|
50
50
|
assertPositionals,
|
|
51
51
|
requireTenant
|
|
52
|
-
} from "./cli-
|
|
52
|
+
} from "./cli-4sy4tytm.js";
|
|
53
53
|
import {
|
|
54
54
|
ApiError,
|
|
55
55
|
callControlAPI
|
|
@@ -14048,7 +14048,7 @@ async function runHarnessCommand(context) {
|
|
|
14048
14048
|
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.");
|
|
14049
14049
|
}
|
|
14050
14050
|
if (context.flags["github-actions"] === "true") {
|
|
14051
|
-
const { runGithubActionsAnalyze } = await import("./harness-github-actions-
|
|
14051
|
+
const { runGithubActionsAnalyze } = await import("./harness-github-actions-112503xs.js");
|
|
14052
14052
|
const result = await runGithubActionsAnalyze(rootDir, {
|
|
14053
14053
|
writeReport: (report2) => {
|
|
14054
14054
|
const normalized = normalizeHarnessReport(report2);
|
package/dist/cli.js
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
import {
|
|
35
35
|
AuditSchema,
|
|
36
36
|
BOOK_PROBLEM_SORTS,
|
|
37
|
+
CLUSTER_COHORT_TIME_RANGES,
|
|
37
38
|
COMMAND_FLAG_SPECS,
|
|
38
39
|
DETECTION_VERDICTS,
|
|
39
40
|
DREAM_PROBLEM_SORTS,
|
|
@@ -68,6 +69,7 @@ import {
|
|
|
68
69
|
kebabFlag,
|
|
69
70
|
manifestFlagFields,
|
|
70
71
|
renderFlagHelp,
|
|
72
|
+
runCohortCommand,
|
|
71
73
|
runProblemReopenCommand,
|
|
72
74
|
runSignalsManagementCommand,
|
|
73
75
|
runUserCommand,
|
|
@@ -79,7 +81,7 @@ import {
|
|
|
79
81
|
unknownSignalsSubcommandError,
|
|
80
82
|
usageLine,
|
|
81
83
|
writeDryRun
|
|
82
|
-
} from "./cli-
|
|
84
|
+
} from "./cli-4sy4tytm.js";
|
|
83
85
|
import {
|
|
84
86
|
ApiError,
|
|
85
87
|
callControlAPI,
|
|
@@ -1453,6 +1455,69 @@ var CANONICAL_LEAVES = [
|
|
|
1453
1455
|
summary: "One tool: calls, recorded schema and payload fields, usage over time, top failure categories",
|
|
1454
1456
|
examples: ["moda tools get <tool_name>", "moda tools get <tool_name> --days-back=30 --full"]
|
|
1455
1457
|
},
|
|
1458
|
+
{
|
|
1459
|
+
noun: "cohorts",
|
|
1460
|
+
verb: "list",
|
|
1461
|
+
path: "cohorts list",
|
|
1462
|
+
args: "",
|
|
1463
|
+
handler: "cohort-list",
|
|
1464
|
+
summary: "Built-in and saved user cohorts with their refs and definitions (the dashboard Users page)",
|
|
1465
|
+
examples: ["moda cohorts list", "moda cohorts list --include-archived"]
|
|
1466
|
+
},
|
|
1467
|
+
{
|
|
1468
|
+
noun: "cohorts",
|
|
1469
|
+
verb: "get",
|
|
1470
|
+
path: "cohorts get",
|
|
1471
|
+
args: "<ref>",
|
|
1472
|
+
handler: "cohort-get",
|
|
1473
|
+
summary: "One cohort: name, definition and revision (ref: builtin:<key> or a saved cohort id)",
|
|
1474
|
+
examples: ["moda cohorts get builtin:power_users", "moda cohorts get <cohort_id>"]
|
|
1475
|
+
},
|
|
1476
|
+
{
|
|
1477
|
+
noun: "cohorts",
|
|
1478
|
+
verb: "fields",
|
|
1479
|
+
path: "cohorts fields",
|
|
1480
|
+
args: "",
|
|
1481
|
+
handler: "cohort-fields",
|
|
1482
|
+
summary: "The fields and operators a cohort definition can use",
|
|
1483
|
+
examples: ["moda cohorts fields"]
|
|
1484
|
+
},
|
|
1485
|
+
{
|
|
1486
|
+
noun: "cohorts",
|
|
1487
|
+
verb: "preview",
|
|
1488
|
+
path: "cohorts preview",
|
|
1489
|
+
args: "",
|
|
1490
|
+
handler: "cohort-preview",
|
|
1491
|
+
summary: "Member count and a sample of users for an unsaved definition",
|
|
1492
|
+
examples: ["moda cohorts preview --file=cohort.json", `moda cohorts preview --definition='{"version":1,"window":"30d","where":{"field":"tool_failure_count","op":"gte","value":3}}'`]
|
|
1493
|
+
},
|
|
1494
|
+
{
|
|
1495
|
+
noun: "cohorts",
|
|
1496
|
+
verb: "compare",
|
|
1497
|
+
path: "cohorts compare",
|
|
1498
|
+
args: "<cohort_a> <cohort_b>",
|
|
1499
|
+
handler: "cohort-compare",
|
|
1500
|
+
summary: "Two cohorts side by side: size, health, top topics and failure mix",
|
|
1501
|
+
examples: ["moda cohorts compare builtin:new_this_week builtin:power_users --days=30"]
|
|
1502
|
+
},
|
|
1503
|
+
{
|
|
1504
|
+
noun: "cohorts",
|
|
1505
|
+
verb: "create",
|
|
1506
|
+
path: "cohorts create",
|
|
1507
|
+
args: "",
|
|
1508
|
+
handler: "cohort-create",
|
|
1509
|
+
summary: "Save a cohort from a definition (write; --dry-run prints the request)",
|
|
1510
|
+
examples: ['moda cohorts create --name="Enterprise" --file=cohort.json --dry-run']
|
|
1511
|
+
},
|
|
1512
|
+
{
|
|
1513
|
+
noun: "cohorts",
|
|
1514
|
+
verb: "update",
|
|
1515
|
+
path: "cohorts update",
|
|
1516
|
+
args: "<cohort_id>",
|
|
1517
|
+
handler: "cohort-update",
|
|
1518
|
+
summary: "Edit a saved cohort: name, definition, description, pin, color (write; --dry-run)",
|
|
1519
|
+
examples: ['moda cohorts update <cohort_id> --file=cohort.json --note="exclude trials" --dry-run']
|
|
1520
|
+
},
|
|
1456
1521
|
{
|
|
1457
1522
|
noun: "review",
|
|
1458
1523
|
verb: "",
|
|
@@ -1486,12 +1551,13 @@ var CANONICAL_LEAVES = [
|
|
|
1486
1551
|
examples: ["moda skills push --dry-run", "moda skills push"]
|
|
1487
1552
|
}
|
|
1488
1553
|
];
|
|
1489
|
-
var CANONICAL_NOUNS = ["traces", "problems", "detections", "tools", "review", "reviews", "skills"];
|
|
1554
|
+
var CANONICAL_NOUNS = ["traces", "problems", "detections", "tools", "cohorts", "review", "reviews", "skills"];
|
|
1490
1555
|
var NOUN_SUMMARIES = {
|
|
1491
1556
|
traces: "Traces (agent runs): list, search, read, findings, world state, raw spans",
|
|
1492
1557
|
problems: "Problems ranked by root cause, their evidence, impact and lifecycle",
|
|
1493
1558
|
detections: "Detections of every family, and the tool failure leaderboard",
|
|
1494
1559
|
tools: "The Tool catalog: every tool with calls and success rate, and one tool's schema, usage and failure categories",
|
|
1560
|
+
cohorts: "User cohorts: list, read, preview and compare them, and save or edit one; scope lists with --cohort",
|
|
1495
1561
|
review: "Mark a detection a false positive, correct, or clear the mark",
|
|
1496
1562
|
reviews: "List false-positive marks and detection reviews",
|
|
1497
1563
|
skills: "Generate, pull, push, and install agent skills"
|
|
@@ -3175,31 +3241,31 @@ function leafManifestFields(leaf, commands) {
|
|
|
3175
3241
|
import { fileURLToPath } from "url";
|
|
3176
3242
|
import { realpathSync } from "fs";
|
|
3177
3243
|
async function runPromptsCommand(...args) {
|
|
3178
|
-
return (await import("./prompts-
|
|
3244
|
+
return (await import("./prompts-qppk0mhp.js")).runPromptsCommand(...args);
|
|
3179
3245
|
}
|
|
3180
3246
|
async function runSkillsCommand(...args) {
|
|
3181
|
-
return (await import("./skills-
|
|
3247
|
+
return (await import("./skills-sh93b156.js")).runSkillsCommand(...args);
|
|
3182
3248
|
}
|
|
3183
3249
|
async function runFixCommand(...args) {
|
|
3184
|
-
return (await import("./fix-
|
|
3250
|
+
return (await import("./fix-aghp304m.js")).runFixCommand(...args);
|
|
3185
3251
|
}
|
|
3186
3252
|
async function runFixesCommand(...args) {
|
|
3187
|
-
return (await import("./fix-
|
|
3253
|
+
return (await import("./fix-aghp304m.js")).runFixesCommand(...args);
|
|
3188
3254
|
}
|
|
3189
3255
|
async function runHarnessCommand(...args) {
|
|
3190
|
-
return (await import("./harness-
|
|
3256
|
+
return (await import("./harness-vabp33ak.js")).runHarnessCommand(...args);
|
|
3191
3257
|
}
|
|
3192
3258
|
async function runSyncCommand(...args) {
|
|
3193
|
-
return (await import("./sync-
|
|
3259
|
+
return (await import("./sync-0pp1c8hs.js")).runSyncCommand(...args);
|
|
3194
3260
|
}
|
|
3195
3261
|
async function runRegistryCommand(...args) {
|
|
3196
|
-
return (await import("./registry-
|
|
3262
|
+
return (await import("./registry-8a1940sr.js")).runRegistryCommand(...args);
|
|
3197
3263
|
}
|
|
3198
3264
|
async function runDoctorCommand(...args) {
|
|
3199
|
-
return (await import("./doctor-
|
|
3265
|
+
return (await import("./doctor-c05njdv8.js")).runDoctorCommand(...args);
|
|
3200
3266
|
}
|
|
3201
3267
|
async function runStatusCommand(...args) {
|
|
3202
|
-
return (await import("./doctor-
|
|
3268
|
+
return (await import("./doctor-c05njdv8.js")).runStatusCommand(...args);
|
|
3203
3269
|
}
|
|
3204
3270
|
async function runAuthCommand(...args) {
|
|
3205
3271
|
return (await import("./profile-commands-se9947c1.js")).runAuthCommand(...args);
|
|
@@ -3211,7 +3277,7 @@ async function runProfilesCommand(...args) {
|
|
|
3211
3277
|
return (await import("./profile-commands-se9947c1.js")).runProfilesCommand(...args);
|
|
3212
3278
|
}
|
|
3213
3279
|
async function runAgentCommand(...args) {
|
|
3214
|
-
return (await import("./agent-
|
|
3280
|
+
return (await import("./agent-86hghww1.js")).runAgentCommand(...args);
|
|
3215
3281
|
}
|
|
3216
3282
|
async function runProductionCommand(...args) {
|
|
3217
3283
|
return (await import("./production-intelligence-e5vsc6cw.js")).runProductionCommand(...args);
|
|
@@ -3515,6 +3581,7 @@ Production data:
|
|
|
3515
3581
|
clusters Browse or search topic clusters
|
|
3516
3582
|
cluster-traces <node_id> List traces in a cluster
|
|
3517
3583
|
users / user <user_id> End users with health and activity (the dashboard Users page)
|
|
3584
|
+
cohorts list|get|compare User cohorts; --cohort=<ref> scopes problems, traces, detections, clusters
|
|
3518
3585
|
tail Live-tail new traces/detections as NDJSON (one line per item)
|
|
3519
3586
|
|
|
3520
3587
|
Traces, Problems, detections, tools and review (moda <noun> --help lists the verbs):
|
|
@@ -4858,10 +4925,7 @@ async function runProblemsList(flags, context, command) {
|
|
|
4858
4925
|
...listVersionWarning(params, listVersion),
|
|
4859
4926
|
...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
4927
|
];
|
|
4861
|
-
context.output.writeData(withLink, {
|
|
4862
|
-
...warnings.length > 0 ? { warnings } : {},
|
|
4863
|
-
...nextCommands.length > 0 ? { nextCommands } : {}
|
|
4864
|
-
});
|
|
4928
|
+
context.output.writeData(withLink, withCohortScope(params.cohort, payload, { warnings, nextCommands }));
|
|
4865
4929
|
}
|
|
4866
4930
|
function writeDreamProblemsList(context, params, dream, page) {
|
|
4867
4931
|
const problems = Array.isArray(dream.problems) ? dream.problems : [];
|
|
@@ -4903,7 +4967,7 @@ function writeDreamProblemsList(context, params, dream, page) {
|
|
|
4903
4967
|
...!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
4968
|
...listVersionWarning(params, listVersion)
|
|
4905
4969
|
];
|
|
4906
|
-
context.output.writeData(data, { warnings, ...
|
|
4970
|
+
context.output.writeData(data, { warnings, ...withCohortScope(params.cohort, dream, { warnings, nextCommands }) });
|
|
4907
4971
|
}
|
|
4908
4972
|
var DREAM_INCIDENTS_DEFAULT_LIMIT = 3;
|
|
4909
4973
|
async function runDreamProblem(params, context, command) {
|
|
@@ -5008,6 +5072,27 @@ function setTraceFilters(query2, params, keys) {
|
|
|
5008
5072
|
query2.set(key, String(value));
|
|
5009
5073
|
}
|
|
5010
5074
|
}
|
|
5075
|
+
function cohortScope(cohort, data) {
|
|
5076
|
+
if (!cohort || cohort === "all")
|
|
5077
|
+
return { warnings: [] };
|
|
5078
|
+
if (asString(asRecord(data)?.cohort) !== cohort) {
|
|
5079
|
+
return {
|
|
5080
|
+
warnings: [`--cohort=${cohort} was sent, but the response does not confirm the cohort scope, so these results may cover every user.`]
|
|
5081
|
+
};
|
|
5082
|
+
}
|
|
5083
|
+
return { line: `Scoped to cohort ${cohort}: only its members' traces count (moda cohorts get ${shellArg(cohort)} shows who is in it).`, warnings: [] };
|
|
5084
|
+
}
|
|
5085
|
+
function withCohortScope(cohort, data, options = {}) {
|
|
5086
|
+
const scope = cohortScope(cohort, data);
|
|
5087
|
+
const summary = [options.summary, scope.line].filter(Boolean).join(" ");
|
|
5088
|
+
const warnings = [...options.warnings ?? [], ...scope.warnings];
|
|
5089
|
+
const merged = {
|
|
5090
|
+
...summary ? { summary } : {},
|
|
5091
|
+
...warnings.length > 0 ? { warnings } : {},
|
|
5092
|
+
...options.nextCommands && options.nextCommands.length > 0 ? { nextCommands: options.nextCommands } : {}
|
|
5093
|
+
};
|
|
5094
|
+
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
5095
|
+
}
|
|
5011
5096
|
function countingSummary(data) {
|
|
5012
5097
|
const record = asRecord(data);
|
|
5013
5098
|
const counting = asString(record?.counting);
|
|
@@ -5702,8 +5787,11 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5702
5787
|
case "clusters": {
|
|
5703
5788
|
const args = flagsToArgs(flags);
|
|
5704
5789
|
const params = parseSpecFlags("clusters", args, command);
|
|
5790
|
+
if (params.cohort && params.cohort !== "all" && params.time_range && !CLUSTER_COHORT_TIME_RANGES.includes(params.time_range)) {
|
|
5791
|
+
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.`);
|
|
5792
|
+
}
|
|
5705
5793
|
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");
|
|
5794
|
+
rejectInapplicableFlags(command, params, params.cohort ? ["parent_id"] : ["parent_id", "time_range"], "to a cluster search (--search/--node-id); they page the cluster hierarchy");
|
|
5707
5795
|
const query3 = new URLSearchParams;
|
|
5708
5796
|
if (params.search !== undefined)
|
|
5709
5797
|
query3.set("q", params.search);
|
|
@@ -5713,11 +5801,15 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5713
5801
|
query3.set("mode", params.mode);
|
|
5714
5802
|
if (params.limit)
|
|
5715
5803
|
query3.set("limit", params.limit.toString());
|
|
5804
|
+
if (params.cohort)
|
|
5805
|
+
query3.set("cohort", params.cohort);
|
|
5806
|
+
if (params.cohort && params.time_range)
|
|
5807
|
+
query3.set("time_range", params.time_range);
|
|
5716
5808
|
const data2 = await callDataAPI(`/task-clusters/search?${query3.toString()}`);
|
|
5717
5809
|
const record = asRecord(data2) ?? {};
|
|
5718
5810
|
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,
|
|
5811
|
+
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}`] : [];
|
|
5812
|
+
context.output.writeData(data2, withCohortScope(params.cohort, data2, { warnings }));
|
|
5721
5813
|
break;
|
|
5722
5814
|
}
|
|
5723
5815
|
rejectInapplicableFlags(command, params, ["mode", "limit"], "without --search or --node-id; they shape a cluster search");
|
|
@@ -5726,9 +5818,11 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5726
5818
|
query2.set("parent_id", params.parent_id);
|
|
5727
5819
|
if (params.time_range)
|
|
5728
5820
|
query2.set("time_range", params.time_range);
|
|
5821
|
+
if (params.cohort)
|
|
5822
|
+
query2.set("cohort", params.cohort);
|
|
5729
5823
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
5730
5824
|
const data = await callDataAPI(`/clusters${queryString}`);
|
|
5731
|
-
context.output.writeData(data);
|
|
5825
|
+
context.output.writeData(data, withCohortScope(params.cohort, data));
|
|
5732
5826
|
break;
|
|
5733
5827
|
}
|
|
5734
5828
|
case "cluster-traces":
|
|
@@ -5775,6 +5869,8 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5775
5869
|
query2.set("outcome", params.outcome);
|
|
5776
5870
|
if (params.sort)
|
|
5777
5871
|
query2.set("sort_by", params.sort);
|
|
5872
|
+
if (params.cohort)
|
|
5873
|
+
query2.set("cohort", params.cohort);
|
|
5778
5874
|
if (params.limit)
|
|
5779
5875
|
query2.set("limit", params.limit.toString());
|
|
5780
5876
|
if (params.offset !== undefined)
|
|
@@ -5800,7 +5896,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5800
5896
|
}
|
|
5801
5897
|
}
|
|
5802
5898
|
searchWarnings.push(...traceStateWarnings(data));
|
|
5803
|
-
const writeOptions =
|
|
5899
|
+
const writeOptions = withCohortScope(params.cohort, raw, { warnings: searchWarnings });
|
|
5804
5900
|
if (params.include_world_state === true) {
|
|
5805
5901
|
const enriched = asRecord(data) ?? {};
|
|
5806
5902
|
const list = Array.isArray(enriched.conversations) ? enriched.conversations : [];
|
|
@@ -5974,8 +6070,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5974
6070
|
setTraceFilters(query2, params, TRACE_GRAIN_FLAGS.frustrations);
|
|
5975
6071
|
const data2 = await callDataAPI(`/emotions?${query2.toString()}`);
|
|
5976
6072
|
const warnings = processingDisabledWarning(data2, "frustration");
|
|
5977
|
-
|
|
5978
|
-
context.output.writeData(data2, { ...summary ? { summary } : {}, ...warnings.length > 0 ? { warnings } : {} });
|
|
6073
|
+
context.output.writeData(data2, withCohortScope(params.cohort, data2, { summary: countingSummary(data2), warnings }));
|
|
5979
6074
|
break;
|
|
5980
6075
|
}
|
|
5981
6076
|
if (params.user_id)
|
|
@@ -5998,7 +6093,12 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5998
6093
|
case "tool-failures": {
|
|
5999
6094
|
const args = flagsToArgs(flags);
|
|
6000
6095
|
const params = parseSpecFlags("tool-failures", args, command);
|
|
6001
|
-
const
|
|
6096
|
+
const tfQuery = new URLSearchParams;
|
|
6097
|
+
if (params.days_back)
|
|
6098
|
+
tfQuery.set("days_back", String(params.days_back));
|
|
6099
|
+
if (params.cohort)
|
|
6100
|
+
tfQuery.set("cohort", params.cohort);
|
|
6101
|
+
const queryString = tfQuery.toString() ? `?${tfQuery.toString()}` : "";
|
|
6002
6102
|
const data = await callDataAPI(`/tool-failures${queryString}`);
|
|
6003
6103
|
const daysBack = params.days_back ?? 7;
|
|
6004
6104
|
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);
|
|
@@ -6006,7 +6106,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6006
6106
|
...index === 0 ? [{ command: toolFailureExamplesCommand(name, daysBack), purpose: `Read failure examples of ${name}, the tool with the most failures.`, mutability: "read", requires_approval: false }] : [],
|
|
6007
6107
|
{ command: toolCatalogGetCommand(name, daysBack), purpose: `Calls, recorded schema, usage over time and failure categories of ${name}.`, mutability: "read", requires_approval: false }
|
|
6008
6108
|
]);
|
|
6009
|
-
context.output.writeData(data,
|
|
6109
|
+
context.output.writeData(data, withCohortScope(params.cohort, data, { nextCommands }));
|
|
6010
6110
|
break;
|
|
6011
6111
|
}
|
|
6012
6112
|
case "tool-catalog": {
|
|
@@ -6403,7 +6503,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6403
6503
|
const params = parseSpecFlags("signal", args, command);
|
|
6404
6504
|
const id = encodeURIComponent(params.id);
|
|
6405
6505
|
if (params.detections !== true) {
|
|
6406
|
-
rejectInapplicableFlags(command, params, ["days_back", "limit", "offset"], "to the signal summary; they page its hits (--detections)");
|
|
6506
|
+
rejectInapplicableFlags(command, params, ["days_back", "limit", "offset", "cohort"], "to the signal summary; they page its hits (--detections)");
|
|
6407
6507
|
const data2 = await callDataAPI(`/custom-signals/${id}`);
|
|
6408
6508
|
context.output.writeData(data2);
|
|
6409
6509
|
break;
|
|
@@ -6415,10 +6515,12 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6415
6515
|
query2.set("limit", params.limit.toString());
|
|
6416
6516
|
if (params.offset !== undefined)
|
|
6417
6517
|
query2.set("offset", params.offset.toString());
|
|
6518
|
+
if (params.cohort)
|
|
6519
|
+
query2.set("cohort", params.cohort);
|
|
6418
6520
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
6419
6521
|
const data = await callDataAPI(`/custom-signals/${id}/detections${queryString}`);
|
|
6420
6522
|
const warnings = customSignalProcessingWarning(data, "detections");
|
|
6421
|
-
context.output.writeData(data,
|
|
6523
|
+
context.output.writeData(data, withCohortScope(params.cohort, data, { warnings }));
|
|
6422
6524
|
break;
|
|
6423
6525
|
}
|
|
6424
6526
|
case "trace-signals": {
|
|
@@ -6649,8 +6751,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6649
6751
|
setTraceFilters(query2, params, TRACE_GRAIN_FLAGS.emotions);
|
|
6650
6752
|
const data2 = await callDataAPI(`/emotions?${query2.toString()}`);
|
|
6651
6753
|
const warnings = processingDisabledWarning(data2, "emotion");
|
|
6652
|
-
|
|
6653
|
-
context.output.writeData(data2, { ...summary2 ? { summary: summary2 } : {}, ...warnings.length > 0 ? { warnings } : {} });
|
|
6754
|
+
context.output.writeData(data2, withCohortScope(params.cohort, data2, { summary: countingSummary(data2), warnings }));
|
|
6654
6755
|
break;
|
|
6655
6756
|
}
|
|
6656
6757
|
if (params.user_id)
|
|
@@ -6690,8 +6791,10 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6690
6791
|
if (params.family)
|
|
6691
6792
|
query2.set("family", params.family);
|
|
6692
6793
|
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");
|
|
6794
|
+
rejectInapplicableFlags(command, params, ["search", "status", "sort", "order", "cohort"], "to one trace's detections (--conversation-id); they filter and order the trace list");
|
|
6694
6795
|
}
|
|
6796
|
+
if (params.cohort)
|
|
6797
|
+
query2.set("cohort", params.cohort);
|
|
6695
6798
|
if (params.search)
|
|
6696
6799
|
query2.set("search", params.search);
|
|
6697
6800
|
if (params.status)
|
|
@@ -6702,8 +6805,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6702
6805
|
query2.set("order", params.order);
|
|
6703
6806
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
6704
6807
|
const data = await callDataAPI(`/laziness${queryString}`);
|
|
6705
|
-
|
|
6706
|
-
context.output.writeData(data, summary ? { summary } : undefined);
|
|
6808
|
+
context.output.writeData(data, withCohortScope(params.cohort, data, { summary: countingSummary(data) }));
|
|
6707
6809
|
break;
|
|
6708
6810
|
}
|
|
6709
6811
|
case "hallucinations": {
|
|
@@ -6729,8 +6831,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
6729
6831
|
}
|
|
6730
6832
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
6731
6833
|
const data = await callDataAPI(`/hallucinations${queryString}`);
|
|
6732
|
-
|
|
6733
|
-
context.output.writeData(data, summary ? { summary } : undefined);
|
|
6834
|
+
context.output.writeData(data, withCohortScope(params.cohort, data, { summary: countingSummary(data) }));
|
|
6734
6835
|
break;
|
|
6735
6836
|
}
|
|
6736
6837
|
case "step-scores": {
|
|
@@ -6919,7 +7020,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
6919
7020
|
resetApiRequestCountBeforeRun: true,
|
|
6920
7021
|
telemetry: "result-and-error",
|
|
6921
7022
|
handler: async (context) => {
|
|
6922
|
-
const { runInit } = await import("./index-
|
|
7023
|
+
const { runInit } = await import("./index-dtxvvcq2.js");
|
|
6923
7024
|
if (context.outputMode === "agent-stream") {
|
|
6924
7025
|
context.output.writeEvent({
|
|
6925
7026
|
event: "started",
|
|
@@ -7233,6 +7334,40 @@ var commandRegistry = createCommandRegistry([
|
|
|
7233
7334
|
telemetry: "result-and-error",
|
|
7234
7335
|
handler: runUserCommand
|
|
7235
7336
|
},
|
|
7337
|
+
{
|
|
7338
|
+
name: "cohorts",
|
|
7339
|
+
description: NOUN_SUMMARIES.cohorts,
|
|
7340
|
+
examples: [...leavesOf("cohorts").flatMap((leaf) => leaf.examples.slice(0, 1))],
|
|
7341
|
+
subcommands: treeSubcommandHelp("cohorts"),
|
|
7342
|
+
auth: "api-key",
|
|
7343
|
+
outputModes: ["human", "json", "agent"],
|
|
7344
|
+
mutability: "write",
|
|
7345
|
+
validateConfigBeforeRun: false,
|
|
7346
|
+
resetApiRequestCountBeforeRun: false,
|
|
7347
|
+
telemetry: "result-and-error",
|
|
7348
|
+
handler: canonicalNounHandler
|
|
7349
|
+
},
|
|
7350
|
+
...[
|
|
7351
|
+
["cohort-list", "Built-in and saved user cohorts", "read"],
|
|
7352
|
+
["cohort-get", "One cohort: name, definition and revision", "read"],
|
|
7353
|
+
["cohort-fields", "The fields and operators a cohort definition can use", "read"],
|
|
7354
|
+
["cohort-preview", "Member count and sample users for an unsaved definition", "read"],
|
|
7355
|
+
["cohort-compare", "Two cohorts side by side: size, health, top topics, failure mix", "read"],
|
|
7356
|
+
["cohort-create", "Save a cohort from a definition", "write"],
|
|
7357
|
+
["cohort-update", "Edit a saved cohort", "write"]
|
|
7358
|
+
].map(([name, description, mutability]) => ({
|
|
7359
|
+
name,
|
|
7360
|
+
description,
|
|
7361
|
+
examples: [...CANONICAL_LEAVES.find((leaf) => leaf.handler === name)?.examples ?? []],
|
|
7362
|
+
hidden: true,
|
|
7363
|
+
auth: "api-key",
|
|
7364
|
+
outputModes: ["human", "json", "agent"],
|
|
7365
|
+
mutability,
|
|
7366
|
+
validateConfigBeforeRun: false,
|
|
7367
|
+
resetApiRequestCountBeforeRun: false,
|
|
7368
|
+
telemetry: "result-and-error",
|
|
7369
|
+
handler: runCohortCommand
|
|
7370
|
+
})),
|
|
7236
7371
|
{
|
|
7237
7372
|
name: "replays",
|
|
7238
7373
|
description: "Read replay results: sets, run history, per-seed verdicts, and playout transcripts",
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
promptsDiscoveredCheck,
|
|
4
4
|
runDoctorCommand,
|
|
5
5
|
runStatusCommand
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-srwzar82.js";
|
|
7
7
|
import"./cli-pmzh2qjy.js";
|
|
8
|
-
import"./cli-
|
|
8
|
+
import"./cli-he8csgsr.js";
|
|
9
9
|
import"./cli-mm48br00.js";
|
|
10
10
|
import"./cli-xq45etg1.js";
|
|
11
11
|
import"./cli-xddtv3yn.js";
|
|
12
|
-
import"./cli-
|
|
12
|
+
import"./cli-4sy4tytm.js";
|
|
13
13
|
import"./cli-0xc5htv7.js";
|
|
14
14
|
import"./cli-t0pb7qbs.js";
|
|
15
15
|
import"./cli-k4tqwah4.js";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildSourceSnapshot
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-vwpbspr5.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
8
|
import"./cli-xddtv3yn.js";
|
|
9
|
-
import"./cli-
|
|
9
|
+
import"./cli-4sy4tytm.js";
|
|
10
10
|
import"./cli-0xc5htv7.js";
|
|
11
11
|
import {
|
|
12
12
|
recordApiRequest
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
writeHarnessAnalyzeResult,
|
|
41
41
|
writeHarnessArtifacts,
|
|
42
42
|
writeHumanProgress
|
|
43
|
-
} from "./cli-
|
|
43
|
+
} from "./cli-vwpbspr5.js";
|
|
44
44
|
import"./cli-xq45etg1.js";
|
|
45
45
|
import"./cli-97fnztpy.js";
|
|
46
46
|
import {
|
|
@@ -48,7 +48,7 @@ import {
|
|
|
48
48
|
} from "./cli-cesds766.js";
|
|
49
49
|
import"./cli-qpq84eee.js";
|
|
50
50
|
import"./cli-xddtv3yn.js";
|
|
51
|
-
import"./cli-
|
|
51
|
+
import"./cli-4sy4tytm.js";
|
|
52
52
|
import"./cli-0xc5htv7.js";
|
|
53
53
|
import"./cli-t0pb7qbs.js";
|
|
54
54
|
import"./cli-k4tqwah4.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildDoctorReport
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-srwzar82.js";
|
|
4
4
|
import {
|
|
5
5
|
selectTenantAndCreateKey
|
|
6
6
|
} from "./cli-1z1sx8dg.js";
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
import {
|
|
21
21
|
agentsMdProblem,
|
|
22
22
|
runSkillSync
|
|
23
|
-
} from "./cli-
|
|
23
|
+
} from "./cli-mxfyq5nq.js";
|
|
24
24
|
import"./cli-qm5b1vck.js";
|
|
25
25
|
import {
|
|
26
26
|
detectAgents
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
import {
|
|
33
33
|
initPrompts,
|
|
34
34
|
runPromptSync
|
|
35
|
-
} from "./cli-
|
|
35
|
+
} from "./cli-he8csgsr.js";
|
|
36
36
|
import"./cli-mm48br00.js";
|
|
37
37
|
import {
|
|
38
38
|
codingAgentDisplayName,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
runCodingAgent,
|
|
47
47
|
runHarnessCommand,
|
|
48
48
|
startRemoteAnalyze
|
|
49
|
-
} from "./cli-
|
|
49
|
+
} from "./cli-vwpbspr5.js";
|
|
50
50
|
import {
|
|
51
51
|
canonicalText,
|
|
52
52
|
renderInitBanner,
|
|
@@ -63,7 +63,7 @@ import"./cli-qpq84eee.js";
|
|
|
63
63
|
import {
|
|
64
64
|
createCommandContext
|
|
65
65
|
} from "./cli-xddtv3yn.js";
|
|
66
|
-
import"./cli-
|
|
66
|
+
import"./cli-4sy4tytm.js";
|
|
67
67
|
import"./cli-0xc5htv7.js";
|
|
68
68
|
import {
|
|
69
69
|
VERSION,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
inventoryFiles,
|
|
3
3
|
safePromptEvidencePath
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-vwpbspr5.js";
|
|
5
5
|
import"./cli-xq45etg1.js";
|
|
6
6
|
import"./cli-97fnztpy.js";
|
|
7
7
|
import"./cli-cesds766.js";
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
require_typescript
|
|
10
10
|
} from "./cli-qpq84eee.js";
|
|
11
11
|
import"./cli-xddtv3yn.js";
|
|
12
|
-
import"./cli-
|
|
12
|
+
import"./cli-4sy4tytm.js";
|
|
13
13
|
import"./cli-0xc5htv7.js";
|
|
14
14
|
import"./cli-t0pb7qbs.js";
|
|
15
15
|
import"./cli-k4tqwah4.js";
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
checkPromptMapping,
|
|
4
4
|
discoverHarnessPromptSources,
|
|
5
5
|
safePromptEvidencePath
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-vwpbspr5.js";
|
|
7
7
|
import"./cli-xq45etg1.js";
|
|
8
8
|
import"./cli-97fnztpy.js";
|
|
9
9
|
import"./cli-cesds766.js";
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
inspectPythonSelectors
|
|
13
13
|
} from "./cli-qpq84eee.js";
|
|
14
14
|
import"./cli-xddtv3yn.js";
|
|
15
|
-
import"./cli-
|
|
15
|
+
import"./cli-4sy4tytm.js";
|
|
16
16
|
import"./cli-0xc5htv7.js";
|
|
17
17
|
import"./cli-t0pb7qbs.js";
|
|
18
18
|
import"./cli-k4tqwah4.js";
|
|
@@ -23,12 +23,12 @@ import {
|
|
|
23
23
|
runPromptAb,
|
|
24
24
|
selectProblemCases,
|
|
25
25
|
waitLabel
|
|
26
|
-
} from "./cli-
|
|
27
|
-
import"./cli-
|
|
26
|
+
} from "./cli-hjm9151g.js";
|
|
27
|
+
import"./cli-he8csgsr.js";
|
|
28
28
|
import"./cli-daqkdnm1.js";
|
|
29
29
|
import"./cli-mm48br00.js";
|
|
30
30
|
import"./cli-xddtv3yn.js";
|
|
31
|
-
import"./cli-
|
|
31
|
+
import"./cli-4sy4tytm.js";
|
|
32
32
|
import"./cli-0xc5htv7.js";
|
|
33
33
|
import"./cli-t0pb7qbs.js";
|
|
34
34
|
import"./cli-k4tqwah4.js";
|
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
formatVerdict,
|
|
8
8
|
rerunWithYes,
|
|
9
9
|
resolvePromptArmSpec
|
|
10
|
-
} from "./cli-
|
|
11
|
-
import"./cli-
|
|
10
|
+
} from "./cli-hjm9151g.js";
|
|
11
|
+
import"./cli-he8csgsr.js";
|
|
12
12
|
import"./cli-daqkdnm1.js";
|
|
13
13
|
import"./cli-mm48br00.js";
|
|
14
14
|
import"./cli-xddtv3yn.js";
|
|
15
|
-
import"./cli-
|
|
15
|
+
import"./cli-4sy4tytm.js";
|
|
16
16
|
import {
|
|
17
17
|
callControlAPI
|
|
18
18
|
} from "./cli-0xc5htv7.js";
|
|
@@ -11,12 +11,12 @@ import {
|
|
|
11
11
|
runPromptSync,
|
|
12
12
|
runPromptsCommand,
|
|
13
13
|
writePromptSyncProgress
|
|
14
|
-
} from "./cli-
|
|
14
|
+
} from "./cli-he8csgsr.js";
|
|
15
15
|
import {
|
|
16
16
|
promptSourceHashPayload
|
|
17
17
|
} from "./cli-mm48br00.js";
|
|
18
18
|
import"./cli-xddtv3yn.js";
|
|
19
|
-
import"./cli-
|
|
19
|
+
import"./cli-4sy4tytm.js";
|
|
20
20
|
import"./cli-0xc5htv7.js";
|
|
21
21
|
import"./cli-t0pb7qbs.js";
|
|
22
22
|
import"./cli-k4tqwah4.js";
|
|
@@ -3,12 +3,12 @@ import {
|
|
|
3
3
|
pullSkills,
|
|
4
4
|
runSkillSync,
|
|
5
5
|
runSkillsCommand
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-mxfyq5nq.js";
|
|
7
7
|
import"./cli-qm5b1vck.js";
|
|
8
8
|
import"./cli-rjav0vj1.js";
|
|
9
9
|
import"./cli-hcwdz9sd.js";
|
|
10
10
|
import"./cli-xddtv3yn.js";
|
|
11
|
-
import"./cli-
|
|
11
|
+
import"./cli-4sy4tytm.js";
|
|
12
12
|
import"./cli-0xc5htv7.js";
|
|
13
13
|
import"./cli-t0pb7qbs.js";
|
|
14
14
|
import"./cli-k4tqwah4.js";
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runSkillsCommand
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-mxfyq5nq.js";
|
|
4
4
|
import"./cli-qm5b1vck.js";
|
|
5
5
|
import"./cli-rjav0vj1.js";
|
|
6
6
|
import"./cli-hcwdz9sd.js";
|
|
7
7
|
import {
|
|
8
8
|
runPromptsCommand
|
|
9
|
-
} from "./cli-
|
|
9
|
+
} from "./cli-he8csgsr.js";
|
|
10
10
|
import"./cli-mm48br00.js";
|
|
11
11
|
import {
|
|
12
12
|
runHarnessCommand
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-vwpbspr5.js";
|
|
14
14
|
import"./cli-xq45etg1.js";
|
|
15
15
|
import"./cli-97fnztpy.js";
|
|
16
16
|
import"./cli-cesds766.js";
|
|
17
17
|
import"./cli-qpq84eee.js";
|
|
18
18
|
import"./cli-xddtv3yn.js";
|
|
19
|
-
import"./cli-
|
|
19
|
+
import"./cli-4sy4tytm.js";
|
|
20
20
|
import"./cli-0xc5htv7.js";
|
|
21
21
|
import"./cli-t0pb7qbs.js";
|
|
22
22
|
import {
|
package/package.json
CHANGED
package/skills/moda-cli/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: moda-cli
|
|
3
|
-
version: 3.0.
|
|
3
|
+
version: 3.0.8
|
|
4
4
|
description: Investigate a production AI agent with the Moda CLI (`moda`) - find where something happened in real traces (traces search, then traces get), check agent health, rank what to fix (investigate, problems), and dig into tool failures, user frustration, and hallucinations. Also prompt registry sync/promote, replays, custom signals, and false-positive marking. Use when the user mentions Moda, production traces or conversations of their agent, agent failures, or asks what to fix.
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -72,6 +72,7 @@ Details: `references/output-protocol.md`.
|
|
|
72
72
|
| Read one whole trace | `moda traces get <id> --all` (pages of up to 500 messages) | `moda traces spans <id>` for raw spans |
|
|
73
73
|
| Read several traces or turns | `moda traces get <id1>@<msg_index> <id2>@<msg_index> ...` (up to 25; or one per line via `--ids-from=-`) | Same for `moda traces spans <id1> <id2> ...` |
|
|
74
74
|
| One user's experience | `moda users`, `moda user <user_id>` | `moda traces search "<words>" --user-id=<id>` |
|
|
75
|
+
| Is this only hurting <segment> (enterprise, new users, ...)? | `moda cohorts list` (the ref of a built-in or saved cohort), then `moda problems list --sort=users --cohort=<ref>` and the same command without `--cohort` | `moda detections list --family=frustration --cohort=<ref>` vs no `--cohort` (totals count traces); `moda cohorts compare <ref> builtin:power_users` for size, health and failure mix |
|
|
75
76
|
| Topic mix | `moda clusters` | `moda cluster-traces <node_id>` |
|
|
76
77
|
| What the agent believed at a turn | `moda traces state <id> --snapshot --msg-index=<n>` | |
|
|
77
78
|
| A synthesized answer | `moda ask "<question>"` only when the user asks: each call is a paid agent run (up to about 200k tokens) | Exit 3 means degraded |
|
|
@@ -54,7 +54,10 @@ Loaded on demand from the moda-cli skill. This table can lag the CLI: `moda <com
|
|
|
54
54
|
| `moda prompts sync` | Upload changed prompt versions and update lockfile |
|
|
55
55
|
| `moda prompts promote <key>` | Move a remote prompt label |
|
|
56
56
|
| `moda registry template\|validate\|push\|status\|coverage\|log\|show\|prompt` | Register prompts, skills, tools, and agent wiring from one agent-written manifest (`--file`, `--dry-run`, `--live`, `--message`, `--days`); every push is a commit in the Registry history; no repo scan |
|
|
57
|
-
| `moda users` / `moda user <id>` | End users with health/activity (`--page-size=N`, alias `--limit=N`; `--page=N
|
|
57
|
+
| `moda users` / `moda user <id>` | End users with health/activity (`--page-size=N`, alias `--limit=N`; `--page=N`; `--cohort=builtin:<key>\|<saved id>`); one user's profile |
|
|
58
|
+
| `moda cohorts list\|get\|fields\|preview\|compare` | User cohorts (built-in and saved): refs and definitions, the definition fields, a member count and sample for an unsaved definition (`--file`/`--definition`), two cohorts side by side (`--days=7\|30\|90`) |
|
|
59
|
+
| `moda cohorts create\|update` | Write: save a cohort (`--name`, `--file`/`--definition`, `--description`, `--pinned`, `--color`) or edit a saved one (`<cohort_id>`, same flags plus `--note`); both take `--dry-run` |
|
|
60
|
+
| `--cohort=<ref>` | Scope `problems list`, `traces list`, `detections list` (emotion/frustration/hallucination per trace, laziness, custom_signal hits), `detections tools` and `clusters` to one cohort (`builtin:<key>` or a saved id from `moda cohorts list`). The summary names the cohort; a warning means the server did not confirm the scope |
|
|
58
61
|
| `moda problems reopen <pid>` | Reopen a Problem marked fixed |
|
|
59
62
|
| `moda signals <create\|update\|activate\|pause\|delete\|examples\|refine\|revise\|proposals\|accept\|reject\|search\|preview>` | Manage custom signals (writes take `--dry-run`; LLM-backed ones are rate-limited per key) |
|
|
60
63
|
| `moda prompts list\|show\|proposals\|usage\|replay-runs\|decide` | Read the prompt registry; merge/reject proposals |
|
|
@@ -5,7 +5,7 @@ Loaded on demand from the moda-cli skill.
|
|
|
5
5
|
### 10. Everything the dashboard does, from the CLI
|
|
6
6
|
|
|
7
7
|
Every command below needs only an API key, and the tenant comes from the key.
|
|
8
|
-
Writes listed here accept `--dry-run`: it validates the call, prints the exact request (method, endpoint, body) and sends nothing, and its `next_commands` entry is the command that sends it for real (`mutability: write`, `requires_approval: true`). That covers `problems feedback|reopen|link`, `review`, `feedback` and the `signals` writes. `prompts promote|ab|propose` refuse `--dry-run` before sending anything, so run them only when you mean it.
|
|
8
|
+
Writes listed here accept `--dry-run`: it validates the call, prints the exact request (method, endpoint, body) and sends nothing, and its `next_commands` entry is the command that sends it for real (`mutability: write`, `requires_approval: true`). That covers `problems feedback|reopen|link`, `review`, `feedback`, `cohorts create|update` and the `signals` writes. `prompts promote|ab|propose` refuse `--dry-run` before sending anything, so run them only when you mean it.
|
|
9
9
|
|
|
10
10
|
| Dashboard | CLI |
|
|
11
11
|
|---|---|
|
|
@@ -14,7 +14,9 @@ Writes listed here accept `--dry-run`: it validates the call, prints the exact r
|
|
|
14
14
|
| Traces list: Processed, Use case confidence, Indexed columns | `moda traces` rows: `processing_status`, `error_message`, `membership_score`, `indexed_at`; `moda traces get <id>`: `trace_state` |
|
|
15
15
|
| Signals tabs: per-trace list, filters, sort | `moda detections list --family=<f> --group-by=trace` plus `--trajectory --elicitor --signal --status --search --sort --order` (emotion), `--rule --source` (hallucination) |
|
|
16
16
|
| Settings: which detectors run | `moda overview` → `detectors` (read-only; switching one is dashboard-only) |
|
|
17
|
-
| Users page / user profile | `moda users [--window --cohort --sort --order --health-status]`, `moda user <id>` |
|
|
17
|
+
| Users page / user profile | `moda users [--window --cohort --sort --order --health-status]`, `moda user <id>` (`--cohort` takes `builtin:<key>`, a saved cohort id, or a bare built-in key) |
|
|
18
|
+
| Cohort selector on Problems, Traces, Signals tabs, custom signals, Topics | `--cohort=builtin:<key>\|<saved id>` on `problems list`, `traces list`, `detections list` (emotion, frustration and hallucination read the per-trace list; laziness; custom_signal `--signal-id`), `detections tools`, `clusters` (`--time-range=all\|3d\|7d\|30d`, also with `--search`). Output says which cohort scoped it (summary line and `cohort` in the data). `traces search` has no cohort scope |
|
|
19
|
+
| Cohort builder: list, fields, preview, compare, save, edit | `moda cohorts list [--include-archived]`, `get <ref>`, `fields`, `preview --file=<definition.json>`, `compare <a> <b> [--days=7\|30\|90]`, `create --name --file [--dry-run]`, `update <cohort_id> [--name --file --note] [--dry-run]` (archiving is dashboard-only) |
|
|
18
20
|
| Tool catalog: every tool, its schema and usage | `moda tools list [--sort=calls\|failure_rate\|failures\|traces\|last_seen --search --direction --offset]`, `moda tools get <tool_name>` |
|
|
19
21
|
| Problems list (dream grouping or Book, as the page decides): sort, cohort, page | `moda problems list [--sort=users --cohort=builtin:<key> --offset=N --list-version=V]`; `--view=book\|dream` forces one |
|
|
20
22
|
| Problem page (dream view): severity, incidents with verdicts | `moda problems get <problem_id> --view=dream [--offset=N]` |
|