@moda-ai/cli 1.55.18 → 1.55.20
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-c5c6f0yw.js → cli-38p87ykc.js} +1 -1
- package/dist/{cli-av3dqgj5.js → cli-4j8nffsm.js} +10 -6
- package/dist/{cli-5hq827jt.js → cli-569hj0bj.js} +1 -1
- package/dist/{cli-3ezzeqcy.js → cli-5ke3xe6y.js} +47 -3
- 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-ssfq84k5.js → cli-sf0g0fjg.js} +133 -18
- package/dist/{cli-0e8bfvn7.js → cli-wf7gfa1e.js} +8 -8
- package/dist/cli.js +331 -930
- 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-ewqbpnwz.js} +13 -13
- 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-br82cpt7.js +19 -0
- package/dist/{skills-bundled-mdmhzfsr.js → skills-bundled-r9a2vs07.js} +2 -2
- package/dist/{sync-r4tncne4.js → sync-25vn78je.js} +9 -9
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/skills/moda-cli/SKILL.md +114 -1434
- package/skills/moda-cli/references/auth.md +176 -0
- package/skills/moda-cli/references/commands.md +74 -0
- package/skills/moda-cli/references/dashboard-parity.md +29 -0
- package/skills/moda-cli/references/detections.md +79 -0
- package/skills/moda-cli/references/feedback.md +45 -0
- package/skills/moda-cli/references/output-protocol.md +260 -0
- package/skills/moda-cli/references/production-intelligence.md +96 -0
- package/skills/moda-cli/references/prompts.md +104 -0
- package/skills/moda-cli/references/recipes.md +74 -0
- package/skills/moda-cli/references/replays-and-registry.md +173 -0
- package/skills/moda-cli/references/search-and-traces.md +180 -0
- package/skills/moda-cli/references/signals-and-false-positives.md +79 -0
- package/skills/moda-cli/references/troubleshooting.md +65 -0
- package/dist/cli-kg0kz05e.js +0 -496
- package/dist/skills-fed17et3.js +0 -19
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,441 +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 ISO_BOUND_MESSAGE = "must be an ISO 8601 date (2026-10-07) or datetime (2026-10-07T14:30:00Z)";
|
|
107
|
-
var ISO_BOUND = /^\d{4}-\d{2}-\d{2}(?:[Tt ]\d{2}:\d{2}(?::\d{2}(?:\.\d{1,9})?)?(?:[Zz]|[+-]\d{2}:?\d{2})?)?$/;
|
|
108
|
-
var isoBoundFlag = () => z.string().trim().regex(ISO_BOUND, ISO_BOUND_MESSAGE).optional();
|
|
109
|
-
var OverviewSchema = z.object({
|
|
110
|
-
days_back: daysBackFlag(7)
|
|
111
|
-
});
|
|
112
|
-
var ClustersSchema = z.object({
|
|
113
|
-
parent_id: z.string().optional(),
|
|
114
|
-
time_range: z.enum(["all", "1h", "3d", "7d", "24h", "30d", "90d"]).default("all").optional(),
|
|
115
|
-
search: z.string().min(2).max(200).optional(),
|
|
116
|
-
node_id: z.string().min(1).max(512).optional(),
|
|
117
|
-
mode: z.enum(["fuzzy", "semantic", "hybrid"]).optional(),
|
|
118
|
-
limit: z.number().min(1).max(50).optional()
|
|
119
|
-
});
|
|
120
|
-
var ClusterConversationsSchema = z.object({
|
|
121
|
-
node_id: z.string(),
|
|
122
|
-
limit: z.number().min(1).max(100).default(10).optional(),
|
|
123
|
-
offset: z.number().min(0).default(0).optional()
|
|
124
|
-
});
|
|
125
|
-
var ConversationsSchema = z.object({
|
|
126
|
-
search: z.string().optional(),
|
|
127
|
-
cluster_id: z.string().optional(),
|
|
128
|
-
user_id: z.string().optional(),
|
|
129
|
-
time_range: z.enum(["all", "1h", "3d", "24h", "7d", "30d", "90d"]).default("all").optional(),
|
|
130
|
-
since: isoBoundFlag(),
|
|
131
|
-
until: isoBoundFlag(),
|
|
132
|
-
environment: z.enum(["all", "development", "staging", "production"]).default("all").optional(),
|
|
133
|
-
world_state: z.string().max(200).optional(),
|
|
134
|
-
outcome: z.enum(["any", "positive", "negative"]).default("any").optional(),
|
|
135
|
-
include_world_state: boolFlag(),
|
|
136
|
-
sort: z.enum(["recent", "longest", "slowest"]).optional(),
|
|
137
|
-
limit: z.number().min(1).max(100).default(20).optional(),
|
|
138
|
-
offset: z.number().min(0).default(0).optional()
|
|
139
|
-
});
|
|
140
|
-
var WorldStateSchema = z.object({
|
|
141
|
-
conversation_id: z.string(),
|
|
142
|
-
summary_only: boolFlag(),
|
|
143
|
-
event_limit: z.number().min(1).max(5000).default(2000).optional(),
|
|
144
|
-
snapshot: boolFlag(),
|
|
145
|
-
msg_index: z.number().min(0).max(1e5).optional(),
|
|
146
|
-
block_index: z.number().min(0).max(1e5).optional(),
|
|
147
|
-
segment_index: z.number().min(0).max(65535).optional(),
|
|
148
|
-
replay: boolFlag(),
|
|
149
|
-
format: z.enum(["frames", "fold-inputs"]).optional(),
|
|
150
|
-
message_count: z.number().min(1).max(1e6).optional()
|
|
151
|
-
});
|
|
152
|
-
var ContextSchema = z.object({
|
|
153
|
-
conversation_id: z.string().min(1),
|
|
154
|
-
msg_index: z.number().int().min(0).optional(),
|
|
155
|
-
window: z.number().int().min(0).optional(),
|
|
156
|
-
metadata_only: boolFlag(),
|
|
157
|
-
all: boolFlag(),
|
|
158
|
-
from: z.number().int().min(0).optional(),
|
|
159
|
-
max_messages: z.number().int().min(1).max(5000).optional(),
|
|
160
|
-
ids_from: z.string().min(1).optional()
|
|
161
|
-
});
|
|
162
|
-
var FrustrationsSchema = z.object({
|
|
163
|
-
days_back: daysBackFlag(7),
|
|
164
|
-
limit: z.number().min(1).max(20).default(10).optional(),
|
|
165
|
-
offset: z.number().min(0).default(0).optional(),
|
|
166
|
-
include_window: boolFlag(),
|
|
167
|
-
window: z.number().min(1).max(5).default(1).optional(),
|
|
168
|
-
user_id: z.string().min(1).max(256).optional(),
|
|
169
|
-
conversation_id: z.string().min(1).max(256).optional()
|
|
170
|
-
});
|
|
171
|
-
var ToolFailuresSchema = z.object({
|
|
172
|
-
days_back: daysBackFlag(7)
|
|
173
|
-
});
|
|
174
|
-
var ProblemsSchema = z.object({
|
|
175
|
-
days_back: daysBackFlag(30),
|
|
176
|
-
limit: z.number().min(1).max(25).default(25).optional()
|
|
177
|
-
});
|
|
178
|
-
var REMAINDER_FAMILIES = [
|
|
179
|
-
"tool_failure",
|
|
180
|
-
"emotion",
|
|
181
|
-
"laziness",
|
|
182
|
-
"hallucination",
|
|
183
|
-
"prm_dip",
|
|
184
|
-
"custom_signal",
|
|
185
|
-
"conversation_reader"
|
|
186
|
-
];
|
|
187
|
-
var ProblemsRemainderSchema = z.object({
|
|
188
|
-
days_back: daysBackFlag(30),
|
|
189
|
-
limit: z.number().min(1).max(25).default(25).optional(),
|
|
190
|
-
family: z.enum(REMAINDER_FAMILIES).optional(),
|
|
191
|
-
cursor: z.string().min(1).max(4096).optional()
|
|
192
|
-
});
|
|
193
|
-
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
194
|
-
var ProblemImpactSchema = z.object({
|
|
195
|
-
node_id: z.string().min(1).max(256).optional(),
|
|
196
|
-
problem_id: z.string().regex(UUID_RE).optional(),
|
|
197
|
-
run_id: z.string().min(1).max(256).optional(),
|
|
198
|
-
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),
|
|
199
|
-
mode: z.enum(["metrics", "trend", "evidence", "catalog", "overview", "affected-use-cases", "trace-use-cases"]).default("metrics"),
|
|
200
|
-
to: z.string().datetime({ precision: 3 }).optional(),
|
|
201
|
-
cursor: z.string().min(1).optional(),
|
|
202
|
-
conversation_ids: z.string().transform((value, ctx) => {
|
|
203
|
-
try {
|
|
204
|
-
return z.array(z.string().min(1).max(512)).min(1).max(25).parse(JSON.parse(value));
|
|
205
|
-
} catch {
|
|
206
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Use a JSON array of 1–25 conversation IDs" });
|
|
207
|
-
return z.NEVER;
|
|
208
|
-
}
|
|
209
|
-
}).optional()
|
|
210
|
-
}).refine((p) => p.mode !== "trace-use-cases" || p.problem_id && p.conversation_ids, {
|
|
211
|
-
message: "Trace use cases require --problem-id and --conversation-ids"
|
|
212
|
-
}).refine((p) => p.node_id || p.problem_id || ["catalog", "overview"].includes(p.mode), {
|
|
213
|
-
message: "Select --node-id or --problem-id, or use --mode=catalog/overview"
|
|
214
|
-
}).refine((p) => !p.cursor || p.mode === "evidence" && p.to && p.run_id, {
|
|
215
|
-
message: "An evidence cursor requires --mode=evidence, --to, and --run-id from the previous response"
|
|
216
|
-
});
|
|
217
|
-
var PROBLEM_FAMILIES = REMAINDER_FAMILIES;
|
|
218
|
-
var PROBLEM_DOORS = ["rubric_match", "local_causal_chain"];
|
|
219
|
-
var ProblemSchema = z.object({
|
|
220
|
-
id: z.string().min(1),
|
|
221
|
-
evidence: boolFlag(),
|
|
222
|
-
reports: boolFlag(),
|
|
223
|
-
traces: boolFlag(),
|
|
224
|
-
conversations: boolFlag(),
|
|
225
|
-
feedback: boolFlag(),
|
|
226
|
-
full: boolFlag(),
|
|
227
|
-
limit: z.number().min(1).max(50).optional(),
|
|
228
|
-
cursor: z.string().optional(),
|
|
229
|
-
family: z.enum(PROBLEM_FAMILIES).optional(),
|
|
230
|
-
door: z.enum(PROBLEM_DOORS).optional()
|
|
231
|
-
});
|
|
232
|
-
var PROBLEM_FEEDBACK_ACTIONS = [
|
|
233
|
-
"mark_fixed",
|
|
234
|
-
"dismiss",
|
|
235
|
-
"flag_attribution",
|
|
236
|
-
"rename"
|
|
237
|
-
];
|
|
238
|
-
var ProblemFeedbackSchema = z.object({
|
|
239
|
-
id: z.string().min(1),
|
|
240
|
-
action: z.enum(PROBLEM_FEEDBACK_ACTIONS),
|
|
241
|
-
reason: z.string().max(2000).optional(),
|
|
242
|
-
attribution_id: z.string().max(64).optional(),
|
|
243
|
-
new_name: z.string().max(255).optional(),
|
|
244
|
-
actor: z.string().max(255).optional()
|
|
245
|
-
});
|
|
246
|
-
var ProblemLinearFileSchema = z.object({
|
|
247
|
-
id: z.string().min(1),
|
|
248
|
-
issue: z.string().max(2048).optional(),
|
|
249
|
-
team_id: z.string().max(255).optional(),
|
|
250
|
-
title: z.string().optional(),
|
|
251
|
-
priority: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).max(4).optional())
|
|
252
|
-
});
|
|
253
|
-
var SignalSchema = z.object({
|
|
254
|
-
id: z.string().min(1).max(255),
|
|
255
|
-
detections: boolFlag(),
|
|
256
|
-
days_back: daysBackFlag(),
|
|
257
|
-
limit: z.number().min(1).max(20).optional(),
|
|
258
|
-
offset: z.number().min(0).max(1e4).optional()
|
|
259
|
-
});
|
|
260
|
-
var SIGNAL_LABELS = ["fits", "does_not_fit"];
|
|
261
|
-
var SignalLabelSchema = z.object({
|
|
262
|
-
id: z.string().min(1).max(255),
|
|
263
|
-
conversation_id: z.string().min(1).max(255),
|
|
264
|
-
label: z.enum(SIGNAL_LABELS),
|
|
265
|
-
note: z.string().max(2000).optional(),
|
|
266
|
-
msg_index: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).optional()),
|
|
267
|
-
msg_dedup_token: z.string().min(1).max(200).optional()
|
|
268
|
-
});
|
|
269
|
-
var DETECTION_VERDICTS = ["correct", "false_positive", "clear"];
|
|
270
|
-
var DetectionReviewSchema = z.object({
|
|
271
|
-
id: z.string().regex(UUID_RE, "Problem id must be a canonical UUID"),
|
|
272
|
-
conversation_id: z.string().min(1).max(255),
|
|
273
|
-
attribution_id: z.string().regex(UUID_RE, "Attribution id must be a UUID"),
|
|
274
|
-
verdict: z.enum(DETECTION_VERDICTS),
|
|
275
|
-
note: z.string().max(2000).optional()
|
|
276
|
-
});
|
|
277
|
-
var FALSE_POSITIVE_KINDS = ["problem", "problem-detection", "quote", "tool", "laziness", "hallucination", "custom-signal"];
|
|
278
|
-
var FalsePositiveSchema = z.object({
|
|
279
|
-
kind: z.enum(FALSE_POSITIVE_KINDS),
|
|
280
|
-
target: z.string().min(1).max(255),
|
|
281
|
-
undo: z.boolean(),
|
|
282
|
-
reason: z.string().max(2000).optional(),
|
|
283
|
-
conversation_id: z.string().min(1).max(255).optional(),
|
|
284
|
-
attribution_id: z.string().regex(UUID_RE, "Attribution id must be a UUID").optional(),
|
|
285
|
-
family: z.string().regex(/^[a-z_]{1,64}$/, "Family must be a lowercase emotion family").optional(),
|
|
286
|
-
turn: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).optional()),
|
|
287
|
-
quote: z.string().min(1).max(4000).optional(),
|
|
288
|
-
tool: z.string().min(1).max(255).optional(),
|
|
289
|
-
tool_use_id: z.string().min(1).max(255).optional(),
|
|
290
|
-
msg_index: z.preprocess((v) => typeof v === "string" && /^\d+$/.test(v.trim()) ? Number(v) : v, z.number().int().min(0).optional()),
|
|
291
|
-
msg_dedup_token: z.string().min(1).max(200).optional()
|
|
292
|
-
}).superRefine((v, ctx) => {
|
|
293
|
-
const need = (ok, message) => {
|
|
294
|
-
if (!ok)
|
|
295
|
-
ctx.addIssue({ code: z.ZodIssueCode.custom, message });
|
|
296
|
-
};
|
|
297
|
-
if (v.kind === "problem") {
|
|
298
|
-
need(UUID_RE.test(v.target), "Problem id must be a canonical UUID");
|
|
299
|
-
need(!v.undo, "A problem dismissal cannot be undone from the CLI");
|
|
300
|
-
}
|
|
301
|
-
if (v.kind === "problem-detection") {
|
|
302
|
-
need(UUID_RE.test(v.target), "Problem id must be a canonical UUID");
|
|
303
|
-
need(v.conversation_id, "--conversation-id is required for problem-detection");
|
|
304
|
-
need(v.attribution_id, "--attribution-id is required for problem-detection");
|
|
305
|
-
}
|
|
306
|
-
if (v.kind === "quote") {
|
|
307
|
-
need(v.family && v.turn !== undefined && v.quote, "--family, --turn and --quote are required for quote (copy them from moda emotions)");
|
|
308
|
-
}
|
|
309
|
-
if (v.kind === "tool") {
|
|
310
|
-
need(v.tool, "--tool is required for tool (the failing tool name)");
|
|
311
|
-
need(v.tool_use_id || v.msg_index !== undefined, "--tool-use-id or --msg-index is required for tool (from moda tool-failure-detail)");
|
|
312
|
-
}
|
|
313
|
-
if (v.kind === "custom-signal") {
|
|
314
|
-
need(v.conversation_id, "--conversation-id is required for custom-signal");
|
|
315
|
-
}
|
|
316
|
-
});
|
|
317
|
-
var EMOTION_FAMILIES = [
|
|
318
|
-
"frustration",
|
|
319
|
-
"disapproval",
|
|
320
|
-
"sadness",
|
|
321
|
-
"confusion",
|
|
322
|
-
"anxiety",
|
|
323
|
-
"trust",
|
|
324
|
-
"positive"
|
|
325
|
-
];
|
|
326
|
-
var EmotionsSchema = z.object({
|
|
327
|
-
days_back: daysBackFlag(7),
|
|
328
|
-
limit: z.number().min(1).max(20).default(10).optional(),
|
|
329
|
-
offset: z.number().min(0).max(1e4).optional(),
|
|
330
|
-
family: z.enum(EMOTION_FAMILIES).optional(),
|
|
331
|
-
user_id: z.string().min(1).max(256).optional(),
|
|
332
|
-
conversation_id: z.string().min(1).max(256).optional(),
|
|
333
|
-
include_window: boolFlag()
|
|
334
|
-
});
|
|
335
|
-
var HallucinationsSchema = z.object({
|
|
336
|
-
days_back: daysBackFlag(7),
|
|
337
|
-
limit: z.number().min(1).max(20).default(10).optional(),
|
|
338
|
-
offset: z.number().min(0).max(1e4).optional(),
|
|
339
|
-
conversation_id: z.string().max(200).optional(),
|
|
340
|
-
kind: z.enum(["contradicted", "verified"]).optional()
|
|
341
|
-
});
|
|
342
|
-
var LAZINESS_FAMILIES = [
|
|
343
|
-
"omission_comment",
|
|
344
|
-
"omission_phrase",
|
|
345
|
-
"stub_body",
|
|
346
|
-
"refusal_prefix",
|
|
347
|
-
"deflection",
|
|
348
|
-
"data_quality_truncation",
|
|
349
|
-
"promise_no_delivery",
|
|
350
|
-
"capability_refusal_here",
|
|
351
|
-
"capability_refusal_verb",
|
|
352
|
-
"error_admission",
|
|
353
|
-
"irreversibility",
|
|
354
|
-
"stall_recheck",
|
|
355
|
-
"diy_handoff",
|
|
356
|
-
"tool_selection",
|
|
357
|
-
"completion",
|
|
358
|
-
"code_artifact",
|
|
359
|
-
"repeated_tool_call",
|
|
360
|
-
"target_overshoot",
|
|
361
|
-
"data_regression"
|
|
362
|
-
];
|
|
363
|
-
var LazinessSchema = z.object({
|
|
364
|
-
days_back: daysBackFlag(7),
|
|
365
|
-
limit: z.number().min(1).max(50).default(10).optional(),
|
|
366
|
-
offset: z.number().min(0).max(1e4).optional(),
|
|
367
|
-
conversation_id: z.string().max(200).optional(),
|
|
368
|
-
family: z.enum(LAZINESS_FAMILIES).optional()
|
|
369
|
-
});
|
|
370
|
-
var StepScoresSchema = z.object({
|
|
371
|
-
conversation_id: z.string().min(1)
|
|
372
|
-
});
|
|
373
|
-
var TAIL_SIGNALS = ["traces", "conversations", "emotions", "all"];
|
|
374
|
-
var TailSchema = z.object({
|
|
375
|
-
interval: z.number().min(5).max(3600).default(15).optional(),
|
|
376
|
-
signal: z.enum(TAIL_SIGNALS).default("traces").optional(),
|
|
377
|
-
once: boolFlag(),
|
|
378
|
-
limit: z.number().min(1).max(50).default(20).optional(),
|
|
379
|
-
max_events: z.number().min(1).max(1e5).optional(),
|
|
380
|
-
full_scan: boolFlag()
|
|
381
|
-
});
|
|
382
|
-
var ToolFailureDetailSchema = z.object({
|
|
383
|
-
tool_name: z.string(),
|
|
384
|
-
subtype: z.string().optional(),
|
|
385
|
-
days_back: daysBackFlag(7),
|
|
386
|
-
limit: z.number().min(1).max(20).default(5).optional(),
|
|
387
|
-
offset: z.number().min(0).default(0).optional(),
|
|
388
|
-
include_window: boolFlag(),
|
|
389
|
-
compact: boolFlag(),
|
|
390
|
-
window: z.number().min(1).max(5).default(1).optional()
|
|
391
|
-
});
|
|
392
|
-
var AuditSchema = z.object({
|
|
393
|
-
id: z.string().min(1),
|
|
394
|
-
kind: z.enum(["auto", "trace", "conversation"]).default("auto").optional(),
|
|
395
|
-
include_raw: boolFlag(),
|
|
396
|
-
include_bodies: boolFlag(),
|
|
397
|
-
limit: z.number().min(1).max(1000).default(200).optional(),
|
|
398
|
-
cursor: z.string().min(1).max(512).optional(),
|
|
399
|
-
ids_from: z.string().min(1).optional()
|
|
400
|
-
});
|
|
401
|
-
var TIME_RANGES = ["all", "1h", "3d", "7d", "24h", "30d", "90d"];
|
|
402
|
-
var SEARCH_MODES = ["keyword", "semantic", "hybrid"];
|
|
403
|
-
var SearchSchema = z.object({
|
|
404
|
-
q: z.string().min(1).max(500),
|
|
405
|
-
mode: z.enum(SEARCH_MODES).default("hybrid").optional(),
|
|
406
|
-
user_id: z.string().optional(),
|
|
407
|
-
conversation_id: z.string().min(1).max(256).optional(),
|
|
408
|
-
time_range: z.enum(TIME_RANGES).default("all").optional(),
|
|
409
|
-
since: isoBoundFlag(),
|
|
410
|
-
until: isoBoundFlag(),
|
|
411
|
-
limit: z.number().min(1).max(100).default(20).optional(),
|
|
412
|
-
include_tool_io: boolFlag(),
|
|
413
|
-
offset: z.number().min(0).max(1e4).optional()
|
|
414
|
-
});
|
|
415
|
-
|
|
416
|
-
// ../../packages/database/src/agent-feedback.ts
|
|
417
|
-
var FEEDBACK_CATEGORIES = [
|
|
418
|
-
"bad_cluster_label",
|
|
419
|
-
"mismatched_frustration",
|
|
420
|
-
"missing_data",
|
|
421
|
-
"noisy_data",
|
|
422
|
-
"wrong_tool_failure",
|
|
423
|
-
"incorrect_loop",
|
|
424
|
-
"api_quirk",
|
|
425
|
-
"false_positive_attribution",
|
|
426
|
-
"misrouted_fix",
|
|
427
|
-
"harness_bug",
|
|
428
|
-
"other"
|
|
429
|
-
];
|
|
430
|
-
var FEEDBACK_SEVERITIES = ["info", "low", "medium", "high"];
|
|
431
|
-
var DEFAULT_FEEDBACK_CATEGORY = "other";
|
|
432
|
-
var RAW_FEEDBACK_CATEGORY_MAX = 64;
|
|
433
|
-
function isFeedbackCategory(value) {
|
|
434
|
-
return typeof value === "string" && FEEDBACK_CATEGORIES.includes(value);
|
|
435
|
-
}
|
|
436
|
-
function normalizeFeedbackCategory(value) {
|
|
437
|
-
if (value === undefined || value === null || value === "")
|
|
438
|
-
return { category: DEFAULT_FEEDBACK_CATEGORY };
|
|
439
|
-
if (isFeedbackCategory(value))
|
|
440
|
-
return { category: value };
|
|
441
|
-
const raw = String(value).trim().slice(0, RAW_FEEDBACK_CATEGORY_MAX);
|
|
442
|
-
return raw ? { category: DEFAULT_FEEDBACK_CATEGORY, raw_category: raw } : { category: DEFAULT_FEEDBACK_CATEGORY };
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// src/feedback.ts
|
|
446
|
-
var FEEDBACK_FLAGS = ["category", "severity", "note", "cluster-id", "conversation-id", "run-id", "tool-name"];
|
|
447
|
-
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]";
|
|
448
|
-
var NOTE_MAX = 4000;
|
|
449
|
-
var REF_VALUE_MAX = 256;
|
|
450
|
-
var REF_FLAG_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*-(?:id|ids|index|token)$/;
|
|
451
|
-
var REF_FLAG_WORDS = new Set(["turn", "tool", "family", "kind"]);
|
|
452
|
-
function isFeedbackRefFlag(flag) {
|
|
453
|
-
return REF_FLAG_PATTERN.test(flag) || REF_FLAG_WORDS.has(flag);
|
|
454
|
-
}
|
|
455
|
-
function feedbackCategoryHelp(indent = 35, width = 100) {
|
|
456
|
-
const lines = [];
|
|
457
|
-
let line = "";
|
|
458
|
-
FEEDBACK_CATEGORIES.forEach((category, index) => {
|
|
459
|
-
const piece = index < FEEDBACK_CATEGORIES.length - 1 ? `${category}|` : `${category} (default other)`;
|
|
460
|
-
if (line && indent + line.length + piece.length > width) {
|
|
461
|
-
lines.push(line);
|
|
462
|
-
line = "";
|
|
463
|
-
}
|
|
464
|
-
line += piece;
|
|
465
|
-
});
|
|
466
|
-
lines.push(line);
|
|
467
|
-
return lines.join(`
|
|
468
|
-
${" ".repeat(indent)}`);
|
|
469
|
-
}
|
|
470
|
-
function buildFeedbackRequest(positionals, flags, bareFlags) {
|
|
471
|
-
const isBare = (flag) => bareFlags ? bareFlags.includes(flag) : flags[flag] === "true";
|
|
472
|
-
const flagNote = flags.note !== undefined && !isBare("note") ? flags.note.trim() : "";
|
|
473
|
-
const note = [positionals.join(" ").trim(), flagNote].filter(Boolean).join(`
|
|
474
|
-
`);
|
|
475
|
-
if (note === "")
|
|
476
|
-
throw new CliInputError("<note> is required", FEEDBACK_USAGE);
|
|
477
|
-
if (note.length > NOTE_MAX) {
|
|
478
|
-
throw new CliInputError(`<note> is ${note.length} characters; the limit is ${NOTE_MAX}.`, FEEDBACK_USAGE);
|
|
479
|
-
}
|
|
480
|
-
const severity = flags.severity ?? "low";
|
|
481
|
-
if (!FEEDBACK_SEVERITIES.includes(severity)) {
|
|
482
|
-
throw new CliInputError(`Invalid --severity '${severity}'. Valid severities: ${FEEDBACK_SEVERITIES.join(", ")}.`, FEEDBACK_USAGE);
|
|
483
|
-
}
|
|
484
|
-
const refs = {};
|
|
485
|
-
for (const [flag, value] of Object.entries(flags)) {
|
|
486
|
-
if (flag === "category" || flag === "severity" || flag === "note")
|
|
487
|
-
continue;
|
|
488
|
-
if (!FEEDBACK_FLAGS.includes(flag) && !isFeedbackRefFlag(flag))
|
|
489
|
-
continue;
|
|
490
|
-
const trimmed = value.trim();
|
|
491
|
-
if (value === "true" || trimmed === "") {
|
|
492
|
-
throw new CliInputError(`--${flag} needs a value, e.g. --${flag}=<id>.`, FEEDBACK_USAGE);
|
|
493
|
-
}
|
|
494
|
-
if (trimmed.length > REF_VALUE_MAX) {
|
|
495
|
-
throw new CliInputError(`--${flag} is ${trimmed.length} characters; the limit is ${REF_VALUE_MAX}.`, FEEDBACK_USAGE);
|
|
496
|
-
}
|
|
497
|
-
refs[flag.replace(/-/g, "_")] = trimmed;
|
|
498
|
-
}
|
|
499
|
-
const warnings = [];
|
|
500
|
-
const { category, raw_category: rawCategory } = normalizeFeedbackCategory(flags.category);
|
|
501
|
-
if (rawCategory !== undefined) {
|
|
502
|
-
refs.raw_category = rawCategory;
|
|
503
|
-
warnings.push(`Unknown category '${rawCategory}': sent as 'other' with refs.raw_category. ` + `Valid categories: ${FEEDBACK_CATEGORIES.join(", ")}.`);
|
|
504
|
-
}
|
|
505
|
-
const hint = dedicatedCommandHint(category, rawCategory);
|
|
506
|
-
if (hint)
|
|
507
|
-
warnings.push(hint);
|
|
508
|
-
return { category, severity, note, refs, warnings };
|
|
509
|
-
}
|
|
510
|
-
var MISROUTE_CATEGORIES = new Set(["false_positive_attribution", "misrouted_fix"]);
|
|
511
|
-
var MISROUTE_WORDS = /attribut|misrout|false[\s_-]?positive|wrong[\s_-]?(?:problem|fix)/i;
|
|
512
|
-
function dedicatedCommandHint(category, rawCategory) {
|
|
513
|
-
if (!MISROUTE_CATEGORIES.has(category) && !(rawCategory && MISROUTE_WORDS.test(rawCategory)))
|
|
514
|
-
return;
|
|
515
|
-
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).";
|
|
516
|
-
}
|
|
517
119
|
|
|
518
120
|
// src/replays.ts
|
|
519
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;
|
|
@@ -713,7 +315,7 @@ var SEARCH_SURFACE_BY_COMMAND = {
|
|
|
713
315
|
"world-state": "world_state",
|
|
714
316
|
context: "context"
|
|
715
317
|
};
|
|
716
|
-
var
|
|
318
|
+
var SEARCH_MODES = ["keyword", "semantic", "hybrid"];
|
|
717
319
|
function termCount(query2) {
|
|
718
320
|
return query2.trim().split(/\s+/).filter(Boolean).length;
|
|
719
321
|
}
|
|
@@ -745,7 +347,7 @@ function buildSearchAdoptionTelemetry(input) {
|
|
|
745
347
|
}
|
|
746
348
|
if (command === "search") {
|
|
747
349
|
const requested = (flags.mode ?? "").toLowerCase();
|
|
748
|
-
adoption.search_mode_requested =
|
|
350
|
+
adoption.search_mode_requested = SEARCH_MODES.includes(requested) ? requested : "hybrid";
|
|
749
351
|
}
|
|
750
352
|
if (command === "context") {
|
|
751
353
|
adoption.used_msg_index = flags["msg-index"] !== undefined || flags["message-index"] !== undefined ? 1 : 0;
|
|
@@ -1598,12 +1200,7 @@ var PROBLEMS_SUBCOMMAND_HELP = [
|
|
|
1598
1200
|
name: "remainder",
|
|
1599
1201
|
description: "Signals no Problem explains yet, grouped by family (read-only)",
|
|
1600
1202
|
usage: "moda problems remainder [--family=<family>] [--days-back=N] [--limit=N] [--cursor=<token>]",
|
|
1601
|
-
flags:
|
|
1602
|
-
{ name: "--family=<family>", description: "One of tool_failure, emotion, laziness, hallucination, prm_dip, custom_signal, conversation_reader (frustration is under emotion)." },
|
|
1603
|
-
{ name: "--days-back=<n>", description: "Window in days, 1-90 (default 30)." },
|
|
1604
|
-
{ name: "--limit=<n>", description: "Groups per page, 1-25 (default 25)." },
|
|
1605
|
-
{ name: "--cursor=<token>", description: "The next_cursor from the previous page, verbatim." }
|
|
1606
|
-
],
|
|
1203
|
+
flags: subcommandHelpFlags(COMMAND_FLAG_SPECS.problems.subcommands.remainder),
|
|
1607
1204
|
examples: ["moda problems remainder", "moda problems remainder --family=emotion --days-back=7"]
|
|
1608
1205
|
}
|
|
1609
1206
|
];
|
|
@@ -1813,6 +1410,23 @@ var agentErrorSchema = {
|
|
|
1813
1410
|
message: { type: "string" },
|
|
1814
1411
|
cause: { type: "string" },
|
|
1815
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
|
+
},
|
|
1816
1430
|
input_request: agentInputRequestSchema,
|
|
1817
1431
|
auth: agentAuthSchema,
|
|
1818
1432
|
blocking: { type: "boolean" }
|
|
@@ -2165,7 +1779,8 @@ function buildManifest(commands) {
|
|
|
2165
1779
|
auth: command.auth,
|
|
2166
1780
|
...command.authNote ? { auth_note: command.authNote } : {},
|
|
2167
1781
|
mutability: command.mutability,
|
|
2168
|
-
exit_codes: exitCodesForCommand(command.name)
|
|
1782
|
+
exit_codes: exitCodesForCommand(command.name),
|
|
1783
|
+
...commandFlagFields(command)
|
|
2169
1784
|
})),
|
|
2170
1785
|
concepts: [
|
|
2171
1786
|
{ term: "tenant", meaning: "A Moda organization/workspace that owns data, prompts, skills, and API keys." },
|
|
@@ -2197,6 +1812,29 @@ function renderManifestHuman(manifest) {
|
|
|
2197
1812
|
].join(`
|
|
2198
1813
|
`);
|
|
2199
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
|
+
}
|
|
2200
1838
|
function event(name, when, terminal, deprecated = false) {
|
|
2201
1839
|
return { name, event_version: 1, when, terminal, ...deprecated ? { deprecated: true } : {} };
|
|
2202
1840
|
}
|
|
@@ -2212,46 +1850,46 @@ function exitCodesForCommand(command) {
|
|
|
2212
1850
|
import { fileURLToPath } from "url";
|
|
2213
1851
|
import { realpathSync } from "fs";
|
|
2214
1852
|
async function runPromptsCommand(...args) {
|
|
2215
|
-
return (await import("./prompts-
|
|
1853
|
+
return (await import("./prompts-1tkhrxkq.js")).runPromptsCommand(...args);
|
|
2216
1854
|
}
|
|
2217
1855
|
async function runSkillsCommand(...args) {
|
|
2218
|
-
return (await import("./skills-
|
|
1856
|
+
return (await import("./skills-br82cpt7.js")).runSkillsCommand(...args);
|
|
2219
1857
|
}
|
|
2220
1858
|
async function runFixCommand(...args) {
|
|
2221
|
-
return (await import("./fix-
|
|
1859
|
+
return (await import("./fix-9fmy6p2x.js")).runFixCommand(...args);
|
|
2222
1860
|
}
|
|
2223
1861
|
async function runFixesCommand(...args) {
|
|
2224
|
-
return (await import("./fix-
|
|
1862
|
+
return (await import("./fix-9fmy6p2x.js")).runFixesCommand(...args);
|
|
2225
1863
|
}
|
|
2226
1864
|
async function runHarnessCommand(...args) {
|
|
2227
|
-
return (await import("./harness-
|
|
1865
|
+
return (await import("./harness-xvg6ws6x.js")).runHarnessCommand(...args);
|
|
2228
1866
|
}
|
|
2229
1867
|
async function runSyncCommand(...args) {
|
|
2230
|
-
return (await import("./sync-
|
|
1868
|
+
return (await import("./sync-25vn78je.js")).runSyncCommand(...args);
|
|
2231
1869
|
}
|
|
2232
1870
|
async function runRegistryCommand(...args) {
|
|
2233
|
-
return (await import("./registry-
|
|
1871
|
+
return (await import("./registry-atqyb5fa.js")).runRegistryCommand(...args);
|
|
2234
1872
|
}
|
|
2235
1873
|
async function runDoctorCommand(...args) {
|
|
2236
|
-
return (await import("./doctor-
|
|
1874
|
+
return (await import("./doctor-mx6jf435.js")).runDoctorCommand(...args);
|
|
2237
1875
|
}
|
|
2238
1876
|
async function runStatusCommand(...args) {
|
|
2239
|
-
return (await import("./doctor-
|
|
1877
|
+
return (await import("./doctor-mx6jf435.js")).runStatusCommand(...args);
|
|
2240
1878
|
}
|
|
2241
1879
|
async function runAuthCommand(...args) {
|
|
2242
|
-
return (await import("./profile-commands-
|
|
1880
|
+
return (await import("./profile-commands-kmmd9y86.js")).runAuthCommand(...args);
|
|
2243
1881
|
}
|
|
2244
1882
|
async function runConfigCommand(...args) {
|
|
2245
|
-
return (await import("./profile-commands-
|
|
1883
|
+
return (await import("./profile-commands-kmmd9y86.js")).runConfigCommand(...args);
|
|
2246
1884
|
}
|
|
2247
1885
|
async function runProfilesCommand(...args) {
|
|
2248
|
-
return (await import("./profile-commands-
|
|
1886
|
+
return (await import("./profile-commands-kmmd9y86.js")).runProfilesCommand(...args);
|
|
2249
1887
|
}
|
|
2250
1888
|
async function runAgentCommand(...args) {
|
|
2251
|
-
return (await import("./agent-
|
|
1889
|
+
return (await import("./agent-mj622k8s.js")).runAgentCommand(...args);
|
|
2252
1890
|
}
|
|
2253
1891
|
async function runProductionCommand(...args) {
|
|
2254
|
-
return (await import("./production-intelligence-
|
|
1892
|
+
return (await import("./production-intelligence-dbe9dmc5.js")).runProductionCommand(...args);
|
|
2255
1893
|
}
|
|
2256
1894
|
function parseArgs(argv) {
|
|
2257
1895
|
const args = argv.slice(2);
|
|
@@ -2456,403 +2094,101 @@ function buildResumeCommand(command, flags) {
|
|
|
2456
2094
|
function printHelp() {
|
|
2457
2095
|
console.log(`Usage: moda <command> [options]
|
|
2458
2096
|
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
auth logout Clear cached Moda auth
|
|
2471
|
-
auth whoami Show the authenticated Moda identity (session or API key)
|
|
2472
|
-
profiles list List local Moda profiles
|
|
2473
|
-
profiles use <name> Switch active Moda profile
|
|
2474
|
-
profiles create <name> Create or update a local Moda profile
|
|
2475
|
-
profiles doctor [name] Validate a local Moda profile
|
|
2476
|
-
config show Show resolved Moda config
|
|
2477
|
-
harness analyze Produce a cited structured harness report
|
|
2478
|
-
harness pull Fetch a server-side analyze run (status, or result when done)
|
|
2479
|
-
harness validate-report Validate .moda/harness-report.json citations
|
|
2480
|
-
harness approve Approve a validated harness report for sync
|
|
2481
|
-
harness scan Discover local runtime agents and write .moda/harness.json
|
|
2482
|
-
harness candidates Static (no-LLM) harness candidate pre-pass with file:line citations
|
|
2483
|
-
harness sync Sync the local harness graph to Moda Cloud
|
|
2484
|
-
harness delete <id-or-key> Permanently delete a synced harness from Moda Cloud
|
|
2485
|
-
harness list|show|versions|diff List synced harnesses, show one, its versions, or a version diff
|
|
2486
|
-
harness register [name] Bundle this repo for Replay Environments and upload it (--dry-run to review)
|
|
2487
|
-
harness registration list|status List registrations, or show one with what Moda still needs
|
|
2488
|
-
harness agents List detected runtime agents and families
|
|
2489
|
-
harness explain Explain the discovered harness graph
|
|
2490
|
-
agent context Emit local Moda context for coding agents
|
|
2491
|
-
agent next-action Emit prioritized next commands for agents
|
|
2492
|
-
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
|
|
2493
2108
|
investigate Rank production issues (tool failures, frustrations, top Problems)
|
|
2494
2109
|
failures Tool failures only, ranked (no frustrations or Problems)
|
|
2495
|
-
ask "question"
|
|
2496
|
-
sync Sync the local harness graph to Moda Cloud
|
|
2497
|
-
sync harness Sync the local harness graph to Moda Cloud
|
|
2498
|
-
sync prompts Sync prompt versions to Moda Cloud
|
|
2499
|
-
doctor --json Emit structured diagnostic checks
|
|
2500
|
-
status --json Emit concise setup state
|
|
2501
|
-
manifest --json Emit the CLI machine protocol manifest
|
|
2502
|
-
overview Harness health briefing with production signals
|
|
2503
|
-
clusters Browse topic cluster hierarchy
|
|
2504
|
-
cluster-traces <node_id> List traces in a cluster
|
|
2505
|
-
traces Search and filter traces (agent runs)
|
|
2506
|
-
traces --sort=longest Sort traces: recent (default), longest, slowest
|
|
2110
|
+
ask "<question>" Ask Moda a production question (one paid agent run)
|
|
2507
2111
|
search "<query>" Search trace messages (keyword/semantic/hybrid)
|
|
2508
|
-
|
|
2509
|
-
context <conversation_id>
|
|
2510
|
-
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
|
|
2511
2114
|
context <id>[@N] <id>[@N] ... Batch: up to 25 traces in one call (or --ids-from=-|<file>)
|
|
2512
2115
|
audit <conversation_id|trace_id> Raw span audit (spans, hierarchy, orphans, duplicates)
|
|
2513
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, ...)
|
|
2514
2125
|
frustrations Frustration detections (same data as emotions --family=frustration)
|
|
2515
|
-
|
|
2516
|
-
hallucinations Grounding detections: contradicted/verified outputs with rule breakdown
|
|
2126
|
+
hallucinations Grounding detections: contradicted/verified outputs
|
|
2517
2127
|
laziness Laziness detections per trace (repeated calls, premature handoffs, ...)
|
|
2518
|
-
tool-failures
|
|
2519
|
-
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:
|
|
2520
2132
|
problems Rank cross-signal Problems by root cause (what to fix first)
|
|
2521
|
-
|
|
2522
|
-
problem-impact Live problem/use-case impact
|
|
2523
|
-
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
|
|
2524
2135
|
problem-feedback <problem_id> Mark a Problem fixed, dismiss, rename, or flag a bad attribution
|
|
2525
|
-
problem-reopen <problem_id> Reopen a Problem marked fixed
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
problem-linear <problem_id> Show the Linear issue linked to a Problem (key, state, URL)
|
|
2529
|
-
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
|
|
2530
2139
|
detection-reviews <conv_id> Problem detections on a trace with their review state
|
|
2531
|
-
detection-review <problem_id> Mark a problem detection correct, a false positive, or clear
|
|
2532
|
-
|
|
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
|
|
2533
2144
|
signal <signal_id> One custom signal, or --detections for its recent hits
|
|
2534
|
-
signals create|update|activate|pause|delete ...
|
|
2535
|
-
Manage custom signals (also draft, examples, refine, revise,
|
|
2536
|
-
proposals, accept, reject, search, preview); writes take --dry-run
|
|
2537
|
-
users / user <user_id> End users with health and activity (the dashboard Users page)
|
|
2538
2145
|
trace-signals <conversation_id> Custom signal hits on one trace
|
|
2539
2146
|
signal-label <signal_id> Label a trace fits / does_not_fit (false positive) for a signal
|
|
2540
|
-
tail Live-tail new traces/detections as NDJSON (one line per item)
|
|
2541
2147
|
feedback "<note>" Flag wrong/missing data or CLI quirks to the Moda team
|
|
2542
2148
|
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
prompts sync --watch Upload again when prompt files change
|
|
2554
|
-
prompts list|show|proposals|usage|replay-runs|decide
|
|
2555
|
-
Read the prompt registry; decide merges/rejects a proposal
|
|
2556
|
-
prompts promote <key> Move a dev/staging/prod label
|
|
2557
|
-
prompts ab Run a judged prompt A/B replay experiment
|
|
2558
|
-
prompts propose Revise a prompt from a run's failures (--gate to auto-A/B, --promote-on-win)
|
|
2559
|
-
|
|
2560
|
-
Replays (read-only results):
|
|
2561
|
-
replays sets List replay sets
|
|
2562
|
-
replays runs <set_id> Run history for a set (every status)
|
|
2563
|
-
replays run <set_id> <run_id> One run: per-case and per-seed verdicts, playout count
|
|
2564
|
-
replays playouts <set_id> <run_id>
|
|
2565
|
-
Playouts per case/arm/seed (--transcript inlines messages and tool calls)
|
|
2566
|
-
replays playout <set_id> <run_id> <playout_id>
|
|
2567
|
-
One playout transcript
|
|
2568
|
-
|
|
2569
|
-
Skills:
|
|
2570
|
-
skills gen Kick off tenant-wide skill generation
|
|
2571
|
-
skills status [run-id] Show a generation run's status, outcome, and recent events (default: latest run)
|
|
2572
|
-
skills pull Pull tenant-generated skills into .claude/skills (and .cursor/rules)
|
|
2573
|
-
skills install <id...> Install bundled integration guides into .claude/skills (--list to browse)
|
|
2574
|
-
skills pull --status=proposed Include not-yet-promoted skills (default: approved)
|
|
2575
|
-
skills sync Push local .claude/skills/**/SKILL.md up to Moda
|
|
2576
|
-
skills sync --dry-run Show what would be pushed without writing
|
|
2577
|
-
skills list|show|policy List pushed skills, show one, or set --live/--local
|
|
2578
|
-
registry push Push prompts, skills, tools, and agent wiring from one JSON manifest
|
|
2579
|
-
|
|
2580
|
-
Options:
|
|
2581
|
-
--help Show this help message
|
|
2582
|
-
--version Show version number
|
|
2583
|
-
--json-schemas Print JSON Schemas for the agent output contract
|
|
2584
|
-
|
|
2585
|
-
Common flags (a command rejects any it does not take; see 'moda <command> --help'):
|
|
2586
|
-
--days-back=N Whole days to look back, 1-90 (overview, problems, emotions, laziness, tool-failures, ...)
|
|
2587
|
-
--time-range=RANGE Window for traces, search, clusters instead (all|1h|3d|7d|24h|30d|90d)
|
|
2588
|
-
--limit=N Maximum results to return (users: alias of --page-size)
|
|
2589
|
-
--offset=N Number of results to skip (paged lists)
|
|
2590
|
-
--profile=NAME Use a named local Moda profile
|
|
2591
|
-
--json Emit machine-readable JSON
|
|
2592
|
-
--agent Emit schema-versioned agent JSON
|
|
2593
|
-
--stream With --agent, emit NDJSON agent events
|
|
2594
|
-
--human Force human prose (overrides auto-detection)
|
|
2595
|
-
--no-stream Disable live ask progress (buffered request)
|
|
2596
|
-
|
|
2597
|
-
Output auto-detection (no flags needed):
|
|
2598
|
-
Piped/redirected stdout, CI, or an agent env (CLAUDECODE/CURSOR/MODA_AGENT)
|
|
2599
|
-
=> schema-versioned agent JSON. An interactive terminal => human prose.
|
|
2600
|
-
Override with the flags above or MODA_FORMAT=human|json|agent|agent-stream.
|
|
2601
|
-
Exit codes: 0 ok, 1 error (errors[0].code says which, e.g. not_found), 3 degraded (local fallback),
|
|
2602
|
-
4 auth required (no key or key rejected), 5 input required, 130 cancelled.
|
|
2603
|
-
--dry-run Show the planned mutation when supported
|
|
2604
|
-
--yes Accept explicit automation defaults
|
|
2605
|
-
--tui Force the human analyst dashboard when supported
|
|
2606
|
-
--no-tui Show raw analyst stream instead of dashboard
|
|
2607
|
-
--no-update-check Skip the daily new-version check (or MODA_CLI_UPDATE_CHECK=0)
|
|
2608
|
-
|
|
2609
|
-
Traces flags:
|
|
2610
|
-
--search=TEXT Ranked trace search (hybrid when embeddings exist, else keyword)
|
|
2611
|
-
--world-state=KEYWORDS Match world-state content (slots + durable profile); comma = AND
|
|
2612
|
-
--outcome=any|positive|negative Filter by trace outcome (trajectory + frustration)
|
|
2613
|
-
--include-world-state Attach each result's world-state summary
|
|
2614
|
-
--user-id=ID Filter to a single user
|
|
2615
|
-
--environment=ENV Filter by environment (all|development|staging|production)
|
|
2616
|
-
--since=DATE --until=DATE Absolute UTC bounds: ISO date or datetime, inclusive; a date --until covers that whole day
|
|
2617
|
-
|
|
2618
|
-
Search flags:
|
|
2619
|
-
--mode=keyword|semantic|hybrid Search mode (default hybrid)
|
|
2620
|
-
--user-id=ID Filter to a single user
|
|
2621
|
-
--conversation-id=ID Search inside one trace only
|
|
2622
|
-
--time-range=RANGE Time range filter (all|1h|3d|7d|24h|30d|90d)
|
|
2623
|
-
--since=DATE --until=DATE Absolute UTC bounds: ISO date or datetime, inclusive; a date --until covers that whole day
|
|
2624
|
-
--limit=N Maximum results to return (1-100, default 20)
|
|
2625
|
-
|
|
2626
|
-
World-state flags:
|
|
2627
|
-
--summary-only Return segment summaries only (omit the event stream)
|
|
2628
|
-
--event-limit=N Max world-state events to return (1-5000, default 2000)
|
|
2629
|
-
--snapshot Folded slots at an exact tick (what the agent believed at that turn)
|
|
2630
|
-
--msg-index=N --block-index=M Snapshot tick (defaults 0; --segment-index=K scopes to a segment)
|
|
2631
|
-
--replay State-over-time replay; frames mode REQUIRES --message-count=N
|
|
2632
|
-
--format=frames|fold-inputs Replay format (default frames)
|
|
2633
|
-
--message-count=N Number of frames to fold (frames mode)
|
|
2634
|
-
|
|
2635
|
-
Emotions flags:
|
|
2636
|
-
--family=F frustration|disapproval|sadness|confusion|anxiety|trust|positive
|
|
2637
|
-
--days-back=N --limit=N Window 1-90 (default 7); page size 1-20 (default 10)
|
|
2638
|
-
--offset=N Skip N detections (0-10000)
|
|
2639
|
-
--include-window Keep each detection's conversation window in agent output
|
|
2640
|
-
(also frustrations; omitted by default, use context_command)
|
|
2641
|
-
|
|
2642
|
-
Laziness flags:
|
|
2643
|
-
--family=F One laziness family (e.g. omission_phrase, stub_body, deflection, completion, tool_selection)
|
|
2644
|
-
--conversation-id=ID One trace's detections
|
|
2645
|
-
--days-back=N --limit=N Window 1-90 (default 7); page size 1-50 (default 10)
|
|
2646
|
-
|
|
2647
|
-
Hallucinations flags:
|
|
2648
|
-
--kind=contradicted|verified Narrow the detections list
|
|
2649
|
-
--conversation-id=ID Scope summary + list to one trace ID
|
|
2650
|
-
--days-back=N --limit=N Window 1-90 (default 7); page size 1-20 (default 10)
|
|
2651
|
-
|
|
2652
|
-
Problem flags (moda problem <id>):
|
|
2653
|
-
--full Whole dossier in agent output (default there: header, summary,
|
|
2654
|
-
top 5 evidence anchors, report titles)
|
|
2655
|
-
--evidence|--reports|--traces|--feedback
|
|
2656
|
-
Open one sub-resource page (at most one)
|
|
2657
|
-
--limit=N --cursor=TOKEN Keyset paging (1-50; pass next_cursor back verbatim)
|
|
2658
|
-
--family=F --door=D Filter --traces (families: tool_failure|emotion|laziness|hallucination|prm_dip|custom_signal|conversation_reader)
|
|
2659
|
-
|
|
2660
|
-
Problem-feedback flags:
|
|
2661
|
-
--action=A mark_fixed|dismiss|flag_attribution|rename (required)
|
|
2662
|
-
--reason=TEXT Required for flag_attribution; optional for dismiss
|
|
2663
|
-
--attribution-id=UUID Required for flag_attribution (ids come from problem --evidence)
|
|
2664
|
-
--new-name=NAME Required for rename
|
|
2665
|
-
|
|
2666
|
-
False-positive flags (moda false-positive <kind> <target>):
|
|
2667
|
-
--reason=TEXT Why it is wrong (optional)
|
|
2668
|
-
--undo Remove an earlier mark (every kind except problem)
|
|
2669
|
-
problem <problem_id> Dismiss the problem: hidden at once, logged for review, folded into reconcile
|
|
2670
|
-
problem-detection <problem_id> One detection on a trace; needs --conversation-id and --attribution-id; teaches the problem
|
|
2671
|
-
quote <conversation_id> A user quote; needs --family, --turn and --quote (from moda emotions); audit only
|
|
2672
|
-
tool <conversation_id> One failing tool call; needs --tool and --tool-use-id (or --msg-index); audit only
|
|
2673
|
-
laziness <conversation_id> Laziness on that trace; audit only
|
|
2674
|
-
hallucination <conversation_id> Hallucinations on that trace; audit only
|
|
2675
|
-
custom-signal <signal_id> A hit on that trace (--conversation-id); saved as does_not_fit, a labelled counterexample for the signal
|
|
2676
|
-
|
|
2677
|
-
Problem-linear-file flags (needs Linear connected: Integrations -> Linear):
|
|
2678
|
-
--issue=ENG-123|URL Link an existing Linear issue instead of filing a new one
|
|
2679
|
-
--team-id=ID File into this Linear team (default: the integration's default team)
|
|
2680
|
-
--title=TEXT Issue title (default: the Problem's name)
|
|
2681
|
-
--priority=N 0 none, 1 urgent, 2 high, 3 medium, 4 low
|
|
2682
|
-
--issue excludes --team-id/--title/--priority
|
|
2683
|
-
|
|
2684
|
-
Detection-review flags (moda detection-review <problem_id>):
|
|
2685
|
-
--conversation-id=ID Trace the detection is on (required)
|
|
2686
|
-
--attribution-id=UUID Detection id (from problem --evidence or detection-reviews; required)
|
|
2687
|
-
--verdict=V correct|false_positive|clear (required; clear undoes a review)
|
|
2688
|
-
--note=TEXT Why (optional; kept with the review)
|
|
2689
|
-
|
|
2690
|
-
Signal flags:
|
|
2691
|
-
--detections moda signal <id>: list recent hits instead of the summary
|
|
2692
|
-
--days-back=N --limit=N --offset=N
|
|
2693
|
-
Hits window 1-90 (default 7); page size 1-20 (default 10)
|
|
2694
|
-
|
|
2695
|
-
Signal-label flags (moda signal-label <signal_id>):
|
|
2696
|
-
--conversation-id=ID Trace to label (required)
|
|
2697
|
-
--label=fits|does_not_fit does_not_fit marks a false positive and retracts the hit (required)
|
|
2698
|
-
--note=TEXT Why (recommended for does_not_fit)
|
|
2699
|
-
--msg-index=N --msg-dedup-token=T
|
|
2700
|
-
Anchor message (from the hit's anchor_msg_index / anchor_dedup_token)
|
|
2701
|
-
|
|
2702
|
-
Tail flags:
|
|
2703
|
-
--signal=S traces|emotions|all (default traces)
|
|
2704
|
-
--interval=N Poll every N seconds (5-3600, default 15)
|
|
2705
|
-
--once One poll, then exit (baseline page)
|
|
2706
|
-
--limit=N --max-events=N Page size per poll; stop after N stdout records
|
|
2707
|
-
(metadata included; a slot is reserved for the
|
|
2708
|
-
emotions coverage record, which falls back to
|
|
2709
|
-
stderr if the bound leaves no room)
|
|
2710
|
-
--full-scan Emotions: scan the whole window instead of the
|
|
2711
|
-
top-scoring prefix (many more requests). /emotions
|
|
2712
|
-
is score-ranked with no cursor, so the default
|
|
2713
|
-
follows the highest-scoring detections and emits a
|
|
2714
|
-
tail_coverage line stating exactly what it saw.
|
|
2715
|
-
|
|
2716
|
-
Clusters search flags:
|
|
2717
|
-
--search="query" Find clusters by name/meaning (task-cluster search)
|
|
2718
|
-
--node-id=ID Deterministically resolve one cluster node (deep link)
|
|
2719
|
-
--mode=fuzzy|semantic|hybrid Cluster search mode (default hybrid)
|
|
2720
|
-
|
|
2721
|
-
Feedback flags:
|
|
2722
|
-
--category=CAT ${feedbackCategoryHelp()}
|
|
2723
|
-
An unknown category is sent as other (with refs.raw_category)
|
|
2724
|
-
--severity=info|low|medium|high How bad it is (default low)
|
|
2725
|
-
--note=TEXT The note, if not given as the positional argument
|
|
2726
|
-
--conversation-id=ID Attach the trace ID you were looking at
|
|
2727
|
-
--cluster-id=ID Attach a cluster node id
|
|
2728
|
-
--tool-name=NAME Attach a tool name
|
|
2729
|
-
--run-id=ID Attach a run id
|
|
2730
|
-
--<name>-id=ID Any other id (--problem-id, --fix-id, --attribution-id,
|
|
2731
|
-
--trace-id, --span-id, --message-index, ...) goes into refs
|
|
2732
|
-
(set MODA_CLI_TIPS=0 to hide the feedback tip line)
|
|
2733
|
-
|
|
2734
|
-
Init flags:
|
|
2735
|
-
--yes Accept all defaults (non-interactive)
|
|
2736
|
-
--analyst=auto|claude|codex|cursor|local-scan
|
|
2737
|
-
Choose harness analyst adapter
|
|
2738
|
-
--analyst-model=MODEL Model for the claude analyst (default: sonnet;
|
|
2739
|
-
"default" = the claude CLI's own default;
|
|
2740
|
-
env: MODA_HARNESS_ANALYST_MODEL)
|
|
2741
|
-
--assist=none Disable agent fallback for prompt discovery
|
|
2742
|
-
--concern=topology|tools|prompts|evals
|
|
2743
|
-
Harness analyze: restrict the pass to one
|
|
2744
|
-
concern (whole repo, one report scope); an
|
|
2745
|
-
orchestrator merges the per-concern reports
|
|
2746
|
-
(env: MODA_HARNESS_CONCERN, flag wins)
|
|
2747
|
-
--allow-no-agents Allow harness sync to push a graph with zero
|
|
2748
|
-
runtime agents despite detected LLM usage
|
|
2749
|
-
--remote Run harness analysis server-side (Moda-hosted,
|
|
2750
|
-
the default): upload a safe source snapshot; no
|
|
2751
|
-
local coding agent required
|
|
2752
|
-
--local Run harness analysis with a LOCAL coding agent
|
|
2753
|
-
instead of server-side (opt out of remote)
|
|
2754
|
-
--tui Show full-screen analyst dashboard in human TTYs
|
|
2755
|
-
--no-tui Show raw external analyst output
|
|
2756
|
-
--sdk-integrate Run your coding agent to install the Moda SDK and instrument LLM calls
|
|
2757
|
-
--no-sdk-integrate Skip SDK integration (alias: --no-sdk-guide)
|
|
2758
|
-
--verification-id=ID Tag the SDK integration's test trace with this id
|
|
2759
|
-
(the onb_ id from the Moda onboarding page)
|
|
2760
|
-
--connect-code=CODE Sign in with the one-time mcc_ code from the Moda
|
|
2761
|
-
onboarding page instead of the browser (10 min, single use)
|
|
2762
|
-
--ci-cd Create GitHub Actions Moda validation workflow
|
|
2763
|
-
--no-ci-cd Skip CI/CD workflow creation
|
|
2764
|
-
--autosync Create GitHub Actions workflow to sync prompts + skills to Moda on push to main
|
|
2765
|
-
--no-autosync Skip autosync workflow creation
|
|
2766
|
-
--harness-rescan Create GitHub Actions workflow to re-scan the harness and sync it to Moda on push to main
|
|
2767
|
-
--no-harness-rescan Skip harness rescan workflow creation
|
|
2768
|
-
--harness-rescan-paths=GLOBS Comma-separated path globs that scope which pushes trigger the
|
|
2769
|
-
harness rescan workflow (implies --harness-rescan)
|
|
2770
|
-
--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
|
|
2771
2159
|
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
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
|
|
2779
2167
|
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
moda auth whoami
|
|
2784
|
-
moda provision --tenant-id=<org-id>
|
|
2785
|
-
moda status
|
|
2786
|
-
moda manifest --json
|
|
2787
|
-
moda doctor --json
|
|
2788
|
-
moda profiles list
|
|
2789
|
-
moda profiles use staging
|
|
2790
|
-
moda config show --profile=prod
|
|
2791
|
-
moda harness analyze --experimental --summary
|
|
2792
|
-
moda harness analyze --experimental --remote
|
|
2793
|
-
moda harness analyze --experimental --analyst=claude --tui
|
|
2794
|
-
moda harness analyze --experimental --analyst=claude --no-tui
|
|
2795
|
-
moda harness analyze --experimental --analyst=claude --summary
|
|
2796
|
-
moda harness analyze --experimental --analyst=local-scan --summary
|
|
2797
|
-
moda harness pull --sync
|
|
2798
|
-
moda harness validate-report
|
|
2799
|
-
moda harness approve --yes
|
|
2800
|
-
moda harness sync --from-report .moda/harness-report.json
|
|
2801
|
-
moda harness delete my-harness-key --yes
|
|
2802
|
-
moda --agent doctor
|
|
2803
|
-
moda agent context
|
|
2804
|
-
moda agent next-action
|
|
2805
|
-
moda agent evidence doctor:api_key_resolves
|
|
2806
|
-
moda investigate
|
|
2807
|
-
moda failures
|
|
2808
|
-
moda ask "what should I fix first?"
|
|
2809
|
-
moda sync --dry-run
|
|
2810
|
-
moda sync harness --profile=prod
|
|
2811
|
-
moda harness scan --json
|
|
2812
|
-
moda harness candidates --out=.moda/harness-candidates.json
|
|
2813
|
-
moda harness explain --agent=agent_support
|
|
2814
|
-
moda init --ci-cd
|
|
2815
|
-
moda init --autosync
|
|
2816
|
-
moda init --harness-rescan --harness-rescan-paths='src/agents/**'
|
|
2817
|
-
moda overview --days-back=30
|
|
2818
|
-
moda clusters --time-range=7d
|
|
2819
|
-
moda traces --search="error" --limit=5
|
|
2820
|
-
moda traces --world-state="enterprise" --outcome=positive
|
|
2821
|
-
moda traces --world-state="refund,billing" --include-world-state
|
|
2822
|
-
moda search "billing error" --mode=hybrid
|
|
2823
|
-
moda search "refund flow" --mode=semantic --time-range=7d --limit=10
|
|
2824
|
-
moda world-state <conversation_id> --summary-only
|
|
2825
|
-
moda world-state <conversation_id> --snapshot --msg-index=42
|
|
2826
|
-
moda world-state <conversation_id> --replay --message-count=50
|
|
2827
|
-
moda clusters --search="billing disputes"
|
|
2828
|
-
moda emotions --family=confusion --days-back=14
|
|
2829
|
-
moda hallucinations --kind=contradicted
|
|
2830
|
-
moda problems --days-back=7
|
|
2831
|
-
moda problem <problem_id> --evidence --limit=10
|
|
2832
|
-
moda problem-feedback <problem_id> --action=mark_fixed
|
|
2833
|
-
moda problem-linear <problem_id>
|
|
2834
|
-
moda problem-linear-file <problem_id> --priority=2
|
|
2835
|
-
moda detection-reviews <conversation_id>
|
|
2836
|
-
moda detection-review <problem_id> --conversation-id=<id> --attribution-id=<uuid> --verdict=false_positive --note="expected retry"
|
|
2837
|
-
moda signals
|
|
2838
|
-
moda signal <signal_id> --detections --days-back=30
|
|
2839
|
-
moda signal-label <signal_id> --conversation-id=<id> --label=does_not_fit --note="refund was approved"
|
|
2840
|
-
moda tail --signal=all --interval=30
|
|
2841
|
-
moda frustrations --days-back=14 --limit=20
|
|
2842
|
-
moda feedback "cluster label looks wrong" --category=bad_cluster_label --cluster-id=<node_id>
|
|
2843
|
-
moda context <conversation_id> --window=3
|
|
2844
|
-
moda audit <conversation_id|trace_id>
|
|
2845
|
-
moda audit <trace_id> --kind=trace --json
|
|
2846
|
-
moda prompts status
|
|
2847
|
-
moda prompts sync
|
|
2848
|
-
moda prompts promote support.triage --label=prod --version=pver_abc123
|
|
2849
|
-
moda prompts ab --baseline=prompts/agent.prompt.md --candidate=prompts/agent-v2.prompt.md --traces=conv_1,conv_2
|
|
2850
|
-
moda prompts ab --baseline=prompts/agent.prompt.md --candidate=prompts/agent-v2.prompt.md --traces=conv_1@412 # replay from msg 412
|
|
2851
|
-
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.
|
|
2852
2171
|
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
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;
|
|
2856
2192
|
}
|
|
2857
2193
|
function printCommandHelp(definition) {
|
|
2858
2194
|
const lines = [];
|
|
@@ -2866,6 +2202,17 @@ function printCommandHelp(definition) {
|
|
|
2866
2202
|
for (const note of definition.helpNotes ?? []) {
|
|
2867
2203
|
lines.push("", note);
|
|
2868
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
|
+
}
|
|
2869
2216
|
if (definition.subcommands && definition.subcommands.length > 0) {
|
|
2870
2217
|
lines.push("", "Subcommands:");
|
|
2871
2218
|
const width = Math.max(...definition.subcommands.map((entry) => entry.name.length));
|
|
@@ -2880,7 +2227,7 @@ function printCommandHelp(definition) {
|
|
|
2880
2227
|
lines.push(` ${example}`);
|
|
2881
2228
|
}
|
|
2882
2229
|
}
|
|
2883
|
-
lines.push("",
|
|
2230
|
+
lines.push("", ...globalFlagHelpLines(flagSpec ? specFlagKeys(flagSpec) : []), flagSpec ? "Any other flag is rejected." : "Run 'moda --help' for the command list.");
|
|
2884
2231
|
console.log(lines.join(`
|
|
2885
2232
|
`));
|
|
2886
2233
|
}
|
|
@@ -3263,7 +2610,7 @@ function recordSearchTelemetry(context, data) {
|
|
|
3263
2610
|
const pagination = asRecord(record.pagination);
|
|
3264
2611
|
const hasMore = pagination?.has_more;
|
|
3265
2612
|
context.recordTelemetry({
|
|
3266
|
-
search_mode_effective:
|
|
2613
|
+
search_mode_effective: SEARCH_MODES.includes(effective) ? effective : undefined,
|
|
3267
2614
|
result_count: results.length,
|
|
3268
2615
|
has_more: hasMore === true ? "yes" : hasMore === false ? "no" : "na",
|
|
3269
2616
|
...typeof record.degrade_reason === "string" && record.degrade_reason ? { degrade_reason: record.degrade_reason.slice(0, 64) } : {}
|
|
@@ -3344,7 +2691,6 @@ var GLOBAL_FLAG_NAMES = new Set([
|
|
|
3344
2691
|
"no-telemetry",
|
|
3345
2692
|
"no-update-check"
|
|
3346
2693
|
]);
|
|
3347
|
-
var OVERVIEW_PRODUCTION_FLAGS = ["raw"];
|
|
3348
2694
|
var WINDOW_FLAG_HINTS = {
|
|
3349
2695
|
days_back: "This command takes --time-range (e.g. --time-range=7d), not --days-back.",
|
|
3350
2696
|
time_range: "This command takes --days-back=N (1-90), not --time-range."
|
|
@@ -3355,27 +2701,8 @@ var COMMAND_FLAG_HINTS = {
|
|
|
3355
2701
|
cursor: "'moda problems' has no cursor; 'moda problems remainder --cursor=<next_cursor>' pages the unexplained signals."
|
|
3356
2702
|
}
|
|
3357
2703
|
};
|
|
3358
|
-
function editDistance(a, b) {
|
|
3359
|
-
const row = Array.from({ length: b.length + 1 }, (_, index) => index);
|
|
3360
|
-
for (let i = 1;i <= a.length; i++) {
|
|
3361
|
-
let previous = row[0];
|
|
3362
|
-
row[0] = i;
|
|
3363
|
-
for (let j = 1;j <= b.length; j++) {
|
|
3364
|
-
const current = row[j];
|
|
3365
|
-
row[j] = Math.min(row[j] + 1, row[j - 1] + 1, previous + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
3366
|
-
previous = current;
|
|
3367
|
-
}
|
|
3368
|
-
}
|
|
3369
|
-
return row[b.length];
|
|
3370
|
-
}
|
|
3371
|
-
function schemaFlagKeys(schema) {
|
|
3372
|
-
let current = schema;
|
|
3373
|
-
while (current instanceof z2.ZodEffects)
|
|
3374
|
-
current = current.innerType();
|
|
3375
|
-
return current instanceof z2.ZodObject ? Object.keys(current.shape) : [];
|
|
3376
|
-
}
|
|
3377
2704
|
function parseCommandFlags(schema, args, command, options = {}) {
|
|
3378
|
-
const schemaKeys =
|
|
2705
|
+
const schemaKeys = Object.keys(schemaShape(schema));
|
|
3379
2706
|
const known = new Set([
|
|
3380
2707
|
...schemaKeys,
|
|
3381
2708
|
...[...GLOBAL_FLAG_NAMES, ...options.extraFlags ?? []].map((flag) => flag.replace(/-/g, "_"))
|
|
@@ -3385,24 +2712,70 @@ function parseCommandFlags(schema, args, command, options = {}) {
|
|
|
3385
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");
|
|
3386
2713
|
}
|
|
3387
2714
|
if (unknown.length > 0) {
|
|
3388
|
-
const flagKeys =
|
|
3389
|
-
|
|
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 = [];
|
|
3390
2722
|
const hints = unknown.map((key) => {
|
|
3391
2723
|
const commandHint = COMMAND_FLAG_HINTS[command]?.[key];
|
|
3392
2724
|
if (commandHint)
|
|
3393
2725
|
return commandHint;
|
|
3394
2726
|
const windowAlternative = key === "days_back" ? "time_range" : key === "time_range" ? "days_back" : undefined;
|
|
3395
|
-
if (windowAlternative && WINDOW_FLAG_HINTS[key] && flagKeys.includes(windowAlternative))
|
|
2727
|
+
if (windowAlternative && WINDOW_FLAG_HINTS[key] && flagKeys.includes(windowAlternative)) {
|
|
2728
|
+
didYouMean.push(kebabFlag(windowAlternative));
|
|
3396
2729
|
return WINDOW_FLAG_HINTS[key];
|
|
2730
|
+
}
|
|
3397
2731
|
if (windowAlternative)
|
|
3398
2732
|
return `This command has no time-window flag.`;
|
|
3399
|
-
const close =
|
|
3400
|
-
|
|
2733
|
+
const close = closestMatches(kebabFlag(key), candidates, 1)[0];
|
|
2734
|
+
if (close)
|
|
2735
|
+
didYouMean.push(close);
|
|
2736
|
+
return close ? `Did you mean ${close}?` : "";
|
|
3401
2737
|
}).filter(Boolean);
|
|
3402
|
-
const names = unknown.map(
|
|
3403
|
-
|
|
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
|
+
});
|
|
3404
2746
|
}
|
|
3405
|
-
|
|
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
|
+
};
|
|
3406
2779
|
}
|
|
3407
2780
|
function withStringIdFlags(args, flags) {
|
|
3408
2781
|
for (const flag of ["user-id", "conversation-id"]) {
|
|
@@ -3590,36 +2963,12 @@ function serverWarnings(data) {
|
|
|
3590
2963
|
function isDefinedRecord(value) {
|
|
3591
2964
|
return value !== undefined && value !== null;
|
|
3592
2965
|
}
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
signals: [],
|
|
3600
|
-
"problem-feedback": ["action", "actor", "reason", "attribution-id", "new-name"],
|
|
3601
|
-
"problem-linear": [],
|
|
3602
|
-
"problem-linear-file": ["issue", "priority", "title", "team-id"],
|
|
3603
|
-
"signal-label": ["label", "note", "conversation-id", "msg-dedup-token", "msg-index"],
|
|
3604
|
-
"detection-reviews": ["attribution-id"],
|
|
3605
|
-
"detection-review": ["note", "verdict", "attribution-id", "conversation-id"],
|
|
3606
|
-
"false-positive": [
|
|
3607
|
-
"family",
|
|
3608
|
-
"quote",
|
|
3609
|
-
"reason",
|
|
3610
|
-
"tool",
|
|
3611
|
-
"turn",
|
|
3612
|
-
"undo",
|
|
3613
|
-
"attribution-id",
|
|
3614
|
-
"conversation-id",
|
|
3615
|
-
"msg-dedup-token",
|
|
3616
|
-
"msg-index",
|
|
3617
|
-
"tool-use-id"
|
|
3618
|
-
],
|
|
3619
|
-
"false-positives": ["all", "kind", "limit"],
|
|
3620
|
-
feedback: FEEDBACK_FLAGS,
|
|
3621
|
-
"problem-impact": ["mode", "node-id", "problem-id", "run-id", "to", "cursor", "conversation-ids", "days-back"]
|
|
3622
|
-
};
|
|
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
|
+
}
|
|
3623
2972
|
var NO_POSITIONAL_COMMANDS = new Set([
|
|
3624
2973
|
"overview",
|
|
3625
2974
|
"investigate",
|
|
@@ -3645,18 +2994,18 @@ function assertHandParsedFlags(command, flags, positionals) {
|
|
|
3645
2994
|
if (NO_POSITIONAL_COMMANDS.has(command) && positionals.length > 0) {
|
|
3646
2995
|
throw new CliInputError(`'moda ${command}' takes no arguments, but got '${positionals.join(" ")}'.`, `Nothing was run. See 'moda ${command} --help' for its flags.`);
|
|
3647
2996
|
}
|
|
3648
|
-
const
|
|
3649
|
-
if (!
|
|
2997
|
+
const hand = handParsedFlags(command);
|
|
2998
|
+
if (!hand)
|
|
3650
2999
|
return;
|
|
3651
|
-
const checked =
|
|
3652
|
-
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()])));
|
|
3653
3002
|
const args = Object.fromEntries(checked.map((flag) => [flag.replace(/-/g, "_"), true]));
|
|
3654
3003
|
try {
|
|
3655
|
-
parseCommandFlags(shape.passthrough(), args, command);
|
|
3004
|
+
parseCommandFlags(shape.passthrough(), args, command, { flagAliases: hand.spec.flagAliases });
|
|
3656
3005
|
} catch (error) {
|
|
3657
3006
|
if (command !== "feedback" || !(error instanceof CliInputError))
|
|
3658
3007
|
throw error;
|
|
3659
|
-
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);
|
|
3660
3009
|
}
|
|
3661
3010
|
}
|
|
3662
3011
|
function normalizeBooleanFlags(target) {
|
|
@@ -3679,7 +3028,7 @@ function normalizeBooleanFlags(target) {
|
|
|
3679
3028
|
}
|
|
3680
3029
|
var PROFILE_MANAGING_COMMANDS = new Set(["profiles", "auth", "init", "provision", "status", "config", "manifest", "agent", "doctor"]);
|
|
3681
3030
|
async function runProblemsRemainder(flags, context) {
|
|
3682
|
-
const params = parseCommandFlags(ProblemsRemainderSchema, flagsToArgs(flags), "problems remainder");
|
|
3031
|
+
const params = parseCommandFlags(ProblemsRemainderSchema, flagsToArgs(flags), "problems remainder", specParseOptions(COMMAND_FLAG_SPECS.problems.subcommands.remainder));
|
|
3683
3032
|
const query2 = new URLSearchParams;
|
|
3684
3033
|
if (params.days_back)
|
|
3685
3034
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -3744,7 +3093,7 @@ function parseContextRequest(positional, rawFlags) {
|
|
|
3744
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.`);
|
|
3745
3094
|
}
|
|
3746
3095
|
const args = { ...flagsToArgs(flags), conversation_id: conversationId };
|
|
3747
|
-
const params =
|
|
3096
|
+
const params = parseSpecFlags("context", args);
|
|
3748
3097
|
if (params.metadata_only === true && params.window !== undefined) {
|
|
3749
3098
|
throw new CliInputError("--metadata-only reads no messages, so it cannot be combined with --window; drop --window.", CONTEXT_USAGE, "flag_conflict");
|
|
3750
3099
|
}
|
|
@@ -3896,8 +3245,8 @@ async function readFullTranscript(conversationId, opts = {}) {
|
|
|
3896
3245
|
if (tied > 0 || synthetic > 0) {
|
|
3897
3246
|
out.push(`Message order may not be chronological: ${tied} of ${total} messages share a timestamp with another message (ordered by id, not time)${synthetic > 0 ? ` and ${synthetic} carry a synthetic pre-2022 timestamp` : ""}.`);
|
|
3898
3247
|
}
|
|
3899
|
-
if (returned.some(isTruncated)) {
|
|
3900
|
-
out.push(`
|
|
3248
|
+
if (legacy && returned.some(isTruncated)) {
|
|
3249
|
+
out.push(`This Moda server is older and truncates message text, tool-call inputs and tool results longer than ${CONTEXT_MESSAGE_TRUNCATE_CHARS} characters. For full content (prompts, tool arguments/results) use \`moda audit <conversation_id> --include-bodies\` (or \`--include-raw\` for the verbatim events).`);
|
|
3901
3250
|
}
|
|
3902
3251
|
return {
|
|
3903
3252
|
data: stripLoneSurrogates({
|
|
@@ -4180,7 +3529,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4180
3529
|
}
|
|
4181
3530
|
case "overview": {
|
|
4182
3531
|
const args = flagsToArgs(flags);
|
|
4183
|
-
|
|
3532
|
+
parseSpecFlags("overview", args, command);
|
|
4184
3533
|
return (await runProductionCommand(context)).exitCode;
|
|
4185
3534
|
}
|
|
4186
3535
|
case "investigate":
|
|
@@ -4190,7 +3539,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4190
3539
|
}
|
|
4191
3540
|
case "clusters": {
|
|
4192
3541
|
const args = flagsToArgs(flags);
|
|
4193
|
-
const params =
|
|
3542
|
+
const params = parseSpecFlags("clusters", args, command);
|
|
4194
3543
|
if (params.search !== undefined || params.node_id !== undefined) {
|
|
4195
3544
|
const query3 = new URLSearchParams;
|
|
4196
3545
|
if (params.search !== undefined)
|
|
@@ -4224,7 +3573,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4224
3573
|
throw new CliInputError("<node_id> is required", "Usage: moda cluster-traces <node_id> [--limit=N] [--offset=N]");
|
|
4225
3574
|
}
|
|
4226
3575
|
const args = flagsToArgs(flags, "node_id", positional);
|
|
4227
|
-
const params =
|
|
3576
|
+
const params = parseSpecFlags("cluster-traces", args, command);
|
|
4228
3577
|
const query2 = new URLSearchParams;
|
|
4229
3578
|
if (params.limit)
|
|
4230
3579
|
query2.set("limit", params.limit.toString());
|
|
@@ -4240,7 +3589,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4240
3589
|
case "traces":
|
|
4241
3590
|
case "conversations": {
|
|
4242
3591
|
const args = withStringIdFlags(flagsToArgs(flags), flags);
|
|
4243
|
-
const params =
|
|
3592
|
+
const params = parseSpecFlags("traces", args, command);
|
|
4244
3593
|
const query2 = new URLSearchParams;
|
|
4245
3594
|
if (params.search)
|
|
4246
3595
|
query2.set("search", params.search);
|
|
@@ -4302,7 +3651,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4302
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]');
|
|
4303
3652
|
}
|
|
4304
3653
|
const args = withStringIdFlags(flagsToArgs(flags, "q", positional), flags);
|
|
4305
|
-
const params =
|
|
3654
|
+
const params = parseSpecFlags("search", args, command);
|
|
4306
3655
|
const query2 = new URLSearchParams;
|
|
4307
3656
|
query2.set("q", params.q);
|
|
4308
3657
|
if (params.mode)
|
|
@@ -4358,7 +3707,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4358
3707
|
throw new CliInputError("<conversation_id> is required", "Usage: moda world-state <conversation_id> [--summary-only] [--event-limit=N]");
|
|
4359
3708
|
}
|
|
4360
3709
|
const args = flagsToArgs(flags, "conversation_id", positional);
|
|
4361
|
-
const params =
|
|
3710
|
+
const params = parseSpecFlags("world-state", args, command);
|
|
4362
3711
|
if (params.snapshot === true && params.replay === true) {
|
|
4363
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]]");
|
|
4364
3713
|
}
|
|
@@ -4416,7 +3765,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4416
3765
|
throw new CliInputError("<conversation_id|trace_id> is required", AUDIT_USAGE);
|
|
4417
3766
|
}
|
|
4418
3767
|
const args = flagsToArgs(flags, "id", positional);
|
|
4419
|
-
const params =
|
|
3768
|
+
const params = parseSpecFlags("audit", args, command);
|
|
4420
3769
|
const agentMode = context.output.mode === "agent" || context.output.mode === "agent-stream";
|
|
4421
3770
|
const page = await readAuditItem(command, params, agentMode ? {
|
|
4422
3771
|
maxBytes: Math.max(AUDIT_MIN_PAGE_BYTES, agentMaxOutputBytes() - AUDIT_AGENT_RESERVE_BYTES),
|
|
@@ -4427,7 +3776,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4427
3776
|
}
|
|
4428
3777
|
case "frustrations": {
|
|
4429
3778
|
const args = withStringIdFlags(flagsToArgs(flags), flags);
|
|
4430
|
-
const params =
|
|
3779
|
+
const params = parseSpecFlags("frustrations", args, command);
|
|
4431
3780
|
const query2 = new URLSearchParams;
|
|
4432
3781
|
if (params.days_back)
|
|
4433
3782
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -4449,7 +3798,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4449
3798
|
}
|
|
4450
3799
|
case "tool-failures": {
|
|
4451
3800
|
const args = flagsToArgs(flags);
|
|
4452
|
-
const params =
|
|
3801
|
+
const params = parseSpecFlags("tool-failures", args, command);
|
|
4453
3802
|
const queryString = params.days_back ? `?days_back=${params.days_back}` : "";
|
|
4454
3803
|
const data = await callDataAPI(`/tool-failures${queryString}`);
|
|
4455
3804
|
context.output.writeData(data);
|
|
@@ -4467,7 +3816,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4467
3816
|
toolFlags["include-window"] = "false";
|
|
4468
3817
|
}
|
|
4469
3818
|
const args = flagsToArgs(toolFlags, "tool_name", positional);
|
|
4470
|
-
const params =
|
|
3819
|
+
const params = parseSpecFlags("tool-failure-detail", args, command);
|
|
4471
3820
|
const dropConversation = params.compact === true || params.include_window === false;
|
|
4472
3821
|
if (params.compact === true && params.include_window === true) {
|
|
4473
3822
|
throw new CliInputError("--compact drops the conversation window; drop --include-window, or drop --compact.");
|
|
@@ -4547,7 +3896,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4547
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>'.");
|
|
4548
3897
|
}
|
|
4549
3898
|
const args = flagsToArgs(flags);
|
|
4550
|
-
const params =
|
|
3899
|
+
const params = parseSpecFlags("problems", args, command);
|
|
4551
3900
|
const query2 = new URLSearchParams;
|
|
4552
3901
|
if (params.days_back)
|
|
4553
3902
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -4574,7 +3923,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4574
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]");
|
|
4575
3924
|
}
|
|
4576
3925
|
const args = flagsToArgs(flags, "id", positional);
|
|
4577
|
-
const params =
|
|
3926
|
+
const params = parseSpecFlags("problem", args, command);
|
|
4578
3927
|
const traceView = params.traces === true || params.conversations === true;
|
|
4579
3928
|
const views = ["evidence", "reports", "conversations", "feedback"].filter((view2) => view2 === "conversations" ? traceView : params[view2] === true);
|
|
4580
3929
|
if (views.length > 1) {
|
|
@@ -4748,7 +4097,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4748
4097
|
}
|
|
4749
4098
|
const args = flagsToArgs(flags, "id", positional);
|
|
4750
4099
|
args.id = positional;
|
|
4751
|
-
const params =
|
|
4100
|
+
const params = parseSpecFlags("signal", args, command);
|
|
4752
4101
|
const id = encodeURIComponent(params.id);
|
|
4753
4102
|
if (params.detections !== true) {
|
|
4754
4103
|
const data2 = await callDataAPI(`/custom-signals/${id}`);
|
|
@@ -4941,7 +4290,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4941
4290
|
}
|
|
4942
4291
|
case "emotions": {
|
|
4943
4292
|
const args = withStringIdFlags(flagsToArgs(flags), flags);
|
|
4944
|
-
const params =
|
|
4293
|
+
const params = parseSpecFlags("emotions", args, command);
|
|
4945
4294
|
const query2 = new URLSearchParams;
|
|
4946
4295
|
if (params.days_back)
|
|
4947
4296
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -4969,7 +4318,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4969
4318
|
if (flags["conversation-id"] !== undefined) {
|
|
4970
4319
|
args.conversation_id = flags["conversation-id"];
|
|
4971
4320
|
}
|
|
4972
|
-
const params =
|
|
4321
|
+
const params = parseSpecFlags("laziness", args, command);
|
|
4973
4322
|
const query2 = new URLSearchParams;
|
|
4974
4323
|
if (params.days_back)
|
|
4975
4324
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -4991,7 +4340,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
4991
4340
|
if (flags["conversation-id"] !== undefined) {
|
|
4992
4341
|
args.conversation_id = flags["conversation-id"];
|
|
4993
4342
|
}
|
|
4994
|
-
const params =
|
|
4343
|
+
const params = parseSpecFlags("hallucinations", args, command);
|
|
4995
4344
|
const query2 = new URLSearchParams;
|
|
4996
4345
|
if (params.days_back)
|
|
4997
4346
|
query2.set("days_back", params.days_back.toString());
|
|
@@ -5025,7 +4374,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5025
4374
|
}
|
|
5026
4375
|
case "tail": {
|
|
5027
4376
|
const args = flagsToArgs(flags);
|
|
5028
|
-
const params =
|
|
4377
|
+
const params = parseSpecFlags("tail", args, command);
|
|
5029
4378
|
await runTailCommand(params, context);
|
|
5030
4379
|
break;
|
|
5031
4380
|
}
|
|
@@ -5050,7 +4399,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
5050
4399
|
break;
|
|
5051
4400
|
}
|
|
5052
4401
|
default:
|
|
5053
|
-
throw
|
|
4402
|
+
throw unknownCommandError(command);
|
|
5054
4403
|
}
|
|
5055
4404
|
return 0;
|
|
5056
4405
|
}
|
|
@@ -5153,6 +4502,30 @@ var commandRegistry = createCommandRegistry([
|
|
|
5153
4502
|
name: "init",
|
|
5154
4503
|
description: "Set up Moda in your project",
|
|
5155
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
|
+
],
|
|
5156
4529
|
auth: "none",
|
|
5157
4530
|
outputModes: ["human", "json", "agent"],
|
|
5158
4531
|
mutability: "write",
|
|
@@ -5160,7 +4533,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
5160
4533
|
resetApiRequestCountBeforeRun: true,
|
|
5161
4534
|
telemetry: "result-and-error",
|
|
5162
4535
|
handler: async (context) => {
|
|
5163
|
-
const { runInit } = await import("./index-
|
|
4536
|
+
const { runInit } = await import("./index-ewqbpnwz.js");
|
|
5164
4537
|
if (context.outputMode === "agent-stream") {
|
|
5165
4538
|
context.output.writeEvent({
|
|
5166
4539
|
event: "started",
|
|
@@ -5194,6 +4567,12 @@ var commandRegistry = createCommandRegistry([
|
|
|
5194
4567
|
"moda provision --tenant-id=<org-id> --label=ci-runner --save",
|
|
5195
4568
|
"KEY=$(moda provision --tenant-id <org-id> | jq -r .apiKey)"
|
|
5196
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
|
+
],
|
|
5197
4576
|
auth: "none",
|
|
5198
4577
|
outputModes: ["human", "json", "agent"],
|
|
5199
4578
|
mutability: "write",
|
|
@@ -5201,7 +4580,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
5201
4580
|
resetApiRequestCountBeforeRun: true,
|
|
5202
4581
|
telemetry: "result-and-error",
|
|
5203
4582
|
handler: async (context) => {
|
|
5204
|
-
const { runProvision } = await import("./provision-
|
|
4583
|
+
const { runProvision } = await import("./provision-wzttap58.js");
|
|
5205
4584
|
return runProvision(context, {
|
|
5206
4585
|
resumeCommand: buildResumeCommand("provision", context.rawFlags)
|
|
5207
4586
|
});
|
|
@@ -5800,6 +5179,9 @@ var commandRegistry = createCommandRegistry([
|
|
|
5800
5179
|
legacyCommand({
|
|
5801
5180
|
name: "false-positive",
|
|
5802
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
|
+
],
|
|
5803
5185
|
examples: [
|
|
5804
5186
|
'moda false-positive problem <problem_id> --reason="two unrelated tools"',
|
|
5805
5187
|
'moda false-positive problem-detection <problem_id> --conversation-id=<id> --attribution-id=<uuid> --reason="refund was approved"',
|
|
@@ -5917,6 +5299,9 @@ var commandRegistry = createCommandRegistry([
|
|
|
5917
5299
|
'moda feedback "search finds nothing for a trace I can open" --category=missing_data --conversation-id=<id>',
|
|
5918
5300
|
'moda feedback "trace is about refunds, not this problem" --category=false_positive_attribution --problem-id=<id> --conversation-id=<id>'
|
|
5919
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
|
+
],
|
|
5920
5305
|
...dataApiDefaults,
|
|
5921
5306
|
mutability: "write"
|
|
5922
5307
|
}),
|
|
@@ -6116,7 +5501,7 @@ function classifyCliError(error) {
|
|
|
6116
5501
|
return "auth_error";
|
|
6117
5502
|
if (error instanceof ApiError && error.statusCode === 403)
|
|
6118
5503
|
return "access_error";
|
|
6119
|
-
if (error instanceof
|
|
5504
|
+
if (error instanceof z.ZodError || error instanceof CliInputError || error instanceof CliInputRequiredError) {
|
|
6120
5505
|
return "validation_error";
|
|
6121
5506
|
}
|
|
6122
5507
|
if (error instanceof ApiError || isApiLikeError(error)) {
|
|
@@ -6128,7 +5513,7 @@ function classifyCliError(error) {
|
|
|
6128
5513
|
return "unknown_error";
|
|
6129
5514
|
}
|
|
6130
5515
|
function cliValidationReason(error) {
|
|
6131
|
-
if (error instanceof
|
|
5516
|
+
if (error instanceof z.ZodError) {
|
|
6132
5517
|
const issue = error.issues[0];
|
|
6133
5518
|
if (!issue)
|
|
6134
5519
|
return "zod";
|
|
@@ -6155,7 +5540,7 @@ function printCliError(error) {
|
|
|
6155
5540
|
if (error.guidance)
|
|
6156
5541
|
safeWriteStderr(`${error.guidance}
|
|
6157
5542
|
`);
|
|
6158
|
-
} else if (error instanceof
|
|
5543
|
+
} else if (error instanceof z.ZodError) {
|
|
6159
5544
|
const issues = error.errors.map((e) => {
|
|
6160
5545
|
const field = e.path.length ? e.path.join(".") : "input";
|
|
6161
5546
|
return ` ${field}: ${e.message}`;
|
|
@@ -6199,6 +5584,21 @@ function printFeedbackTip(commandName, context) {
|
|
|
6199
5584
|
${colorOk ? `\x1B[2m${text}\x1B[0m` : text}
|
|
6200
5585
|
`);
|
|
6201
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
|
+
}
|
|
6202
5602
|
function printAgentCliError(command, error, mode = "agent") {
|
|
6203
5603
|
const output = createCliOutput({
|
|
6204
5604
|
command: command || "unknown",
|
|
@@ -6296,9 +5696,8 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
|
|
|
6296
5696
|
return 1;
|
|
6297
5697
|
};
|
|
6298
5698
|
const definition = commandRegistry.find(command);
|
|
6299
|
-
if (!definition)
|
|
6300
|
-
return failEarly(
|
|
6301
|
-
}
|
|
5699
|
+
if (!definition)
|
|
5700
|
+
return failEarly(unknownCommandError(command));
|
|
6302
5701
|
if (parsed.shortFlags?.length) {
|
|
6303
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);
|
|
6304
5703
|
}
|
|
@@ -6485,6 +5884,7 @@ if (isMain) {
|
|
|
6485
5884
|
});
|
|
6486
5885
|
}
|
|
6487
5886
|
export {
|
|
5887
|
+
unknownCommandError,
|
|
6488
5888
|
telemetrySubcommandNames,
|
|
6489
5889
|
telemetryCommandName,
|
|
6490
5890
|
stripLoneSurrogates,
|
|
@@ -6499,6 +5899,7 @@ export {
|
|
|
6499
5899
|
parseArgs,
|
|
6500
5900
|
normalizeBooleanFlags,
|
|
6501
5901
|
initFlagsForContext,
|
|
5902
|
+
globalFlagHelpLines,
|
|
6502
5903
|
flagsToArgs,
|
|
6503
5904
|
dispatchParsedCommand,
|
|
6504
5905
|
detectCallerAgent,
|