@moda-ai/cli 1.55.25 → 1.55.27
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-t7dxmpdq.js → agent-vp9prdma.js} +8 -8
- package/dist/{cli-qycsmxev.js → cli-0pkc8jhg.js} +3 -3
- package/dist/{cli-mebf5vtr.js → cli-4h0ave0f.js} +5 -5
- package/dist/{cli-m0045npe.js → cli-6et4z504.js} +10 -8
- package/dist/{cli-9hc5bg2r.js → cli-ccjfwzqx.js} +1 -1
- package/dist/{cli-0wr3483h.js → cli-hmjdgxrn.js} +1 -1
- package/dist/{cli-9btx12wp.js → cli-pg5qfmqc.js} +1 -1
- package/dist/{cli-m805msp6.js → cli-q9nsvqqg.js} +14 -14
- package/dist/{cli-7xc585hc.js → cli-qwgct6x7.js} +7 -6
- package/dist/{cli-dve50x7p.js → cli-r5pp7qny.js} +140 -455
- package/dist/{cli-qvg26twp.js → cli-v8q7sd7g.js} +38 -13
- package/dist/cli-vdkwkkp5.js +567 -0
- package/dist/{cli-dn91fb56.js → cli-wzds257x.js} +92 -49
- package/dist/cli.js +986 -362
- package/dist/{doctor-q21mr5ya.js → doctor-wmre3mr7.js} +8 -8
- package/dist/{fix-0qdtdz5h.js → fix-75s9s0d6.js} +45 -47
- package/dist/{harness-vzy7n7ea.js → harness-a7tb9a23.js} +5 -5
- package/dist/{harness-github-actions-atc5bbkj.js → harness-github-actions-6v4wydb8.js} +5 -5
- package/dist/{index-4b1ybz51.js → index-91bpc8g8.js} +15 -14
- package/dist/{production-intelligence-c8e0xw3n.js → production-intelligence-7nqddd4f.js} +88 -28
- package/dist/{profile-commands-6e2dgv72.js → profile-commands-49yn02yg.js} +5 -4
- package/dist/prompt-source-mcp.js +5 -5
- package/dist/{prompts-3h5jcjrw.js → prompts-17wyrst6.js} +6 -6
- package/dist/{provision-q86phh4a.js → provision-bc3h68e1.js} +5 -5
- package/dist/{registry-s2vdsfw8.js → registry-fpzhjznj.js} +3 -3
- package/dist/{skills-vq3njc8a.js → skills-ccdbqghj.js} +5 -5
- package/dist/{sync-hq9dpqpr.js → sync-hkxce5zh.js} +7 -7
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
- package/skills/moda-cli/SKILL.md +4 -1
- package/skills/moda-cli/references/dashboard-parity.md +1 -1
- package/skills/moda-cli/references/output-protocol.md +35 -10
- package/skills/moda-cli/references/search-and-traces.md +20 -2
- package/dist/cli-bb7133m7.js +0 -144
|
@@ -449,6 +449,14 @@ function resolveBaseUrl(options = {}) {
|
|
|
449
449
|
return PROD_BASE_URL;
|
|
450
450
|
}
|
|
451
451
|
}
|
|
452
|
+
function resolveBaseUrlStrict(options = {}) {
|
|
453
|
+
try {
|
|
454
|
+
getActiveProfile(options);
|
|
455
|
+
} catch {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
return resolveBaseUrl(options);
|
|
459
|
+
}
|
|
452
460
|
function resolveIngestUrl(options = {}) {
|
|
453
461
|
const environment = activeProfileEnvironment(options);
|
|
454
462
|
const envIngest = optionalString(getEnv(options).MODA_INGEST_URL);
|
|
@@ -668,6 +676,9 @@ var MODA_INGEST_URL = process.env.MODA_INGEST_URL || DEFAULT_INGEST_URL;
|
|
|
668
676
|
function resolveModaBaseUrl(options = {}) {
|
|
669
677
|
return resolveBaseUrl(options) || PROD_BASE_URL;
|
|
670
678
|
}
|
|
679
|
+
function resolveModaBaseUrlStrict(options = {}) {
|
|
680
|
+
return resolveBaseUrlStrict(options);
|
|
681
|
+
}
|
|
671
682
|
function validateConfig() {
|
|
672
683
|
if (!resolveApiKey()) {
|
|
673
684
|
throw new CliAuthError('No Moda API key found. Set MODA_API_KEY=moda_sk_... in the environment, save one with "moda auth login --api-key", or run "moda init" for interactive setup.', {
|
|
@@ -689,427 +700,6 @@ function resetApiRequestCount() {
|
|
|
689
700
|
apiRequestCount = 0;
|
|
690
701
|
}
|
|
691
702
|
|
|
692
|
-
// src/batch-reads.ts
|
|
693
|
-
import { readFile } from "node:fs/promises";
|
|
694
|
-
var BATCH_MAX_TARGETS = 25;
|
|
695
|
-
var BATCH_CONCURRENCY = 4;
|
|
696
|
-
var ANCHOR_SUFFIX = /^(.+)@(\d+)$/;
|
|
697
|
-
function parseBatchTarget(text, anchors, usage) {
|
|
698
|
-
const raw = text.trim();
|
|
699
|
-
if (raw.startsWith("{")) {
|
|
700
|
-
let parsed;
|
|
701
|
-
try {
|
|
702
|
-
parsed = JSON.parse(raw);
|
|
703
|
-
} catch {
|
|
704
|
-
throw new CliInputError(`Could not parse the JSON target ${JSON.stringify(raw)}.`, usage, "bad_batch_target");
|
|
705
|
-
}
|
|
706
|
-
const record = parsed;
|
|
707
|
-
const id = record?.id ?? record?.conversation_id ?? record?.trace_id;
|
|
708
|
-
if (typeof id !== "string" || id.trim() === "") {
|
|
709
|
-
throw new CliInputError(`JSON target ${JSON.stringify(raw)} has no "id" string.`, usage, "bad_batch_target");
|
|
710
|
-
}
|
|
711
|
-
const index = record.msg_index ?? record.message_index;
|
|
712
|
-
if (index !== undefined && index !== null) {
|
|
713
|
-
if (!anchors) {
|
|
714
|
-
throw new CliInputError(`JSON target ${JSON.stringify(raw)} has a msg_index, which this command does not take.`, usage, "bad_batch_target");
|
|
715
|
-
}
|
|
716
|
-
if (typeof index !== "number" || !Number.isSafeInteger(index) || index < 0) {
|
|
717
|
-
throw new CliInputError(`JSON target ${JSON.stringify(raw)} has an invalid msg_index (want an integer >= 0).`, usage, "bad_batch_target");
|
|
718
|
-
}
|
|
719
|
-
return { raw, id, msgIndex: index };
|
|
720
|
-
}
|
|
721
|
-
return { raw, id };
|
|
722
|
-
}
|
|
723
|
-
if (anchors) {
|
|
724
|
-
const match = ANCHOR_SUFFIX.exec(raw);
|
|
725
|
-
if (match) {
|
|
726
|
-
const msgIndex = Number(match[2]);
|
|
727
|
-
if (!Number.isSafeInteger(msgIndex)) {
|
|
728
|
-
throw new CliInputError(`Target ${JSON.stringify(raw)} has an @msg_index past ${Number.MAX_SAFE_INTEGER}. ` + 'If the id itself ends in @<digits>, pass it as {"id": "..."}.', usage, "bad_batch_target");
|
|
729
|
-
}
|
|
730
|
-
return { raw, id: match[1], msgIndex };
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
|
-
return { raw, id: raw };
|
|
734
|
-
}
|
|
735
|
-
function parseTargetLines(text, anchors, usage) {
|
|
736
|
-
return text.split(/\r?\n/).map((line) => line.trim()).filter((line) => line !== "").map((line) => parseBatchTarget(line, anchors, usage));
|
|
737
|
-
}
|
|
738
|
-
async function readStdinText() {
|
|
739
|
-
if (process.stdin.isTTY) {
|
|
740
|
-
throw new CliInputError("--ids-from=- reads targets from stdin, but stdin is a terminal. Pipe ids in (one per line) or pass a file path.", undefined, "ids_from_tty");
|
|
741
|
-
}
|
|
742
|
-
const chunks = [];
|
|
743
|
-
for await (const chunk of process.stdin)
|
|
744
|
-
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
745
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
746
|
-
}
|
|
747
|
-
async function readIdsFrom(source, usage) {
|
|
748
|
-
if (source === "" || source === "true") {
|
|
749
|
-
throw new CliInputError("--ids-from needs a value: - (stdin) or a file path.", usage, "missing_flag_value");
|
|
750
|
-
}
|
|
751
|
-
if (source === "-")
|
|
752
|
-
return readStdinText();
|
|
753
|
-
try {
|
|
754
|
-
return await readFile(source, "utf8");
|
|
755
|
-
} catch (error) {
|
|
756
|
-
const code = error.code;
|
|
757
|
-
throw new CliInputError(`Could not read --ids-from file ${JSON.stringify(source)}${typeof code === "string" ? ` (${code})` : ""}.`, usage, "ids_from_unreadable");
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
async function collectBatchTargets(positionals, idsFrom, options) {
|
|
761
|
-
const targets = positionals.map((value) => parseBatchTarget(value, options.anchors, options.usage));
|
|
762
|
-
if (idsFrom !== undefined) {
|
|
763
|
-
targets.push(...parseTargetLines(await readIdsFrom(idsFrom, options.usage), options.anchors, options.usage));
|
|
764
|
-
}
|
|
765
|
-
const seen = new Set;
|
|
766
|
-
const unique = targets.filter((target) => {
|
|
767
|
-
const key = `${target.id}\x00${target.msgIndex ?? ""}`;
|
|
768
|
-
if (seen.has(key))
|
|
769
|
-
return false;
|
|
770
|
-
seen.add(key);
|
|
771
|
-
return true;
|
|
772
|
-
});
|
|
773
|
-
if (unique.length === 0) {
|
|
774
|
-
throw new CliInputError(`No targets: --ids-from gave no ids (one per line).`, options.usage, "missing_positional");
|
|
775
|
-
}
|
|
776
|
-
if (unique.length > BATCH_MAX_TARGETS) {
|
|
777
|
-
throw new CliInputError(`Got ${unique.length} targets; 'moda ${options.command}' reads at most ${BATCH_MAX_TARGETS} per call, so nothing was read. ` + `Split the ids into calls of ${BATCH_MAX_TARGETS} or fewer.`, options.usage, "batch_too_large");
|
|
778
|
-
}
|
|
779
|
-
return unique;
|
|
780
|
-
}
|
|
781
|
-
async function mapWithConcurrency(items, limit, fn) {
|
|
782
|
-
const results = new Array(items.length);
|
|
783
|
-
let next = 0;
|
|
784
|
-
let failure;
|
|
785
|
-
const worker = async () => {
|
|
786
|
-
while (!failure && next < items.length) {
|
|
787
|
-
const index = next++;
|
|
788
|
-
try {
|
|
789
|
-
results[index] = await fn(items[index], index);
|
|
790
|
-
} catch (error) {
|
|
791
|
-
failure ??= { error };
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
};
|
|
795
|
-
await Promise.all(Array.from({ length: Math.max(1, Math.min(limit, items.length)) }, worker));
|
|
796
|
-
if (failure)
|
|
797
|
-
throw failure.error;
|
|
798
|
-
return results;
|
|
799
|
-
}
|
|
800
|
-
function idNeedsJsonTarget(id) {
|
|
801
|
-
return ANCHOR_SUFFIX.test(id);
|
|
802
|
-
}
|
|
803
|
-
function contextTarget(id) {
|
|
804
|
-
const verbatim = id === id.trim() && !id.startsWith("{") && !idNeedsJsonTarget(id);
|
|
805
|
-
return verbatim ? id : JSON.stringify({ id });
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
// src/transforms.ts
|
|
809
|
-
function asRecord(value) {
|
|
810
|
-
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
811
|
-
return value;
|
|
812
|
-
}
|
|
813
|
-
return null;
|
|
814
|
-
}
|
|
815
|
-
function asString(value) {
|
|
816
|
-
return typeof value === "string" ? value : null;
|
|
817
|
-
}
|
|
818
|
-
function asNumber(value) {
|
|
819
|
-
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
820
|
-
}
|
|
821
|
-
function frustrationAnchorIndex(row) {
|
|
822
|
-
if (!row)
|
|
823
|
-
return null;
|
|
824
|
-
const userQuotes = Array.isArray(row.user_quotes) ? row.user_quotes : [];
|
|
825
|
-
const firstQuote = asRecord(userQuotes[0]);
|
|
826
|
-
const resolved = asNumber(firstQuote?.msg_index) ?? asNumber(row.anchor_msg_index);
|
|
827
|
-
if (resolved !== null)
|
|
828
|
-
return resolved;
|
|
829
|
-
const keyTurns = Array.isArray(row.key_turns) ? row.key_turns : [];
|
|
830
|
-
const firstTurn = keyTurns.find((t) => typeof t === "number");
|
|
831
|
-
if (firstTurn !== undefined)
|
|
832
|
-
return firstTurn;
|
|
833
|
-
return asNumber(firstQuote?.turn);
|
|
834
|
-
}
|
|
835
|
-
function buildFrustrationAnchor(row) {
|
|
836
|
-
const conversation_id = asString(row.conversation_id) ?? "";
|
|
837
|
-
const userQuotes = Array.isArray(row.user_quotes) ? row.user_quotes : [];
|
|
838
|
-
const firstQuote = asRecord(userQuotes[0]);
|
|
839
|
-
const keyTurnsRaw = Array.isArray(row.key_turns) ? row.key_turns : [];
|
|
840
|
-
const all_turns = keyTurnsRaw.filter((t) => typeof t === "number");
|
|
841
|
-
const msg_index = frustrationAnchorIndex(row);
|
|
842
|
-
let signal = null;
|
|
843
|
-
let quote_preview = null;
|
|
844
|
-
if (firstQuote) {
|
|
845
|
-
signal = asString(firstQuote.signal);
|
|
846
|
-
const quote = asString(firstQuote.quote);
|
|
847
|
-
if (quote !== null) {
|
|
848
|
-
let end = 0;
|
|
849
|
-
let points = 0;
|
|
850
|
-
for (const ch of quote) {
|
|
851
|
-
if (points++ === 200)
|
|
852
|
-
break;
|
|
853
|
-
end += ch.length;
|
|
854
|
-
}
|
|
855
|
-
quote_preview = quote.slice(0, end);
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
return {
|
|
859
|
-
kind: "frustration",
|
|
860
|
-
conversation_id,
|
|
861
|
-
msg_index,
|
|
862
|
-
signal,
|
|
863
|
-
quote_preview,
|
|
864
|
-
all_turns,
|
|
865
|
-
no_anchor: msg_index === null
|
|
866
|
-
};
|
|
867
|
-
}
|
|
868
|
-
function buildToolFailureAnchor(row, toolName) {
|
|
869
|
-
const conversation_id = asString(row.conversation_id) ?? "";
|
|
870
|
-
const msg_index = asNumber(row.msg_index);
|
|
871
|
-
const tool_use_id = asString(row.tool_use_id);
|
|
872
|
-
const error_subtype = asString(row.error_subtype);
|
|
873
|
-
return {
|
|
874
|
-
kind: "tool_failure",
|
|
875
|
-
conversation_id,
|
|
876
|
-
msg_index,
|
|
877
|
-
tool_name: toolName,
|
|
878
|
-
tool_use_id,
|
|
879
|
-
error_subtype,
|
|
880
|
-
no_anchor: msg_index === null
|
|
881
|
-
};
|
|
882
|
-
}
|
|
883
|
-
function frustrationsFromEmotions(response) {
|
|
884
|
-
if (!Array.isArray(response.detections) || Array.isArray(response.frustrations))
|
|
885
|
-
return response;
|
|
886
|
-
const summary = asRecord(response.summary) ?? {};
|
|
887
|
-
const pagination = asRecord(response.pagination) ?? {};
|
|
888
|
-
const byFamily = asRecord(summary.by_family) ?? {};
|
|
889
|
-
const totalAnalyzed = asNumber(summary.conversations_analyzed) ?? 0;
|
|
890
|
-
const byFamilyConversations = asRecord(summary.conversations_by_family);
|
|
891
|
-
const frustrated = asNumber(byFamilyConversations?.frustration) ?? asNumber(byFamily.frustration) ?? 0;
|
|
892
|
-
const frustrations = response.detections.map((item) => asRecord(item)).filter((row) => row !== null && (row.family === undefined || row.family === "frustration")).map(({ conversation_context, score, is_detected, ...row }) => ({
|
|
893
|
-
...row,
|
|
894
|
-
is_frustrated: is_detected === true,
|
|
895
|
-
frustration_score: score,
|
|
896
|
-
target: row.elicitor === "bot" || row.elicitor === "external" ? row.elicitor : "ambiguous",
|
|
897
|
-
conversation: conversation_context ?? null
|
|
898
|
-
}));
|
|
899
|
-
const atRisk = asNumber(pagination.at_risk) ?? Math.max(0, (asNumber(pagination.total) ?? 0) - frustrated);
|
|
900
|
-
const signalBreakdown = {};
|
|
901
|
-
for (const item of Array.isArray(response.signal_breakdown) ? response.signal_breakdown : []) {
|
|
902
|
-
const row = asRecord(item);
|
|
903
|
-
if (row?.family === "frustration" && typeof row.signal === "string") {
|
|
904
|
-
signalBreakdown[row.signal] = asNumber(row.count) ?? 0;
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
const { detections: _detections, ...rest } = response;
|
|
908
|
-
return {
|
|
909
|
-
...rest,
|
|
910
|
-
summary: {
|
|
911
|
-
total_analyzed: totalAnalyzed,
|
|
912
|
-
frustrated_count: frustrated,
|
|
913
|
-
at_risk_count: atRisk,
|
|
914
|
-
frustration_rate_pct: totalAnalyzed > 0 ? Math.round(frustrated / totalAnalyzed * 1000) / 10 : 0
|
|
915
|
-
},
|
|
916
|
-
signal_breakdown: signalBreakdown,
|
|
917
|
-
frustrations,
|
|
918
|
-
source: "emotion_detections"
|
|
919
|
-
};
|
|
920
|
-
}
|
|
921
|
-
function withFrustrationAnchors(response) {
|
|
922
|
-
if (!Array.isArray(response.frustrations))
|
|
923
|
-
return response;
|
|
924
|
-
const frustrations = response.frustrations.map((item) => {
|
|
925
|
-
const row = asRecord(item);
|
|
926
|
-
if (!row)
|
|
927
|
-
return item;
|
|
928
|
-
const anchor = buildFrustrationAnchor(row);
|
|
929
|
-
return { ...row, anchor };
|
|
930
|
-
});
|
|
931
|
-
return { ...response, frustrations };
|
|
932
|
-
}
|
|
933
|
-
var TOOL_FAILURE_CONTEXT_RADIUS = 2;
|
|
934
|
-
function shellWord(value) {
|
|
935
|
-
return /^[\w@%+=:,./-]+$/.test(value) ? value : `'${value.replace(/'/g, `'\\''`)}'`;
|
|
936
|
-
}
|
|
937
|
-
function trimFailureWindow(value, radius, fallbackCenter) {
|
|
938
|
-
const conv = asRecord(value);
|
|
939
|
-
if (!conv)
|
|
940
|
-
return value ?? null;
|
|
941
|
-
const { coverage: _coverage, context, ...convRest } = conv;
|
|
942
|
-
const ctx = asRecord(context);
|
|
943
|
-
if (!ctx)
|
|
944
|
-
return convRest;
|
|
945
|
-
const center = asNumber(ctx.center_index) ?? fallbackCenter;
|
|
946
|
-
const messages = (Array.isArray(ctx.messages) ? ctx.messages : []).map((message) => asRecord(message)).filter((message) => {
|
|
947
|
-
const index = asNumber(message?.index);
|
|
948
|
-
return message !== null && (center === null || index === null || Math.abs(index - center) <= radius);
|
|
949
|
-
}).map(({ content_blocks, ...message }) => {
|
|
950
|
-
const covered = typeof message.content === "string" && message.content.length > 0 || Array.isArray(message.tool_calls) && message.tool_calls.length > 0 || Array.isArray(message.tool_results) && message.tool_results.length > 0;
|
|
951
|
-
return covered || content_blocks === undefined ? message : { ...message, content_blocks };
|
|
952
|
-
});
|
|
953
|
-
const indexes = messages.map((message) => asNumber(message.index)).filter((index) => index !== null);
|
|
954
|
-
return {
|
|
955
|
-
...convRest,
|
|
956
|
-
context: {
|
|
957
|
-
...ctx,
|
|
958
|
-
...indexes.length > 0 ? { from_index: Math.min(...indexes), to_index: Math.max(...indexes) } : {},
|
|
959
|
-
messages
|
|
960
|
-
}
|
|
961
|
-
};
|
|
962
|
-
}
|
|
963
|
-
function trimToolFailureConversations(response, opts) {
|
|
964
|
-
if (!Array.isArray(response.examples))
|
|
965
|
-
return response;
|
|
966
|
-
const examples = response.examples.map((item) => {
|
|
967
|
-
const row = asRecord(item);
|
|
968
|
-
if (!row)
|
|
969
|
-
return item;
|
|
970
|
-
const { conversation, window, ...rest } = row;
|
|
971
|
-
const conversationId = asString(row.conversation_id);
|
|
972
|
-
const msgIndex = asNumber(asRecord(row.anchor)?.msg_index) ?? asNumber(row.msg_index);
|
|
973
|
-
return {
|
|
974
|
-
...rest,
|
|
975
|
-
...conversationId && msgIndex !== null ? { context_command: `moda traces get ${shellWord(contextTarget(conversationId))} --msg-index=${msgIndex} --window=${TOOL_FAILURE_CONTEXT_RADIUS}` } : {},
|
|
976
|
-
...opts.drop ? {} : { conversation: trimFailureWindow(conversation, TOOL_FAILURE_CONTEXT_RADIUS, msgIndex) },
|
|
977
|
-
..."window" in row ? { window: trimFailureWindow(window, opts.windowRadius ?? TOOL_FAILURE_CONTEXT_RADIUS, msgIndex) } : {}
|
|
978
|
-
};
|
|
979
|
-
});
|
|
980
|
-
return { ...response, examples };
|
|
981
|
-
}
|
|
982
|
-
function withToolFailureAnchors(response) {
|
|
983
|
-
if (!Array.isArray(response.examples))
|
|
984
|
-
return response;
|
|
985
|
-
const toolName = asString(response.tool_name) ?? "";
|
|
986
|
-
const examples = response.examples.map((item) => {
|
|
987
|
-
const row = asRecord(item);
|
|
988
|
-
if (!row)
|
|
989
|
-
return item;
|
|
990
|
-
const anchor = buildToolFailureAnchor(row, toolName);
|
|
991
|
-
return { ...row, anchor };
|
|
992
|
-
});
|
|
993
|
-
return { ...response, examples };
|
|
994
|
-
}
|
|
995
|
-
function embeddedWindowSize(conversation) {
|
|
996
|
-
if (!conversation)
|
|
997
|
-
return null;
|
|
998
|
-
const ctx = asRecord(conversation.context);
|
|
999
|
-
if (!ctx)
|
|
1000
|
-
return null;
|
|
1001
|
-
const center = asNumber(ctx.center_index);
|
|
1002
|
-
const from = asNumber(ctx.from_index);
|
|
1003
|
-
const to = asNumber(ctx.to_index);
|
|
1004
|
-
if (center === null || from === null || to === null)
|
|
1005
|
-
return null;
|
|
1006
|
-
return Math.min(center - from, to - center);
|
|
1007
|
-
}
|
|
1008
|
-
var DETECTION_CONTEXT_RADIUS = 2;
|
|
1009
|
-
function withoutDetectionWindows(response, listKey, windowKey) {
|
|
1010
|
-
const list = response[listKey];
|
|
1011
|
-
if (!Array.isArray(list))
|
|
1012
|
-
return response;
|
|
1013
|
-
const rows = list.map((item) => {
|
|
1014
|
-
const row = asRecord(item);
|
|
1015
|
-
if (!row)
|
|
1016
|
-
return item;
|
|
1017
|
-
const { [windowKey]: _window, ...rest } = row;
|
|
1018
|
-
const conversationId = asString(row.conversation_id);
|
|
1019
|
-
const msgIndex = asNumber(asRecord(row.anchor)?.msg_index) ?? frustrationAnchorIndex(row);
|
|
1020
|
-
return {
|
|
1021
|
-
...rest,
|
|
1022
|
-
...conversationId && msgIndex !== null ? { context_command: `moda traces get ${shellWord(contextTarget(conversationId))} --msg-index=${msgIndex} --window=${DETECTION_CONTEXT_RADIUS}` } : {}
|
|
1023
|
-
};
|
|
1024
|
-
});
|
|
1025
|
-
return { ...response, [listKey]: rows };
|
|
1026
|
-
}
|
|
1027
|
-
var PROBLEM_COMPACT_EVIDENCE = 5;
|
|
1028
|
-
var PROBLEM_COMPACT_OMITTED_BLOCKS = [
|
|
1029
|
-
"rubric",
|
|
1030
|
-
"trend",
|
|
1031
|
-
"sub_problems",
|
|
1032
|
-
"affected_conversations",
|
|
1033
|
-
"remainder",
|
|
1034
|
-
"confidence",
|
|
1035
|
-
"change_history",
|
|
1036
|
-
"stories"
|
|
1037
|
-
];
|
|
1038
|
-
function readCommand(command, purpose) {
|
|
1039
|
-
return { command, purpose, mutability: "read", requires_approval: false };
|
|
1040
|
-
}
|
|
1041
|
-
function evidenceMsgIndex(row) {
|
|
1042
|
-
return asNumber(row.anchor_msg_index) ?? asNumber(asRecord(asRecord(row.snippet_parsed)?.anchor)?.msg_index);
|
|
1043
|
-
}
|
|
1044
|
-
function compactProblemDossier(response, problemId) {
|
|
1045
|
-
const id = shellWord(asString(response.problem_id) ?? problemId);
|
|
1046
|
-
const evidence = (Array.isArray(response.evidence) ? response.evidence : []).map((item) => asRecord(item)).filter((row) => row !== null);
|
|
1047
|
-
const topEvidence = evidence.slice(0, PROBLEM_COMPACT_EVIDENCE).map((row) => {
|
|
1048
|
-
const conversationId = asString(row.conversation_id);
|
|
1049
|
-
const msgIndex = evidenceMsgIndex(row);
|
|
1050
|
-
return {
|
|
1051
|
-
attribution_id: row.attribution_id ?? null,
|
|
1052
|
-
conversation_id: conversationId,
|
|
1053
|
-
msg_index: msgIndex,
|
|
1054
|
-
signal_family: row.signal_family ?? null,
|
|
1055
|
-
signal_type: row.signal_type ?? null,
|
|
1056
|
-
confidence: row.confidence ?? null,
|
|
1057
|
-
causal_rationale: row.causal_rationale ?? null,
|
|
1058
|
-
door: row.door ?? null,
|
|
1059
|
-
replay_verified: row.replay_verified ?? null,
|
|
1060
|
-
...conversationId && msgIndex !== null ? { context_command: `moda traces get ${shellWord(contextTarget(conversationId))} --msg-index=${msgIndex}` } : {}
|
|
1061
|
-
};
|
|
1062
|
-
});
|
|
1063
|
-
const reportsBlock = asRecord(response.investigation_reports);
|
|
1064
|
-
const reports = (Array.isArray(reportsBlock?.items) ? reportsBlock.items : []).map((item) => asRecord(item)).filter((row) => row !== null).map((row) => ({
|
|
1065
|
-
report_id: row.report_id ?? null,
|
|
1066
|
-
conversation_id: row.conversation_id ?? null,
|
|
1067
|
-
mechanism: row.mechanism ?? null,
|
|
1068
|
-
suspected_surface: row.suspected_surface ?? null,
|
|
1069
|
-
severity: row.severity ?? null,
|
|
1070
|
-
problem_found: row.problem_found ?? null
|
|
1071
|
-
}));
|
|
1072
|
-
const verification = asRecord(response.verification);
|
|
1073
|
-
const { samples: _samples, ...verificationCounts } = verification ?? {};
|
|
1074
|
-
const dossier = asRecord(response.dossier);
|
|
1075
|
-
const { representative_story_keys: _storyKeys, ...dossierSummary } = dossier ?? {};
|
|
1076
|
-
const trend = Array.isArray(response.trend) ? response.trend : [];
|
|
1077
|
-
const data = {
|
|
1078
|
-
found: response.found ?? true,
|
|
1079
|
-
problem_id: response.problem_id ?? problemId,
|
|
1080
|
-
requested_problem_id: response.requested_problem_id ?? problemId,
|
|
1081
|
-
alias_resolved: response.alias_resolved ?? false,
|
|
1082
|
-
view: "compact",
|
|
1083
|
-
header: response.header ?? null,
|
|
1084
|
-
dossier: dossier ? dossierSummary : null,
|
|
1085
|
-
verification: verification ? verificationCounts : null,
|
|
1086
|
-
...response.impact_identity !== undefined ? { impact_identity: response.impact_identity } : {},
|
|
1087
|
-
...response.hierarchy !== undefined ? { hierarchy: response.hierarchy } : {},
|
|
1088
|
-
...trend.length > 0 ? { trend_latest: trend[trend.length - 1], trend_points: trend.length } : {},
|
|
1089
|
-
top_evidence: topEvidence,
|
|
1090
|
-
evidence_in_dossier: evidence.length,
|
|
1091
|
-
reports,
|
|
1092
|
-
omitted: {
|
|
1093
|
-
evidence_rows: Math.max(0, evidence.length - topEvidence.length),
|
|
1094
|
-
report_narratives: reports.length,
|
|
1095
|
-
reports_has_more: reportsBlock?.has_more === true,
|
|
1096
|
-
blocks: PROBLEM_COMPACT_OMITTED_BLOCKS.filter((key) => (key in response))
|
|
1097
|
-
},
|
|
1098
|
-
full_command: `moda problems get ${id} --full`
|
|
1099
|
-
};
|
|
1100
|
-
const nextCommands = [
|
|
1101
|
-
readCommand(`moda problems get ${id} --evidence --limit=20`, "Page every evidence row with its anchor (follow next_cursor)."),
|
|
1102
|
-
readCommand(`moda problems get ${id} --reports`, "Page investigation reports with narratives and citations."),
|
|
1103
|
-
readCommand(`moda problems get ${id} --traces`, "Page affected traces with their latest anchor."),
|
|
1104
|
-
readCommand(`moda problems get ${id} --full`, "The complete dossier, every block (large).")
|
|
1105
|
-
];
|
|
1106
|
-
const first = topEvidence.find((row) => typeof row.context_command === "string");
|
|
1107
|
-
if (first?.context_command) {
|
|
1108
|
-
nextCommands.push(readCommand(first.context_command, "Read the trace around the top evidence anchor."));
|
|
1109
|
-
}
|
|
1110
|
-
return { data, nextCommands };
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
703
|
// ../../packages/harness-snapshot/src/policy.ts
|
|
1114
704
|
var MAX_SCANNED_FILE_BYTES = 512 * 1024;
|
|
1115
705
|
var DEFAULT_MAX_INVENTORY_FILES = 12000;
|
|
@@ -1450,6 +1040,15 @@ function packSnapshot(inputs, opts) {
|
|
|
1450
1040
|
skips
|
|
1451
1041
|
};
|
|
1452
1042
|
}
|
|
1043
|
+
// src/shell-quote.ts
|
|
1044
|
+
function shellArg(value) {
|
|
1045
|
+
if (/^[A-Za-z0-9_.,:@%+/=-]+$/.test(value))
|
|
1046
|
+
return value;
|
|
1047
|
+
if (!/["$`\\!]/.test(value))
|
|
1048
|
+
return `"${value}"`;
|
|
1049
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1453
1052
|
// src/legacy-names.ts
|
|
1454
1053
|
var LEGACY_NAMES = [
|
|
1455
1054
|
{ legacy: "conversations", use: "moda traces list", canonical: { command: "traces", subcommand: "list" }, silent: true },
|
|
@@ -1542,7 +1141,9 @@ function quotedArgumentSpans(text) {
|
|
|
1542
1141
|
return spans;
|
|
1543
1142
|
}
|
|
1544
1143
|
function canonicalInvocation(entry, rest) {
|
|
1545
|
-
|
|
1144
|
+
const separator = rest.indexOf("--");
|
|
1145
|
+
const afterSeparator = separator === -1 ? [] : rest.slice(separator);
|
|
1146
|
+
let words = separator === -1 ? [...rest] : rest.slice(0, separator);
|
|
1546
1147
|
const takeFlag = (pattern) => {
|
|
1547
1148
|
const index = words.findIndex((word2) => pattern.test(word2));
|
|
1548
1149
|
if (index === -1)
|
|
@@ -1563,7 +1164,7 @@ function canonicalInvocation(entry, rest) {
|
|
|
1563
1164
|
takeFlag(/^--detections(=true)?$/);
|
|
1564
1165
|
break;
|
|
1565
1166
|
case "false-positive":
|
|
1566
|
-
words = words.map((word) => /^--undo(=true)
|
|
1167
|
+
words = words.filter((word) => !/^--undo=(false|0)$/i.test(word)).map((word) => /^--undo(=true|=1)?$/i.test(word) ? "--verdict=clear" : word);
|
|
1567
1168
|
break;
|
|
1568
1169
|
case "signal-label":
|
|
1569
1170
|
words = words.map((word) => word.replace(/^--label=fits$/, "--verdict=correct").replace(/^--label=does_not_fit$/, "--verdict=false_positive").replace(/^--label=.*$/, "--verdict=correct|false_positive"));
|
|
@@ -1585,7 +1186,7 @@ function canonicalInvocation(entry, rest) {
|
|
|
1585
1186
|
out.push(token.startsWith("--family=") ? `${token}${familySuffix}` : token);
|
|
1586
1187
|
}
|
|
1587
1188
|
}
|
|
1588
|
-
return [...out, ...positionals, ...words].join(" ");
|
|
1189
|
+
return [...out, ...positionals, ...words, ...afterSeparator].join(" ");
|
|
1589
1190
|
}
|
|
1590
1191
|
function canonicalCommandText(text) {
|
|
1591
1192
|
if (!text.includes("moda "))
|
|
@@ -1616,8 +1217,8 @@ function canonicalCommandText(text) {
|
|
|
1616
1217
|
|
|
1617
1218
|
// src/output.ts
|
|
1618
1219
|
import { randomUUID } from "node:crypto";
|
|
1619
|
-
import { lstatSync, mkdirSync as mkdirSync2, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1620
|
-
import { tmpdir } from "node:os";
|
|
1220
|
+
import { chmodSync as chmodSync2, lstatSync, mkdirSync as mkdirSync2, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1221
|
+
import { tmpdir, userInfo } from "node:os";
|
|
1621
1222
|
import { join as join2 } from "node:path";
|
|
1622
1223
|
var SUGGESTION_KEY = /(_commands?|^hints?|^suggestions?)$/i;
|
|
1623
1224
|
function canonicalDeep(value, rewriteStrings) {
|
|
@@ -1684,20 +1285,51 @@ var MODA_COMMAND = /^(?:moda |.*\| moda )/;
|
|
|
1684
1285
|
function withProfileFlag(command, flag) {
|
|
1685
1286
|
return MODA_COMMAND.test(command) && !/(?:^|\s)--profile(?:[=\s]|$)/.test(command) ? `${command} ${flag}` : command;
|
|
1686
1287
|
}
|
|
1288
|
+
var GENERATED_COMMAND_KEY = /_commands?$/;
|
|
1289
|
+
var GENERATED_COMMAND_LIST_KEY = /(?:_commands|^recommended_actions|^recommendedActions|^setupPlan)$/;
|
|
1290
|
+
var CUSTOMER_CONTENT_KEYS = new Set([
|
|
1291
|
+
"messages",
|
|
1292
|
+
"context",
|
|
1293
|
+
"conversation",
|
|
1294
|
+
"conversation_context",
|
|
1295
|
+
"window",
|
|
1296
|
+
"tool_calls",
|
|
1297
|
+
"tool_results",
|
|
1298
|
+
"content",
|
|
1299
|
+
"content_blocks",
|
|
1300
|
+
"input",
|
|
1301
|
+
"output",
|
|
1302
|
+
"tool_input",
|
|
1303
|
+
"tool_output",
|
|
1304
|
+
"spans",
|
|
1305
|
+
"ingest",
|
|
1306
|
+
"raw_event",
|
|
1307
|
+
"attributes",
|
|
1308
|
+
"payload",
|
|
1309
|
+
"snippet_parsed",
|
|
1310
|
+
"evidence_snippet",
|
|
1311
|
+
"request",
|
|
1312
|
+
"response"
|
|
1313
|
+
]);
|
|
1687
1314
|
function withProfileOnCommands(value, profile) {
|
|
1688
|
-
const flag = `--profile=${
|
|
1689
|
-
const visit = (node, key) => {
|
|
1690
|
-
const isCommandKey = key !== undefined &&
|
|
1315
|
+
const flag = `--profile=${shellArg(profile)}`;
|
|
1316
|
+
const visit = (node, key, inCommandList) => {
|
|
1317
|
+
const isCommandKey = key !== undefined && (GENERATED_COMMAND_KEY.test(key) || inCommandList && key === "command");
|
|
1691
1318
|
if (typeof node === "string")
|
|
1692
1319
|
return isCommandKey ? withProfileFlag(node, flag) : node;
|
|
1693
|
-
if (Array.isArray(node))
|
|
1694
|
-
|
|
1695
|
-
|
|
1320
|
+
if (Array.isArray(node)) {
|
|
1321
|
+
const list = key !== undefined && GENERATED_COMMAND_LIST_KEY.test(key);
|
|
1322
|
+
return node.map((item) => typeof item === "string" ? visit(item, isCommandKey ? key : undefined, false) : visit(item, undefined, list));
|
|
1323
|
+
}
|
|
1324
|
+
const record = asRecord(node);
|
|
1696
1325
|
if (!record)
|
|
1697
1326
|
return node;
|
|
1698
|
-
return Object.fromEntries(Object.entries(record).map(([entryKey, entry]) => [
|
|
1327
|
+
return Object.fromEntries(Object.entries(record).map(([entryKey, entry]) => [
|
|
1328
|
+
entryKey,
|
|
1329
|
+
CUSTOMER_CONTENT_KEYS.has(entryKey) ? entry : visit(entry, entryKey, inCommandList)
|
|
1330
|
+
]));
|
|
1699
1331
|
};
|
|
1700
|
-
return visit(value, undefined);
|
|
1332
|
+
return visit(value, undefined, false);
|
|
1701
1333
|
}
|
|
1702
1334
|
var FALLBACK_RUN_ID = randomUUID();
|
|
1703
1335
|
var fallbackSeq = 0;
|
|
@@ -1879,12 +1511,16 @@ function createCliOutput(options) {
|
|
|
1879
1511
|
if (options.quiet && !bypassQuiet)
|
|
1880
1512
|
return;
|
|
1881
1513
|
const profile = options.invocation?.flags.profile;
|
|
1514
|
+
const agentOutput = options.mode === "agent" || options.mode === "agent-stream";
|
|
1882
1515
|
if (profile) {
|
|
1883
|
-
|
|
1516
|
+
if (agentOutput)
|
|
1517
|
+
data = withProfileOnCommands(data, profile);
|
|
1884
1518
|
if (writeOptions.nextCommands)
|
|
1885
|
-
writeOptions = { ...writeOptions, nextCommands: withProfileOnCommands(writeOptions.nextCommands, profile) };
|
|
1519
|
+
writeOptions = { ...writeOptions, nextCommands: withProfileOnCommands({ next_commands: writeOptions.nextCommands }, profile).next_commands };
|
|
1520
|
+
if (writeOptions.recommendedActions)
|
|
1521
|
+
writeOptions = { ...writeOptions, recommendedActions: withProfileOnCommands({ recommended_actions: writeOptions.recommendedActions }, profile).recommended_actions };
|
|
1886
1522
|
}
|
|
1887
|
-
if (
|
|
1523
|
+
if (agentOutput) {
|
|
1888
1524
|
if (state.terminal)
|
|
1889
1525
|
return;
|
|
1890
1526
|
const envelope = writeEnvelope(data, writeOptions);
|
|
@@ -1905,7 +1541,8 @@ function createCliOutput(options) {
|
|
|
1905
1541
|
}
|
|
1906
1542
|
return;
|
|
1907
1543
|
}
|
|
1908
|
-
|
|
1544
|
+
const indent = options.mode === "human" || (options.pretty ?? Boolean(process.stdout.isTTY)) ? 2 : undefined;
|
|
1545
|
+
safeWriteStdout(`${JSON.stringify(canonicalSuggestionFields(redactDeep(data)), null, indent)}
|
|
1909
1546
|
`);
|
|
1910
1547
|
for (const warning of writeOptions.warnings ?? []) {
|
|
1911
1548
|
safeWriteStderr(`Warning: ${canonicalCommandText(warning)}
|
|
@@ -2368,6 +2005,16 @@ function errorToAgentError(error) {
|
|
|
2368
2005
|
blocking: true
|
|
2369
2006
|
};
|
|
2370
2007
|
}
|
|
2008
|
+
if (apiErrorStatus(error) === 404 && !error.readable) {
|
|
2009
|
+
const suggestions = "suggestions" in error && Array.isArray(error.suggestions) ? error.suggestions.filter((s) => typeof s === "string") : [];
|
|
2010
|
+
return {
|
|
2011
|
+
code: "not_found",
|
|
2012
|
+
message: `Not found (HTTP 404): ${serverErrorMessage(error) ?? "the Moda API has no such resource"}.`,
|
|
2013
|
+
cause: "The id may be mistyped, from another tenant or profile, or deleted.",
|
|
2014
|
+
...suggestions.length > 0 ? { suggested_commands: suggestions } : {},
|
|
2015
|
+
blocking: true
|
|
2016
|
+
};
|
|
2017
|
+
}
|
|
2371
2018
|
if (isApiLikeError(error)) {
|
|
2372
2019
|
const statusCode = "statusCode" in error ? error.statusCode : undefined;
|
|
2373
2020
|
const typedCode = "code" in error && typeof error.code === "string" ? error.code : undefined;
|
|
@@ -2445,11 +2092,11 @@ function normalizeSummary(summary, command, status, data) {
|
|
|
2445
2092
|
return inferSummary(command, status, data);
|
|
2446
2093
|
}
|
|
2447
2094
|
function inferSummary(command, status, data) {
|
|
2448
|
-
const record =
|
|
2095
|
+
const record = asRecord(data);
|
|
2449
2096
|
if (status === "error") {
|
|
2450
2097
|
return { text: `${command} failed.`, confidence: "high" };
|
|
2451
2098
|
}
|
|
2452
|
-
const summary =
|
|
2099
|
+
const summary = asRecord(record?.summary);
|
|
2453
2100
|
if (summary) {
|
|
2454
2101
|
const statusValue = typeof summary.status === "string" ? summary.status : undefined;
|
|
2455
2102
|
const fail = typeof summary.fail === "number" ? summary.fail : undefined;
|
|
@@ -2501,11 +2148,11 @@ function inferMutability(command) {
|
|
|
2501
2148
|
return "read";
|
|
2502
2149
|
}
|
|
2503
2150
|
function inferWarnings(data) {
|
|
2504
|
-
const record =
|
|
2151
|
+
const record = asRecord(data);
|
|
2505
2152
|
const direct = record?.warnings;
|
|
2506
2153
|
if (Array.isArray(direct))
|
|
2507
2154
|
return direct.filter((item) => typeof item === "string");
|
|
2508
|
-
const validation =
|
|
2155
|
+
const validation = asRecord(record?.validation);
|
|
2509
2156
|
if (Array.isArray(validation?.warnings)) {
|
|
2510
2157
|
return validation.warnings.filter((item) => typeof item === "string");
|
|
2511
2158
|
}
|
|
@@ -2543,10 +2190,37 @@ function pruneAgentFullOutputs(dir, keep, now = Date.now()) {
|
|
|
2543
2190
|
} catch {}
|
|
2544
2191
|
}
|
|
2545
2192
|
}
|
|
2193
|
+
function currentUserTag() {
|
|
2194
|
+
if (typeof process.getuid === "function")
|
|
2195
|
+
return String(process.getuid());
|
|
2196
|
+
try {
|
|
2197
|
+
return userInfo().username.replace(/[^A-Za-z0-9_.-]+/g, "_") || "user";
|
|
2198
|
+
} catch {
|
|
2199
|
+
return "user";
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
function defaultAgentOutputDir() {
|
|
2203
|
+
return join2(tmpdir(), `moda-agent-output-${currentUserTag()}`);
|
|
2204
|
+
}
|
|
2205
|
+
function ensurePrivateDir(dir) {
|
|
2206
|
+
mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
2207
|
+
const stat = lstatSync(dir);
|
|
2208
|
+
if (!stat.isDirectory())
|
|
2209
|
+
throw new Error(`${dir} is not a directory.`);
|
|
2210
|
+
if (typeof process.getuid === "function" && stat.uid !== process.getuid()) {
|
|
2211
|
+
throw new Error(`${dir} is owned by another user.`);
|
|
2212
|
+
}
|
|
2213
|
+
if (process.platform !== "win32" && (stat.mode & 63) !== 0)
|
|
2214
|
+
chmodSync2(dir, 448);
|
|
2215
|
+
}
|
|
2546
2216
|
function writeAgentFullOutput(command, data) {
|
|
2547
2217
|
try {
|
|
2548
|
-
const
|
|
2549
|
-
|
|
2218
|
+
const configured = process.env.MODA_AGENT_OUTPUT_DIR;
|
|
2219
|
+
const dir = configured || defaultAgentOutputDir();
|
|
2220
|
+
if (configured)
|
|
2221
|
+
mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
2222
|
+
else
|
|
2223
|
+
ensurePrivateDir(dir);
|
|
2550
2224
|
const slug = command.replace(/[^a-zA-Z0-9_-]+/g, "-").replace(/^-+|-+$/g, "") || "output";
|
|
2551
2225
|
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
2552
2226
|
const path = join2(dir, `${slug}-${stamp}-${randomUUID().slice(0, 8)}.json`);
|
|
@@ -2567,7 +2241,7 @@ function contentBlocksRedundant(message) {
|
|
|
2567
2241
|
const hasToolResults = Array.isArray(message.tool_results) && message.tool_results.length > 0;
|
|
2568
2242
|
const texts = [];
|
|
2569
2243
|
for (const item of blocks) {
|
|
2570
|
-
const block =
|
|
2244
|
+
const block = asRecord(item);
|
|
2571
2245
|
if (!block)
|
|
2572
2246
|
return false;
|
|
2573
2247
|
if (block.type === "text") {
|
|
@@ -2599,7 +2273,7 @@ function shedRedundantContentBlocks(value) {
|
|
|
2599
2273
|
visit(item);
|
|
2600
2274
|
return;
|
|
2601
2275
|
}
|
|
2602
|
-
const record =
|
|
2276
|
+
const record = asRecord(node);
|
|
2603
2277
|
if (!record)
|
|
2604
2278
|
return;
|
|
2605
2279
|
if ("content_blocks" in record && contentBlocksRedundant(record)) {
|
|
@@ -2618,22 +2292,29 @@ function continuationCommand(invocation, overrides) {
|
|
|
2618
2292
|
const normalize2 = (key) => key.replace(/_/g, "-");
|
|
2619
2293
|
const overridden = new Set(Object.keys(overrides).map(normalize2));
|
|
2620
2294
|
const bare = new Set((invocation.bareFlags ?? []).map(normalize2));
|
|
2621
|
-
const
|
|
2295
|
+
const dashAt = invocation.positionals.findIndex((value) => value.startsWith("-"));
|
|
2296
|
+
const leading = dashAt === -1 ? invocation.positionals : invocation.positionals.slice(0, dashAt);
|
|
2297
|
+
const trailing = dashAt === -1 ? [] : invocation.positionals.slice(dashAt);
|
|
2298
|
+
const parts = ["moda", invocation.command, ...leading.map((value) => shellArg(value))];
|
|
2622
2299
|
for (const [key, value] of Object.entries(invocation.flags)) {
|
|
2623
2300
|
const flag = normalize2(key);
|
|
2624
2301
|
if (overridden.has(flag) || CONTINUATION_SECRET_FLAGS.has(flag))
|
|
2625
2302
|
continue;
|
|
2626
|
-
parts.push(bare.has(flag) && value === "true" ? `--${flag}` : `--${flag}=${
|
|
2303
|
+
parts.push(bare.has(flag) && value === "true" ? `--${flag}` : `--${flag}=${shellArg(String(value))}`);
|
|
2627
2304
|
}
|
|
2628
2305
|
for (const [key, value] of Object.entries(overrides))
|
|
2629
|
-
parts.push(`--${normalize2(key)}=${
|
|
2306
|
+
parts.push(`--${normalize2(key)}=${shellArg(String(value))}`);
|
|
2307
|
+
if (trailing.length > 0)
|
|
2308
|
+
parts.push("--", ...trailing.map((value) => shellArg(value)));
|
|
2630
2309
|
return canonicalCommandText(parts.join(" "));
|
|
2631
2310
|
}
|
|
2632
2311
|
var PAGED_LIST_BY_COMMAND = {
|
|
2633
2312
|
"tool-failure-detail": "examples",
|
|
2634
2313
|
emotions: "detections",
|
|
2635
2314
|
frustrations: "frustrations",
|
|
2636
|
-
|
|
2315
|
+
laziness: "conversations",
|
|
2316
|
+
"problems remainder": "groups",
|
|
2317
|
+
"problem remainder": "groups"
|
|
2637
2318
|
};
|
|
2638
2319
|
function pagedListFor(invocation) {
|
|
2639
2320
|
const { command, positionals } = invocation.routedAs ?? invocation;
|
|
@@ -2645,7 +2326,7 @@ function rewritePagination(list, isTopLevel, invocation) {
|
|
|
2645
2326
|
const { parent, array, originalLength } = list;
|
|
2646
2327
|
if (!parent)
|
|
2647
2328
|
return;
|
|
2648
|
-
const nested =
|
|
2329
|
+
const nested = asRecord(parent.pagination);
|
|
2649
2330
|
const inline = !nested && !isTopLevel && (("has_more" in parent) || ("next_cursor" in parent)) ? parent : undefined;
|
|
2650
2331
|
const pagination = nested ?? inline;
|
|
2651
2332
|
if (!pagination)
|
|
@@ -2663,7 +2344,7 @@ function rewritePagination(list, isTopLevel, invocation) {
|
|
|
2663
2344
|
const kept = array.length;
|
|
2664
2345
|
const omitted = originalLength - kept;
|
|
2665
2346
|
const offset = typeof pagination.offset === "number" && Number.isFinite(pagination.offset) ? pagination.offset : undefined;
|
|
2666
|
-
const hadCursor = typeof pagination.next_cursor === "string" && pagination.next_cursor.length > 0;
|
|
2347
|
+
const hadCursor = typeof pagination.next_cursor === "string" && pagination.next_cursor.length > 0 || typeof pagination.nextCursor === "string" && pagination.nextCursor.length > 0;
|
|
2667
2348
|
if (typeof pagination.limit === "number") {
|
|
2668
2349
|
pagination.requested_limit = pagination.limit;
|
|
2669
2350
|
pagination.limit = kept;
|
|
@@ -2671,6 +2352,10 @@ function rewritePagination(list, isTopLevel, invocation) {
|
|
|
2671
2352
|
pagination.returned = kept;
|
|
2672
2353
|
pagination.omitted_for_byte_limit = omitted;
|
|
2673
2354
|
pagination.has_more = true;
|
|
2355
|
+
if ("hasMore" in pagination)
|
|
2356
|
+
pagination.hasMore = true;
|
|
2357
|
+
if ("nextCursor" in pagination && typeof pagination.nextCursor === "string" && pagination.nextCursor)
|
|
2358
|
+
pagination.nextCursor = null;
|
|
2674
2359
|
const pastOffsetCap = offset !== undefined && offset + kept > MAX_PAGE_OFFSET;
|
|
2675
2360
|
if (offset !== undefined && !pastOffsetCap)
|
|
2676
2361
|
pagination.next_offset = offset + kept;
|
|
@@ -2781,7 +2466,7 @@ function boundForAgent(data, maxBytes = agentMaxOutputBytes(), options = {}) {
|
|
|
2781
2466
|
fullOutputPath
|
|
2782
2467
|
};
|
|
2783
2468
|
}
|
|
2784
|
-
const root =
|
|
2469
|
+
const root = asRecord(bounded);
|
|
2785
2470
|
const notes = [];
|
|
2786
2471
|
const nextCommands = [];
|
|
2787
2472
|
for (const list of droppedLists.values()) {
|
|
@@ -2819,7 +2504,7 @@ function boundForAgent(data, maxBytes = agentMaxOutputBytes(), options = {}) {
|
|
|
2819
2504
|
...nextCommands.length > 0 ? { nextCommands } : {}
|
|
2820
2505
|
};
|
|
2821
2506
|
}
|
|
2822
|
-
function
|
|
2507
|
+
function asRecord(value) {
|
|
2823
2508
|
return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
2824
2509
|
}
|
|
2825
2510
|
function extractSuggestedCommands(text) {
|
|
@@ -2852,4 +2537,4 @@ function apiKeyHeaders(key, options = {}, url) {
|
|
|
2852
2537
|
return headers;
|
|
2853
2538
|
}
|
|
2854
2539
|
|
|
2855
|
-
export { PROD_BASE_URL, DEFAULT_INGEST_URL, getModaPaths, getModaDir, isLoopbackBaseUrl, describeBaseUrlSource, loadProfileConfig, saveProfileConfig, getActiveProfile, setActiveProfile, upsertProfile, clearStoredApiKeyCredentials, secretFilePathFromRef, resolveSecretReference, resolveApiKeyFromActiveProfile, resolveTenantIdFromActiveProfile, ensureSecretFilePermissions, writeSecretJsonFile, CliInputError, attachInputDetails, inputDetailsOf, CliAccessError, CliInputRequiredError, CliAuthError, CliNotFoundError, CliCancellationError, isNetworkLikeError, isApiLikeError, apiErrorStatus, VERSION, MODA_BASE_URL, loadCliConfig, saveCliConfig, resolveApiKey, embeddedTenantIdFromApiKey, resolveIngestUrl2 as resolveIngestUrl, resolveTenantId, resolveApiTenantId, resolveModaBaseUrl, validateConfig, isPlatformApiKey, setPlatformTenantOverride, apiKeyHeaders, recordApiRequest, getApiRequestCount, resetApiRequestCount,
|
|
2540
|
+
export { PROD_BASE_URL, DEFAULT_INGEST_URL, getModaPaths, getModaDir, isLoopbackBaseUrl, describeBaseUrlSource, loadProfileConfig, saveProfileConfig, getActiveProfile, setActiveProfile, upsertProfile, clearStoredApiKeyCredentials, secretFilePathFromRef, resolveSecretReference, resolveApiKeyFromActiveProfile, resolveTenantIdFromActiveProfile, ensureSecretFilePermissions, writeSecretJsonFile, CliInputError, attachInputDetails, inputDetailsOf, CliAccessError, CliInputRequiredError, CliAuthError, CliNotFoundError, CliCancellationError, isNetworkLikeError, isApiLikeError, apiErrorStatus, VERSION, MODA_BASE_URL, loadCliConfig, saveCliConfig, resolveApiKey, embeddedTenantIdFromApiKey, resolveIngestUrl2 as resolveIngestUrl, resolveTenantId, resolveApiTenantId, resolveModaBaseUrl, resolveModaBaseUrlStrict, validateConfig, isPlatformApiKey, setPlatformTenantOverride, apiKeyHeaders, recordApiRequest, getApiRequestCount, resetApiRequestCount, MAX_SCANNED_FILE_BYTES, DEFAULT_MAX_INVENTORY_FILES, DEFAULT_MAX_INVENTORY_TEXT_BYTES, MAX_RECORDED_SKIPS, SKIPPED_DIRS, isSkippedDir, isSkippedPathPrefix, isEvalLikePath, shouldInventoryFile, isTextFile, isSecretishPath, SECRET_KEYS, redactDeep, redactString, packSnapshot, shellArg, LEGACY_NAMES, canonicalCommandText, setAgentUpdateNotice, EXIT_OK, EXIT_ERROR, EXIT_DEGRADED, EXIT_AUTH_REQUIRED, EXIT_INPUT_REQUIRED, EXIT_CANCELLED, AGENT_ERROR_CODES, wasOutputCancelled, safeWriteStdout, safeWriteStderr, explicitOutputMode, outputModeFromFlags, resolveOutputMode, createCliOutput, agentEnvelopeFits, errorToAgentError, agentMaxOutputBytes, continuationCommand };
|