@moda-ai/cli 1.50.0 → 1.52.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/dist/{cli-xrs02c0t.js → cli-ac3p2byq.js} +3 -1
- package/dist/{cli-jqfm8dp4.js → cli-ha40mgy1.js} +4 -4
- package/dist/{cli-x0x0n35w.js → cli-he2wb4hd.js} +2 -2
- package/dist/{cli-7kbzqact.js → cli-kxwm7y62.js} +1 -1
- package/dist/{cli-h4k23fb0.js → cli-sq6g0tk5.js} +2 -2
- package/dist/cli.js +141 -33
- package/dist/{harness-github-actions-q9kewzb6.js → harness-github-actions-gbty3k66.js} +2 -2
- package/dist/{harness-7gr0xbtc.js → harness-s13wvdxt.js} +2 -2
- package/dist/{index-z0jpjcsm.js → index-pykaaezb.js} +5 -5
- package/dist/prompt-source-mcp.js +2 -2
- package/dist/{provision-qkazpt0c.js → provision-d1dfj6as.js} +3 -3
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/skills/moda-cli/SKILL.md +15 -9
|
@@ -534,9 +534,11 @@ function writeSecretJsonFile(path, value) {
|
|
|
534
534
|
// src/errors.ts
|
|
535
535
|
class CliInputError extends Error {
|
|
536
536
|
usage;
|
|
537
|
-
|
|
537
|
+
reason;
|
|
538
|
+
constructor(message, usage, reason) {
|
|
538
539
|
super(message);
|
|
539
540
|
this.usage = usage;
|
|
541
|
+
this.reason = reason;
|
|
540
542
|
this.name = "CliInputError";
|
|
541
543
|
}
|
|
542
544
|
}
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
resolvePromptSource,
|
|
14
14
|
safePromptEvidencePath,
|
|
15
15
|
scanHarness
|
|
16
|
-
} from "./cli-
|
|
16
|
+
} from "./cli-he2wb4hd.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-kxwm7y62.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-ac3p2byq.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-s13wvdxt.js");
|
|
6715
6715
|
const result = await analyzeHarnessPrompts({
|
|
6716
6716
|
rootDir: process.cwd(),
|
|
6717
6717
|
existing: established.flatMap((prompt) => prompt.sourceDefinition ? [prompt.sourceDefinition.source] : []),
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
resolveTenantId,
|
|
26
26
|
shouldInventoryFile,
|
|
27
27
|
stringOption
|
|
28
|
-
} from "./cli-
|
|
28
|
+
} from "./cli-ac3p2byq.js";
|
|
29
29
|
import {
|
|
30
30
|
__commonJS,
|
|
31
31
|
__require,
|
|
@@ -184857,7 +184857,7 @@ async function runHarnessCommand(context) {
|
|
|
184857
184857
|
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.");
|
|
184858
184858
|
}
|
|
184859
184859
|
if (context.flags["github-actions"] === "true") {
|
|
184860
|
-
const { runGithubActionsAnalyze } = await import("./harness-github-actions-
|
|
184860
|
+
const { runGithubActionsAnalyze } = await import("./harness-github-actions-gbty3k66.js");
|
|
184861
184861
|
const result = await runGithubActionsAnalyze(rootDir, {
|
|
184862
184862
|
writeReport: (report2) => {
|
|
184863
184863
|
const normalized = normalizeHarnessReport(report2);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
authFetch,
|
|
3
3
|
getCachedLoginContext
|
|
4
|
-
} from "./cli-
|
|
4
|
+
} from "./cli-kxwm7y62.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-ac3p2byq.js";
|
|
19
19
|
|
|
20
20
|
// src/init/tenant.ts
|
|
21
21
|
import { randomUUID } from "node:crypto";
|
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-ha40mgy1.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-he2wb4hd.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-kxwm7y62.js";
|
|
50
50
|
import {
|
|
51
51
|
AGENT_ERROR_CODES,
|
|
52
52
|
CliAccessError,
|
|
@@ -97,7 +97,7 @@ import {
|
|
|
97
97
|
validateConfig,
|
|
98
98
|
wasOutputCancelled,
|
|
99
99
|
writeSecretJsonFile
|
|
100
|
-
} from "./cli-
|
|
100
|
+
} from "./cli-ac3p2byq.js";
|
|
101
101
|
import {
|
|
102
102
|
__require
|
|
103
103
|
} from "./cli-0v6na3yp.js";
|
|
@@ -150,11 +150,20 @@ var WorldStateSchema = z.object({
|
|
|
150
150
|
format: z.enum(["frames", "fold-inputs"]).optional(),
|
|
151
151
|
message_count: z.number().min(1).max(1e6).optional()
|
|
152
152
|
});
|
|
153
|
+
var lenientBoolFlag = () => z.preprocess((val) => {
|
|
154
|
+
const text = String(val).toLowerCase();
|
|
155
|
+
if (["true", "1", "yes", "on"].includes(text))
|
|
156
|
+
return true;
|
|
157
|
+
if (["false", "0", "no", "off"].includes(text))
|
|
158
|
+
return false;
|
|
159
|
+
return val;
|
|
160
|
+
}, z.boolean()).optional();
|
|
153
161
|
var ContextSchema = z.object({
|
|
154
|
-
conversation_id: z.string(),
|
|
155
|
-
msg_index: z.number().min(0).optional(),
|
|
162
|
+
conversation_id: z.string().min(1),
|
|
163
|
+
msg_index: z.number().int().min(0).optional(),
|
|
156
164
|
window: z.number().int().min(0).optional(),
|
|
157
|
-
|
|
165
|
+
metadata_only: lenientBoolFlag(),
|
|
166
|
+
all: lenientBoolFlag(),
|
|
158
167
|
from: z.number().int().min(0).optional(),
|
|
159
168
|
max_messages: z.number().int().min(1).max(5000).optional()
|
|
160
169
|
});
|
|
@@ -3534,6 +3543,11 @@ function stripTelemetryFlag(flags) {
|
|
|
3534
3543
|
function isTelemetryDisabled(flags) {
|
|
3535
3544
|
return flags[TELEMETRY_FLAG] === "true" || process.env.MODA_CLI_TELEMETRY === "0" || process.env.DO_NOT_TRACK === "1";
|
|
3536
3545
|
}
|
|
3546
|
+
var VALIDATION_REASON_MAX = 128;
|
|
3547
|
+
function sanitizeValidationReason(reason) {
|
|
3548
|
+
const cleaned = reason?.replace(/[^A-Za-z0-9_.:-]/g, "_").slice(0, VALIDATION_REASON_MAX);
|
|
3549
|
+
return cleaned ? cleaned : undefined;
|
|
3550
|
+
}
|
|
3537
3551
|
function sanitizedFlagNames(flags) {
|
|
3538
3552
|
return Object.keys(stripTelemetryFlag(flags)).sort();
|
|
3539
3553
|
}
|
|
@@ -3541,6 +3555,7 @@ async function sendCliUsageTelemetry(input) {
|
|
|
3541
3555
|
if (!input.apiKey || isTelemetryDisabled(input.flags)) {
|
|
3542
3556
|
return;
|
|
3543
3557
|
}
|
|
3558
|
+
const validationReason = sanitizeValidationReason(input.validationReason);
|
|
3544
3559
|
const controller = new AbortController;
|
|
3545
3560
|
const timeout = setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS);
|
|
3546
3561
|
if (typeof timeout.unref === "function") {
|
|
@@ -3558,6 +3573,7 @@ async function sendCliUsageTelemetry(input) {
|
|
|
3558
3573
|
command: input.command.slice(0, 64),
|
|
3559
3574
|
status: input.status,
|
|
3560
3575
|
error_type: input.errorType,
|
|
3576
|
+
...validationReason ? { validation_reason: validationReason } : {},
|
|
3561
3577
|
exit_code: input.exitCode,
|
|
3562
3578
|
duration_ms: Math.max(0, Math.round(input.durationMs)),
|
|
3563
3579
|
api_request_count: Math.max(0, Math.round(input.apiRequestCount)),
|
|
@@ -6663,7 +6679,7 @@ function frustrationFindings(data, daysBack, evidenceRefs) {
|
|
|
6663
6679
|
id: "action_frustration_window",
|
|
6664
6680
|
title: "Read the frustration window.",
|
|
6665
6681
|
rationale: "The user quote and nearby turns reveal what confused or blocked the user.",
|
|
6666
|
-
command: conversationId ? `moda context ${conversationId}${anchorIndex !== null ? ` --msg-index=${anchorIndex}` : ""} --window=3` : `moda frustrations --days-back=${daysBack} --include-window`,
|
|
6682
|
+
command: conversationId ? `moda context ${shellWord(conversationId)}${anchorIndex !== null ? ` --msg-index=${anchorIndex}` : ""} --window=3` : `moda frustrations --days-back=${daysBack} --include-window`,
|
|
6667
6683
|
mutability: "read",
|
|
6668
6684
|
requiresApproval: false
|
|
6669
6685
|
}]
|
|
@@ -7750,7 +7766,7 @@ function parseArgs(argv) {
|
|
|
7750
7766
|
if (!endOfOptions && arg === "--" && command !== "") {
|
|
7751
7767
|
endOfOptions = true;
|
|
7752
7768
|
} else if (!endOfOptions && arg.startsWith("--")) {
|
|
7753
|
-
i = parseFlag(args, i, flags, command === "", bareFlags);
|
|
7769
|
+
i = parseFlag(args, i, flags, command === "", bareFlags, command);
|
|
7754
7770
|
} else if (!endOfOptions && command !== "" && /^-[A-Za-z]/.test(arg)) {
|
|
7755
7771
|
shortFlags.push(arg);
|
|
7756
7772
|
} else if (command === "") {
|
|
@@ -7790,7 +7806,10 @@ var GLOBAL_BOOLEAN_FLAGS = new Set([
|
|
|
7790
7806
|
"tui",
|
|
7791
7807
|
"no-tui"
|
|
7792
7808
|
]);
|
|
7793
|
-
|
|
7809
|
+
var COMMAND_BOOLEAN_FLAGS = {
|
|
7810
|
+
context: new Set(["all", "metadata-only"])
|
|
7811
|
+
};
|
|
7812
|
+
function parseFlag(args, index, flags, beforeCommand, bareFlags, command = "") {
|
|
7794
7813
|
const set = (key2, value, bare) => {
|
|
7795
7814
|
flags[key2] = value;
|
|
7796
7815
|
const at = bareFlags.indexOf(key2);
|
|
@@ -7811,6 +7830,10 @@ function parseFlag(args, index, flags, beforeCommand, bareFlags) {
|
|
|
7811
7830
|
set(key, "true", true);
|
|
7812
7831
|
return index;
|
|
7813
7832
|
}
|
|
7833
|
+
if (!beforeCommand && COMMAND_BOOLEAN_FLAGS[command]?.has(key.replace(/_/g, "-")) && next !== "true" && next !== "false") {
|
|
7834
|
+
set(key, "true", true);
|
|
7835
|
+
return index;
|
|
7836
|
+
}
|
|
7814
7837
|
if (next !== undefined && !next.startsWith("--")) {
|
|
7815
7838
|
set(key, next, false);
|
|
7816
7839
|
return index + 1;
|
|
@@ -7903,7 +7926,7 @@ Commands:
|
|
|
7903
7926
|
traces --sort=longest Sort traces: recent (default), longest, slowest
|
|
7904
7927
|
search "<query>" Search trace messages (keyword/semantic/hybrid)
|
|
7905
7928
|
world-state <conversation_id> Get a trace's world state (slots/threads/events)
|
|
7906
|
-
context <conversation_id> Get windowed trace context
|
|
7929
|
+
context <conversation_id> Get windowed trace context (--metadata-only: summary + counts only)
|
|
7907
7930
|
context <conversation_id> --all Whole transcript in order (first 500; --from=N --max-messages=N to continue)
|
|
7908
7931
|
audit <conversation_id|trace_id> Raw span audit (spans, hierarchy, orphans, duplicates)
|
|
7909
7932
|
frustrations Frustration detections (same data as emotions --family=frustration)
|
|
@@ -8736,7 +8759,7 @@ function parseCommandFlags(schema, args, command, options = {}) {
|
|
|
8736
8759
|
]);
|
|
8737
8760
|
const unknown = Object.keys(args).filter((key) => !known.has(key));
|
|
8738
8761
|
if (unknown.includes("dry_run")) {
|
|
8739
|
-
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, prompts sync/decide, skills sync/policy, signals <write subcommands>, problem-reopen
|
|
8762
|
+
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, prompts sync/decide, skills sync/policy, signals <write subcommands>, problem-reopen.`, "unsupported_dry_run");
|
|
8740
8763
|
}
|
|
8741
8764
|
if (unknown.length > 0) {
|
|
8742
8765
|
const flagKeys = schemaKeys.filter((key) => key !== options.positionalKey);
|
|
@@ -8751,7 +8774,7 @@ function parseCommandFlags(schema, args, command, options = {}) {
|
|
|
8751
8774
|
return close ? `Did you mean --${close.candidate.replace(/_/g, "-")}?` : "";
|
|
8752
8775
|
}).filter(Boolean);
|
|
8753
8776
|
const names = unknown.map((key) => `--${key.replace(/_/g, "-")}`).join(", ");
|
|
8754
|
-
throw new CliInputError(`Unknown flag${unknown.length > 1 ? "s" : ""} ${names} for 'moda ${command}'.`, [...hints, `Valid flags: ${valid.join(", ") || "(none)"}. Run 'moda ${command} --help'.`].join(" "));
|
|
8777
|
+
throw new CliInputError(`Unknown flag${unknown.length > 1 ? "s" : ""} ${names} for 'moda ${command}'.`, [...hints, `Valid flags: ${valid.join(", ") || "(none)"}. Run 'moda ${command} --help'.`].join(" "), `unknown_flag:${unknown[0].replace(/_/g, "-")}`);
|
|
8755
8778
|
}
|
|
8756
8779
|
return schema.parse(args);
|
|
8757
8780
|
}
|
|
@@ -8941,7 +8964,7 @@ function assertHandParsedFlags(command, flags, positionals) {
|
|
|
8941
8964
|
} catch (error) {
|
|
8942
8965
|
if (command !== "feedback" || !(error instanceof CliInputError))
|
|
8943
8966
|
throw error;
|
|
8944
|
-
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());
|
|
8967
|
+
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);
|
|
8945
8968
|
}
|
|
8946
8969
|
}
|
|
8947
8970
|
var PROFILE_MANAGING_COMMANDS = new Set(["profiles", "auth", "init", "provision", "status", "config", "keys", "manifest", "agent", "doctor"]);
|
|
@@ -8975,6 +8998,66 @@ function processingDisabledWarning(data, family) {
|
|
|
8975
8998
|
`${family === "emotion" ? "Emotion" : "Frustration"} analysis is disabled for this tenant (${setting} = false), ` + "so zero results do NOT mean users are not frustrated. Enable it in Settings → Account → Signal processing; " + "only traces ingested after enabling are analyzed."
|
|
8976
8999
|
];
|
|
8977
9000
|
}
|
|
9001
|
+
var CONTEXT_USAGE = "Usage: moda context <conversation_id> [--msg-index=N] [--window=0-5 | --metadata-only]";
|
|
9002
|
+
var CONTEXT_ALL_USAGE = "Usage: moda context <conversation_id> --all [--from=N] [--max-messages=N]";
|
|
9003
|
+
var CONTEXT_MAX_WINDOW = 5;
|
|
9004
|
+
var EMPTY_ANCHOR_VALUES = new Set(["", "null", "undefined", "none"]);
|
|
9005
|
+
function parseContextRequest(positional, rawFlags) {
|
|
9006
|
+
const flags = {};
|
|
9007
|
+
const flagIds = [];
|
|
9008
|
+
for (const [rawKey, value] of Object.entries(rawFlags)) {
|
|
9009
|
+
const key = rawKey.replace(/_/g, "-");
|
|
9010
|
+
if (key === "conversation-id") {
|
|
9011
|
+
if (value !== "true")
|
|
9012
|
+
flagIds.push(value);
|
|
9013
|
+
} else if (flags[key] !== undefined && flags[key] !== value) {
|
|
9014
|
+
throw new CliInputError(`Got two different values for --${key} (both spellings were passed), so nothing was read.`, CONTEXT_USAGE, "flag_conflict");
|
|
9015
|
+
} else {
|
|
9016
|
+
flags[key] = value;
|
|
9017
|
+
}
|
|
9018
|
+
}
|
|
9019
|
+
const flagId = flagIds[0];
|
|
9020
|
+
const warnings = [];
|
|
9021
|
+
if (new Set([...positional !== undefined ? [positional] : [], ...flagIds]).size > 1) {
|
|
9022
|
+
throw new CliInputError("Got two different trace ids (from the positional and --conversation-id), so nothing was read.", CONTEXT_USAGE, "flag_conflict");
|
|
9023
|
+
}
|
|
9024
|
+
const conversationId = positional ?? flagId;
|
|
9025
|
+
if (!conversationId) {
|
|
9026
|
+
throw new CliInputError("<conversation_id> is required", CONTEXT_USAGE, "missing_positional");
|
|
9027
|
+
}
|
|
9028
|
+
const msgIndex = flags["msg-index"];
|
|
9029
|
+
if (msgIndex !== undefined && EMPTY_ANCHOR_VALUES.has(msgIndex.trim().toLowerCase())) {
|
|
9030
|
+
delete flags["msg-index"];
|
|
9031
|
+
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.");
|
|
9032
|
+
}
|
|
9033
|
+
const args = { ...flagsToArgs(flags), conversation_id: conversationId };
|
|
9034
|
+
const params = parseCommandFlags(ContextSchema, args, "context", { positionalKey: "conversation_id" });
|
|
9035
|
+
if (params.metadata_only === true && params.window !== undefined) {
|
|
9036
|
+
throw new CliInputError("--metadata-only reads no messages, so it cannot be combined with --window; drop --window.", CONTEXT_USAGE, "flag_conflict");
|
|
9037
|
+
}
|
|
9038
|
+
if (params.all === true) {
|
|
9039
|
+
if (params.msg_index !== undefined || flags.window !== undefined || params.metadata_only === true) {
|
|
9040
|
+
throw new CliInputError("--all reads the whole trace; drop --msg-index/--window/--metadata-only.", CONTEXT_ALL_USAGE, "flag_conflict");
|
|
9041
|
+
}
|
|
9042
|
+
} else if (params.from !== undefined || params.max_messages !== undefined) {
|
|
9043
|
+
throw new CliInputError("--from and --max-messages page the whole trace and need --all.", CONTEXT_ALL_USAGE, "flag_conflict");
|
|
9044
|
+
}
|
|
9045
|
+
return { params, warnings };
|
|
9046
|
+
}
|
|
9047
|
+
async function readContextMetadataOnly(contextPath, query2) {
|
|
9048
|
+
try {
|
|
9049
|
+
return await callDataAPI(`${contextPath}?${query2.toString()}`);
|
|
9050
|
+
} catch (error) {
|
|
9051
|
+
if (!(error instanceof ApiError) || error.statusCode !== 400 || !/metadata_only/.test(error.message))
|
|
9052
|
+
throw error;
|
|
9053
|
+
const legacy = new URLSearchParams(query2);
|
|
9054
|
+
legacy.delete("metadata_only");
|
|
9055
|
+
legacy.set("window", "0");
|
|
9056
|
+
const data = asRecord(await callDataAPI(`${contextPath}?${legacy.toString()}`)) ?? {};
|
|
9057
|
+
const ctx = asRecord(data.context) ?? {};
|
|
9058
|
+
return { ...data, metadata_only: true, context: { ...ctx, messages: [] } };
|
|
9059
|
+
}
|
|
9060
|
+
}
|
|
8978
9061
|
var FULL_TRANSCRIPT_DEFAULT_MAX_MESSAGES = 500;
|
|
8979
9062
|
var CONTEXT_RANGE_PAGE_SIZE = 200;
|
|
8980
9063
|
var LEGACY_WINDOW_MAX_MESSAGES = 100;
|
|
@@ -9001,7 +9084,6 @@ function pageMessages(page) {
|
|
|
9001
9084
|
const messages = asRecord(page.context)?.messages ?? page.messages;
|
|
9002
9085
|
return (Array.isArray(messages) ? messages : []).map((m) => asRecord(m) ?? {});
|
|
9003
9086
|
}
|
|
9004
|
-
var CONTEXT_MAX_WINDOW = 5;
|
|
9005
9087
|
var CONTEXT_ALL_MAX_MESSAGES = 5000;
|
|
9006
9088
|
async function readFullTranscript(conversationId, opts = {}) {
|
|
9007
9089
|
const start = opts.from ?? 0;
|
|
@@ -9360,40 +9442,37 @@ async function runCommand(command, positional, flags, positionals = positional ?
|
|
|
9360
9442
|
break;
|
|
9361
9443
|
}
|
|
9362
9444
|
case "context": {
|
|
9363
|
-
|
|
9364
|
-
throw new CliInputError("<conversation_id> is required", "Usage: moda context <conversation_id> [--msg-index=N] [--window=N]");
|
|
9365
|
-
}
|
|
9366
|
-
const args = flagsToArgs(flags, "conversation_id", positional);
|
|
9367
|
-
const params = parseCommandFlags(ContextSchema, args, command, { positionalKey: "conversation_id" });
|
|
9445
|
+
const { params, warnings: inputWarnings } = parseContextRequest(positional, flags);
|
|
9368
9446
|
if (params.all === true) {
|
|
9369
|
-
if (params.msg_index !== undefined || flags.window !== undefined) {
|
|
9370
|
-
throw new CliInputError("--all reads the whole trace; drop --msg-index/--window.", "Usage: moda context <conversation_id> --all [--from=N] [--max-messages=N]");
|
|
9371
|
-
}
|
|
9372
9447
|
const agentMode = context.output.mode === "agent" || context.output.mode === "agent-stream";
|
|
9373
9448
|
const full = await readFullTranscript(params.conversation_id, {
|
|
9374
9449
|
from: params.from,
|
|
9375
9450
|
maxMessages: params.max_messages,
|
|
9376
9451
|
fits: agentMode ? (page) => agentEnvelopeFits(command, page.data, { warnings: page.warnings, nextCommands: page.nextCommands }) : undefined
|
|
9377
9452
|
});
|
|
9453
|
+
const fullWarnings = [...inputWarnings, ...full.warnings];
|
|
9378
9454
|
context.output.writeData(full.data, {
|
|
9379
|
-
...
|
|
9455
|
+
...fullWarnings.length > 0 ? { warnings: fullWarnings } : {},
|
|
9380
9456
|
...full.nextCommands.length > 0 ? { nextCommands: full.nextCommands } : {}
|
|
9381
9457
|
});
|
|
9382
9458
|
break;
|
|
9383
9459
|
}
|
|
9384
|
-
if (params.from !== undefined || params.max_messages !== undefined) {
|
|
9385
|
-
throw new CliInputError("--from and --max-messages page the whole trace and need --all.", "Usage: moda context <conversation_id> --all [--from=N] [--max-messages=N]");
|
|
9386
|
-
}
|
|
9387
9460
|
const query2 = new URLSearchParams;
|
|
9388
9461
|
if (params.msg_index !== undefined)
|
|
9389
9462
|
query2.set("msg_index", params.msg_index.toString());
|
|
9463
|
+
if (params.metadata_only === true)
|
|
9464
|
+
query2.set("metadata_only", "1");
|
|
9390
9465
|
const window = params.window === undefined ? undefined : Math.min(params.window, CONTEXT_MAX_WINDOW);
|
|
9391
9466
|
if (window !== undefined)
|
|
9392
9467
|
query2.set("window", window.toString());
|
|
9393
9468
|
const queryString = query2.toString() ? `?${query2.toString()}` : "";
|
|
9394
|
-
const
|
|
9469
|
+
const contextPath = `/conversations/${encodeURIComponent(params.conversation_id)}/context`;
|
|
9470
|
+
const data = params.metadata_only === true ? await readContextMetadataOnly(contextPath, query2) : await callDataAPI(`${contextPath}${queryString}`);
|
|
9395
9471
|
const ctxRecord = asRecord(data) ?? {};
|
|
9396
|
-
const warnings =
|
|
9472
|
+
const warnings = [
|
|
9473
|
+
...inputWarnings,
|
|
9474
|
+
...notFoundWarning("trace", params.conversation_id, asNumber(ctxRecord.total_messages) === 0)
|
|
9475
|
+
];
|
|
9397
9476
|
const nextCommands = [];
|
|
9398
9477
|
if (params.window !== undefined && params.window > CONTEXT_MAX_WINDOW) {
|
|
9399
9478
|
const center = asNumber(asRecord(ctxRecord.context)?.center_index) ?? params.msg_index ?? 0;
|
|
@@ -10147,7 +10226,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
10147
10226
|
resetApiRequestCountBeforeRun: true,
|
|
10148
10227
|
telemetry: "result",
|
|
10149
10228
|
handler: async (context) => {
|
|
10150
|
-
const { runInit } = await import("./index-
|
|
10229
|
+
const { runInit } = await import("./index-pykaaezb.js");
|
|
10151
10230
|
if (context.outputMode === "agent-stream") {
|
|
10152
10231
|
context.output.writeEvent({
|
|
10153
10232
|
event: "started",
|
|
@@ -10188,7 +10267,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
10188
10267
|
resetApiRequestCountBeforeRun: true,
|
|
10189
10268
|
telemetry: "result-and-error",
|
|
10190
10269
|
handler: async (context) => {
|
|
10191
|
-
const { runProvision } = await import("./provision-
|
|
10270
|
+
const { runProvision } = await import("./provision-d1dfj6as.js");
|
|
10192
10271
|
return runProvision(context, {
|
|
10193
10272
|
resumeCommand: buildResumeCommand("provision", context.rawFlags)
|
|
10194
10273
|
});
|
|
@@ -10652,6 +10731,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
10652
10731
|
examples: [
|
|
10653
10732
|
"moda context <conversation_id> --window=3",
|
|
10654
10733
|
"moda context <conversation_id> --msg-index=40 --window=0",
|
|
10734
|
+
"moda context <conversation_id> --metadata-only # summary + total_messages, no messages",
|
|
10655
10735
|
"moda context <conversation_id> --all",
|
|
10656
10736
|
"moda context <conversation_id> --all --from=500 --max-messages=500"
|
|
10657
10737
|
],
|
|
@@ -11062,7 +11142,15 @@ var commandRegistry = createCommandRegistry([
|
|
|
11062
11142
|
}
|
|
11063
11143
|
]);
|
|
11064
11144
|
function classifyCliError(error) {
|
|
11065
|
-
if (error instanceof
|
|
11145
|
+
if (error instanceof CliAuthError)
|
|
11146
|
+
return "auth_error";
|
|
11147
|
+
if (error instanceof CliAccessError)
|
|
11148
|
+
return "access_error";
|
|
11149
|
+
if (error instanceof ApiError && error.statusCode === 401)
|
|
11150
|
+
return "auth_error";
|
|
11151
|
+
if (error instanceof ApiError && error.statusCode === 403)
|
|
11152
|
+
return "access_error";
|
|
11153
|
+
if (error instanceof z2.ZodError || error instanceof CliInputError || error instanceof CliInputRequiredError) {
|
|
11066
11154
|
return "validation_error";
|
|
11067
11155
|
}
|
|
11068
11156
|
if (error instanceof ApiError || isApiLikeError(error)) {
|
|
@@ -11073,6 +11161,21 @@ function classifyCliError(error) {
|
|
|
11073
11161
|
}
|
|
11074
11162
|
return "unknown_error";
|
|
11075
11163
|
}
|
|
11164
|
+
function cliValidationReason(error) {
|
|
11165
|
+
if (error instanceof z2.ZodError) {
|
|
11166
|
+
const issue = error.issues[0];
|
|
11167
|
+
if (!issue)
|
|
11168
|
+
return "zod";
|
|
11169
|
+
const path = issue.path.join(".") || "_";
|
|
11170
|
+
return issue.code === "invalid_enum_value" ? `bad_enum:${path}` : `zod:${path}:${issue.code}`;
|
|
11171
|
+
}
|
|
11172
|
+
if (error instanceof CliInputRequiredError)
|
|
11173
|
+
return "input_required";
|
|
11174
|
+
if (error instanceof CliInputError) {
|
|
11175
|
+
return error.reason ?? (/^<[^>]+> is required/.test(error.message) ? "missing_positional" : "input_error");
|
|
11176
|
+
}
|
|
11177
|
+
return;
|
|
11178
|
+
}
|
|
11076
11179
|
function printCliError(error) {
|
|
11077
11180
|
if (error instanceof CliInputError) {
|
|
11078
11181
|
safeWriteStderr(`Error: ${error.message}
|
|
@@ -11256,6 +11359,7 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
|
|
|
11256
11359
|
flags: commandFlags,
|
|
11257
11360
|
status: "error",
|
|
11258
11361
|
errorType: classifyCliError(error),
|
|
11362
|
+
validationReason: cliValidationReason(error),
|
|
11259
11363
|
exitCode: exitCodeForError(error),
|
|
11260
11364
|
durationMs: Date.now() - startedAt,
|
|
11261
11365
|
apiRequestCount: getApiRequestCount(),
|
|
@@ -11316,6 +11420,7 @@ async function dispatchParsedCommandInner(parsed, startedAt) {
|
|
|
11316
11420
|
flags: commandFlags,
|
|
11317
11421
|
status: "error",
|
|
11318
11422
|
errorType: classifyCliError(error),
|
|
11423
|
+
validationReason: cliValidationReason(error),
|
|
11319
11424
|
exitCode: exitCodeForError(error),
|
|
11320
11425
|
durationMs: Date.now() - startedAt,
|
|
11321
11426
|
apiRequestCount: getApiRequestCount(),
|
|
@@ -11383,6 +11488,7 @@ export {
|
|
|
11383
11488
|
runCommand,
|
|
11384
11489
|
resolveTailSignal,
|
|
11385
11490
|
printCliError,
|
|
11491
|
+
parseContextRequest,
|
|
11386
11492
|
parseCommandFlags,
|
|
11387
11493
|
parseArgs,
|
|
11388
11494
|
initFlagsForContext,
|
|
@@ -11391,6 +11497,7 @@ export {
|
|
|
11391
11497
|
detectCallerAgent,
|
|
11392
11498
|
describeLinearLink,
|
|
11393
11499
|
commandRegistry,
|
|
11500
|
+
cliValidationReason,
|
|
11394
11501
|
classifyCliError,
|
|
11395
11502
|
capProblemsBlocks,
|
|
11396
11503
|
buildResumeCommand,
|
|
@@ -11398,5 +11505,6 @@ export {
|
|
|
11398
11505
|
TAIL_LIMITS,
|
|
11399
11506
|
LEGACY_WINDOW_MAX_MESSAGES,
|
|
11400
11507
|
FULL_TRANSCRIPT_DEFAULT_MAX_MESSAGES,
|
|
11401
|
-
CliInputError
|
|
11508
|
+
CliInputError,
|
|
11509
|
+
CONTEXT_MAX_WINDOW
|
|
11402
11510
|
};
|
|
@@ -42,8 +42,8 @@ import {
|
|
|
42
42
|
writeHarnessAnalyzeResult,
|
|
43
43
|
writeHarnessArtifacts,
|
|
44
44
|
writeHumanProgress
|
|
45
|
-
} from "./cli-
|
|
46
|
-
import"./cli-
|
|
45
|
+
} from "./cli-he2wb4hd.js";
|
|
46
|
+
import"./cli-ac3p2byq.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-ha40mgy1.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-he2wb4hd.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-sq6g0tk5.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-kxwm7y62.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-ac3p2byq.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-sq6g0tk5.js";
|
|
4
4
|
import {
|
|
5
5
|
loadAuthSession
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-kxwm7y62.js";
|
|
7
7
|
import {
|
|
8
8
|
CliAuthError,
|
|
9
9
|
resolveIngestUrl,
|
|
10
10
|
resolveModaBaseUrl,
|
|
11
11
|
stringOption
|
|
12
|
-
} from "./cli-
|
|
12
|
+
} from "./cli-ac3p2byq.js";
|
|
13
13
|
import"./cli-0v6na3yp.js";
|
|
14
14
|
|
|
15
15
|
// src/provision.ts
|
package/package.json
CHANGED
package/skills/moda-cli/SKILL.md
CHANGED
|
@@ -458,6 +458,8 @@ fail instead of being clamped.
|
|
|
458
458
|
time window. On `context`, `--window=0` returns only the anchor message (plus
|
|
459
459
|
`total_messages`), and a value above 5 is clamped to 5 with a warning that
|
|
460
460
|
prints the `--all --from --max-messages` command for a wider slice.
|
|
461
|
+
`--metadata-only` returns only the summary and `total_messages`, with no
|
|
462
|
+
messages.
|
|
461
463
|
|
|
462
464
|
### Schema introspection
|
|
463
465
|
|
|
@@ -546,11 +548,13 @@ compare scores across modes.
|
|
|
546
548
|
Hand the anchors straight to `moda context`:
|
|
547
549
|
|
|
548
550
|
```bash
|
|
549
|
-
# Find, then read the exact turn
|
|
550
|
-
|
|
551
|
+
# Find, then read the exact turn. --json prints the bare payload; piped output
|
|
552
|
+
# without it is the agent envelope, where results sit under .data.results.
|
|
553
|
+
hit=$(moda search "double charge" --limit=1 --json | jq -c '.results[0] // empty')
|
|
551
554
|
cid=$(echo "$hit" | jq -r '.conversation_id')
|
|
552
|
-
|
|
553
|
-
|
|
555
|
+
# Trace-level fallback hits (match_grain: "trace") have no message_index.
|
|
556
|
+
idx=$(echo "$hit" | jq -r '.message_index // empty')
|
|
557
|
+
moda context "$cid" ${idx:+--msg-index="$idx"}
|
|
554
558
|
```
|
|
555
559
|
|
|
556
560
|
### 2. Overview (start here for health questions)
|
|
@@ -647,6 +651,7 @@ moda context <conversation_id> # default window around middle
|
|
|
647
651
|
moda context <conversation_id> --msg-index=5 # center on message 5
|
|
648
652
|
moda context <conversation_id> --window=3 # 3 messages each side (max 5)
|
|
649
653
|
moda context <conversation_id> --msg-index=40 --window=0 # just message 40 + total_messages
|
|
654
|
+
moda context <conversation_id> --metadata-only # summary + total_messages, no messages
|
|
650
655
|
moda context <conversation_id> --all # whole trace in order, first 500 messages
|
|
651
656
|
moda context <conversation_id> --all --from=500 --max-messages=500 # continue (max 5000)
|
|
652
657
|
```
|
|
@@ -1128,16 +1133,17 @@ and archiving an active custom signal (pause it, or delete a draft).
|
|
|
1128
1133
|
|
|
1129
1134
|
```bash
|
|
1130
1135
|
# Semantic: find the moment a user expressed an intent, in their own words
|
|
1131
|
-
moda search "user wants to cancel subscription" --mode=semantic --limit=5 \
|
|
1136
|
+
moda search "user wants to cancel subscription" --mode=semantic --limit=5 --json \
|
|
1132
1137
|
| jq -r '.results[] | "\(.conversation_id) @\(.message_index) \(.snippet)"'
|
|
1133
1138
|
|
|
1134
1139
|
# Keyword: locate every tool call/result mentioning an exact identifier
|
|
1135
1140
|
moda search "stripe.refunds.create" --mode=keyword --limit=10
|
|
1136
1141
|
|
|
1137
|
-
# Search, then open the top hit at the exact turn
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
|
1142
|
+
# Search, then open the top message-level hit at the exact turn (skips
|
|
1143
|
+
# trace-level fallback hits, which have no message_index)
|
|
1144
|
+
moda search "rate limit exceeded" --limit=5 --json \
|
|
1145
|
+
| jq -r 'first(.results[] | select(.message_index != null)) | "\(.conversation_id) \(.message_index)"' \
|
|
1146
|
+
| xargs -r -n2 sh -c 'moda context "$0" --msg-index="$1"'
|
|
1141
1147
|
```
|
|
1142
1148
|
|
|
1143
1149
|
### Daily health check
|