@moda-ai/cli 1.45.2 → 1.48.0
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/README.md +1 -0
- package/dist/{cli-bvnw7585.js → cli-233xm35b.js} +1 -0
- package/dist/{cli-nnwegmzh.js → cli-eaaegm7a.js} +4 -4
- package/dist/{cli-dy2aavbe.js → cli-fpt3jkyh.js} +1 -1
- package/dist/{cli-phgzghwq.js → cli-ss2nere4.js} +2 -2
- package/dist/{cli-3xh2w7hb.js → cli-tznhpmf2.js} +2 -2
- package/dist/cli.js +154 -58
- package/dist/{harness-github-actions-ky4ym5n3.js → harness-github-actions-379faaqe.js} +2 -2
- package/dist/{harness-9qpbj2qj.js → harness-vf1e1t2h.js} +2 -2
- package/dist/{index-bcn5chmf.js → index-p8vab4p4.js} +5 -5
- package/dist/prompt-source-mcp.js +2 -2
- package/dist/{provision-mqw8s0jb.js → provision-e4cnxpdh.js} +3 -3
- package/package.json +3 -1
- package/skills/integration/index.json +2 -2
- package/skills/moda-cli/SKILL.md +19 -4
package/README.md
CHANGED
|
@@ -116,6 +116,7 @@ Feedback:
|
|
|
116
116
|
|
|
117
117
|
```bash
|
|
118
118
|
moda feedback "cluster label looks wrong" --category=bad_cluster_label
|
|
119
|
+
moda feedback "trace belongs to another problem" --category=false_positive_attribution --problem-id=<id>
|
|
119
120
|
```
|
|
120
121
|
|
|
121
122
|
Output adapts to where it runs: piped/CI/agent environments get schema-versioned
|
|
@@ -1692,6 +1692,7 @@ function createCommandContext(input, options = {}) {
|
|
|
1692
1692
|
positionals: input.positionals,
|
|
1693
1693
|
flags,
|
|
1694
1694
|
rawFlags,
|
|
1695
|
+
...input.bareFlags ? { bareFlags: input.bareFlags } : {},
|
|
1695
1696
|
startedAt: options.startedAt ?? Date.now(),
|
|
1696
1697
|
cwd: options.cwd ?? process.cwd(),
|
|
1697
1698
|
env: options.env ?? process.env,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
resolvePromptSource,
|
|
14
14
|
safePromptEvidencePath,
|
|
15
15
|
scanHarness
|
|
16
|
-
} from "./cli-
|
|
16
|
+
} from "./cli-tznhpmf2.js";
|
|
17
17
|
import {
|
|
18
18
|
SKILL_SOURCE_HARNESS,
|
|
19
19
|
SKILL_SOURCE_INTEGRATION_BUNDLED,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
import {
|
|
27
27
|
isAuthSessionValid,
|
|
28
28
|
loadAuthSession
|
|
29
|
-
} from "./cli-
|
|
29
|
+
} from "./cli-fpt3jkyh.js";
|
|
30
30
|
import {
|
|
31
31
|
CliInputError,
|
|
32
32
|
EXIT_ERROR,
|
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
resolveTenantId,
|
|
46
46
|
secretFilePathFromRef,
|
|
47
47
|
validateConfig
|
|
48
|
-
} from "./cli-
|
|
48
|
+
} from "./cli-233xm35b.js";
|
|
49
49
|
import {
|
|
50
50
|
__commonJS,
|
|
51
51
|
__require,
|
|
@@ -6711,7 +6711,7 @@ async function runPromptSyncExclusive(flags, profileOptions, options) {
|
|
|
6711
6711
|
const analyzedDefinitions = new Map;
|
|
6712
6712
|
if (flags["no-analyze"] !== "true") {
|
|
6713
6713
|
options.onProgress?.("Analyzing prompt sources before sync.");
|
|
6714
|
-
const { analyzeHarnessPrompts } = await import("./harness-
|
|
6714
|
+
const { analyzeHarnessPrompts } = await import("./harness-vf1e1t2h.js");
|
|
6715
6715
|
const result = await analyzeHarnessPrompts({
|
|
6716
6716
|
rootDir: process.cwd(),
|
|
6717
6717
|
existing: established.flatMap((prompt) => prompt.sourceDefinition ? [prompt.sourceDefinition.source] : []),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
authFetch,
|
|
3
3
|
getCachedLoginContext
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-fpt3jkyh.js";
|
|
5
5
|
import {
|
|
6
6
|
CliAccessError,
|
|
7
7
|
CliInputError,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
resolveTenantIdFromActiveProfile,
|
|
16
16
|
saveCliConfig,
|
|
17
17
|
writeSecretJsonFile
|
|
18
|
-
} from "./cli-
|
|
18
|
+
} from "./cli-233xm35b.js";
|
|
19
19
|
|
|
20
20
|
// src/init/tenant.ts
|
|
21
21
|
import { randomUUID } from "node:crypto";
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
resolveTenantId,
|
|
26
26
|
shouldInventoryFile,
|
|
27
27
|
stringOption
|
|
28
|
-
} from "./cli-
|
|
28
|
+
} from "./cli-233xm35b.js";
|
|
29
29
|
import {
|
|
30
30
|
__commonJS,
|
|
31
31
|
__require,
|
|
@@ -184813,7 +184813,7 @@ async function runHarnessCommand(context) {
|
|
|
184813
184813
|
throw new CliInputError("Focused remote prompt analysis is not supported yet.", "Use local --analyst=claude|codex|cursor|local-scan, or drop --concern for a full remote report.");
|
|
184814
184814
|
}
|
|
184815
184815
|
if (context.flags["github-actions"] === "true") {
|
|
184816
|
-
const { runGithubActionsAnalyze } = await import("./harness-github-actions-
|
|
184816
|
+
const { runGithubActionsAnalyze } = await import("./harness-github-actions-379faaqe.js");
|
|
184817
184817
|
const result = await runGithubActionsAnalyze(rootDir, {
|
|
184818
184818
|
writeReport: (report2) => {
|
|
184819
184819
|
const normalized = normalizeHarnessReport(report2);
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
runPromptsCommand,
|
|
9
9
|
runSkillsCommand,
|
|
10
10
|
runStatusCommand
|
|
11
|
-
} from "./cli-
|
|
11
|
+
} from "./cli-eaaegm7a.js";
|
|
12
12
|
import {
|
|
13
13
|
ApiError,
|
|
14
14
|
HARNESS_REPORT_APPROVAL_PATH,
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
terminalStyles,
|
|
38
38
|
unknownSignalsSubcommandError,
|
|
39
39
|
validateHarnessReport
|
|
40
|
-
} from "./cli-
|
|
40
|
+
} from "./cli-tznhpmf2.js";
|
|
41
41
|
import"./cli-ssfq84k5.js";
|
|
42
42
|
import {
|
|
43
43
|
authFetch,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
loadAuthSession,
|
|
47
47
|
login,
|
|
48
48
|
revokeCliSessionToken
|
|
49
|
-
} from "./cli-
|
|
49
|
+
} from "./cli-fpt3jkyh.js";
|
|
50
50
|
import {
|
|
51
51
|
AGENT_ERROR_CODES,
|
|
52
52
|
CliAccessError,
|
|
@@ -96,7 +96,7 @@ import {
|
|
|
96
96
|
validateConfig,
|
|
97
97
|
wasOutputCancelled,
|
|
98
98
|
writeSecretJsonFile
|
|
99
|
-
} from "./cli-
|
|
99
|
+
} from "./cli-233xm35b.js";
|
|
100
100
|
import {
|
|
101
101
|
__require
|
|
102
102
|
} from "./cli-0v6na3yp.js";
|
|
@@ -402,6 +402,8 @@ var SearchSchema = z.object({
|
|
|
402
402
|
include_tool_io: boolFlag(),
|
|
403
403
|
offset: z.number().min(0).max(1e4).optional()
|
|
404
404
|
});
|
|
405
|
+
|
|
406
|
+
// ../../packages/database/src/agent-feedback.ts
|
|
405
407
|
var FEEDBACK_CATEGORIES = [
|
|
406
408
|
"bad_cluster_label",
|
|
407
409
|
"mismatched_frustration",
|
|
@@ -410,18 +412,98 @@ var FEEDBACK_CATEGORIES = [
|
|
|
410
412
|
"wrong_tool_failure",
|
|
411
413
|
"incorrect_loop",
|
|
412
414
|
"api_quirk",
|
|
415
|
+
"false_positive_attribution",
|
|
416
|
+
"misrouted_fix",
|
|
417
|
+
"harness_bug",
|
|
413
418
|
"other"
|
|
414
419
|
];
|
|
415
420
|
var FEEDBACK_SEVERITIES = ["info", "low", "medium", "high"];
|
|
416
|
-
var
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
421
|
+
var DEFAULT_FEEDBACK_CATEGORY = "other";
|
|
422
|
+
var RAW_FEEDBACK_CATEGORY_MAX = 64;
|
|
423
|
+
function isFeedbackCategory(value) {
|
|
424
|
+
return typeof value === "string" && FEEDBACK_CATEGORIES.includes(value);
|
|
425
|
+
}
|
|
426
|
+
function normalizeFeedbackCategory(value) {
|
|
427
|
+
if (value === undefined || value === null || value === "")
|
|
428
|
+
return { category: DEFAULT_FEEDBACK_CATEGORY };
|
|
429
|
+
if (isFeedbackCategory(value))
|
|
430
|
+
return { category: value };
|
|
431
|
+
const raw = String(value).trim().slice(0, RAW_FEEDBACK_CATEGORY_MAX);
|
|
432
|
+
return raw ? { category: DEFAULT_FEEDBACK_CATEGORY, raw_category: raw } : { category: DEFAULT_FEEDBACK_CATEGORY };
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// src/feedback.ts
|
|
436
|
+
var FEEDBACK_FLAGS = ["category", "severity", "note", "cluster-id", "conversation-id", "run-id", "tool-name"];
|
|
437
|
+
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]";
|
|
438
|
+
var NOTE_MAX = 4000;
|
|
439
|
+
var REF_VALUE_MAX = 256;
|
|
440
|
+
var REF_FLAG_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*-(?:id|ids|index|token)$/;
|
|
441
|
+
var REF_FLAG_WORDS = new Set(["turn", "tool", "family", "kind"]);
|
|
442
|
+
function isFeedbackRefFlag(flag) {
|
|
443
|
+
return REF_FLAG_PATTERN.test(flag) || REF_FLAG_WORDS.has(flag);
|
|
444
|
+
}
|
|
445
|
+
function feedbackCategoryHelp(indent = 35, width = 100) {
|
|
446
|
+
const lines = [];
|
|
447
|
+
let line = "";
|
|
448
|
+
FEEDBACK_CATEGORIES.forEach((category, index) => {
|
|
449
|
+
const piece = index < FEEDBACK_CATEGORIES.length - 1 ? `${category}|` : `${category} (default other)`;
|
|
450
|
+
if (line && indent + line.length + piece.length > width) {
|
|
451
|
+
lines.push(line);
|
|
452
|
+
line = "";
|
|
453
|
+
}
|
|
454
|
+
line += piece;
|
|
455
|
+
});
|
|
456
|
+
lines.push(line);
|
|
457
|
+
return lines.join(`
|
|
458
|
+
${" ".repeat(indent)}`);
|
|
459
|
+
}
|
|
460
|
+
function buildFeedbackRequest(positionals, flags, bareFlags) {
|
|
461
|
+
const isBare = (flag) => bareFlags ? bareFlags.includes(flag) : flags[flag] === "true";
|
|
462
|
+
const flagNote = flags.note !== undefined && !isBare("note") ? flags.note.trim() : "";
|
|
463
|
+
const note = [positionals.join(" ").trim(), flagNote].filter(Boolean).join(`
|
|
464
|
+
`);
|
|
465
|
+
if (note === "")
|
|
466
|
+
throw new CliInputError("<note> is required", FEEDBACK_USAGE);
|
|
467
|
+
if (note.length > NOTE_MAX) {
|
|
468
|
+
throw new CliInputError(`<note> is ${note.length} characters; the limit is ${NOTE_MAX}.`, FEEDBACK_USAGE);
|
|
469
|
+
}
|
|
470
|
+
const severity = flags.severity ?? "low";
|
|
471
|
+
if (!FEEDBACK_SEVERITIES.includes(severity)) {
|
|
472
|
+
throw new CliInputError(`Invalid --severity '${severity}'. Valid severities: ${FEEDBACK_SEVERITIES.join(", ")}.`, FEEDBACK_USAGE);
|
|
473
|
+
}
|
|
474
|
+
const refs = {};
|
|
475
|
+
for (const [flag, value] of Object.entries(flags)) {
|
|
476
|
+
if (flag === "category" || flag === "severity" || flag === "note")
|
|
477
|
+
continue;
|
|
478
|
+
if (!FEEDBACK_FLAGS.includes(flag) && !isFeedbackRefFlag(flag))
|
|
479
|
+
continue;
|
|
480
|
+
const trimmed = value.trim();
|
|
481
|
+
if (value === "true" || trimmed === "") {
|
|
482
|
+
throw new CliInputError(`--${flag} needs a value, e.g. --${flag}=<id>.`, FEEDBACK_USAGE);
|
|
483
|
+
}
|
|
484
|
+
if (trimmed.length > REF_VALUE_MAX) {
|
|
485
|
+
throw new CliInputError(`--${flag} is ${trimmed.length} characters; the limit is ${REF_VALUE_MAX}.`, FEEDBACK_USAGE);
|
|
486
|
+
}
|
|
487
|
+
refs[flag.replace(/-/g, "_")] = trimmed;
|
|
488
|
+
}
|
|
489
|
+
const warnings = [];
|
|
490
|
+
const { category, raw_category: rawCategory } = normalizeFeedbackCategory(flags.category);
|
|
491
|
+
if (rawCategory !== undefined) {
|
|
492
|
+
refs.raw_category = rawCategory;
|
|
493
|
+
warnings.push(`Unknown category '${rawCategory}': sent as 'other' with refs.raw_category. ` + `Valid categories: ${FEEDBACK_CATEGORIES.join(", ")}.`);
|
|
494
|
+
}
|
|
495
|
+
const hint = dedicatedCommandHint(category, rawCategory);
|
|
496
|
+
if (hint)
|
|
497
|
+
warnings.push(hint);
|
|
498
|
+
return { category, severity, note, refs, warnings };
|
|
499
|
+
}
|
|
500
|
+
var MISROUTE_CATEGORIES = new Set(["false_positive_attribution", "misrouted_fix"]);
|
|
501
|
+
var MISROUTE_WORDS = /attribut|misrout|false[\s_-]?positive|wrong[\s_-]?(?:problem|fix)/i;
|
|
502
|
+
function dedicatedCommandHint(category, rawCategory) {
|
|
503
|
+
if (!MISROUTE_CATEGORIES.has(category) && !(rawCategory && MISROUTE_WORDS.test(rawCategory)))
|
|
504
|
+
return;
|
|
505
|
+
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).";
|
|
506
|
+
}
|
|
425
507
|
|
|
426
508
|
// src/transforms.ts
|
|
427
509
|
function asRecord(value) {
|
|
@@ -3385,6 +3467,9 @@ function buildSearchAdoptionTelemetry(input) {
|
|
|
3385
3467
|
output_mode: outputMode,
|
|
3386
3468
|
search_surface: SEARCH_SURFACE_BY_COMMAND[command] ?? "none"
|
|
3387
3469
|
};
|
|
3470
|
+
if (positional && input.subcommands?.includes(positional)) {
|
|
3471
|
+
adoption.subcommand = positional;
|
|
3472
|
+
}
|
|
3388
3473
|
let queryText;
|
|
3389
3474
|
if (command === "search")
|
|
3390
3475
|
queryText = positional;
|
|
@@ -7664,6 +7749,7 @@ function parseArgs(argv) {
|
|
|
7664
7749
|
const flags = {};
|
|
7665
7750
|
const positionals = [];
|
|
7666
7751
|
const shortFlags = [];
|
|
7752
|
+
const bareFlags = [];
|
|
7667
7753
|
let positional;
|
|
7668
7754
|
let i = 0;
|
|
7669
7755
|
let endOfOptions = false;
|
|
@@ -7672,7 +7758,7 @@ function parseArgs(argv) {
|
|
|
7672
7758
|
if (!endOfOptions && arg === "--" && command !== "") {
|
|
7673
7759
|
endOfOptions = true;
|
|
7674
7760
|
} else if (!endOfOptions && arg.startsWith("--")) {
|
|
7675
|
-
i = parseFlag(args, i, flags, command === "");
|
|
7761
|
+
i = parseFlag(args, i, flags, command === "", bareFlags);
|
|
7676
7762
|
} else if (!endOfOptions && command !== "" && /^-[A-Za-z]/.test(arg)) {
|
|
7677
7763
|
shortFlags.push(arg);
|
|
7678
7764
|
} else if (command === "") {
|
|
@@ -7685,7 +7771,14 @@ function parseArgs(argv) {
|
|
|
7685
7771
|
}
|
|
7686
7772
|
i++;
|
|
7687
7773
|
}
|
|
7688
|
-
return {
|
|
7774
|
+
return {
|
|
7775
|
+
command,
|
|
7776
|
+
positional,
|
|
7777
|
+
positionals,
|
|
7778
|
+
flags,
|
|
7779
|
+
...shortFlags.length > 0 ? { shortFlags } : {},
|
|
7780
|
+
...bareFlags.length > 0 ? { bareFlags } : {}
|
|
7781
|
+
};
|
|
7689
7782
|
}
|
|
7690
7783
|
var DRY_RUN_TRUE = new Set(["true", "yes", "1", "on"]);
|
|
7691
7784
|
var DRY_RUN_FALSE = new Set(["false", "no", "0", "off"]);
|
|
@@ -7705,24 +7798,32 @@ var GLOBAL_BOOLEAN_FLAGS = new Set([
|
|
|
7705
7798
|
"tui",
|
|
7706
7799
|
"no-tui"
|
|
7707
7800
|
]);
|
|
7708
|
-
function parseFlag(args, index, flags, beforeCommand) {
|
|
7801
|
+
function parseFlag(args, index, flags, beforeCommand, bareFlags) {
|
|
7802
|
+
const set = (key2, value, bare) => {
|
|
7803
|
+
flags[key2] = value;
|
|
7804
|
+
const at = bareFlags.indexOf(key2);
|
|
7805
|
+
if (at !== -1)
|
|
7806
|
+
bareFlags.splice(at, 1);
|
|
7807
|
+
if (bare)
|
|
7808
|
+
bareFlags.push(key2);
|
|
7809
|
+
};
|
|
7709
7810
|
const arg = args[index];
|
|
7710
7811
|
const eqIndex = arg.indexOf("=");
|
|
7711
7812
|
if (eqIndex !== -1) {
|
|
7712
|
-
|
|
7813
|
+
set(arg.slice(2, eqIndex), arg.slice(eqIndex + 1), false);
|
|
7713
7814
|
return index;
|
|
7714
7815
|
}
|
|
7715
7816
|
const key = arg.slice(2);
|
|
7716
7817
|
const next = args[index + 1];
|
|
7717
7818
|
if (beforeCommand && GLOBAL_BOOLEAN_FLAGS.has(key)) {
|
|
7718
|
-
|
|
7819
|
+
set(key, "true", true);
|
|
7719
7820
|
return index;
|
|
7720
7821
|
}
|
|
7721
7822
|
if (next !== undefined && !next.startsWith("--")) {
|
|
7722
|
-
|
|
7823
|
+
set(key, next, false);
|
|
7723
7824
|
return index + 1;
|
|
7724
7825
|
}
|
|
7725
|
-
|
|
7826
|
+
set(key, "true", true);
|
|
7726
7827
|
return index;
|
|
7727
7828
|
}
|
|
7728
7829
|
function initFlagsForContext(flags, outputMode, stdinIsTTY) {
|
|
@@ -8013,13 +8114,16 @@ Clusters search flags:
|
|
|
8013
8114
|
--mode=fuzzy|semantic|hybrid Cluster search mode (default hybrid)
|
|
8014
8115
|
|
|
8015
8116
|
Feedback flags:
|
|
8016
|
-
--category=CAT
|
|
8017
|
-
|
|
8117
|
+
--category=CAT ${feedbackCategoryHelp()}
|
|
8118
|
+
An unknown category is sent as other (with refs.raw_category)
|
|
8018
8119
|
--severity=info|low|medium|high How bad it is (default low)
|
|
8120
|
+
--note=TEXT The note, if not given as the positional argument
|
|
8019
8121
|
--conversation-id=ID Attach the trace ID you were looking at
|
|
8020
8122
|
--cluster-id=ID Attach a cluster node id
|
|
8021
8123
|
--tool-name=NAME Attach a tool name
|
|
8022
8124
|
--run-id=ID Attach a run id
|
|
8125
|
+
--<name>-id=ID Any other id (--problem-id, --fix-id, --attribution-id,
|
|
8126
|
+
--trace-id, --span-id, --message-index, ...) goes into refs
|
|
8023
8127
|
(set MODA_CLI_TIPS=0 to hide the feedback tip line)
|
|
8024
8128
|
|
|
8025
8129
|
Init flags:
|
|
@@ -8752,7 +8856,7 @@ var HAND_PARSED_COMMAND_FLAGS = {
|
|
|
8752
8856
|
"tool-use-id"
|
|
8753
8857
|
],
|
|
8754
8858
|
"false-positives": ["all", "kind", "limit"],
|
|
8755
|
-
feedback:
|
|
8859
|
+
feedback: FEEDBACK_FLAGS,
|
|
8756
8860
|
"problem-impact": ["mode", "node-id", "problem-id", "run-id", "to", "cursor", "conversation-ids", "days-back"]
|
|
8757
8861
|
};
|
|
8758
8862
|
var NO_POSITIONAL_COMMANDS = new Set([
|
|
@@ -8783,9 +8887,16 @@ function assertHandParsedFlags(command, flags, positionals) {
|
|
|
8783
8887
|
const allowed = HAND_PARSED_COMMAND_FLAGS[command];
|
|
8784
8888
|
if (!allowed)
|
|
8785
8889
|
return;
|
|
8890
|
+
const checked = command === "feedback" ? Object.keys(flags).filter((flag2) => !isFeedbackRefFlag(flag2)) : Object.keys(flags);
|
|
8786
8891
|
const shape = z2.object(Object.fromEntries(allowed.map((flag2) => [flag2.replace(/-/g, "_"), z2.unknown()])));
|
|
8787
|
-
const args = Object.fromEntries(
|
|
8788
|
-
|
|
8892
|
+
const args = Object.fromEntries(checked.map((flag2) => [flag2.replace(/-/g, "_"), true]));
|
|
8893
|
+
try {
|
|
8894
|
+
parseCommandFlags(shape.passthrough(), args, command);
|
|
8895
|
+
} catch (error) {
|
|
8896
|
+
if (command !== "feedback" || !(error instanceof CliInputError))
|
|
8897
|
+
throw error;
|
|
8898
|
+
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());
|
|
8899
|
+
}
|
|
8789
8900
|
}
|
|
8790
8901
|
var PROFILE_MANAGING_COMMANDS = new Set(["profiles", "auth", "init", "provision", "status", "config", "keys", "manifest", "agent", "doctor"]);
|
|
8791
8902
|
async function runProblemsRemainder(flags, context) {
|
|
@@ -9883,30 +9994,7 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
9883
9994
|
break;
|
|
9884
9995
|
}
|
|
9885
9996
|
case "feedback": {
|
|
9886
|
-
const note = positionals
|
|
9887
|
-
if (note === "") {
|
|
9888
|
-
throw new CliInputError("<note> is required", `Usage: moda feedback "<note>" [--category=${FEEDBACK_CATEGORIES.join("|")}] [--severity=${FEEDBACK_SEVERITIES.join("|")}] [--conversation-id=ID] [--cluster-id=ID] [--tool-name=NAME] [--run-id=ID]`);
|
|
9889
|
-
}
|
|
9890
|
-
const params = FeedbackSchema.parse({
|
|
9891
|
-
note,
|
|
9892
|
-
...flags.category !== undefined ? { category: flags.category } : {},
|
|
9893
|
-
...flags.severity !== undefined ? { severity: flags.severity } : {},
|
|
9894
|
-
...flags["conversation-id"] !== undefined ? { conversation_id: flags["conversation-id"] } : {},
|
|
9895
|
-
...flags["cluster-id"] !== undefined ? { cluster_id: flags["cluster-id"] } : {},
|
|
9896
|
-
...flags["tool-name"] !== undefined ? { tool_name: flags["tool-name"] } : {},
|
|
9897
|
-
...flags["run-id"] !== undefined ? { run_id: flags["run-id"] } : {}
|
|
9898
|
-
});
|
|
9899
|
-
const refs = {};
|
|
9900
|
-
if (params.conversation_id)
|
|
9901
|
-
refs.conversation_id = params.conversation_id;
|
|
9902
|
-
if (params.cluster_id)
|
|
9903
|
-
refs.cluster_id = params.cluster_id;
|
|
9904
|
-
if (params.tool_name)
|
|
9905
|
-
refs.tool_name = params.tool_name;
|
|
9906
|
-
if (params.run_id)
|
|
9907
|
-
refs.run_id = params.run_id;
|
|
9908
|
-
const category = params.category ?? "other";
|
|
9909
|
-
const severity = params.severity ?? "low";
|
|
9997
|
+
const { category, severity, note, refs, warnings } = buildFeedbackRequest(positionals, flags, context.bareFlags);
|
|
9910
9998
|
const data = await callDataAPI("/feedback", {
|
|
9911
9999
|
method: "POST",
|
|
9912
10000
|
body: JSON.stringify({
|
|
@@ -9915,11 +10003,14 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
9915
10003
|
source: "cli",
|
|
9916
10004
|
agent: detectCallerAgent(process.env),
|
|
9917
10005
|
cli_version: VERSION,
|
|
9918
|
-
note
|
|
10006
|
+
note,
|
|
9919
10007
|
...Object.keys(refs).length > 0 ? { refs } : {}
|
|
9920
10008
|
})
|
|
9921
10009
|
}, { retries: 0 });
|
|
9922
|
-
context.output.writeData({ submitted: true, category, severity, ...asRecord(data) ?? {} }, {
|
|
10010
|
+
context.output.writeData({ submitted: true, category, severity, ...asRecord(data) ?? {} }, {
|
|
10011
|
+
summary: "Feedback submitted. Thank you for helping us improve!",
|
|
10012
|
+
...warnings.length > 0 ? { warnings } : {}
|
|
10013
|
+
});
|
|
9923
10014
|
break;
|
|
9924
10015
|
}
|
|
9925
10016
|
default:
|
|
@@ -10024,7 +10115,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
10024
10115
|
resetApiRequestCountBeforeRun: true,
|
|
10025
10116
|
telemetry: "result",
|
|
10026
10117
|
handler: async (context) => {
|
|
10027
|
-
const { runInit } = await import("./index-
|
|
10118
|
+
const { runInit } = await import("./index-p8vab4p4.js");
|
|
10028
10119
|
if (context.outputMode === "agent-stream") {
|
|
10029
10120
|
context.output.writeEvent({
|
|
10030
10121
|
event: "started",
|
|
@@ -10065,7 +10156,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
10065
10156
|
resetApiRequestCountBeforeRun: true,
|
|
10066
10157
|
telemetry: "result-and-error",
|
|
10067
10158
|
handler: async (context) => {
|
|
10068
|
-
const { runProvision } = await import("./provision-
|
|
10159
|
+
const { runProvision } = await import("./provision-e4cnxpdh.js");
|
|
10069
10160
|
return runProvision(context, {
|
|
10070
10161
|
resumeCommand: buildResumeCommand("provision", context.rawFlags)
|
|
10071
10162
|
});
|
|
@@ -10207,7 +10298,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
10207
10298
|
description: "Diagnose local Moda setup and data flow",
|
|
10208
10299
|
examples: ["moda doctor", "moda doctor --json", "moda doctor --offline"],
|
|
10209
10300
|
auth: "none",
|
|
10210
|
-
authNote: "
|
|
10301
|
+
authNote: "With an API key it also checks the key and data flow against Moda Cloud; --offline runs local checks only.",
|
|
10211
10302
|
outputModes: ["human", "json", "agent"],
|
|
10212
10303
|
mutability: "read",
|
|
10213
10304
|
validateConfigBeforeRun: false,
|
|
@@ -10766,7 +10857,8 @@ var commandRegistry = createCommandRegistry([
|
|
|
10766
10857
|
description: "Flag wrong/missing data or CLI quirks to the Moda team",
|
|
10767
10858
|
examples: [
|
|
10768
10859
|
'moda feedback "cluster label looks wrong" --category=bad_cluster_label --cluster-id=<node_id>',
|
|
10769
|
-
'moda feedback "search finds nothing for a trace I can open" --category=missing_data --conversation-id=<id>'
|
|
10860
|
+
'moda feedback "search finds nothing for a trace I can open" --category=missing_data --conversation-id=<id>',
|
|
10861
|
+
'moda feedback "trace is about refunds, not this problem" --category=false_positive_attribution --problem-id=<id> --conversation-id=<id>'
|
|
10770
10862
|
],
|
|
10771
10863
|
...dataApiDefaults,
|
|
10772
10864
|
mutability: "write"
|
|
@@ -11108,6 +11200,7 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
|
|
|
11108
11200
|
});
|
|
11109
11201
|
setActiveContext(context);
|
|
11110
11202
|
const telemetryCommand = telemetryCommandName(definition);
|
|
11203
|
+
const telemetrySubcommands = definition.subcommands?.map((subcommand2) => subcommand2.name);
|
|
11111
11204
|
const needsConfig = typeof definition.validateConfigBeforeRun === "function" ? definition.validateConfigBeforeRun(parsed) : definition.validateConfigBeforeRun;
|
|
11112
11205
|
if (needsConfig) {
|
|
11113
11206
|
try {
|
|
@@ -11129,7 +11222,8 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
|
|
|
11129
11222
|
flags: commandFlags,
|
|
11130
11223
|
outputMode: context.outputMode,
|
|
11131
11224
|
recorded: context.getTelemetryMeta(),
|
|
11132
|
-
skillVersion: process.env.MODA_SKILL_VERSION
|
|
11225
|
+
skillVersion: process.env.MODA_SKILL_VERSION,
|
|
11226
|
+
subcommands: telemetrySubcommands
|
|
11133
11227
|
})
|
|
11134
11228
|
});
|
|
11135
11229
|
}
|
|
@@ -11161,7 +11255,8 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
|
|
|
11161
11255
|
flags: commandFlags,
|
|
11162
11256
|
outputMode: context.outputMode,
|
|
11163
11257
|
recorded: context.getTelemetryMeta(),
|
|
11164
|
-
skillVersion: process.env.MODA_SKILL_VERSION
|
|
11258
|
+
skillVersion: process.env.MODA_SKILL_VERSION,
|
|
11259
|
+
subcommands: telemetrySubcommands
|
|
11165
11260
|
})
|
|
11166
11261
|
});
|
|
11167
11262
|
}
|
|
@@ -11187,7 +11282,8 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
|
|
|
11187
11282
|
flags: commandFlags,
|
|
11188
11283
|
outputMode: context.outputMode,
|
|
11189
11284
|
recorded: context.getTelemetryMeta(),
|
|
11190
|
-
skillVersion: process.env.MODA_SKILL_VERSION
|
|
11285
|
+
skillVersion: process.env.MODA_SKILL_VERSION,
|
|
11286
|
+
subcommands: telemetrySubcommands
|
|
11191
11287
|
})
|
|
11192
11288
|
});
|
|
11193
11289
|
}
|
|
@@ -42,8 +42,8 @@ import {
|
|
|
42
42
|
writeHarnessAnalyzeResult,
|
|
43
43
|
writeHarnessArtifacts,
|
|
44
44
|
writeHumanProgress
|
|
45
|
-
} from "./cli-
|
|
46
|
-
import"./cli-
|
|
45
|
+
} from "./cli-tznhpmf2.js";
|
|
46
|
+
import"./cli-233xm35b.js";
|
|
47
47
|
import"./cli-0v6na3yp.js";
|
|
48
48
|
export {
|
|
49
49
|
writeHumanProgress,
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
initPrompts,
|
|
4
4
|
runPromptSync,
|
|
5
5
|
runSkillSync
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-eaaegm7a.js";
|
|
7
7
|
import {
|
|
8
8
|
codingAgentDisplayName,
|
|
9
9
|
describeCodingAgentEvent,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
runHarnessCommand,
|
|
23
23
|
startRemoteAnalyze,
|
|
24
24
|
stripAnsi
|
|
25
|
-
} from "./cli-
|
|
25
|
+
} from "./cli-tznhpmf2.js";
|
|
26
26
|
import {
|
|
27
27
|
bundledSkillsDir,
|
|
28
28
|
installIntegrationSkill,
|
|
@@ -34,14 +34,14 @@ import {
|
|
|
34
34
|
} from "./cli-ssfq84k5.js";
|
|
35
35
|
import {
|
|
36
36
|
selectTenantAndCreateKey
|
|
37
|
-
} from "./cli-
|
|
37
|
+
} from "./cli-ss2nere4.js";
|
|
38
38
|
import {
|
|
39
39
|
ConnectCodeError,
|
|
40
40
|
connectWithCode,
|
|
41
41
|
loadAuthSession,
|
|
42
42
|
loadToken,
|
|
43
43
|
login
|
|
44
|
-
} from "./cli-
|
|
44
|
+
} from "./cli-fpt3jkyh.js";
|
|
45
45
|
import {
|
|
46
46
|
CliAuthError,
|
|
47
47
|
CliInputError,
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
createCommandContext,
|
|
50
50
|
resolveIngestUrl,
|
|
51
51
|
resolveModaBaseUrl
|
|
52
|
-
} from "./cli-
|
|
52
|
+
} from "./cli-233xm35b.js";
|
|
53
53
|
import"./cli-0v6na3yp.js";
|
|
54
54
|
|
|
55
55
|
// src/init/index.ts
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
selectTenantAndCreateKey
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-ss2nere4.js";
|
|
4
4
|
import {
|
|
5
5
|
loadAuthSession
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-fpt3jkyh.js";
|
|
7
7
|
import {
|
|
8
8
|
CliAuthError,
|
|
9
9
|
resolveIngestUrl,
|
|
10
10
|
resolveModaBaseUrl,
|
|
11
11
|
stringOption
|
|
12
|
-
} from "./cli-
|
|
12
|
+
} from "./cli-233xm35b.js";
|
|
13
13
|
import"./cli-0v6na3yp.js";
|
|
14
14
|
|
|
15
15
|
// src/provision.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moda-ai/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.48.0",
|
|
4
4
|
"description": "CLI for Moda - AI agent analytics and observability",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"bundle:skills": "bun scripts/bundle-skills.ts",
|
|
23
|
+
"export:admin-manifest": "bun scripts/export-admin-command-manifest.ts",
|
|
23
24
|
"build": "bun run bundle:skills && tsc --noEmit && bun build ./src/cli.ts ./src/prompt-source-mcp.ts --target=node --format=esm --outdir=dist --splitting --external @inquirer/prompts --external open --external zod",
|
|
24
25
|
"dev": "tsc --watch",
|
|
25
26
|
"typecheck": "tsc --noEmit",
|
|
@@ -55,6 +56,7 @@
|
|
|
55
56
|
"@modelcontextprotocol/sdk": "^1.30.0"
|
|
56
57
|
},
|
|
57
58
|
"devDependencies": {
|
|
59
|
+
"@moda/database": "*",
|
|
58
60
|
"@moda/eslint-config": "*",
|
|
59
61
|
"@moda/harness-snapshot": "*",
|
|
60
62
|
"@moda/integration-skills": "*",
|
package/skills/moda-cli/SKILL.md
CHANGED
|
@@ -1186,15 +1186,30 @@ moda feedback "search finds nothing for a trace I can open" \
|
|
|
1186
1186
|
--category=missing_data --conversation-id=<id>
|
|
1187
1187
|
moda feedback "a cancelled call is counted as a tool failure" \
|
|
1188
1188
|
--category=wrong_tool_failure --tool-name=<tool>
|
|
1189
|
+
moda feedback "trace is a refund request, not this problem" \
|
|
1190
|
+
--category=false_positive_attribution --problem-id=<id> --conversation-id=<id>
|
|
1189
1191
|
```
|
|
1190
1192
|
|
|
1191
|
-
- `<note>` is required (max 4000 chars)
|
|
1193
|
+
- `<note>` is required (max 4000 chars), as the argument or `--note=TEXT`.
|
|
1194
|
+
Say what looked wrong and why.
|
|
1192
1195
|
- `--category`: `bad_cluster_label | mismatched_frustration | missing_data |
|
|
1193
|
-
noisy_data | wrong_tool_failure | incorrect_loop | api_quirk |
|
|
1194
|
-
|
|
1196
|
+
noisy_data | wrong_tool_failure | incorrect_loop | api_quirk |
|
|
1197
|
+
false_positive_attribution | misrouted_fix | harness_bug | other`
|
|
1198
|
+
(default `other`). Use `false_positive_attribution` when a trace is
|
|
1199
|
+
attributed to the wrong problem, `misrouted_fix` when a fix targets the
|
|
1200
|
+
wrong problem or file, and `harness_bug` for a bug in the agent harness
|
|
1201
|
+
Moda analysed. An unknown category is still sent, as `other` with
|
|
1202
|
+
`refs.raw_category`, and a warning lists the valid ones.
|
|
1195
1203
|
- `--severity`: `info | low | medium | high` (default `low`).
|
|
1196
1204
|
- Attach ids when you have them: `--conversation-id`, `--cluster-id`,
|
|
1197
|
-
`--tool-name`, `--run-id
|
|
1205
|
+
`--tool-name`, `--run-id`, or any other `--<name>-id` (`--problem-id`,
|
|
1206
|
+
`--fix-id`, `--attribution-id`, `--trace-id`, `--span-id`,
|
|
1207
|
+
`--message-index`); they go into `refs` and let the team reproduce what
|
|
1208
|
+
you saw.
|
|
1209
|
+
- Feedback does not change the problem itself. To act on a misroute directly,
|
|
1210
|
+
use `moda problem-feedback <problem_id> --action=flag_attribution
|
|
1211
|
+
--attribution-id=<uuid> --reason=TEXT`, `moda false-positive <kind> <target>
|
|
1212
|
+
--reason=TEXT`, or `moda fix dismiss <fix_id> --reason=TEXT`.
|
|
1198
1213
|
- Never include secrets or full transcripts in the note.
|
|
1199
1214
|
|
|
1200
1215
|
## Validation — how to know it worked
|