@moda-ai/cli 1.55.17 → 1.55.19
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-cha3kg9d.js → agent-mj622k8s.js} +9 -9
- package/dist/{cli-1exddmc0.js → cli-033n2mpb.js} +2 -2
- package/dist/{cli-5hq827jt.js → cli-569hj0bj.js} +1 -1
- package/dist/{cli-3ezzeqcy.js → cli-5ke3xe6y.js} +47 -3
- package/dist/{cli-av3dqgj5.js → cli-5km7j04z.js} +4 -4
- package/dist/{cli-eazeanvt.js → cli-7ea02wca.js} +1 -1
- package/dist/{cli-qmjnh4z9.js → cli-9x9adrtj.js} +1 -1
- package/dist/{cli-a1mv0ypm.js → cli-a5c9te95.js} +5 -5
- package/dist/cli-cehskjde.js +1302 -0
- package/dist/{cli-5q1gyvxn.js → cli-pc5cw7mx.js} +5 -5
- package/dist/{cli-c8p69n55.js → cli-rqk6f6n6.js} +2 -2
- package/dist/{cli-0e8bfvn7.js → cli-wf7gfa1e.js} +8 -8
- package/dist/cli.js +346 -921
- package/dist/{doctor-kg0yq1wf.js → doctor-mx6jf435.js} +9 -9
- package/dist/{fix-q8er8egx.js → fix-9fmy6p2x.js} +7 -7
- package/dist/{harness-github-actions-ver6cprq.js → harness-github-actions-c826bfxs.js} +6 -6
- package/dist/{harness-v9s0k9s7.js → harness-xvg6ws6x.js} +6 -6
- package/dist/{index-7zqa7t5c.js → index-6qqmjqb2.js} +11 -11
- package/dist/{production-intelligence-k36jsvqx.js → production-intelligence-dbe9dmc5.js} +3 -3
- package/dist/{profile-commands-88sdwzbg.js → profile-commands-kmmd9y86.js} +3 -3
- package/dist/prompt-source-mcp.js +6 -6
- package/dist/{prompts-2r756vtd.js → prompts-1tkhrxkq.js} +7 -7
- package/dist/{provision-n3r7yway.js → provision-wzttap58.js} +4 -4
- package/dist/{registry-5v63ga01.js → registry-atqyb5fa.js} +4 -4
- package/dist/{skills-fed17et3.js → skills-d35nnm66.js} +6 -6
- package/dist/{sync-r4tncne4.js → sync-n2psdffz.js} +8 -8
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/dist/cli-kg0kz05e.js +0 -496
package/dist/cli.js
CHANGED
|
@@ -5,27 +5,55 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
createCommandContext,
|
|
7
7
|
parseBooleanFlagValue
|
|
8
|
-
} from "./cli-
|
|
8
|
+
} from "./cli-569hj0bj.js";
|
|
9
9
|
import {
|
|
10
|
+
AuditSchema,
|
|
11
|
+
COMMAND_FLAG_SPECS,
|
|
12
|
+
DETECTION_VERDICTS,
|
|
13
|
+
DetectionReviewSchema,
|
|
14
|
+
FALSE_POSITIVE_KINDS,
|
|
15
|
+
FEEDBACK_USAGE,
|
|
16
|
+
FalsePositiveSchema,
|
|
17
|
+
PROBLEM_FEEDBACK_ACTIONS,
|
|
18
|
+
ProblemFeedbackSchema,
|
|
19
|
+
ProblemImpactSchema,
|
|
20
|
+
ProblemLinearFileSchema,
|
|
21
|
+
ProblemsRemainderSchema,
|
|
10
22
|
SIGNALS_MANAGEMENT_SUBCOMMANDS,
|
|
23
|
+
SIGNAL_LABELS,
|
|
24
|
+
SignalLabelSchema,
|
|
25
|
+
StepScoresSchema,
|
|
26
|
+
UUID_RE,
|
|
11
27
|
assertFlags,
|
|
12
28
|
assertPositionals,
|
|
29
|
+
buildFeedbackRequest,
|
|
30
|
+
closestMatches,
|
|
31
|
+
describeSpecFlags,
|
|
32
|
+
flagSpecFor,
|
|
33
|
+
isFeedbackRefFlag,
|
|
34
|
+
kebabFlag,
|
|
35
|
+
manifestFlagFields,
|
|
36
|
+
renderFlagHelp,
|
|
13
37
|
runProblemReopenCommand,
|
|
14
38
|
runSignalsManagementCommand,
|
|
15
39
|
runUserCommand,
|
|
16
40
|
runUsersCommand,
|
|
41
|
+
schemaShape,
|
|
42
|
+
specFlagKeys,
|
|
43
|
+
specFlagNames,
|
|
44
|
+
subcommandHelpFlags,
|
|
17
45
|
unknownSignalsSubcommandError
|
|
18
|
-
} from "./cli-
|
|
46
|
+
} from "./cli-cehskjde.js";
|
|
19
47
|
import {
|
|
20
48
|
ApiError,
|
|
21
49
|
callControlAPI,
|
|
22
50
|
callDataAPI
|
|
23
|
-
} from "./cli-
|
|
51
|
+
} from "./cli-rqk6f6n6.js";
|
|
24
52
|
import {
|
|
25
53
|
apiKeyHeaders,
|
|
26
54
|
isPlatformApiKey,
|
|
27
55
|
setPlatformTenantOverride
|
|
28
|
-
} from "./cli-
|
|
56
|
+
} from "./cli-7ea02wca.js";
|
|
29
57
|
import {
|
|
30
58
|
AGENT_ERROR_CODES,
|
|
31
59
|
BATCH_CONCURRENCY,
|
|
@@ -50,6 +78,7 @@ import {
|
|
|
50
78
|
asNumber,
|
|
51
79
|
asRecord,
|
|
52
80
|
asString,
|
|
81
|
+
attachInputDetails,
|
|
53
82
|
collectBatchTargets,
|
|
54
83
|
compactProblemDossier,
|
|
55
84
|
contextTarget,
|
|
@@ -79,434 +108,14 @@ import {
|
|
|
79
108
|
withFrustrationAnchors,
|
|
80
109
|
withToolFailureAnchors,
|
|
81
110
|
withoutDetectionWindows
|
|
82
|
-
} from "./cli-
|
|
111
|
+
} from "./cli-5ke3xe6y.js";
|
|
83
112
|
import {
|
|
84
113
|
__require
|
|
85
114
|
} from "./cli-0v6na3yp.js";
|
|
86
115
|
|
|
87
116
|
// src/cli.ts
|
|
88
117
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
89
|
-
import { z as z2 } from "zod";
|
|
90
|
-
|
|
91
|
-
// src/schemas.ts
|
|
92
118
|
import { z } from "zod";
|
|
93
|
-
var boolFlag = () => z.preprocess((val) => {
|
|
94
|
-
const text = String(val).toLowerCase();
|
|
95
|
-
if (["true", "1", "yes", "on"].includes(text))
|
|
96
|
-
return true;
|
|
97
|
-
if (["false", "0", "no", "off"].includes(text))
|
|
98
|
-
return false;
|
|
99
|
-
return val;
|
|
100
|
-
}, z.boolean()).optional();
|
|
101
|
-
var DAYS_BACK_MESSAGE = "must be a whole number from 1 to 90 (e.g. --days-back=7)";
|
|
102
|
-
var daysBackFlag = (fallback) => {
|
|
103
|
-
const days = z.number({ invalid_type_error: DAYS_BACK_MESSAGE }).int(DAYS_BACK_MESSAGE).min(1, DAYS_BACK_MESSAGE).max(90, DAYS_BACK_MESSAGE);
|
|
104
|
-
return fallback === undefined ? days.optional() : days.default(fallback).optional();
|
|
105
|
-
};
|
|
106
|
-
var OverviewSchema = z.object({
|
|
107
|
-
days_back: daysBackFlag(7)
|
|
108
|
-
});
|
|
109
|
-
var ClustersSchema = z.object({
|
|
110
|
-
parent_id: z.string().optional(),
|
|
111
|
-
time_range: z.enum(["all", "1h", "3d", "7d", "24h", "30d", "90d"]).default("all").optional(),
|
|
112
|
-
search: z.string().min(2).max(200).optional(),
|
|
113
|
-
node_id: z.string().min(1).max(512).optional(),
|
|
114
|
-
mode: z.enum(["fuzzy", "semantic", "hybrid"]).optional(),
|
|
115
|
-
limit: z.number().min(1).max(50).optional()
|
|
116
|
-
});
|
|
117
|
-
var ClusterConversationsSchema = z.object({
|
|
118
|
-
node_id: z.string(),
|
|
119
|
-
limit: z.number().min(1).max(100).default(10).optional(),
|
|
120
|
-
offset: z.number().min(0).default(0).optional()
|
|
121
|
-
});
|
|
122
|
-
var ConversationsSchema = z.object({
|
|
123
|
-
search: z.string().optional(),
|
|
124
|
-
cluster_id: z.string().optional(),
|
|
125
|
-
user_id: z.string().optional(),
|
|
126
|
-
time_range: z.enum(["all", "1h", "3d", "24h", "7d", "30d", "90d"]).default("all").optional(),
|
|
127
|
-
environment: z.enum(["all", "development", "staging", "production"]).default("all").optional(),
|
|
128
|
-
world_state: z.string().max(200).optional(),
|
|
129
|
-
outcome: z.enum(["any", "positive", "negative"]).default("any").optional(),
|
|
130
|
-
include_world_state: boolFlag(),
|
|
131
|
-
sort: z.enum(["recent", "longest", "slowest"]).optional(),
|
|
132
|
-
limit: z.number().min(1).max(100).default(20).optional(),
|
|
133
|
-
offset: z.number().min(0).default(0).optional()
|
|
134
|
-
});
|
|
135
|
-
var WorldStateSchema = z.object({
|
|
136
|
-
conversation_id: z.string(),
|
|
137
|
-
summary_only: boolFlag(),
|
|
138
|
-
event_limit: z.number().min(1).max(5000).default(2000).optional(),
|
|
139
|
-
snapshot: boolFlag(),
|
|
140
|
-
msg_index: z.number().min(0).max(1e5).optional(),
|
|
141
|
-
block_index: z.number().min(0).max(1e5).optional(),
|
|
142
|
-
segment_index: z.number().min(0).max(65535).optional(),
|
|
143
|
-
replay: boolFlag(),
|
|
144
|
-
format: z.enum(["frames", "fold-inputs"]).optional(),
|
|
145
|
-
message_count: z.number().min(1).max(1e6).optional()
|
|
146
|
-
});
|
|
147
|
-
var ContextSchema = z.object({
|
|
148
|
-
conversation_id: z.string().min(1),
|
|
149
|
-
msg_index: z.number().int().min(0).optional(),
|
|
150
|
-
window: z.number().int().min(0).optional(),
|
|
151
|
-
metadata_only: boolFlag(),
|
|
152
|
-
all: boolFlag(),
|
|
153
|
-
from: z.number().int().min(0).optional(),
|
|
154
|
-
max_messages: z.number().int().min(1).max(5000).optional(),
|
|
155
|
-
ids_from: z.string().min(1).optional()
|
|
156
|
-
});
|
|
157
|
-
var FrustrationsSchema = z.object({
|
|
158
|
-
days_back: daysBackFlag(7),
|
|
159
|
-
limit: z.number().min(1).max(20).default(10).optional(),
|
|
160
|
-
offset: z.number().min(0).default(0).optional(),
|
|
161
|
-
include_window: boolFlag(),
|
|
162
|
-
window: z.number().min(1).max(5).default(1).optional(),
|
|
163
|
-
user_id: z.string().min(1).max(256).optional(),
|
|
164
|
-
conversation_id: z.string().min(1).max(256).optional()
|
|
165
|
-
});
|
|
166
|
-
var ToolFailuresSchema = z.object({
|
|
167
|
-
days_back: daysBackFlag(7)
|
|
168
|
-
});
|
|
169
|
-
var ProblemsSchema = z.object({
|
|
170
|
-
days_back: daysBackFlag(30),
|
|
171
|
-
limit: z.number().min(1).max(25).default(25).optional()
|
|
172
|
-
});
|
|
173
|
-
var REMAINDER_FAMILIES = [
|
|
174
|
-
"tool_failure",
|
|
175
|
-
"emotion",
|
|
176
|
-
"laziness",
|
|
177
|
-
"hallucination",
|
|
178
|
-
"prm_dip",
|
|
179
|
-
"custom_signal",
|
|
180
|
-
"conversation_reader"
|
|
181
|
-
];
|
|
182
|
-
var ProblemsRemainderSchema = z.object({
|
|
183
|
-
days_back: daysBackFlag(30),
|
|
184
|
-
limit: z.number().min(1).max(25).default(25).optional(),
|
|
185
|
-
family: z.enum(REMAINDER_FAMILIES).optional(),
|
|
186
|
-
cursor: z.string().min(1).max(4096).optional()
|
|
187
|
-
});
|
|
188
|
-
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
189
|
-
var ProblemImpactSchema = z.object({
|
|
190
|
-
node_id: z.string().min(1).max(256).optional(),
|
|
191
|
-
problem_id: z.string().regex(UUID_RE).optional(),
|
|
192
|
-
run_id: z.string().min(1).max(256).optional(),
|
|
193
|
-
days_back: z.union([z.literal("all"), z.coerce.number().refine((n) => [1, 3, 7, 30, 90].includes(n), "Use all, 1, 3, 7, 30, or 90 days")]).default(7),
|
|
194
|
-
mode: z.enum(["metrics", "trend", "evidence", "catalog", "overview", "affected-use-cases", "trace-use-cases"]).default("metrics"),
|
|
195
|
-
to: z.string().datetime({ precision: 3 }).optional(),
|
|
196
|
-
cursor: z.string().min(1).optional(),
|
|
197
|
-
conversation_ids: z.string().transform((value, ctx) => {
|
|
198
|
-
try {
|
|
199
|
-
return z.array(z.string().min(1).max(512)).min(1).max(25).parse(JSON.parse(value));
|
|
200
|
-
} catch {
|
|
201
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Use a JSON array of 1–25 conversation IDs" });
|
|
202
|
-
return z.NEVER;
|
|
203
|
-
}
|
|
204
|
-
}).optional()
|
|
205
|
-
}).refine((p) => p.mode !== "trace-use-cases" || p.problem_id && p.conversation_ids, {
|
|
206
|
-
message: "Trace use cases require --problem-id and --conversation-ids"
|
|
207
|
-
}).refine((p) => p.node_id || p.problem_id || ["catalog", "overview"].includes(p.mode), {
|
|
208
|
-
message: "Select --node-id or --problem-id, or use --mode=catalog/overview"
|
|
209
|
-
}).refine((p) => !p.cursor || p.mode === "evidence" && p.to && p.run_id, {
|
|
210
|
-
message: "An evidence cursor requires --mode=evidence, --to, and --run-id from the previous response"
|
|
211
|
-
});
|
|
212
|
-
var PROBLEM_FAMILIES = REMAINDER_FAMILIES;
|
|
213
|
-
var PROBLEM_DOORS = ["rubric_match", "local_causal_chain"];
|
|
214
|
-
var ProblemSchema = z.object({
|
|
215
|
-
id: z.string().min(1),
|
|
216
|
-
evidence: boolFlag(),
|
|
217
|
-
reports: boolFlag(),
|
|
218
|
-
traces: boolFlag(),
|
|
219
|
-
conversations: boolFlag(),
|
|
220
|
-
feedback: boolFlag(),
|
|
221
|
-
full: boolFlag(),
|
|
222
|
-
limit: z.number().min(1).max(50).optional(),
|
|
223
|
-
cursor: z.string().optional(),
|
|
224
|
-
family: z.enum(PROBLEM_FAMILIES).optional(),
|
|
225
|
-
door: z.enum(PROBLEM_DOORS).optional()
|
|
226
|
-
});
|
|
227
|
-
var PROBLEM_FEEDBACK_ACTIONS = [
|
|
228
|
-
"mark_fixed",
|
|
229
|
-
"dismiss",
|
|
230
|
-
"flag_attribution",
|
|
231
|
-
"rename"
|
|
232
|
-
];
|
|
233
|
-
var ProblemFeedbackSchema = z.object({
|
|
234
|
-
id: z.string().min(1),
|
|
235
|
-
action: z.enum(PROBLEM_FEEDBACK_ACTIONS),
|
|
236
|
-
reason: z.string().max(2000).optional(),
|
|
237
|
-
attribution_id: z.string().max(64).optional(),
|
|
238
|
-
new_name: z.string().max(255).optional(),
|
|
239
|
-
actor: z.string().max(255).optional()
|
|
240
|
-
});
|
|
241
|
-
var ProblemLinearFileSchema = z.object({
|
|
242
|
-
id: z.string().min(1),
|
|
243
|
-
issue: z.string().max(2048).optional(),
|
|
244
|
-
team_id: z.string().max(255).optional(),
|
|
245
|
-
title: z.string().optional(),
|
|
246
|
-
priority: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).max(4).optional())
|
|
247
|
-
});
|
|
248
|
-
var SignalSchema = z.object({
|
|
249
|
-
id: z.string().min(1).max(255),
|
|
250
|
-
detections: boolFlag(),
|
|
251
|
-
days_back: daysBackFlag(),
|
|
252
|
-
limit: z.number().min(1).max(20).optional(),
|
|
253
|
-
offset: z.number().min(0).max(1e4).optional()
|
|
254
|
-
});
|
|
255
|
-
var SIGNAL_LABELS = ["fits", "does_not_fit"];
|
|
256
|
-
var SignalLabelSchema = z.object({
|
|
257
|
-
id: z.string().min(1).max(255),
|
|
258
|
-
conversation_id: z.string().min(1).max(255),
|
|
259
|
-
label: z.enum(SIGNAL_LABELS),
|
|
260
|
-
note: z.string().max(2000).optional(),
|
|
261
|
-
msg_index: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).optional()),
|
|
262
|
-
msg_dedup_token: z.string().min(1).max(200).optional()
|
|
263
|
-
});
|
|
264
|
-
var DETECTION_VERDICTS = ["correct", "false_positive", "clear"];
|
|
265
|
-
var DetectionReviewSchema = z.object({
|
|
266
|
-
id: z.string().regex(UUID_RE, "Problem id must be a canonical UUID"),
|
|
267
|
-
conversation_id: z.string().min(1).max(255),
|
|
268
|
-
attribution_id: z.string().regex(UUID_RE, "Attribution id must be a UUID"),
|
|
269
|
-
verdict: z.enum(DETECTION_VERDICTS),
|
|
270
|
-
note: z.string().max(2000).optional()
|
|
271
|
-
});
|
|
272
|
-
var FALSE_POSITIVE_KINDS = ["problem", "problem-detection", "quote", "tool", "laziness", "hallucination", "custom-signal"];
|
|
273
|
-
var FalsePositiveSchema = z.object({
|
|
274
|
-
kind: z.enum(FALSE_POSITIVE_KINDS),
|
|
275
|
-
target: z.string().min(1).max(255),
|
|
276
|
-
undo: z.boolean(),
|
|
277
|
-
reason: z.string().max(2000).optional(),
|
|
278
|
-
conversation_id: z.string().min(1).max(255).optional(),
|
|
279
|
-
attribution_id: z.string().regex(UUID_RE, "Attribution id must be a UUID").optional(),
|
|
280
|
-
family: z.string().regex(/^[a-z_]{1,64}$/, "Family must be a lowercase emotion family").optional(),
|
|
281
|
-
turn: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).optional()),
|
|
282
|
-
quote: z.string().min(1).max(4000).optional(),
|
|
283
|
-
tool: z.string().min(1).max(255).optional(),
|
|
284
|
-
tool_use_id: z.string().min(1).max(255).optional(),
|
|
285
|
-
msg_index: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).optional()),
|
|
286
|
-
msg_dedup_token: z.string().min(1).max(200).optional()
|
|
287
|
-
}).superRefine((v, ctx) => {
|
|
288
|
-
const need = (ok, message) => {
|
|
289
|
-
if (!ok)
|
|
290
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message });
|
|
291
|
-
};
|
|
292
|
-
if (v.kind === "problem") {
|
|
293
|
-
need(UUID_RE.test(v.target), "Problem id must be a canonical UUID");
|
|
294
|
-
need(!v.undo, "A problem dismissal cannot be undone from the CLI");
|
|
295
|
-
}
|
|
296
|
-
if (v.kind === "problem-detection") {
|
|
297
|
-
need(UUID_RE.test(v.target), "Problem id must be a canonical UUID");
|
|
298
|
-
need(v.conversation_id, "--conversation-id is required for problem-detection");
|
|
299
|
-
need(v.attribution_id, "--attribution-id is required for problem-detection");
|
|
300
|
-
}
|
|
301
|
-
if (v.kind === "quote") {
|
|
302
|
-
need(v.family && v.turn !== undefined && v.quote, "--family, --turn and --quote are required for quote (copy them from moda emotions)");
|
|
303
|
-
}
|
|
304
|
-
if (v.kind === "tool") {
|
|
305
|
-
need(v.tool, "--tool is required for tool (the failing tool name)");
|
|
306
|
-
need(v.tool_use_id || v.msg_index !== undefined, "--tool-use-id or --msg-index is required for tool (from moda tool-failure-detail)");
|
|
307
|
-
}
|
|
308
|
-
if (v.kind === "custom-signal") {
|
|
309
|
-
need(v.conversation_id, "--conversation-id is required for custom-signal");
|
|
310
|
-
}
|
|
311
|
-
});
|
|
312
|
-
var EMOTION_FAMILIES = [
|
|
313
|
-
"frustration",
|
|
314
|
-
"disapproval",
|
|
315
|
-
"sadness",
|
|
316
|
-
"confusion",
|
|
317
|
-
"anxiety",
|
|
318
|
-
"trust",
|
|
319
|
-
"positive"
|
|
320
|
-
];
|
|
321
|
-
var EmotionsSchema = z.object({
|
|
322
|
-
days_back: daysBackFlag(7),
|
|
323
|
-
limit: z.number().min(1).max(20).default(10).optional(),
|
|
324
|
-
offset: z.number().min(0).max(1e4).optional(),
|
|
325
|
-
family: z.enum(EMOTION_FAMILIES).optional(),
|
|
326
|
-
user_id: z.string().min(1).max(256).optional(),
|
|
327
|
-
conversation_id: z.string().min(1).max(256).optional(),
|
|
328
|
-
include_window: boolFlag()
|
|
329
|
-
});
|
|
330
|
-
var HallucinationsSchema = z.object({
|
|
331
|
-
days_back: daysBackFlag(7),
|
|
332
|
-
limit: z.number().min(1).max(20).default(10).optional(),
|
|
333
|
-
offset: z.number().min(0).max(1e4).optional(),
|
|
334
|
-
conversation_id: z.string().max(200).optional(),
|
|
335
|
-
kind: z.enum(["contradicted", "verified"]).optional()
|
|
336
|
-
});
|
|
337
|
-
var LAZINESS_FAMILIES = [
|
|
338
|
-
"omission_comment",
|
|
339
|
-
"omission_phrase",
|
|
340
|
-
"stub_body",
|
|
341
|
-
"refusal_prefix",
|
|
342
|
-
"deflection",
|
|
343
|
-
"data_quality_truncation",
|
|
344
|
-
"promise_no_delivery",
|
|
345
|
-
"capability_refusal_here",
|
|
346
|
-
"capability_refusal_verb",
|
|
347
|
-
"error_admission",
|
|
348
|
-
"irreversibility",
|
|
349
|
-
"stall_recheck",
|
|
350
|
-
"diy_handoff",
|
|
351
|
-
"tool_selection",
|
|
352
|
-
"completion",
|
|
353
|
-
"code_artifact",
|
|
354
|
-
"repeated_tool_call",
|
|
355
|
-
"target_overshoot",
|
|
356
|
-
"data_regression"
|
|
357
|
-
];
|
|
358
|
-
var LazinessSchema = z.object({
|
|
359
|
-
days_back: daysBackFlag(7),
|
|
360
|
-
limit: z.number().min(1).max(50).default(10).optional(),
|
|
361
|
-
offset: z.number().min(0).max(1e4).optional(),
|
|
362
|
-
conversation_id: z.string().max(200).optional(),
|
|
363
|
-
family: z.enum(LAZINESS_FAMILIES).optional()
|
|
364
|
-
});
|
|
365
|
-
var StepScoresSchema = z.object({
|
|
366
|
-
conversation_id: z.string().min(1)
|
|
367
|
-
});
|
|
368
|
-
var TAIL_SIGNALS = ["traces", "conversations", "emotions", "all"];
|
|
369
|
-
var TailSchema = z.object({
|
|
370
|
-
interval: z.number().min(5).max(3600).default(15).optional(),
|
|
371
|
-
signal: z.enum(TAIL_SIGNALS).default("traces").optional(),
|
|
372
|
-
once: boolFlag(),
|
|
373
|
-
limit: z.number().min(1).max(50).default(20).optional(),
|
|
374
|
-
max_events: z.number().min(1).max(1e5).optional(),
|
|
375
|
-
full_scan: boolFlag()
|
|
376
|
-
});
|
|
377
|
-
var ToolFailureDetailSchema = z.object({
|
|
378
|
-
tool_name: z.string(),
|
|
379
|
-
subtype: z.string().optional(),
|
|
380
|
-
days_back: daysBackFlag(7),
|
|
381
|
-
limit: z.number().min(1).max(20).default(5).optional(),
|
|
382
|
-
offset: z.number().min(0).default(0).optional(),
|
|
383
|
-
include_window: boolFlag(),
|
|
384
|
-
compact: boolFlag(),
|
|
385
|
-
window: z.number().min(1).max(5).default(1).optional()
|
|
386
|
-
});
|
|
387
|
-
var AuditSchema = z.object({
|
|
388
|
-
id: z.string().min(1),
|
|
389
|
-
kind: z.enum(["auto", "trace", "conversation"]).default("auto").optional(),
|
|
390
|
-
include_raw: boolFlag(),
|
|
391
|
-
include_bodies: boolFlag(),
|
|
392
|
-
limit: z.number().min(1).max(1000).default(200).optional(),
|
|
393
|
-
cursor: z.string().min(1).max(512).optional(),
|
|
394
|
-
ids_from: z.string().min(1).optional()
|
|
395
|
-
});
|
|
396
|
-
var TIME_RANGES = ["all", "1h", "3d", "7d", "24h", "30d", "90d"];
|
|
397
|
-
var SEARCH_MODES = ["keyword", "semantic", "hybrid"];
|
|
398
|
-
var SearchSchema = z.object({
|
|
399
|
-
q: z.string().min(1).max(500),
|
|
400
|
-
mode: z.enum(SEARCH_MODES).default("hybrid").optional(),
|
|
401
|
-
user_id: z.string().optional(),
|
|
402
|
-
conversation_id: z.string().min(1).max(256).optional(),
|
|
403
|
-
time_range: z.enum(TIME_RANGES).default("all").optional(),
|
|
404
|
-
limit: z.number().min(1).max(100).default(20).optional(),
|
|
405
|
-
include_tool_io: boolFlag(),
|
|
406
|
-
offset: z.number().min(0).max(1e4).optional()
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
// ../../packages/database/src/agent-feedback.ts
|
|
410
|
-
var FEEDBACK_CATEGORIES = [
|
|
411
|
-
"bad_cluster_label",
|
|
412
|
-
"mismatched_frustration",
|
|
413
|
-
"missing_data",
|
|
414
|
-
"noisy_data",
|
|
415
|
-
"wrong_tool_failure",
|
|
416
|
-
"incorrect_loop",
|
|
417
|
-
"api_quirk",
|
|
418
|
-
"false_positive_attribution",
|
|
419
|
-
"misrouted_fix",
|
|
420
|
-
"harness_bug",
|
|
421
|
-
"other"
|
|
422
|
-
];
|
|
423
|
-
var FEEDBACK_SEVERITIES = ["info", "low", "medium", "high"];
|
|
424
|
-
var DEFAULT_FEEDBACK_CATEGORY = "other";
|
|
425
|
-
var RAW_FEEDBACK_CATEGORY_MAX = 64;
|
|
426
|
-
function isFeedbackCategory(value) {
|
|
427
|
-
return typeof value === "string" && FEEDBACK_CATEGORIES.includes(value);
|
|
428
|
-
}
|
|
429
|
-
function normalizeFeedbackCategory(value) {
|
|
430
|
-
if (value === undefined || value === null || value === "")
|
|
431
|
-
return { category: DEFAULT_FEEDBACK_CATEGORY };
|
|
432
|
-
if (isFeedbackCategory(value))
|
|
433
|
-
return { category: value };
|
|
434
|
-
const raw = String(value).trim().slice(0, RAW_FEEDBACK_CATEGORY_MAX);
|
|
435
|
-
return raw ? { category: DEFAULT_FEEDBACK_CATEGORY, raw_category: raw } : { category: DEFAULT_FEEDBACK_CATEGORY };
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// src/feedback.ts
|
|
439
|
-
var FEEDBACK_FLAGS = ["category", "severity", "note", "cluster-id", "conversation-id", "run-id", "tool-name"];
|
|
440
|
-
var FEEDBACK_USAGE = `Usage: moda feedback "<note>" [--category=${FEEDBACK_CATEGORIES.join("|")}] ` + `[--severity=${FEEDBACK_SEVERITIES.join("|")}] [--conversation-id=ID] [--cluster-id=ID] ` + "[--tool-name=NAME] [--run-id=ID] [--<name>-id=ID]";
|
|
441
|
-
var NOTE_MAX = 4000;
|
|
442
|
-
var REF_VALUE_MAX = 256;
|
|
443
|
-
var REF_FLAG_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*-(?:id|ids|index|token)$/;
|
|
444
|
-
var REF_FLAG_WORDS = new Set(["turn", "tool", "family", "kind"]);
|
|
445
|
-
function isFeedbackRefFlag(flag) {
|
|
446
|
-
return REF_FLAG_PATTERN.test(flag) || REF_FLAG_WORDS.has(flag);
|
|
447
|
-
}
|
|
448
|
-
function feedbackCategoryHelp(indent = 35, width = 100) {
|
|
449
|
-
const lines = [];
|
|
450
|
-
let line = "";
|
|
451
|
-
FEEDBACK_CATEGORIES.forEach((category, index) => {
|
|
452
|
-
const piece = index < FEEDBACK_CATEGORIES.length - 1 ? `${category}|` : `${category} (default other)`;
|
|
453
|
-
if (line && indent + line.length + piece.length > width) {
|
|
454
|
-
lines.push(line);
|
|
455
|
-
line = "";
|
|
456
|
-
}
|
|
457
|
-
line += piece;
|
|
458
|
-
});
|
|
459
|
-
lines.push(line);
|
|
460
|
-
return lines.join(`
|
|
461
|
-
${" ".repeat(indent)}`);
|
|
462
|
-
}
|
|
463
|
-
function buildFeedbackRequest(positionals, flags, bareFlags) {
|
|
464
|
-
const isBare = (flag) => bareFlags ? bareFlags.includes(flag) : flags[flag] === "true";
|
|
465
|
-
const flagNote = flags.note !== undefined && !isBare("note") ? flags.note.trim() : "";
|
|
466
|
-
const note = [positionals.join(" ").trim(), flagNote].filter(Boolean).join(`
|
|
467
|
-
`);
|
|
468
|
-
if (note === "")
|
|
469
|
-
throw new CliInputError("<note> is required", FEEDBACK_USAGE);
|
|
470
|
-
if (note.length > NOTE_MAX) {
|
|
471
|
-
throw new CliInputError(`<note> is ${note.length} characters; the limit is ${NOTE_MAX}.`, FEEDBACK_USAGE);
|
|
472
|
-
}
|
|
473
|
-
const severity = flags.severity ?? "low";
|
|
474
|
-
if (!FEEDBACK_SEVERITIES.includes(severity)) {
|
|
475
|
-
throw new CliInputError(`Invalid --severity '${severity}'. Valid severities: ${FEEDBACK_SEVERITIES.join(", ")}.`, FEEDBACK_USAGE);
|
|
476
|
-
}
|
|
477
|
-
const refs = {};
|
|
478
|
-
for (const [flag, value] of Object.entries(flags)) {
|
|
479
|
-
if (flag === "category" || flag === "severity" || flag === "note")
|
|
480
|
-
continue;
|
|
481
|
-
if (!FEEDBACK_FLAGS.includes(flag) && !isFeedbackRefFlag(flag))
|
|
482
|
-
continue;
|
|
483
|
-
const trimmed = value.trim();
|
|
484
|
-
if (value === "true" || trimmed === "") {
|
|
485
|
-
throw new CliInputError(`--${flag} needs a value, e.g. --${flag}=<id>.`, FEEDBACK_USAGE);
|
|
486
|
-
}
|
|
487
|
-
if (trimmed.length > REF_VALUE_MAX) {
|
|
488
|
-
throw new CliInputError(`--${flag} is ${trimmed.length} characters; the limit is ${REF_VALUE_MAX}.`, FEEDBACK_USAGE);
|
|
489
|
-
}
|
|
490
|
-
refs[flag.replace(/-/g, "_")] = trimmed;
|
|
491
|
-
}
|
|
492
|
-
const warnings = [];
|
|
493
|
-
const { category, raw_category: rawCategory } = normalizeFeedbackCategory(flags.category);
|
|
494
|
-
if (rawCategory !== undefined) {
|
|
495
|
-
refs.raw_category = rawCategory;
|
|
496
|
-
warnings.push(`Unknown category '${rawCategory}': sent as 'other' with refs.raw_category. ` + `Valid categories: ${FEEDBACK_CATEGORIES.join(", ")}.`);
|
|
497
|
-
}
|
|
498
|
-
const hint = dedicatedCommandHint(category, rawCategory);
|
|
499
|
-
if (hint)
|
|
500
|
-
warnings.push(hint);
|
|
501
|
-
return { category, severity, note, refs, warnings };
|
|
502
|
-
}
|
|
503
|
-
var MISROUTE_CATEGORIES = new Set(["false_positive_attribution", "misrouted_fix"]);
|
|
504
|
-
var MISROUTE_WORDS = /attribut|misrout|false[\s_-]?positive|wrong[\s_-]?(?:problem|fix)/i;
|
|
505
|
-
function dedicatedCommandHint(category, rawCategory) {
|
|
506
|
-
if (!MISROUTE_CATEGORIES.has(category) && !(rawCategory && MISROUTE_WORDS.test(rawCategory)))
|
|
507
|
-
return;
|
|
508
|
-
return "Feedback is read by the Moda team but does not change the problem. To act on it directly, use " + "`moda problem-feedback <problem_id> --action=flag_attribution --attribution-id=<uuid> --reason=TEXT` (a trace wrongly " + "attributed to a problem), `moda false-positive <kind> <target> --reason=TEXT` (a detection that should not " + "have fired), or `moda fix dismiss <fix_id> --reason=TEXT` (a fix aimed at the wrong problem).";
|
|
509
|
-
}
|
|
510
119
|
|
|
511
120
|
// src/replays.ts
|
|
512
121
|
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -706,7 +315,7 @@ var SEARCH_SURFACE_BY_COMMAND = {
|
|
|
706
315
|
"world-state": "world_state",
|
|
707
316
|
context: "context"
|
|
708
317
|
};
|
|
709
|
-
var
|
|
318
|
+
var SEARCH_MODES = ["keyword", "semantic", "hybrid"];
|
|
710
319
|
function termCount(query2) {
|
|
711
320
|
return query2.trim().split(/\s+/).filter(Boolean).length;
|
|
712
321
|
}
|
|
@@ -738,7 +347,7 @@ function buildSearchAdoptionTelemetry(input) {
|
|
|
738
347
|
}
|
|
739
348
|
if (command === "search") {
|
|
740
349
|
const requested = (flags.mode ?? "").toLowerCase();
|
|
741
|
-
adoption.search_mode_requested =
|
|
350
|
+
adoption.search_mode_requested = SEARCH_MODES.includes(requested) ? requested : "hybrid";
|
|
742
351
|
}
|
|
743
352
|
if (command === "context") {
|
|
744
353
|
adoption.used_msg_index = flags["msg-index"] !== undefined || flags["message-index"] !== undefined ? 1 : 0;
|
|
@@ -1591,12 +1200,7 @@ var PROBLEMS_SUBCOMMAND_HELP = [
|
|
|
1591
1200
|
name: "remainder",
|
|
1592
1201
|
description: "Signals no Problem explains yet, grouped by family (read-only)",
|
|
1593
1202
|
usage: "moda problems remainder [--family=<family>] [--days-back=N] [--limit=N] [--cursor=<token>]",
|
|
1594
|
-
flags:
|
|
1595
|
-
{ name: "--family=<family>", description: "One of tool_failure, emotion, laziness, hallucination, prm_dip, custom_signal, conversation_reader (frustration is under emotion)." },
|
|
1596
|
-
{ name: "--days-back=<n>", description: "Window in days, 1-90 (default 30)." },
|
|
1597
|
-
{ name: "--limit=<n>", description: "Groups per page, 1-25 (default 25)." },
|
|
1598
|
-
{ name: "--cursor=<token>", description: "The next_cursor from the previous page, verbatim." }
|
|
1599
|
-
],
|
|
1203
|
+
flags: subcommandHelpFlags(COMMAND_FLAG_SPECS.problems.subcommands.remainder),
|
|
1600
1204
|
examples: ["moda problems remainder", "moda problems remainder --family=emotion --days-back=7"]
|
|
1601
1205
|
}
|
|
1602
1206
|
];
|
|
@@ -1806,6 +1410,23 @@ var agentErrorSchema = {
|
|
|
1806
1410
|
message: { type: "string" },
|
|
1807
1411
|
cause: { type: "string" },
|
|
1808
1412
|
suggested_commands: { type: "array", items: { type: "string" } },
|
|
1413
|
+
field: { type: "string", description: "input_error: the rejected flag (e.g. --days-back) or argument (e.g. <command>)." },
|
|
1414
|
+
allowed: {
|
|
1415
|
+
type: "array",
|
|
1416
|
+
items: { type: "string" },
|
|
1417
|
+
description: "input_error: accepted values for field (enum members, valid flag names, or command names)."
|
|
1418
|
+
},
|
|
1419
|
+
range: {
|
|
1420
|
+
type: "object",
|
|
1421
|
+
additionalProperties: false,
|
|
1422
|
+
description: "input_error: accepted numeric range for field.",
|
|
1423
|
+
properties: { min: { type: "number" }, max: { type: "number" } }
|
|
1424
|
+
},
|
|
1425
|
+
did_you_mean: {
|
|
1426
|
+
type: "array",
|
|
1427
|
+
items: { type: "string" },
|
|
1428
|
+
description: "input_error: closest valid spellings of the rejected flag or command, best first."
|
|
1429
|
+
},
|
|
1809
1430
|
input_request: agentInputRequestSchema,
|
|
1810
1431
|
auth: agentAuthSchema,
|
|
1811
1432
|
blocking: { type: "boolean" }
|
|
@@ -2158,7 +1779,8 @@ function buildManifest(commands) {
|
|
|
2158
1779
|
auth: command.auth,
|
|
2159
1780
|
...command.authNote ? { auth_note: command.authNote } : {},
|
|
2160
1781
|
mutability: command.mutability,
|
|
2161
|
-
exit_codes: exitCodesForCommand(command.name)
|
|
1782
|
+
exit_codes: exitCodesForCommand(command.name),
|
|
1783
|
+
...commandFlagFields(command)
|
|
2162
1784
|
})),
|
|
2163
1785
|
concepts: [
|
|
2164
1786
|
{ term: "tenant", meaning: "A Moda organization/workspace that owns data, prompts, skills, and API keys." },
|
|
@@ -2190,6 +1812,29 @@ function renderManifestHuman(manifest) {
|
|
|
2190
1812
|
].join(`
|
|
2191
1813
|
`);
|
|
2192
1814
|
}
|
|
1815
|
+
function commandFlagFields(command) {
|
|
1816
|
+
const spec = flagSpecFor(command.name);
|
|
1817
|
+
if (spec)
|
|
1818
|
+
return manifestFlagFields(spec);
|
|
1819
|
+
if (command.documentedFlags?.length) {
|
|
1820
|
+
return { flags: command.documentedFlags.map(documentedFlag) };
|
|
1821
|
+
}
|
|
1822
|
+
return {
|
|
1823
|
+
flags_help: command.subcommands?.length ? `moda ${command.name} <subcommand> --help` : `moda ${command.name} --help`
|
|
1824
|
+
};
|
|
1825
|
+
}
|
|
1826
|
+
function documentedFlag(flag) {
|
|
1827
|
+
const [name, value] = flag.name.split("=", 2);
|
|
1828
|
+
const values = value?.split("|");
|
|
1829
|
+
const type = value === undefined ? "boolean" : values && values.length > 1 && values.every((entry) => /^[a-z0-9_-]+$/.test(entry)) ? "enum" : "string";
|
|
1830
|
+
return {
|
|
1831
|
+
name,
|
|
1832
|
+
type,
|
|
1833
|
+
...type === "enum" ? { enum: values } : {},
|
|
1834
|
+
description: flag.description,
|
|
1835
|
+
required: false
|
|
1836
|
+
};
|
|
1837
|
+
}
|
|
2193
1838
|
function event(name, when, terminal, deprecated = false) {
|
|
2194
1839
|
return { name, event_version: 1, when, terminal, ...deprecated ? { deprecated: true } : {} };
|
|
2195
1840
|
}
|
|
@@ -2205,46 +1850,46 @@ function exitCodesForCommand(command) {
|
|
|
2205
1850
|
import { fileURLToPath } from "url";
|
|
2206
1851
|
import { realpathSync } from "fs";
|
|
2207
1852
|
async function runPromptsCommand(...args) {
|
|
2208
|
-
return (await import("./prompts-
|
|
1853
|
+
return (await import("./prompts-1tkhrxkq.js")).runPromptsCommand(...args);
|
|
2209
1854
|
}
|
|
2210
1855
|
async function runSkillsCommand(...args) {
|
|
2211
|
-
return (await import("./skills-
|
|
1856
|
+
return (await import("./skills-d35nnm66.js")).runSkillsCommand(...args);
|
|
2212
1857
|
}
|
|
2213
1858
|
async function runFixCommand(...args) {
|
|
2214
|
-
return (await import("./fix-
|
|
1859
|
+
return (await import("./fix-9fmy6p2x.js")).runFixCommand(...args);
|
|
2215
1860
|
}
|
|
2216
1861
|
async function runFixesCommand(...args) {
|
|
2217
|
-
return (await import("./fix-
|
|
1862
|
+
return (await import("./fix-9fmy6p2x.js")).runFixesCommand(...args);
|
|
2218
1863
|
}
|
|
2219
1864
|
async function runHarnessCommand(...args) {
|
|
2220
|
-
return (await import("./harness-
|
|
1865
|
+
return (await import("./harness-xvg6ws6x.js")).runHarnessCommand(...args);
|
|
2221
1866
|
}
|
|
2222
1867
|
async function runSyncCommand(...args) {
|
|
2223
|
-
return (await import("./sync-
|
|
1868
|
+
return (await import("./sync-n2psdffz.js")).runSyncCommand(...args);
|
|
2224
1869
|
}
|
|
2225
1870
|
async function runRegistryCommand(...args) {
|
|
2226
|
-
return (await import("./registry-
|
|
1871
|
+
return (await import("./registry-atqyb5fa.js")).runRegistryCommand(...args);
|
|
2227
1872
|
}
|
|
2228
1873
|
async function runDoctorCommand(...args) {
|
|
2229
|
-
return (await import("./doctor-
|
|
1874
|
+
return (await import("./doctor-mx6jf435.js")).runDoctorCommand(...args);
|
|
2230
1875
|
}
|
|
2231
1876
|
async function runStatusCommand(...args) {
|
|
2232
|
-
return (await import("./doctor-
|
|
1877
|
+
return (await import("./doctor-mx6jf435.js")).runStatusCommand(...args);
|
|
2233
1878
|
}
|
|
2234
1879
|
async function runAuthCommand(...args) {
|
|
2235
|
-
return (await import("./profile-commands-
|
|
1880
|
+
return (await import("./profile-commands-kmmd9y86.js")).runAuthCommand(...args);
|
|
2236
1881
|
}
|
|
2237
1882
|
async function runConfigCommand(...args) {
|
|
2238
|
-
return (await import("./profile-commands-
|
|
1883
|
+
return (await import("./profile-commands-kmmd9y86.js")).runConfigCommand(...args);
|
|
2239
1884
|
}
|
|
2240
1885
|
async function runProfilesCommand(...args) {
|
|
2241
|
-
return (await import("./profile-commands-
|
|
1886
|
+
return (await import("./profile-commands-kmmd9y86.js")).runProfilesCommand(...args);
|
|
2242
1887
|
}
|
|
2243
1888
|
async function runAgentCommand(...args) {
|
|
2244
|
-
return (await import("./agent-
|
|
1889
|
+
return (await import("./agent-mj622k8s.js")).runAgentCommand(...args);
|
|
2245
1890
|
}
|
|
2246
1891
|
async function runProductionCommand(...args) {
|
|
2247
|
-
return (await import("./production-intelligence-
|
|
1892
|
+
return (await import("./production-intelligence-dbe9dmc5.js")).runProductionCommand(...args);
|
|
2248
1893
|
}
|
|
2249
1894
|
function parseArgs(argv) {
|
|
2250
1895
|
const args = argv.slice(2);
|
|
@@ -2449,401 +2094,101 @@ function buildResumeCommand(command, flags) {
|
|
|
2449
2094
|
function printHelp() {
|
|
2450
2095
|
console.log(`Usage: moda <command> [options]
|
|
2451
2096
|
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
auth logout Clear cached Moda auth
|
|
2464
|
-
auth whoami Show the authenticated Moda identity (session or API key)
|
|
2465
|
-
profiles list List local Moda profiles
|
|
2466
|
-
profiles use <name> Switch active Moda profile
|
|
2467
|
-
profiles create <name> Create or update a local Moda profile
|
|
2468
|
-
profiles doctor [name] Validate a local Moda profile
|
|
2469
|
-
config show Show resolved Moda config
|
|
2470
|
-
harness analyze Produce a cited structured harness report
|
|
2471
|
-
harness pull Fetch a server-side analyze run (status, or result when done)
|
|
2472
|
-
harness validate-report Validate .moda/harness-report.json citations
|
|
2473
|
-
harness approve Approve a validated harness report for sync
|
|
2474
|
-
harness scan Discover local runtime agents and write .moda/harness.json
|
|
2475
|
-
harness candidates Static (no-LLM) harness candidate pre-pass with file:line citations
|
|
2476
|
-
harness sync Sync the local harness graph to Moda Cloud
|
|
2477
|
-
harness delete <id-or-key> Permanently delete a synced harness from Moda Cloud
|
|
2478
|
-
harness list|show|versions|diff List synced harnesses, show one, its versions, or a version diff
|
|
2479
|
-
harness register [name] Bundle this repo for Replay Environments and upload it (--dry-run to review)
|
|
2480
|
-
harness registration list|status List registrations, or show one with what Moda still needs
|
|
2481
|
-
harness agents List detected runtime agents and families
|
|
2482
|
-
harness explain Explain the discovered harness graph
|
|
2483
|
-
agent context Emit local Moda context for coding agents
|
|
2484
|
-
agent next-action Emit prioritized next commands for agents
|
|
2485
|
-
agent evidence <ref> Expand one evidence reference
|
|
2097
|
+
Start here (goal -> command):
|
|
2098
|
+
find something in traces moda search "<query>" (whole traces: moda traces --search=TEXT)
|
|
2099
|
+
read one trace moda context <conversation_id> (whole trace: --all)
|
|
2100
|
+
what is broken moda overview, then moda problems
|
|
2101
|
+
tool errors moda tool-failures, then moda tool-failure-detail <tool_name>
|
|
2102
|
+
user emotion and frustration moda emotions
|
|
2103
|
+
raw spans for one trace moda audit <conversation_id|trace_id>
|
|
2104
|
+
every flag of a command moda <command> --help (all commands and flags: moda manifest --json)
|
|
2105
|
+
|
|
2106
|
+
Production data:
|
|
2107
|
+
overview Harness health briefing with production signals
|
|
2486
2108
|
investigate Rank production issues (tool failures, frustrations, top Problems)
|
|
2487
2109
|
failures Tool failures only, ranked (no frustrations or Problems)
|
|
2488
|
-
ask "question"
|
|
2489
|
-
sync Sync the local harness graph to Moda Cloud
|
|
2490
|
-
sync harness Sync the local harness graph to Moda Cloud
|
|
2491
|
-
sync prompts Sync prompt versions to Moda Cloud
|
|
2492
|
-
doctor --json Emit structured diagnostic checks
|
|
2493
|
-
status --json Emit concise setup state
|
|
2494
|
-
manifest --json Emit the CLI machine protocol manifest
|
|
2495
|
-
overview Harness health briefing with production signals
|
|
2496
|
-
clusters Browse topic cluster hierarchy
|
|
2497
|
-
cluster-traces <node_id> List traces in a cluster
|
|
2498
|
-
traces Search and filter traces (agent runs)
|
|
2499
|
-
traces --sort=longest Sort traces: recent (default), longest, slowest
|
|
2110
|
+
ask "<question>" Ask Moda a production question (one paid agent run)
|
|
2500
2111
|
search "<query>" Search trace messages (keyword/semantic/hybrid)
|
|
2501
|
-
|
|
2502
|
-
context <conversation_id>
|
|
2503
|
-
context <conversation_id> --all Whole transcript in order (first 500; --from=N --max-messages=N to continue)
|
|
2112
|
+
traces Search and filter traces (agent runs)
|
|
2113
|
+
context <conversation_id> Messages around one turn, or the whole trace with --all
|
|
2504
2114
|
context <id>[@N] <id>[@N] ... Batch: up to 25 traces in one call (or --ids-from=-|<file>)
|
|
2505
2115
|
audit <conversation_id|trace_id> Raw span audit (spans, hierarchy, orphans, duplicates)
|
|
2506
2116
|
audit <id> <id> ... Batch audit: up to 25 ids in one call (or --ids-from=-|<file>)
|
|
2117
|
+
world-state <conversation_id> A trace's world state (slots, threads, events)
|
|
2118
|
+
clusters Browse or search topic clusters
|
|
2119
|
+
cluster-traces <node_id> List traces in a cluster
|
|
2120
|
+
users / user <user_id> End users with health and activity (the dashboard Users page)
|
|
2121
|
+
tail Live-tail new traces/detections as NDJSON (one line per item)
|
|
2122
|
+
|
|
2123
|
+
Detections:
|
|
2124
|
+
emotions Emotion detections (frustration, disapproval, confusion, ...)
|
|
2507
2125
|
frustrations Frustration detections (same data as emotions --family=frustration)
|
|
2508
|
-
|
|
2509
|
-
hallucinations Grounding detections: contradicted/verified outputs with rule breakdown
|
|
2126
|
+
hallucinations Grounding detections: contradicted/verified outputs
|
|
2510
2127
|
laziness Laziness detections per trace (repeated calls, premature handoffs, ...)
|
|
2511
|
-
tool-failures
|
|
2512
|
-
tool-failure-detail <tool_name>
|
|
2128
|
+
tool-failures Tool failure overview
|
|
2129
|
+
tool-failure-detail <tool_name> Per-tool failure examples
|
|
2130
|
+
|
|
2131
|
+
Problems, signals and review:
|
|
2513
2132
|
problems Rank cross-signal Problems by root cause (what to fix first)
|
|
2514
|
-
|
|
2515
|
-
problem-impact Live problem/use-case impact
|
|
2516
|
-
problem <problem_id> Open one Problem: dossier, or --evidence/--reports/--traces/--feedback
|
|
2133
|
+
problem <problem_id> One Problem: dossier, or its evidence/reports/traces/feedback
|
|
2134
|
+
problem-impact Live problem/use-case impact, trend and evidence
|
|
2517
2135
|
problem-feedback <problem_id> Mark a Problem fixed, dismiss, rename, or flag a bad attribution
|
|
2518
|
-
problem-reopen <problem_id> Reopen a Problem marked fixed
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
problem-linear <problem_id> Show the Linear issue linked to a Problem (key, state, URL)
|
|
2522
|
-
problem-linear-file <problem_id> File a Problem as a Linear issue, or link an existing one (--issue)
|
|
2136
|
+
problem-reopen <problem_id> Reopen a Problem marked fixed
|
|
2137
|
+
problem-linear <problem_id> Show the Linear issue linked to a Problem
|
|
2138
|
+
problem-linear-file <problem_id> File a Problem as a Linear issue, or link an existing one
|
|
2523
2139
|
detection-reviews <conv_id> Problem detections on a trace with their review state
|
|
2524
|
-
detection-review <problem_id> Mark a problem detection correct, a false positive, or clear
|
|
2525
|
-
|
|
2140
|
+
detection-review <problem_id> Mark a problem detection correct, a false positive, or clear it
|
|
2141
|
+
false-positive <kind> <target> Mark any detection as a false positive
|
|
2142
|
+
false-positives [conv_id] Current false-positive marks (workspace or one trace)
|
|
2143
|
+
signals List and manage custom signals
|
|
2526
2144
|
signal <signal_id> One custom signal, or --detections for its recent hits
|
|
2527
|
-
signals create|update|activate|pause|delete ...
|
|
2528
|
-
Manage custom signals (also draft, examples, refine, revise,
|
|
2529
|
-
proposals, accept, reject, search, preview); writes take --dry-run
|
|
2530
|
-
users / user <user_id> End users with health and activity (the dashboard Users page)
|
|
2531
2145
|
trace-signals <conversation_id> Custom signal hits on one trace
|
|
2532
2146
|
signal-label <signal_id> Label a trace fits / does_not_fit (false positive) for a signal
|
|
2533
|
-
tail Live-tail new traces/detections as NDJSON (one line per item)
|
|
2534
2147
|
feedback "<note>" Flag wrong/missing data or CLI quirks to the Moda team
|
|
2535
2148
|
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
prompts sync --watch Upload again when prompt files change
|
|
2547
|
-
prompts list|show|proposals|usage|replay-runs|decide
|
|
2548
|
-
Read the prompt registry; decide merges/rejects a proposal
|
|
2549
|
-
prompts promote <key> Move a dev/staging/prod label
|
|
2550
|
-
prompts ab Run a judged prompt A/B replay experiment
|
|
2551
|
-
prompts propose Revise a prompt from a run's failures (--gate to auto-A/B, --promote-on-win)
|
|
2552
|
-
|
|
2553
|
-
Replays (read-only results):
|
|
2554
|
-
replays sets List replay sets
|
|
2555
|
-
replays runs <set_id> Run history for a set (every status)
|
|
2556
|
-
replays run <set_id> <run_id> One run: per-case and per-seed verdicts, playout count
|
|
2557
|
-
replays playouts <set_id> <run_id>
|
|
2558
|
-
Playouts per case/arm/seed (--transcript inlines messages and tool calls)
|
|
2559
|
-
replays playout <set_id> <run_id> <playout_id>
|
|
2560
|
-
One playout transcript
|
|
2561
|
-
|
|
2562
|
-
Skills:
|
|
2563
|
-
skills gen Kick off tenant-wide skill generation
|
|
2564
|
-
skills status [run-id] Show a generation run's status, outcome, and recent events (default: latest run)
|
|
2565
|
-
skills pull Pull tenant-generated skills into .claude/skills (and .cursor/rules)
|
|
2566
|
-
skills install <id...> Install bundled integration guides into .claude/skills (--list to browse)
|
|
2567
|
-
skills pull --status=proposed Include not-yet-promoted skills (default: approved)
|
|
2568
|
-
skills sync Push local .claude/skills/**/SKILL.md up to Moda
|
|
2569
|
-
skills sync --dry-run Show what would be pushed without writing
|
|
2570
|
-
skills list|show|policy List pushed skills, show one, or set --live/--local
|
|
2571
|
-
registry push Push prompts, skills, tools, and agent wiring from one JSON manifest
|
|
2572
|
-
|
|
2573
|
-
Options:
|
|
2574
|
-
--help Show this help message
|
|
2575
|
-
--version Show version number
|
|
2576
|
-
--json-schemas Print JSON Schemas for the agent output contract
|
|
2577
|
-
|
|
2578
|
-
Common flags (a command rejects any it does not take; see 'moda <command> --help'):
|
|
2579
|
-
--days-back=N Whole days to look back, 1-90 (overview, problems, emotions, laziness, tool-failures, ...)
|
|
2580
|
-
--time-range=RANGE Window for traces, search, clusters instead (all|1h|3d|7d|24h|30d|90d)
|
|
2581
|
-
--limit=N Maximum results to return (users: alias of --page-size)
|
|
2582
|
-
--offset=N Number of results to skip (paged lists)
|
|
2583
|
-
--profile=NAME Use a named local Moda profile
|
|
2584
|
-
--json Emit machine-readable JSON
|
|
2585
|
-
--agent Emit schema-versioned agent JSON
|
|
2586
|
-
--stream With --agent, emit NDJSON agent events
|
|
2587
|
-
--human Force human prose (overrides auto-detection)
|
|
2588
|
-
--no-stream Disable live ask progress (buffered request)
|
|
2589
|
-
|
|
2590
|
-
Output auto-detection (no flags needed):
|
|
2591
|
-
Piped/redirected stdout, CI, or an agent env (CLAUDECODE/CURSOR/MODA_AGENT)
|
|
2592
|
-
=> schema-versioned agent JSON. An interactive terminal => human prose.
|
|
2593
|
-
Override with the flags above or MODA_FORMAT=human|json|agent|agent-stream.
|
|
2594
|
-
Exit codes: 0 ok, 1 error (errors[0].code says which, e.g. not_found), 3 degraded (local fallback),
|
|
2595
|
-
4 auth required (no key or key rejected), 5 input required, 130 cancelled.
|
|
2596
|
-
--dry-run Show the planned mutation when supported
|
|
2597
|
-
--yes Accept explicit automation defaults
|
|
2598
|
-
--tui Force the human analyst dashboard when supported
|
|
2599
|
-
--no-tui Show raw analyst stream instead of dashboard
|
|
2600
|
-
--no-update-check Skip the daily new-version check (or MODA_CLI_UPDATE_CHECK=0)
|
|
2601
|
-
|
|
2602
|
-
Traces flags:
|
|
2603
|
-
--search=TEXT Ranked trace search (hybrid when embeddings exist, else keyword)
|
|
2604
|
-
--world-state=KEYWORDS Match world-state content (slots + durable profile); comma = AND
|
|
2605
|
-
--outcome=any|positive|negative Filter by trace outcome (trajectory + frustration)
|
|
2606
|
-
--include-world-state Attach each result's world-state summary
|
|
2607
|
-
--user-id=ID Filter to a single user
|
|
2608
|
-
--environment=ENV Filter by environment (all|development|staging|production)
|
|
2609
|
-
|
|
2610
|
-
Search flags:
|
|
2611
|
-
--mode=keyword|semantic|hybrid Search mode (default hybrid)
|
|
2612
|
-
--user-id=ID Filter to a single user
|
|
2613
|
-
--conversation-id=ID Search inside one trace only
|
|
2614
|
-
--time-range=RANGE Time range filter (all|1h|3d|7d|24h|30d|90d)
|
|
2615
|
-
--limit=N Maximum results to return (1-100, default 20)
|
|
2616
|
-
|
|
2617
|
-
World-state flags:
|
|
2618
|
-
--summary-only Return segment summaries only (omit the event stream)
|
|
2619
|
-
--event-limit=N Max world-state events to return (1-5000, default 2000)
|
|
2620
|
-
--snapshot Folded slots at an exact tick (what the agent believed at that turn)
|
|
2621
|
-
--msg-index=N --block-index=M Snapshot tick (defaults 0; --segment-index=K scopes to a segment)
|
|
2622
|
-
--replay State-over-time replay; frames mode REQUIRES --message-count=N
|
|
2623
|
-
--format=frames|fold-inputs Replay format (default frames)
|
|
2624
|
-
--message-count=N Number of frames to fold (frames mode)
|
|
2625
|
-
|
|
2626
|
-
Emotions flags:
|
|
2627
|
-
--family=F frustration|disapproval|sadness|confusion|anxiety|trust|positive
|
|
2628
|
-
--days-back=N --limit=N Window 1-90 (default 7); page size 1-20 (default 10)
|
|
2629
|
-
--offset=N Skip N detections (0-10000)
|
|
2630
|
-
--include-window Keep each detection's conversation window in agent output
|
|
2631
|
-
(also frustrations; omitted by default, use context_command)
|
|
2632
|
-
|
|
2633
|
-
Laziness flags:
|
|
2634
|
-
--family=F One laziness family (e.g. omission_phrase, stub_body, deflection, completion, tool_selection)
|
|
2635
|
-
--conversation-id=ID One trace's detections
|
|
2636
|
-
--days-back=N --limit=N Window 1-90 (default 7); page size 1-50 (default 10)
|
|
2637
|
-
|
|
2638
|
-
Hallucinations flags:
|
|
2639
|
-
--kind=contradicted|verified Narrow the detections list
|
|
2640
|
-
--conversation-id=ID Scope summary + list to one trace ID
|
|
2641
|
-
--days-back=N --limit=N Window 1-90 (default 7); page size 1-20 (default 10)
|
|
2642
|
-
|
|
2643
|
-
Problem flags (moda problem <id>):
|
|
2644
|
-
--full Whole dossier in agent output (default there: header, summary,
|
|
2645
|
-
top 5 evidence anchors, report titles)
|
|
2646
|
-
--evidence|--reports|--traces|--feedback
|
|
2647
|
-
Open one sub-resource page (at most one)
|
|
2648
|
-
--limit=N --cursor=TOKEN Keyset paging (1-50; pass next_cursor back verbatim)
|
|
2649
|
-
--family=F --door=D Filter --traces (families: tool_failure|emotion|laziness|hallucination|prm_dip|custom_signal|conversation_reader)
|
|
2650
|
-
|
|
2651
|
-
Problem-feedback flags:
|
|
2652
|
-
--action=A mark_fixed|dismiss|flag_attribution|rename (required)
|
|
2653
|
-
--reason=TEXT Required for flag_attribution; optional for dismiss
|
|
2654
|
-
--attribution-id=UUID Required for flag_attribution (ids come from problem --evidence)
|
|
2655
|
-
--new-name=NAME Required for rename
|
|
2656
|
-
|
|
2657
|
-
False-positive flags (moda false-positive <kind> <target>):
|
|
2658
|
-
--reason=TEXT Why it is wrong (optional)
|
|
2659
|
-
--undo Remove an earlier mark (every kind except problem)
|
|
2660
|
-
problem <problem_id> Dismiss the problem: hidden at once, logged for review, folded into reconcile
|
|
2661
|
-
problem-detection <problem_id> One detection on a trace; needs --conversation-id and --attribution-id; teaches the problem
|
|
2662
|
-
quote <conversation_id> A user quote; needs --family, --turn and --quote (from moda emotions); audit only
|
|
2663
|
-
tool <conversation_id> One failing tool call; needs --tool and --tool-use-id (or --msg-index); audit only
|
|
2664
|
-
laziness <conversation_id> Laziness on that trace; audit only
|
|
2665
|
-
hallucination <conversation_id> Hallucinations on that trace; audit only
|
|
2666
|
-
custom-signal <signal_id> A hit on that trace (--conversation-id); saved as does_not_fit, a labelled counterexample for the signal
|
|
2667
|
-
|
|
2668
|
-
Problem-linear-file flags (needs Linear connected: Integrations -> Linear):
|
|
2669
|
-
--issue=ENG-123|URL Link an existing Linear issue instead of filing a new one
|
|
2670
|
-
--team-id=ID File into this Linear team (default: the integration's default team)
|
|
2671
|
-
--title=TEXT Issue title (default: the Problem's name)
|
|
2672
|
-
--priority=N 0 none, 1 urgent, 2 high, 3 medium, 4 low
|
|
2673
|
-
--issue excludes --team-id/--title/--priority
|
|
2674
|
-
|
|
2675
|
-
Detection-review flags (moda detection-review <problem_id>):
|
|
2676
|
-
--conversation-id=ID Trace the detection is on (required)
|
|
2677
|
-
--attribution-id=UUID Detection id (from problem --evidence or detection-reviews; required)
|
|
2678
|
-
--verdict=V correct|false_positive|clear (required; clear undoes a review)
|
|
2679
|
-
--note=TEXT Why (optional; kept with the review)
|
|
2680
|
-
|
|
2681
|
-
Signal flags:
|
|
2682
|
-
--detections moda signal <id>: list recent hits instead of the summary
|
|
2683
|
-
--days-back=N --limit=N --offset=N
|
|
2684
|
-
Hits window 1-90 (default 7); page size 1-20 (default 10)
|
|
2685
|
-
|
|
2686
|
-
Signal-label flags (moda signal-label <signal_id>):
|
|
2687
|
-
--conversation-id=ID Trace to label (required)
|
|
2688
|
-
--label=fits|does_not_fit does_not_fit marks a false positive and retracts the hit (required)
|
|
2689
|
-
--note=TEXT Why (recommended for does_not_fit)
|
|
2690
|
-
--msg-index=N --msg-dedup-token=T
|
|
2691
|
-
Anchor message (from the hit's anchor_msg_index / anchor_dedup_token)
|
|
2692
|
-
|
|
2693
|
-
Tail flags:
|
|
2694
|
-
--signal=S traces|emotions|all (default traces)
|
|
2695
|
-
--interval=N Poll every N seconds (5-3600, default 15)
|
|
2696
|
-
--once One poll, then exit (baseline page)
|
|
2697
|
-
--limit=N --max-events=N Page size per poll; stop after N stdout records
|
|
2698
|
-
(metadata included; a slot is reserved for the
|
|
2699
|
-
emotions coverage record, which falls back to
|
|
2700
|
-
stderr if the bound leaves no room)
|
|
2701
|
-
--full-scan Emotions: scan the whole window instead of the
|
|
2702
|
-
top-scoring prefix (many more requests). /emotions
|
|
2703
|
-
is score-ranked with no cursor, so the default
|
|
2704
|
-
follows the highest-scoring detections and emits a
|
|
2705
|
-
tail_coverage line stating exactly what it saw.
|
|
2706
|
-
|
|
2707
|
-
Clusters search flags:
|
|
2708
|
-
--search="query" Find clusters by name/meaning (task-cluster search)
|
|
2709
|
-
--node-id=ID Deterministically resolve one cluster node (deep link)
|
|
2710
|
-
--mode=fuzzy|semantic|hybrid Cluster search mode (default hybrid)
|
|
2711
|
-
|
|
2712
|
-
Feedback flags:
|
|
2713
|
-
--category=CAT ${feedbackCategoryHelp()}
|
|
2714
|
-
An unknown category is sent as other (with refs.raw_category)
|
|
2715
|
-
--severity=info|low|medium|high How bad it is (default low)
|
|
2716
|
-
--note=TEXT The note, if not given as the positional argument
|
|
2717
|
-
--conversation-id=ID Attach the trace ID you were looking at
|
|
2718
|
-
--cluster-id=ID Attach a cluster node id
|
|
2719
|
-
--tool-name=NAME Attach a tool name
|
|
2720
|
-
--run-id=ID Attach a run id
|
|
2721
|
-
--<name>-id=ID Any other id (--problem-id, --fix-id, --attribution-id,
|
|
2722
|
-
--trace-id, --span-id, --message-index, ...) goes into refs
|
|
2723
|
-
(set MODA_CLI_TIPS=0 to hide the feedback tip line)
|
|
2724
|
-
|
|
2725
|
-
Init flags:
|
|
2726
|
-
--yes Accept all defaults (non-interactive)
|
|
2727
|
-
--analyst=auto|claude|codex|cursor|local-scan
|
|
2728
|
-
Choose harness analyst adapter
|
|
2729
|
-
--analyst-model=MODEL Model for the claude analyst (default: sonnet;
|
|
2730
|
-
"default" = the claude CLI's own default;
|
|
2731
|
-
env: MODA_HARNESS_ANALYST_MODEL)
|
|
2732
|
-
--assist=none Disable agent fallback for prompt discovery
|
|
2733
|
-
--concern=topology|tools|prompts|evals
|
|
2734
|
-
Harness analyze: restrict the pass to one
|
|
2735
|
-
concern (whole repo, one report scope); an
|
|
2736
|
-
orchestrator merges the per-concern reports
|
|
2737
|
-
(env: MODA_HARNESS_CONCERN, flag wins)
|
|
2738
|
-
--allow-no-agents Allow harness sync to push a graph with zero
|
|
2739
|
-
runtime agents despite detected LLM usage
|
|
2740
|
-
--remote Run harness analysis server-side (Moda-hosted,
|
|
2741
|
-
the default): upload a safe source snapshot; no
|
|
2742
|
-
local coding agent required
|
|
2743
|
-
--local Run harness analysis with a LOCAL coding agent
|
|
2744
|
-
instead of server-side (opt out of remote)
|
|
2745
|
-
--tui Show full-screen analyst dashboard in human TTYs
|
|
2746
|
-
--no-tui Show raw external analyst output
|
|
2747
|
-
--sdk-integrate Run your coding agent to install the Moda SDK and instrument LLM calls
|
|
2748
|
-
--no-sdk-integrate Skip SDK integration (alias: --no-sdk-guide)
|
|
2749
|
-
--verification-id=ID Tag the SDK integration's test trace with this id
|
|
2750
|
-
(the onb_ id from the Moda onboarding page)
|
|
2751
|
-
--connect-code=CODE Sign in with the one-time mcc_ code from the Moda
|
|
2752
|
-
onboarding page instead of the browser (10 min, single use)
|
|
2753
|
-
--ci-cd Create GitHub Actions Moda validation workflow
|
|
2754
|
-
--no-ci-cd Skip CI/CD workflow creation
|
|
2755
|
-
--autosync Create GitHub Actions workflow to sync prompts + skills to Moda on push to main
|
|
2756
|
-
--no-autosync Skip autosync workflow creation
|
|
2757
|
-
--harness-rescan Create GitHub Actions workflow to re-scan the harness and sync it to Moda on push to main
|
|
2758
|
-
--no-harness-rescan Skip harness rescan workflow creation
|
|
2759
|
-
--harness-rescan-paths=GLOBS Comma-separated path globs that scope which pushes trigger the
|
|
2760
|
-
harness rescan workflow (implies --harness-rescan)
|
|
2761
|
-
--offline Run final validation offline (skip the online telemetry check)
|
|
2149
|
+
Setup:
|
|
2150
|
+
init Set up Moda in your project
|
|
2151
|
+
provision Headless tenant + API key provisioning (JSON credentials on stdout)
|
|
2152
|
+
auth Log in (browser or --api-key), status, token, whoami, logout
|
|
2153
|
+
status Show concise local Moda setup status
|
|
2154
|
+
doctor Diagnose local Moda setup and data flow
|
|
2155
|
+
profiles List, switch, create and check local profiles
|
|
2156
|
+
config Show resolved Moda config
|
|
2157
|
+
manifest The CLI machine contract: commands, flags, events, exit codes
|
|
2158
|
+
agent Context, next actions and evidence for coding agents
|
|
2762
2159
|
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2160
|
+
Groups with their own subcommands (run 'moda <group> --help'):
|
|
2161
|
+
harness Analyze, scan, validate, approve, sync and register the agent harness
|
|
2162
|
+
prompts Code-first prompt versions: init, status, sync, promote, A/B, propose
|
|
2163
|
+
replays Replay results: sets, runs, playouts and transcripts
|
|
2164
|
+
skills Generate, pull, install and sync agent skills
|
|
2165
|
+
sync Sync the harness graph and prompts to Moda Cloud
|
|
2166
|
+
registry Push prompts, skills, tools and agent wiring from one JSON manifest
|
|
2770
2167
|
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
moda auth whoami
|
|
2775
|
-
moda provision --tenant-id=<org-id>
|
|
2776
|
-
moda status
|
|
2777
|
-
moda manifest --json
|
|
2778
|
-
moda doctor --json
|
|
2779
|
-
moda profiles list
|
|
2780
|
-
moda profiles use staging
|
|
2781
|
-
moda config show --profile=prod
|
|
2782
|
-
moda harness analyze --experimental --summary
|
|
2783
|
-
moda harness analyze --experimental --remote
|
|
2784
|
-
moda harness analyze --experimental --analyst=claude --tui
|
|
2785
|
-
moda harness analyze --experimental --analyst=claude --no-tui
|
|
2786
|
-
moda harness analyze --experimental --analyst=claude --summary
|
|
2787
|
-
moda harness analyze --experimental --analyst=local-scan --summary
|
|
2788
|
-
moda harness pull --sync
|
|
2789
|
-
moda harness validate-report
|
|
2790
|
-
moda harness approve --yes
|
|
2791
|
-
moda harness sync --from-report .moda/harness-report.json
|
|
2792
|
-
moda harness delete my-harness-key --yes
|
|
2793
|
-
moda --agent doctor
|
|
2794
|
-
moda agent context
|
|
2795
|
-
moda agent next-action
|
|
2796
|
-
moda agent evidence doctor:api_key_resolves
|
|
2797
|
-
moda investigate
|
|
2798
|
-
moda failures
|
|
2799
|
-
moda ask "what should I fix first?"
|
|
2800
|
-
moda sync --dry-run
|
|
2801
|
-
moda sync harness --profile=prod
|
|
2802
|
-
moda harness scan --json
|
|
2803
|
-
moda harness candidates --out=.moda/harness-candidates.json
|
|
2804
|
-
moda harness explain --agent=agent_support
|
|
2805
|
-
moda init --ci-cd
|
|
2806
|
-
moda init --autosync
|
|
2807
|
-
moda init --harness-rescan --harness-rescan-paths='src/agents/**'
|
|
2808
|
-
moda overview --days-back=30
|
|
2809
|
-
moda clusters --time-range=7d
|
|
2810
|
-
moda traces --search="error" --limit=5
|
|
2811
|
-
moda traces --world-state="enterprise" --outcome=positive
|
|
2812
|
-
moda traces --world-state="refund,billing" --include-world-state
|
|
2813
|
-
moda search "billing error" --mode=hybrid
|
|
2814
|
-
moda search "refund flow" --mode=semantic --time-range=7d --limit=10
|
|
2815
|
-
moda world-state <conversation_id> --summary-only
|
|
2816
|
-
moda world-state <conversation_id> --snapshot --msg-index=42
|
|
2817
|
-
moda world-state <conversation_id> --replay --message-count=50
|
|
2818
|
-
moda clusters --search="billing disputes"
|
|
2819
|
-
moda emotions --family=confusion --days-back=14
|
|
2820
|
-
moda hallucinations --kind=contradicted
|
|
2821
|
-
moda problems --days-back=7
|
|
2822
|
-
moda problem <problem_id> --evidence --limit=10
|
|
2823
|
-
moda problem-feedback <problem_id> --action=mark_fixed
|
|
2824
|
-
moda problem-linear <problem_id>
|
|
2825
|
-
moda problem-linear-file <problem_id> --priority=2
|
|
2826
|
-
moda detection-reviews <conversation_id>
|
|
2827
|
-
moda detection-review <problem_id> --conversation-id=<id> --attribution-id=<uuid> --verdict=false_positive --note="expected retry"
|
|
2828
|
-
moda signals
|
|
2829
|
-
moda signal <signal_id> --detections --days-back=30
|
|
2830
|
-
moda signal-label <signal_id> --conversation-id=<id> --label=does_not_fit --note="refund was approved"
|
|
2831
|
-
moda tail --signal=all --interval=30
|
|
2832
|
-
moda frustrations --days-back=14 --limit=20
|
|
2833
|
-
moda feedback "cluster label looks wrong" --category=bad_cluster_label --cluster-id=<node_id>
|
|
2834
|
-
moda context <conversation_id> --window=3
|
|
2835
|
-
moda audit <conversation_id|trace_id>
|
|
2836
|
-
moda audit <trace_id> --kind=trace --json
|
|
2837
|
-
moda prompts status
|
|
2838
|
-
moda prompts sync
|
|
2839
|
-
moda prompts promote support.triage --label=prod --version=pver_abc123
|
|
2840
|
-
moda prompts ab --baseline=prompts/agent.prompt.md --candidate=prompts/agent-v2.prompt.md --traces=conv_1,conv_2
|
|
2841
|
-
moda prompts ab --baseline=prompts/agent.prompt.md --candidate=prompts/agent-v2.prompt.md --traces=conv_1@412 # replay from msg 412
|
|
2842
|
-
moda skills pull
|
|
2168
|
+
Legacy aliases (same behavior): conversations = traces, cluster-conversations = cluster-traces,
|
|
2169
|
+
trace = audit, --conversations = --traces, --signal=conversations = --signal=traces.
|
|
2170
|
+
<conversation_id> is the trace ID.
|
|
2843
2171
|
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2172
|
+
Output: piped stdout, CI or an agent env (CLAUDECODE/CURSOR/MODA_AGENT) => agent JSON; a terminal => prose.
|
|
2173
|
+
--json | --agent [--stream] | --human Force an output mode (or MODA_FORMAT=human|json|agent|agent-stream)
|
|
2174
|
+
--profile=NAME --quiet --no-update-check --version --json-schemas
|
|
2175
|
+
Exit codes: 0 ok, 1 error (errors[0].code says which), 3 degraded, 4 auth required, 5 input required, 130 cancelled.
|
|
2176
|
+
A command rejects any flag it does not take; the error lists errors[0].allowed and errors[0].did_you_mean.`);
|
|
2177
|
+
}
|
|
2178
|
+
function globalFlagHelpLines(commandFlags = []) {
|
|
2179
|
+
const own = new Set(commandFlags.map((key) => kebabFlag(key).slice(2)));
|
|
2180
|
+
const flags = [...GLOBAL_FLAG_NAMES].filter((flag) => flag !== "help" && !own.has(flag)).map((flag) => flag === "profile" ? "--profile=NAME" : flag === "format" ? "--format=ndjson" : `--${flag}`);
|
|
2181
|
+
const lines = [];
|
|
2182
|
+
let line = "Global flags (every command):";
|
|
2183
|
+
for (const flag of flags) {
|
|
2184
|
+
if (line.length + flag.length + 1 > 100) {
|
|
2185
|
+
lines.push(line);
|
|
2186
|
+
line = " ";
|
|
2187
|
+
}
|
|
2188
|
+
line += ` ${flag}`;
|
|
2189
|
+
}
|
|
2190
|
+
lines.push(line);
|
|
2191
|
+
return lines;
|
|
2847
2192
|
}
|
|
2848
2193
|
function printCommandHelp(definition) {
|
|
2849
2194
|
const lines = [];
|
|
@@ -2857,6 +2202,17 @@ function printCommandHelp(definition) {
|
|
|
2857
2202
|
for (const note of definition.helpNotes ?? []) {
|
|
2858
2203
|
lines.push("", note);
|
|
2859
2204
|
}
|
|
2205
|
+
const flagSpec = flagSpecFor(definition.name);
|
|
2206
|
+
if (flagSpec) {
|
|
2207
|
+
lines.push("", ...renderFlagHelp(definition.name, flagSpec));
|
|
2208
|
+
} else if (definition.documentedFlags && definition.documentedFlags.length > 0) {
|
|
2209
|
+
lines.push("", "Flags:");
|
|
2210
|
+
const width = Math.min(34, Math.max(...definition.documentedFlags.map((flag) => flag.name.length)));
|
|
2211
|
+
for (const flag of definition.documentedFlags) {
|
|
2212
|
+
lines.push(flag.name.length > width ? ` ${flag.name}
|
|
2213
|
+
${" ".repeat(width)} ${flag.description}` : ` ${flag.name.padEnd(width)} ${flag.description}`);
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2860
2216
|
if (definition.subcommands && definition.subcommands.length > 0) {
|
|
2861
2217
|
lines.push("", "Subcommands:");
|
|
2862
2218
|
const width = Math.max(...definition.subcommands.map((entry) => entry.name.length));
|
|
@@ -2871,7 +2227,7 @@ function printCommandHelp(definition) {
|
|
|
2871
2227
|
lines.push(` ${example}`);
|
|
2872
2228
|
}
|
|
2873
2229
|
}
|
|
2874
|
-
lines.push("",
|
|
2230
|
+
lines.push("", ...globalFlagHelpLines(flagSpec ? specFlagKeys(flagSpec) : []), flagSpec ? "Any other flag is rejected." : "Run 'moda --help' for the command list.");
|
|
2875
2231
|
console.log(lines.join(`
|
|
2876
2232
|
`));
|
|
2877
2233
|
}
|
|
@@ -3254,7 +2610,7 @@ function recordSearchTelemetry(context, data) {
|
|
|
3254
2610
|
const pagination = asRecord(record.pagination);
|
|
3255
2611
|
const hasMore = pagination?.has_more;
|
|
3256
2612
|
context.recordTelemetry({
|
|
3257
|
-
search_mode_effective:
|
|
2613
|
+
search_mode_effective: SEARCH_MODES.includes(effective) ? effective : undefined,
|
|
3258
2614
|
result_count: results.length,
|
|
3259
2615
|
has_more: hasMore === true ? "yes" : hasMore === false ? "no" : "na",
|
|
3260
2616
|
...typeof record.degrade_reason === "string" && record.degrade_reason ? { degrade_reason: record.degrade_reason.slice(0, 64) } : {}
|
|
@@ -3335,7 +2691,6 @@ var GLOBAL_FLAG_NAMES = new Set([
|
|
|
3335
2691
|
"no-telemetry",
|
|
3336
2692
|
"no-update-check"
|
|
3337
2693
|
]);
|
|
3338
|
-
var OVERVIEW_PRODUCTION_FLAGS = ["raw"];
|
|
3339
2694
|
var WINDOW_FLAG_HINTS = {
|
|
3340
2695
|
days_back: "This command takes --time-range (e.g. --time-range=7d), not --days-back.",
|
|
3341
2696
|
time_range: "This command takes --days-back=N (1-90), not --time-range."
|
|
@@ -3346,27 +2701,8 @@ var COMMAND_FLAG_HINTS = {
|
|
|
3346
2701
|
cursor: "'moda problems' has no cursor; 'moda problems remainder --cursor=<next_cursor>' pages the unexplained signals."
|
|
3347
2702
|
}
|
|
3348
2703
|
};
|
|
3349
|
-
function editDistance(a, b) {
|
|
3350
|
-
const row = Array.from({ length: b.length + 1 }, (_, index) => index);
|
|
3351
|
-
for (let i = 1;i <= a.length; i++) {
|
|
3352
|
-
let previous = row[0];
|
|
3353
|
-
row[0] = i;
|
|
3354
|
-
for (let j = 1;j <= b.length; j++) {
|
|
3355
|
-
const current = row[j];
|
|
3356
|
-
row[j] = Math.min(row[j] + 1, row[j - 1] + 1, previous + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
3357
|
-
previous = current;
|
|
3358
|
-
}
|
|
3359
|
-
}
|
|
3360
|
-
return row[b.length];
|
|
3361
|
-
}
|
|
3362
|
-
function schemaFlagKeys(schema) {
|
|
3363
|
-
let current = schema;
|
|
3364
|
-
while (current instanceof z2.ZodEffects)
|
|
3365
|
-
current = current.innerType();
|
|
3366
|
-
return current instanceof z2.ZodObject ? Object.keys(current.shape) : [];
|
|
3367
|
-
}
|
|
3368
2704
|
function parseCommandFlags(schema, args, command, options = {}) {
|
|
3369
|
-
const schemaKeys =
|
|
2705
|
+
const schemaKeys = Object.keys(schemaShape(schema));
|
|
3370
2706
|
const known = new Set([
|
|
3371
2707
|
...schemaKeys,
|
|
3372
2708
|
...[...GLOBAL_FLAG_NAMES, ...options.extraFlags ?? []].map((flag) => flag.replace(/-/g, "_"))
|
|
@@ -3376,24 +2712,70 @@ function parseCommandFlags(schema, args, command, options = {}) {
|
|
|
3376
2712
|
throw new CliInputError(`'moda ${command}' has no dry-run mode, so nothing was sent.`, `Remove --dry-run to run it for real. Commands with a real dry-run: sync, registry push, harness sync/delete/register, prompts sync/decide, skills sync/policy, signals <write subcommands>, problem-reopen.`, "unsupported_dry_run");
|
|
3377
2713
|
}
|
|
3378
2714
|
if (unknown.length > 0) {
|
|
3379
|
-
const flagKeys =
|
|
3380
|
-
|
|
2715
|
+
const flagKeys = [
|
|
2716
|
+
...schemaKeys.filter((key) => key !== options.positionalKey),
|
|
2717
|
+
...(options.extraFlags ?? []).map((flag) => flag.replace(/-/g, "_"))
|
|
2718
|
+
];
|
|
2719
|
+
const valid = flagKeys.map(kebabFlag);
|
|
2720
|
+
const candidates = [...valid, ...Object.keys(options.flagAliases ?? {}).map((alias) => `--${alias}`)];
|
|
2721
|
+
const didYouMean = [];
|
|
3381
2722
|
const hints = unknown.map((key) => {
|
|
3382
2723
|
const commandHint = COMMAND_FLAG_HINTS[command]?.[key];
|
|
3383
2724
|
if (commandHint)
|
|
3384
2725
|
return commandHint;
|
|
3385
2726
|
const windowAlternative = key === "days_back" ? "time_range" : key === "time_range" ? "days_back" : undefined;
|
|
3386
|
-
if (windowAlternative && WINDOW_FLAG_HINTS[key] && flagKeys.includes(windowAlternative))
|
|
2727
|
+
if (windowAlternative && WINDOW_FLAG_HINTS[key] && flagKeys.includes(windowAlternative)) {
|
|
2728
|
+
didYouMean.push(kebabFlag(windowAlternative));
|
|
3387
2729
|
return WINDOW_FLAG_HINTS[key];
|
|
2730
|
+
}
|
|
3388
2731
|
if (windowAlternative)
|
|
3389
2732
|
return `This command has no time-window flag.`;
|
|
3390
|
-
const close =
|
|
3391
|
-
|
|
2733
|
+
const close = closestMatches(kebabFlag(key), candidates, 1)[0];
|
|
2734
|
+
if (close)
|
|
2735
|
+
didYouMean.push(close);
|
|
2736
|
+
return close ? `Did you mean ${close}?` : "";
|
|
3392
2737
|
}).filter(Boolean);
|
|
3393
|
-
const names = unknown.map(
|
|
3394
|
-
|
|
2738
|
+
const names = unknown.map(kebabFlag).join(", ");
|
|
2739
|
+
const helpCommand = `moda ${command} --help`;
|
|
2740
|
+
throw new CliInputError(`Unknown flag${unknown.length > 1 ? "s" : ""} ${names} for 'moda ${command}'.` + (didYouMean.length > 0 ? ` Did you mean ${didYouMean.join(", ")}?` : ""), [...hints, `Valid flags: ${valid.join(", ") || "(none)"}. Run '${helpCommand}'.`].join(" "), `unknown_flag:${unknown[0].replace(/_/g, "-")}`, {
|
|
2741
|
+
field: kebabFlag(unknown[0]),
|
|
2742
|
+
allowed: valid,
|
|
2743
|
+
...didYouMean.length > 0 ? { didYouMean: [...new Set(didYouMean)] } : {},
|
|
2744
|
+
suggestedCommands: [helpCommand]
|
|
2745
|
+
});
|
|
3395
2746
|
}
|
|
3396
|
-
|
|
2747
|
+
try {
|
|
2748
|
+
return schema.parse(args);
|
|
2749
|
+
} catch (error) {
|
|
2750
|
+
if (error instanceof z.ZodError)
|
|
2751
|
+
attachFlagDetails(error, schema, command);
|
|
2752
|
+
throw error;
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
function attachFlagDetails(error, schema, command) {
|
|
2756
|
+
const key = error.issues[0]?.path[0];
|
|
2757
|
+
if (typeof key !== "string")
|
|
2758
|
+
return;
|
|
2759
|
+
const field = describeSpecFlags({ schema }).find((flag) => flag.name === kebabFlag(key));
|
|
2760
|
+
if (!field)
|
|
2761
|
+
return;
|
|
2762
|
+
attachInputDetails(error, {
|
|
2763
|
+
field: field.name,
|
|
2764
|
+
...field.enum ? { allowed: field.enum } : {},
|
|
2765
|
+
...field.min !== undefined || field.max !== undefined ? { range: { ...field.min !== undefined ? { min: field.min } : {}, ...field.max !== undefined ? { max: field.max } : {} } } : {},
|
|
2766
|
+
suggestedCommands: [`moda ${command} --help`]
|
|
2767
|
+
});
|
|
2768
|
+
}
|
|
2769
|
+
function parseSpecFlags(name, args, command = name) {
|
|
2770
|
+
return parseCommandFlags(COMMAND_FLAG_SPECS[name].schema, args, command, specParseOptions(COMMAND_FLAG_SPECS[name]));
|
|
2771
|
+
}
|
|
2772
|
+
function specParseOptions(spec) {
|
|
2773
|
+
const positional = spec.positionals?.find((entry) => entry.key && !entry.alsoFlag);
|
|
2774
|
+
return {
|
|
2775
|
+
extraFlags: Object.keys(spec.extra?.shape ?? {}),
|
|
2776
|
+
...positional?.key ? { positionalKey: positional.key } : {},
|
|
2777
|
+
...spec.flagAliases ? { flagAliases: spec.flagAliases } : {}
|
|
2778
|
+
};
|
|
3397
2779
|
}
|
|
3398
2780
|
function withStringIdFlags(args, flags) {
|
|
3399
2781
|
for (const flag of ["user-id", "conversation-id"]) {
|
|
@@ -3478,6 +2860,10 @@ async function searchFallbackToTraces(params) {
|
|
|
3478
2860
|
query2.set("user_id", params.user_id);
|
|
3479
2861
|
if (params.time_range)
|
|
3480
2862
|
query2.set("time_range", params.time_range);
|
|
2863
|
+
if (params.since)
|
|
2864
|
+
query2.set("since", params.since);
|
|
2865
|
+
if (params.until)
|
|
2866
|
+
query2.set("until", params.until);
|
|
3481
2867
|
query2.set("limit", String(limit));
|
|
3482
2868
|
if (offset > 0)
|
|
3483
2869
|
query2.set("offset", String(offset));
|
|
@@ -3485,6 +2871,8 @@ async function searchFallbackToTraces(params) {
|
|
|
3485
2871
|
`moda traces --search=${shellArg(params.q)}`,
|
|
3486
2872
|
params.user_id ? `--user-id=${shellArg(params.user_id)}` : "",
|
|
3487
2873
|
params.time_range ? `--time-range=${shellArg(params.time_range)}` : "",
|
|
2874
|
+
params.since ? `--since=${shellArg(params.since)}` : "",
|
|
2875
|
+
params.until ? `--until=${shellArg(params.until)}` : "",
|
|
3488
2876
|
`--limit=${limit}`
|
|
3489
2877
|
].filter(Boolean).join(" ");
|
|
3490
2878
|
let traces;
|
|
@@ -3575,36 +2963,12 @@ function serverWarnings(data) {
|
|
|
3575
2963
|
function isDefinedRecord(value) {
|
|
3576
2964
|
return value !== undefined && value !== null;
|
|
3577
2965
|
}
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
signals: [],
|
|
3585
|
-
"problem-feedback": ["action", "actor", "reason", "attribution-id", "new-name"],
|
|
3586
|
-
"problem-linear": [],
|
|
3587
|
-
"problem-linear-file": ["issue", "priority", "title", "team-id"],
|
|
3588
|
-
"signal-label": ["label", "note", "conversation-id", "msg-dedup-token", "msg-index"],
|
|
3589
|
-
"detection-reviews": ["attribution-id"],
|
|
3590
|
-
"detection-review": ["note", "verdict", "attribution-id", "conversation-id"],
|
|
3591
|
-
"false-positive": [
|
|
3592
|
-
"family",
|
|
3593
|
-
"quote",
|
|
3594
|
-
"reason",
|
|
3595
|
-
"tool",
|
|
3596
|
-
"turn",
|
|
3597
|
-
"undo",
|
|
3598
|
-
"attribution-id",
|
|
3599
|
-
"conversation-id",
|
|
3600
|
-
"msg-dedup-token",
|
|
3601
|
-
"msg-index",
|
|
3602
|
-
"tool-use-id"
|
|
3603
|
-
],
|
|
3604
|
-
"false-positives": ["all", "kind", "limit"],
|
|
3605
|
-
feedback: FEEDBACK_FLAGS,
|
|
3606
|
-
"problem-impact": ["mode", "node-id", "problem-id", "run-id", "to", "cursor", "conversation-ids", "days-back"]
|
|
3607
|
-
};
|
|
2966
|
+
function handParsedFlags(command) {
|
|
2967
|
+
const spec = flagSpecFor(command);
|
|
2968
|
+
if (!spec?.handParsed || ["users", "user", "problem-reopen"].includes(command))
|
|
2969
|
+
return;
|
|
2970
|
+
return { spec, allowed: specFlagNames(spec) };
|
|
2971
|
+
}
|
|
3608
2972
|
var NO_POSITIONAL_COMMANDS = new Set([
|
|
3609
2973
|
"overview",
|
|
3610
2974
|
"investigate",
|
|
@@ -3630,18 +2994,18 @@ function assertHandParsedFlags(command, flags, positionals) {
|
|
|
3630
2994
|
if (NO_POSITIONAL_COMMANDS.has(command) && positionals.length > 0) {
|
|
3631
2995
|
throw new CliInputError(`'moda ${command}' takes no arguments, but got '${positionals.join(" ")}'.`, `Nothing was run. See 'moda ${command} --help' for its flags.`);
|
|
3632
2996
|
}
|
|
3633
|
-
const
|
|
3634
|
-
if (!
|
|
2997
|
+
const hand = handParsedFlags(command);
|
|
2998
|
+
if (!hand)
|
|
3635
2999
|
return;
|
|
3636
|
-
const checked =
|
|
3637
|
-
const shape =
|
|
3000
|
+
const checked = hand.spec.idRefFlags ? Object.keys(flags).filter((flag) => !isFeedbackRefFlag(flag)) : Object.keys(flags);
|
|
3001
|
+
const shape = z.object(Object.fromEntries(hand.allowed.map((flag) => [flag.replace(/-/g, "_"), z.unknown()])));
|
|
3638
3002
|
const args = Object.fromEntries(checked.map((flag) => [flag.replace(/-/g, "_"), true]));
|
|
3639
3003
|
try {
|
|
3640
|
-
parseCommandFlags(shape.passthrough(), args, command);
|
|
3004
|
+
parseCommandFlags(shape.passthrough(), args, command, { flagAliases: hand.spec.flagAliases });
|
|
3641
3005
|
} catch (error) {
|
|
3642
3006
|
if (command !== "feedback" || !(error instanceof CliInputError))
|
|
3643
3007
|
throw error;
|
|
3644
|
-
throw new CliInputError(/nothing was sent/i.test(error.message) ? error.message : `${error.message} Nothing was sent.`, `${error.usage ?? ""} Id flags (--<name>-id=ID) are attached as refs; put other detail in the note. ${FEEDBACK_USAGE}`.trim(), error.reason);
|
|
3008
|
+
throw new CliInputError(/nothing was sent/i.test(error.message) ? error.message : `${error.message} Nothing was sent.`, `${error.usage ?? ""} Id flags (--<name>-id=ID) are attached as refs; put other detail in the note. ${FEEDBACK_USAGE}`.trim(), error.reason, error.details);
|
|
3645
3009
|
}
|
|
3646
3010
|
}
|
|
3647
3011
|
function normalizeBooleanFlags(target) {
|
|
@@ -3664,7 +3028,7 @@ function normalizeBooleanFlags(target) {
|
|
|
3664
3028
|
}
|
|
3665
3029
|
var PROFILE_MANAGING_COMMANDS = new Set(["profiles", "auth", "init", "provision", "status", "config", "manifest", "agent", "doctor"]);
|
|
3666
3030
|
async function runProblemsRemainder(flags, context) {
|
|
3667
|
-
const params = parseCommandFlags(ProblemsRemainderSchema, flagsToArgs(flags), "problems remainder");
|
|
3031
|
+
const params = parseCommandFlags(ProblemsRemainderSchema, flagsToArgs(flags), "problems remainder", specParseOptions(COMMAND_FLAG_SPECS.problems.subcommands.remainder));
|
|
3668
3032
|
const query2 = new URLSearchParams;
|
|
3669
3033
|
if (params.days_back)
|
|
3670
3034
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -3729,7 +3093,7 @@ function parseContextRequest(positional, rawFlags) {
|
|
|
3729
3093
|
warnings.push(`--msg-index had no value (${JSON.stringify(msgIndex)}), so the window is centered on the middle of the trace. Trace-level search hits have no message_index; pass one only when the hit has it.`);
|
|
3730
3094
|
}
|
|
3731
3095
|
const args = { ...flagsToArgs(flags), conversation_id: conversationId };
|
|
3732
|
-
const params =
|
|
3096
|
+
const params = parseSpecFlags("context", args);
|
|
3733
3097
|
if (params.metadata_only === true && params.window !== undefined) {
|
|
3734
3098
|
throw new CliInputError("--metadata-only reads no messages, so it cannot be combined with --window; drop --window.", CONTEXT_USAGE, "flag_conflict");
|
|
3735
3099
|
}
|
|
@@ -4165,7 +3529,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4165
3529
|
}
|
|
4166
3530
|
case "overview": {
|
|
4167
3531
|
const args = flagsToArgs(flags);
|
|
4168
|
-
|
|
3532
|
+
parseSpecFlags("overview", args, command);
|
|
4169
3533
|
return (await runProductionCommand(context)).exitCode;
|
|
4170
3534
|
}
|
|
4171
3535
|
case "investigate":
|
|
@@ -4175,7 +3539,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4175
3539
|
}
|
|
4176
3540
|
case "clusters": {
|
|
4177
3541
|
const args = flagsToArgs(flags);
|
|
4178
|
-
const params =
|
|
3542
|
+
const params = parseSpecFlags("clusters", args, command);
|
|
4179
3543
|
if (params.search !== undefined || params.node_id !== undefined) {
|
|
4180
3544
|
const query3 = new URLSearchParams;
|
|
4181
3545
|
if (params.search !== undefined)
|
|
@@ -4209,7 +3573,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4209
3573
|
throw new CliInputError("<node_id> is required", "Usage: moda cluster-traces <node_id> [--limit=N] [--offset=N]");
|
|
4210
3574
|
}
|
|
4211
3575
|
const args = flagsToArgs(flags, "node_id", positional);
|
|
4212
|
-
const params =
|
|
3576
|
+
const params = parseSpecFlags("cluster-traces", args, command);
|
|
4213
3577
|
const query2 = new URLSearchParams;
|
|
4214
3578
|
if (params.limit)
|
|
4215
3579
|
query2.set("limit", params.limit.toString());
|
|
@@ -4225,7 +3589,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4225
3589
|
case "traces":
|
|
4226
3590
|
case "conversations": {
|
|
4227
3591
|
const args = withStringIdFlags(flagsToArgs(flags), flags);
|
|
4228
|
-
const params =
|
|
3592
|
+
const params = parseSpecFlags("traces", args, command);
|
|
4229
3593
|
const query2 = new URLSearchParams;
|
|
4230
3594
|
if (params.search)
|
|
4231
3595
|
query2.set("search", params.search);
|
|
@@ -4235,6 +3599,10 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4235
3599
|
query2.set("user_id", params.user_id);
|
|
4236
3600
|
if (params.time_range)
|
|
4237
3601
|
query2.set("time_range", params.time_range);
|
|
3602
|
+
if (params.since)
|
|
3603
|
+
query2.set("since", params.since);
|
|
3604
|
+
if (params.until)
|
|
3605
|
+
query2.set("until", params.until);
|
|
4238
3606
|
if (params.environment)
|
|
4239
3607
|
query2.set("environment", params.environment);
|
|
4240
3608
|
if (params.world_state)
|
|
@@ -4280,10 +3648,10 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4280
3648
|
}
|
|
4281
3649
|
case "search": {
|
|
4282
3650
|
if (!positional || positional.trim() === "") {
|
|
4283
|
-
throw new CliInputError("<query> is required", 'Usage: moda search "<query>" [--mode=keyword|semantic|hybrid] [--user-id=ID] [--conversation-id=ID] [--time-range=RANGE] [--include-tool-io] [--limit=N]');
|
|
3651
|
+
throw new CliInputError("<query> is required", 'Usage: moda search "<query>" [--mode=keyword|semantic|hybrid] [--user-id=ID] [--conversation-id=ID] [--time-range=RANGE] [--since=DATE] [--until=DATE] [--include-tool-io] [--limit=N]');
|
|
4284
3652
|
}
|
|
4285
3653
|
const args = withStringIdFlags(flagsToArgs(flags, "q", positional), flags);
|
|
4286
|
-
const params =
|
|
3654
|
+
const params = parseSpecFlags("search", args, command);
|
|
4287
3655
|
const query2 = new URLSearchParams;
|
|
4288
3656
|
query2.set("q", params.q);
|
|
4289
3657
|
if (params.mode)
|
|
@@ -4294,6 +3662,10 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4294
3662
|
query2.set("conversation_id", params.conversation_id);
|
|
4295
3663
|
if (params.time_range)
|
|
4296
3664
|
query2.set("time_range", params.time_range);
|
|
3665
|
+
if (params.since)
|
|
3666
|
+
query2.set("since", params.since);
|
|
3667
|
+
if (params.until)
|
|
3668
|
+
query2.set("until", params.until);
|
|
4297
3669
|
if (params.limit)
|
|
4298
3670
|
query2.set("limit", params.limit.toString());
|
|
4299
3671
|
if (params.include_tool_io)
|
|
@@ -4335,7 +3707,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4335
3707
|
throw new CliInputError("<conversation_id> is required", "Usage: moda world-state <conversation_id> [--summary-only] [--event-limit=N]");
|
|
4336
3708
|
}
|
|
4337
3709
|
const args = flagsToArgs(flags, "conversation_id", positional);
|
|
4338
|
-
const params =
|
|
3710
|
+
const params = parseSpecFlags("world-state", args, command);
|
|
4339
3711
|
if (params.snapshot === true && params.replay === true) {
|
|
4340
3712
|
throw new CliInputError("Choose either --snapshot or --replay, not both.", "Usage: moda world-state <conversation_id> [--snapshot --msg-index=N [--block-index=M] [--segment-index=K]] | [--replay --message-count=N [--format=frames|fold-inputs]]");
|
|
4341
3713
|
}
|
|
@@ -4393,7 +3765,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4393
3765
|
throw new CliInputError("<conversation_id|trace_id> is required", AUDIT_USAGE);
|
|
4394
3766
|
}
|
|
4395
3767
|
const args = flagsToArgs(flags, "id", positional);
|
|
4396
|
-
const params =
|
|
3768
|
+
const params = parseSpecFlags("audit", args, command);
|
|
4397
3769
|
const agentMode = context.output.mode === "agent" || context.output.mode === "agent-stream";
|
|
4398
3770
|
const page = await readAuditItem(command, params, agentMode ? {
|
|
4399
3771
|
maxBytes: Math.max(AUDIT_MIN_PAGE_BYTES, agentMaxOutputBytes() - AUDIT_AGENT_RESERVE_BYTES),
|
|
@@ -4404,7 +3776,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4404
3776
|
}
|
|
4405
3777
|
case "frustrations": {
|
|
4406
3778
|
const args = withStringIdFlags(flagsToArgs(flags), flags);
|
|
4407
|
-
const params =
|
|
3779
|
+
const params = parseSpecFlags("frustrations", args, command);
|
|
4408
3780
|
const query2 = new URLSearchParams;
|
|
4409
3781
|
if (params.days_back)
|
|
4410
3782
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -4426,7 +3798,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4426
3798
|
}
|
|
4427
3799
|
case "tool-failures": {
|
|
4428
3800
|
const args = flagsToArgs(flags);
|
|
4429
|
-
const params =
|
|
3801
|
+
const params = parseSpecFlags("tool-failures", args, command);
|
|
4430
3802
|
const queryString = params.days_back ? `?days_back=${params.days_back}` : "";
|
|
4431
3803
|
const data = await callDataAPI(`/tool-failures${queryString}`);
|
|
4432
3804
|
context.output.writeData(data);
|
|
@@ -4444,7 +3816,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4444
3816
|
toolFlags["include-window"] = "false";
|
|
4445
3817
|
}
|
|
4446
3818
|
const args = flagsToArgs(toolFlags, "tool_name", positional);
|
|
4447
|
-
const params =
|
|
3819
|
+
const params = parseSpecFlags("tool-failure-detail", args, command);
|
|
4448
3820
|
const dropConversation = params.compact === true || params.include_window === false;
|
|
4449
3821
|
if (params.compact === true && params.include_window === true) {
|
|
4450
3822
|
throw new CliInputError("--compact drops the conversation window; drop --include-window, or drop --compact.");
|
|
@@ -4524,7 +3896,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4524
3896
|
throw new CliInputError(`Unknown problems subcommand '${positional}'.`, "Usage: moda problems [--days-back=N] [--limit=N] | moda problems remainder [--family=F] [--days-back=N] [--limit=N] [--cursor=TOKEN]. For one Problem use 'moda problem <id>'.");
|
|
4525
3897
|
}
|
|
4526
3898
|
const args = flagsToArgs(flags);
|
|
4527
|
-
const params =
|
|
3899
|
+
const params = parseSpecFlags("problems", args, command);
|
|
4528
3900
|
const query2 = new URLSearchParams;
|
|
4529
3901
|
if (params.days_back)
|
|
4530
3902
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -4551,7 +3923,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4551
3923
|
throw new CliInputError("<problem_id> is required", "Usage: moda problem <problem_id> [--full | --evidence|--reports|--traces|--feedback] [--limit=N] [--cursor=TOKEN] [--family=F] [--door=D]");
|
|
4552
3924
|
}
|
|
4553
3925
|
const args = flagsToArgs(flags, "id", positional);
|
|
4554
|
-
const params =
|
|
3926
|
+
const params = parseSpecFlags("problem", args, command);
|
|
4555
3927
|
const traceView = params.traces === true || params.conversations === true;
|
|
4556
3928
|
const views = ["evidence", "reports", "conversations", "feedback"].filter((view2) => view2 === "conversations" ? traceView : params[view2] === true);
|
|
4557
3929
|
if (views.length > 1) {
|
|
@@ -4725,7 +4097,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4725
4097
|
}
|
|
4726
4098
|
const args = flagsToArgs(flags, "id", positional);
|
|
4727
4099
|
args.id = positional;
|
|
4728
|
-
const params =
|
|
4100
|
+
const params = parseSpecFlags("signal", args, command);
|
|
4729
4101
|
const id = encodeURIComponent(params.id);
|
|
4730
4102
|
if (params.detections !== true) {
|
|
4731
4103
|
const data2 = await callDataAPI(`/custom-signals/${id}`);
|
|
@@ -4918,7 +4290,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4918
4290
|
}
|
|
4919
4291
|
case "emotions": {
|
|
4920
4292
|
const args = withStringIdFlags(flagsToArgs(flags), flags);
|
|
4921
|
-
const params =
|
|
4293
|
+
const params = parseSpecFlags("emotions", args, command);
|
|
4922
4294
|
const query2 = new URLSearchParams;
|
|
4923
4295
|
if (params.days_back)
|
|
4924
4296
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -4946,7 +4318,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4946
4318
|
if (flags["conversation-id"] !== undefined) {
|
|
4947
4319
|
args.conversation_id = flags["conversation-id"];
|
|
4948
4320
|
}
|
|
4949
|
-
const params =
|
|
4321
|
+
const params = parseSpecFlags("laziness", args, command);
|
|
4950
4322
|
const query2 = new URLSearchParams;
|
|
4951
4323
|
if (params.days_back)
|
|
4952
4324
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -4968,7 +4340,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4968
4340
|
if (flags["conversation-id"] !== undefined) {
|
|
4969
4341
|
args.conversation_id = flags["conversation-id"];
|
|
4970
4342
|
}
|
|
4971
|
-
const params =
|
|
4343
|
+
const params = parseSpecFlags("hallucinations", args, command);
|
|
4972
4344
|
const query2 = new URLSearchParams;
|
|
4973
4345
|
if (params.days_back)
|
|
4974
4346
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -5002,7 +4374,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5002
4374
|
}
|
|
5003
4375
|
case "tail": {
|
|
5004
4376
|
const args = flagsToArgs(flags);
|
|
5005
|
-
const params =
|
|
4377
|
+
const params = parseSpecFlags("tail", args, command);
|
|
5006
4378
|
await runTailCommand(params, context);
|
|
5007
4379
|
break;
|
|
5008
4380
|
}
|
|
@@ -5027,7 +4399,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5027
4399
|
break;
|
|
5028
4400
|
}
|
|
5029
4401
|
default:
|
|
5030
|
-
throw
|
|
4402
|
+
throw unknownCommandError(command);
|
|
5031
4403
|
}
|
|
5032
4404
|
return 0;
|
|
5033
4405
|
}
|
|
@@ -5130,6 +4502,30 @@ var commandRegistry = createCommandRegistry([
|
|
|
5130
4502
|
name: "init",
|
|
5131
4503
|
description: "Set up Moda in your project",
|
|
5132
4504
|
examples: ["moda init", "moda init --sdk-integrate", "moda init --ci-cd", "moda init --autosync", "moda init --harness-rescan"],
|
|
4505
|
+
documentedFlags: [
|
|
4506
|
+
{ name: "--yes", description: "Accept all defaults (non-interactive)" },
|
|
4507
|
+
{ name: "--analyst=auto|claude|codex|cursor|local-scan", description: "Choose the harness analyst adapter" },
|
|
4508
|
+
{ name: "--analyst-model=MODEL", description: 'Model for the claude analyst (default sonnet; "default" = the claude CLI default; env MODA_HARNESS_ANALYST_MODEL)' },
|
|
4509
|
+
{ name: "--assist=none", description: "Disable agent fallback for prompt discovery" },
|
|
4510
|
+
{ name: "--concern=topology|tools|prompts|evals", description: "Harness analyze: restrict the pass to one concern (env MODA_HARNESS_CONCERN, flag wins)" },
|
|
4511
|
+
{ name: "--allow-no-agents", description: "Allow harness sync to push a graph with zero runtime agents despite detected LLM usage" },
|
|
4512
|
+
{ name: "--remote", description: "Run harness analysis server-side (the default): upload a safe source snapshot" },
|
|
4513
|
+
{ name: "--local", description: "Run harness analysis with a local coding agent instead of server-side" },
|
|
4514
|
+
{ name: "--tui", description: "Show the full-screen analyst dashboard in human TTYs" },
|
|
4515
|
+
{ name: "--no-tui", description: "Show raw external analyst output" },
|
|
4516
|
+
{ name: "--sdk-integrate", description: "Run your coding agent to install the Moda SDK and instrument LLM calls" },
|
|
4517
|
+
{ name: "--no-sdk-integrate", description: "Skip SDK integration (alias: --no-sdk-guide)" },
|
|
4518
|
+
{ name: "--verification-id=ID", description: "Tag the SDK integration's test trace with this id (the onb_ id from the onboarding page)" },
|
|
4519
|
+
{ name: "--connect-code=CODE", description: "Sign in with the one-time mcc_ code from the onboarding page instead of the browser (10 min, single use)" },
|
|
4520
|
+
{ name: "--ci-cd", description: "Create the GitHub Actions Moda validation workflow" },
|
|
4521
|
+
{ name: "--no-ci-cd", description: "Skip CI/CD workflow creation" },
|
|
4522
|
+
{ name: "--autosync", description: "Create a GitHub Actions workflow that syncs prompts + skills to Moda on push to main" },
|
|
4523
|
+
{ name: "--no-autosync", description: "Skip autosync workflow creation" },
|
|
4524
|
+
{ name: "--harness-rescan", description: "Create a GitHub Actions workflow that re-scans the harness and syncs it on push to main" },
|
|
4525
|
+
{ name: "--no-harness-rescan", description: "Skip harness rescan workflow creation" },
|
|
4526
|
+
{ name: "--harness-rescan-paths=GLOBS", description: "Comma-separated path globs that scope which pushes trigger the rescan (implies --harness-rescan)" },
|
|
4527
|
+
{ name: "--offline", description: "Run final validation offline (skip the online telemetry check)" }
|
|
4528
|
+
],
|
|
5133
4529
|
auth: "none",
|
|
5134
4530
|
outputModes: ["human", "json", "agent"],
|
|
5135
4531
|
mutability: "write",
|
|
@@ -5137,7 +4533,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
5137
4533
|
resetApiRequestCountBeforeRun: true,
|
|
5138
4534
|
telemetry: "result-and-error",
|
|
5139
4535
|
handler: async (context) => {
|
|
5140
|
-
const { runInit } = await import("./index-
|
|
4536
|
+
const { runInit } = await import("./index-6qqmjqb2.js");
|
|
5141
4537
|
if (context.outputMode === "agent-stream") {
|
|
5142
4538
|
context.output.writeEvent({
|
|
5143
4539
|
event: "started",
|
|
@@ -5171,6 +4567,12 @@ var commandRegistry = createCommandRegistry([
|
|
|
5171
4567
|
"moda provision --tenant-id=<org-id> --label=ci-runner --save",
|
|
5172
4568
|
"KEY=$(moda provision --tenant-id <org-id> | jq -r .apiKey)"
|
|
5173
4569
|
],
|
|
4570
|
+
helpNotes: ['Headless: requires an existing "moda auth login" session and never prompts, even on a TTY.'],
|
|
4571
|
+
documentedFlags: [
|
|
4572
|
+
{ name: "--tenant-id=ID", description: "Organization to provision (required with multiple organizations; MODA_TENANT_ID is also honored, flag wins)" },
|
|
4573
|
+
{ name: "--label=TEXT", description: "API key label (default: machine hostname)" },
|
|
4574
|
+
{ name: "--save", description: "Also persist the key to ~/.moda/config.json (default: print only; headless callers own storage)" }
|
|
4575
|
+
],
|
|
5174
4576
|
auth: "none",
|
|
5175
4577
|
outputModes: ["human", "json", "agent"],
|
|
5176
4578
|
mutability: "write",
|
|
@@ -5178,7 +4580,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
5178
4580
|
resetApiRequestCountBeforeRun: true,
|
|
5179
4581
|
telemetry: "result-and-error",
|
|
5180
4582
|
handler: async (context) => {
|
|
5181
|
-
const { runProvision } = await import("./provision-
|
|
4583
|
+
const { runProvision } = await import("./provision-wzttap58.js");
|
|
5182
4584
|
return runProvision(context, {
|
|
5183
4585
|
resumeCommand: buildResumeCommand("provision", context.rawFlags)
|
|
5184
4586
|
});
|
|
@@ -5621,7 +5023,8 @@ var commandRegistry = createCommandRegistry([
|
|
|
5621
5023
|
description: "Search trace messages (keyword, semantic, or hybrid)",
|
|
5622
5024
|
examples: [
|
|
5623
5025
|
'moda search "billing error"',
|
|
5624
|
-
'moda search "refund flow" --mode=semantic --time-range=7d --limit=10'
|
|
5026
|
+
'moda search "refund flow" --mode=semantic --time-range=7d --limit=10',
|
|
5027
|
+
'moda search "area code" --since=2026-10-07 --until=2026-10-07'
|
|
5625
5028
|
],
|
|
5626
5029
|
...dataApiDefaults
|
|
5627
5030
|
}),
|
|
@@ -5776,6 +5179,9 @@ var commandRegistry = createCommandRegistry([
|
|
|
5776
5179
|
legacyCommand({
|
|
5777
5180
|
name: "false-positive",
|
|
5778
5181
|
description: "Flag a detection as a false positive with a reason: problem, problem-detection, quote, tool, laziness, hallucination, or custom-signal",
|
|
5182
|
+
helpNotes: [
|
|
5183
|
+
"Kinds: problem <problem_id> dismisses the Problem (hidden at once, logged for review); problem-detection <problem_id> marks one detection on a trace (needs --conversation-id and --attribution-id); quote <conversation_id> needs --family, --turn and --quote (from moda emotions); tool <conversation_id> needs --tool and --tool-use-id or --msg-index; laziness and hallucination <conversation_id> mark that trace; custom-signal <signal_id> needs --conversation-id and is saved as a does_not_fit label. quote, tool, laziness and hallucination marks are audit-only."
|
|
5184
|
+
],
|
|
5779
5185
|
examples: [
|
|
5780
5186
|
'moda false-positive problem <problem_id> --reason="two unrelated tools"',
|
|
5781
5187
|
'moda false-positive problem-detection <problem_id> --conversation-id=<id> --attribution-id=<uuid> --reason="refund was approved"',
|
|
@@ -5893,6 +5299,9 @@ var commandRegistry = createCommandRegistry([
|
|
|
5893
5299
|
'moda feedback "search finds nothing for a trace I can open" --category=missing_data --conversation-id=<id>',
|
|
5894
5300
|
'moda feedback "trace is about refunds, not this problem" --category=false_positive_attribution --problem-id=<id> --conversation-id=<id>'
|
|
5895
5301
|
],
|
|
5302
|
+
helpNotes: [
|
|
5303
|
+
"Any other id flag (--problem-id, --fix-id, --attribution-id, --trace-id, --span-id, --message-index, ...) is attached as a ref. Set MODA_CLI_TIPS=0 to hide the feedback tip line."
|
|
5304
|
+
],
|
|
5896
5305
|
...dataApiDefaults,
|
|
5897
5306
|
mutability: "write"
|
|
5898
5307
|
}),
|
|
@@ -6092,7 +5501,7 @@ function classifyCliError(error) {
|
|
|
6092
5501
|
return "auth_error";
|
|
6093
5502
|
if (error instanceof ApiError && error.statusCode === 403)
|
|
6094
5503
|
return "access_error";
|
|
6095
|
-
if (error instanceof
|
|
5504
|
+
if (error instanceof z.ZodError || error instanceof CliInputError || error instanceof CliInputRequiredError) {
|
|
6096
5505
|
return "validation_error";
|
|
6097
5506
|
}
|
|
6098
5507
|
if (error instanceof ApiError || isApiLikeError(error)) {
|
|
@@ -6104,7 +5513,7 @@ function classifyCliError(error) {
|
|
|
6104
5513
|
return "unknown_error";
|
|
6105
5514
|
}
|
|
6106
5515
|
function cliValidationReason(error) {
|
|
6107
|
-
if (error instanceof
|
|
5516
|
+
if (error instanceof z.ZodError) {
|
|
6108
5517
|
const issue = error.issues[0];
|
|
6109
5518
|
if (!issue)
|
|
6110
5519
|
return "zod";
|
|
@@ -6131,7 +5540,7 @@ function printCliError(error) {
|
|
|
6131
5540
|
if (error.guidance)
|
|
6132
5541
|
safeWriteStderr(`${error.guidance}
|
|
6133
5542
|
`);
|
|
6134
|
-
} else if (error instanceof
|
|
5543
|
+
} else if (error instanceof z.ZodError) {
|
|
6135
5544
|
const issues = error.errors.map((e) => {
|
|
6136
5545
|
const field = e.path.length ? e.path.join(".") : "input";
|
|
6137
5546
|
return ` ${field}: ${e.message}`;
|
|
@@ -6175,6 +5584,21 @@ function printFeedbackTip(commandName, context) {
|
|
|
6175
5584
|
${colorOk ? `\x1B[2m${text}\x1B[0m` : text}
|
|
6176
5585
|
`);
|
|
6177
5586
|
}
|
|
5587
|
+
function unknownCommandError(command) {
|
|
5588
|
+
const visible = commandRegistry.all().filter((entry) => !entry.hidden);
|
|
5589
|
+
const names = visible.flatMap((entry) => [entry.name, ...entry.aliases ?? []]);
|
|
5590
|
+
const matches = closestMatches(command, names);
|
|
5591
|
+
const suggestion = matches.length > 0 ? ` Did you mean ${matches.map((name) => `'${name}'`).join(" or ")}?` : "";
|
|
5592
|
+
return new CliInputError(`Unknown command '${command}'.${suggestion}`, [
|
|
5593
|
+
...matches.map((name) => `\`moda ${name} --help\``),
|
|
5594
|
+
"Run `moda --help` for the command list."
|
|
5595
|
+
].join(" "), "unknown_command", {
|
|
5596
|
+
field: "<command>",
|
|
5597
|
+
allowed: visible.map((entry) => entry.name),
|
|
5598
|
+
...matches.length > 0 ? { didYouMean: matches } : {},
|
|
5599
|
+
suggestedCommands: [...matches.map((name) => `moda ${name} --help`), "moda --help"]
|
|
5600
|
+
});
|
|
5601
|
+
}
|
|
6178
5602
|
function printAgentCliError(command, error, mode = "agent") {
|
|
6179
5603
|
const output = createCliOutput({
|
|
6180
5604
|
command: command || "unknown",
|
|
@@ -6272,9 +5696,8 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
|
|
|
6272
5696
|
return 1;
|
|
6273
5697
|
};
|
|
6274
5698
|
const definition = commandRegistry.find(command);
|
|
6275
|
-
if (!definition)
|
|
6276
|
-
return failEarly(
|
|
6277
|
-
}
|
|
5699
|
+
if (!definition)
|
|
5700
|
+
return failEarly(unknownCommandError(command));
|
|
6278
5701
|
if (parsed.shortFlags?.length) {
|
|
6279
5702
|
return failEarly(new CliInputError(`Short options are not supported (${parsed.shortFlags.join(", ")}), so nothing was run.`, `Use the long form, e.g. --dry-run, --json, --quiet. See 'moda ${command} --help'.`, "short_flag"), definition);
|
|
6280
5703
|
}
|
|
@@ -6461,6 +5884,7 @@ if (isMain) {
|
|
|
6461
5884
|
});
|
|
6462
5885
|
}
|
|
6463
5886
|
export {
|
|
5887
|
+
unknownCommandError,
|
|
6464
5888
|
telemetrySubcommandNames,
|
|
6465
5889
|
telemetryCommandName,
|
|
6466
5890
|
stripLoneSurrogates,
|
|
@@ -6475,6 +5899,7 @@ export {
|
|
|
6475
5899
|
parseArgs,
|
|
6476
5900
|
normalizeBooleanFlags,
|
|
6477
5901
|
initFlagsForContext,
|
|
5902
|
+
globalFlagHelpLines,
|
|
6478
5903
|
flagsToArgs,
|
|
6479
5904
|
dispatchParsedCommand,
|
|
6480
5905
|
detectCallerAgent,
|