@moda-ai/cli 1.55.50 → 1.55.52
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-vdqppnq3.js → agent-nxn5df1w.js} +3 -3
- package/dist/{cli-79pzgqtj.js → cli-arze1hgb.js} +3 -3
- package/dist/{cli-n3bjh1pc.js → cli-xx73daeb.js} +862 -13
- package/dist/{cli-73x2yznb.js → cli-zgmxsmbt.js} +2 -2
- package/dist/cli.js +9 -8
- package/dist/{doctor-dz8gfz2h.js → doctor-66qe8hq9.js} +2 -2
- package/dist/{harness-github-actions-jfbcsx2s.js → harness-github-actions-p3g8cjf2.js} +1 -1
- package/dist/{harness-fx091nmr.js → harness-t2xjak6g.js} +5 -1
- package/dist/{index-q2d1fva7.js → index-tt5rmqyq.js} +3 -3
- package/dist/{prompt-attribution-avvkfq8c.js → prompt-attribution-ey193cg9.js} +1 -1
- package/dist/prompt-source-mcp.js +1 -1
- package/dist/{prompts-hcecy2na.js → prompts-z2v4k4q7.js} +1 -1
- package/dist/{sync-v0me021f.js → sync-tzvrgzqs.js} +2 -2
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
buildDoctorReport
|
|
3
|
-
} from "./cli-
|
|
3
|
+
} from "./cli-zgmxsmbt.js";
|
|
4
4
|
import"./cli-rdh9jjr2.js";
|
|
5
|
-
import"./cli-
|
|
5
|
+
import"./cli-arze1hgb.js";
|
|
6
6
|
import"./cli-mm48br00.js";
|
|
7
7
|
import {
|
|
8
8
|
readHarnessSyncState
|
|
@@ -95,7 +95,7 @@ async function buildAgentContext(context) {
|
|
|
95
95
|
const graph = readHarnessGraphIfPresent(context.cwd);
|
|
96
96
|
const reportState = readHarnessReportState(context.cwd);
|
|
97
97
|
const syncState = readHarnessSyncState(context.cwd);
|
|
98
|
-
const harness = graph ? await import("./harness-
|
|
98
|
+
const harness = graph ? await import("./harness-t2xjak6g.js") : undefined;
|
|
99
99
|
const topFindings = doctor.checks.filter((check) => check.status === "fail" || check.status === "warning").slice(0, 12).map(checkToFinding);
|
|
100
100
|
const evidenceRefs = [
|
|
101
101
|
...doctor.checks.map(checkToEvidenceRef),
|
|
@@ -5768,7 +5768,7 @@ async function runPromptSyncExclusive(flags, profileOptions, options) {
|
|
|
5768
5768
|
const analyzedDefinitions = new Map;
|
|
5769
5769
|
if (flags["no-analyze"] !== "true") {
|
|
5770
5770
|
options.onProgress?.("Analyzing prompt sources before sync.");
|
|
5771
|
-
const { analyzeHarnessPrompts } = await import("./harness-
|
|
5771
|
+
const { analyzeHarnessPrompts } = await import("./harness-t2xjak6g.js");
|
|
5772
5772
|
const result = await analyzeHarnessPrompts({
|
|
5773
5773
|
rootDir: process.cwd(),
|
|
5774
5774
|
existing: established.flatMap((prompt) => prompt.sourceDefinition ? [prompt.sourceDefinition.source] : []),
|
|
@@ -5796,7 +5796,7 @@ async function runPromptSyncExclusive(flags, profileOptions, options) {
|
|
|
5796
5796
|
const mergedSources = mergePromptSources(manifest.sources, extraSources);
|
|
5797
5797
|
const manifestUpdate = stableJson(mergedSources) === stableJson(mergePromptSources(manifest.sources, [])) ? undefined : $stringify({ version: 2, prompt_paths: manifest.promptPaths, sources: mergedSources });
|
|
5798
5798
|
const prompts = await discoverPrompts(extraSources);
|
|
5799
|
-
const { checkPromptAttribution } = await import("./prompt-attribution-
|
|
5799
|
+
const { checkPromptAttribution } = await import("./prompt-attribution-ey193cg9.js");
|
|
5800
5800
|
const attribution = checkPromptAttribution(process.cwd(), prompts.map((prompt) => prompt.key));
|
|
5801
5801
|
const brokenAttribution = attribution.references.filter((reference) => reference.status === "missing");
|
|
5802
5802
|
if (brokenAttribution.length) {
|
|
@@ -6102,7 +6102,7 @@ async function migratePromptManifest(options = {}) {
|
|
|
6102
6102
|
let addedSources = [];
|
|
6103
6103
|
let pendingSources = [];
|
|
6104
6104
|
if (options.discover) {
|
|
6105
|
-
const { analyzeHarnessPrompts } = await import("./harness-
|
|
6105
|
+
const { analyzeHarnessPrompts } = await import("./harness-t2xjak6g.js");
|
|
6106
6106
|
const result = await analyzeHarnessPrompts({
|
|
6107
6107
|
rootDir: root,
|
|
6108
6108
|
existing: manifest.sources,
|
|
@@ -12333,6 +12333,7 @@ var NON_PROMPT_DOC_BASENAMES = new Set([
|
|
|
12333
12333
|
"requirements.txt"
|
|
12334
12334
|
]);
|
|
12335
12335
|
var PROMPT_NAME_HINT = /(prompt|system[-_]?message|instruction|persona|sop)/i;
|
|
12336
|
+
var PROMPTS_DIR = /(^|\/)(?:system[-_]?)?prompts?(\/|$)/i;
|
|
12336
12337
|
var AGENTIC_DIR_HINT = /(^|\/)(agents?|prompts?|llm|ai|assistants?|chains?|crew|graph)s?(\/|$)/i;
|
|
12337
12338
|
var INSTRUCTION_MARKERS = [
|
|
12338
12339
|
/\byou are\b/i,
|
|
@@ -12532,6 +12533,9 @@ function detectPromptFile(file, out) {
|
|
|
12532
12533
|
if (nameHint) {
|
|
12533
12534
|
confidence2 = "high";
|
|
12534
12535
|
signal = "prompt_file.name_hint";
|
|
12536
|
+
} else if (PROMPTS_DIR.test(dir)) {
|
|
12537
|
+
confidence2 = "high";
|
|
12538
|
+
signal = "prompt_file.prompts_dir";
|
|
12535
12539
|
} else if (dirHint && score >= 3) {
|
|
12536
12540
|
confidence2 = "medium";
|
|
12537
12541
|
signal = "prompt_file.agent_dir_instruction_text";
|
|
@@ -13554,7 +13558,7 @@ function applyPromptDiscovery(graph, discovery) {
|
|
|
13554
13558
|
|
|
13555
13559
|
// src/harness-candidate-promotion.ts
|
|
13556
13560
|
import { readFileSync as readFileSync11 } from "node:fs";
|
|
13557
|
-
import { resolve as resolve9 } from "node:path";
|
|
13561
|
+
import { extname as extname7, posix, resolve as resolve9 } from "node:path";
|
|
13558
13562
|
var PROMOTED_CONFIDENCE = {
|
|
13559
13563
|
high: 0.85,
|
|
13560
13564
|
medium: 0.6
|
|
@@ -13566,7 +13570,6 @@ var JS_ASSIGNMENT_NAME = /(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=/;
|
|
|
13566
13570
|
var JS_PROPERTY_NAME = /^\s*(?:public\s+|readonly\s+)?([A-Za-z_$][\w$]*)\s*:\s*(?:new\s+)?(?:[\w.$]*\.)?(?:tool|functionTool|createTool|dynamicTool|DynamicStructuredTool)\s*\(/;
|
|
13567
13571
|
var JS_TRAILING_ASSIGNMENT_NAME = /(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:new\s+)?$/;
|
|
13568
13572
|
var REGISTRY_CALL_NAME = /\b(?:register_tool|registerTool|add_tool)\s*\(\s*["']?([A-Za-z_$][\w$]*)/;
|
|
13569
|
-
var PROMPT_ASSIGNMENT_NAME = /^\s*(?:export\s+)?(?:(?:const|let|var)\s+)?([A-Za-z_$][\w$]*)\s*[:=]/;
|
|
13570
13573
|
var MODEL_STRING = /["'`]([\w.:/-]*(?:gpt-|o[134](?:-mini)?\b|claude|gemini|llama|mistral|mixtral|deepseek|qwen|grok|sonnet|opus|haiku|command-r|glm|gemma)[\w.:/-]*)["'`]/i;
|
|
13571
13574
|
function candidateEvidence(candidate) {
|
|
13572
13575
|
return [{
|
|
@@ -13641,17 +13644,786 @@ function promotePromptFileCandidate(candidate, confidence2) {
|
|
|
13641
13644
|
evidence: candidateEvidence(candidate)
|
|
13642
13645
|
};
|
|
13643
13646
|
}
|
|
13644
|
-
|
|
13647
|
+
var MODEL_INPUT_KEYS = [
|
|
13648
|
+
"system",
|
|
13649
|
+
"systemPrompt",
|
|
13650
|
+
"system_prompt",
|
|
13651
|
+
"systemMessage",
|
|
13652
|
+
"system_message",
|
|
13653
|
+
"systemInstruction",
|
|
13654
|
+
"system_instruction",
|
|
13655
|
+
"instructions",
|
|
13656
|
+
"prompt",
|
|
13657
|
+
"userPrompt",
|
|
13658
|
+
"user_prompt",
|
|
13659
|
+
"backstory",
|
|
13660
|
+
"content",
|
|
13661
|
+
"input",
|
|
13662
|
+
"template",
|
|
13663
|
+
"text"
|
|
13664
|
+
];
|
|
13665
|
+
var DIRECT_PROMPT_KEYS = new Set([
|
|
13666
|
+
"system",
|
|
13667
|
+
"systemPrompt",
|
|
13668
|
+
"system_prompt",
|
|
13669
|
+
"systemMessage",
|
|
13670
|
+
"system_message",
|
|
13671
|
+
"systemInstruction",
|
|
13672
|
+
"system_instruction",
|
|
13673
|
+
"instructions",
|
|
13674
|
+
"prompt",
|
|
13675
|
+
"userPrompt",
|
|
13676
|
+
"user_prompt",
|
|
13677
|
+
"backstory",
|
|
13678
|
+
"system_template",
|
|
13679
|
+
"instance_template"
|
|
13680
|
+
]);
|
|
13681
|
+
var GENERIC_IDENTIFIERS = new Set([
|
|
13682
|
+
"prompt",
|
|
13683
|
+
"template",
|
|
13684
|
+
"system",
|
|
13685
|
+
"instructions",
|
|
13686
|
+
"content",
|
|
13687
|
+
"text",
|
|
13688
|
+
"message",
|
|
13689
|
+
"input",
|
|
13690
|
+
"body",
|
|
13691
|
+
"value"
|
|
13692
|
+
]);
|
|
13693
|
+
var CONFIG_EXTENSIONS = new Set([".json", ".yaml", ".yml"]);
|
|
13694
|
+
var PROMPT_NAMED_IDENTIFIER = /prompt|system|instruction/i;
|
|
13695
|
+
var SECOND_PERSON_OPENING = /^\s*(?:\[[A-Z]+:\s*|<\w+>\s*)*(?:you|your)\b/i;
|
|
13696
|
+
var MIN_UNNAMED_REFERENCED_PROMPT_CHARS = 200;
|
|
13697
|
+
var REFERENCED_PROMPT_CONFIDENCE = 0.7;
|
|
13698
|
+
var MIN_RESOLVED_PROMPT_CHARS = 20;
|
|
13699
|
+
var MIN_CONFIG_PROMPT_CHARS = 40;
|
|
13700
|
+
var MAX_BUILDER_LOOKBEHIND_LINES = 40;
|
|
13701
|
+
var DEFINITION_HEAD = /^\s*(?:export\s+)?(?:(?:const|let|var|readonly|static|public|private)\s+)*["']?([A-Za-z_$][\w$]*)["']?\s*(?:(?::\s*[\w$.<>[\]|, ]+?)?\s*(=)(?![=>])|(:))\s*(.*)$/;
|
|
13702
|
+
var VALUE_WRAPPERS = /^(?:\(|\[|(?:textwrap\.)?dedent\(|inspect\.cleandoc\(|outdent|stripIndent)\s*/;
|
|
13703
|
+
var STRING_OPENER = /^(?:[fFrRbBuU]{1,2})?("""|\'\'\'|"|'|`)/;
|
|
13704
|
+
var BUILDER_HEAD = /^\s*(?:export\s+)?(?:async\s+)?(?:function\s+([A-Za-z_$][\w$]*)\s*\(|def\s+([A-Za-z_]\w*)\s*\(|(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:async\s+)?(?:\([^)]*\)|[A-Za-z_$][\w$]*)\s*=>)/;
|
|
13705
|
+
var CODE_LIKE_CONTENT = [
|
|
13706
|
+
/^\s*(?:SELECT|WITH|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP)\b[\s\S]*\b(?:FROM|INTO|SET|TABLE|AS)\b/i,
|
|
13707
|
+
/^\s*[a-z][\w+.-]*:\/\/\S*$/i,
|
|
13708
|
+
/^\s*(?:<![Dd][Oo][Cc][Tt][Yy][Pp][Ee]\b|<(?:html|head|body|div|span|p|a|ul|ol|li|table|tr|td|th|button|img|svg|path|section|header|footer|nav|main|form|input|label|select|option|textarea|h[1-6]|br|hr|meta|link|script|style|template|iframe|video)[\s/>]|<[A-Z][\w.]*[\s/>]|<[A-Za-z][\w.-]*\s+[\w:-]+=)/
|
|
13709
|
+
];
|
|
13710
|
+
var INLINE_PROMPT_KEY = new RegExp(`(?<![\\w$.])["']?(${[...new Set([...MODEL_INPUT_KEYS, ...DIRECT_PROMPT_KEYS])].join("|")})["']?\\s*(?::|=(?![=>]))\\s*`, "g");
|
|
13711
|
+
function escapeRegExp(value) {
|
|
13712
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
13713
|
+
}
|
|
13714
|
+
function readStringLiteral(text, start) {
|
|
13715
|
+
const opener = text.startsWith('"""', start) || text.startsWith("'''", start) ? text.slice(start, start + 3) : text[start];
|
|
13716
|
+
let i = start + opener.length;
|
|
13717
|
+
while (i < text.length) {
|
|
13718
|
+
const char = text[i];
|
|
13719
|
+
if (char === "\\") {
|
|
13720
|
+
i += 2;
|
|
13721
|
+
continue;
|
|
13722
|
+
}
|
|
13723
|
+
if (opener.length === 1 && opener !== "`" && char === `
|
|
13724
|
+
`)
|
|
13725
|
+
return;
|
|
13726
|
+
if (opener === "`" && char === "$" && text[i + 1] === "{") {
|
|
13727
|
+
let depth = 1;
|
|
13728
|
+
i += 2;
|
|
13729
|
+
while (i < text.length && depth > 0) {
|
|
13730
|
+
if (text[i] === "`" || text[i] === '"' || text[i] === "'") {
|
|
13731
|
+
const nested = readStringLiteral(text, i);
|
|
13732
|
+
if (nested) {
|
|
13733
|
+
i = nested.end;
|
|
13734
|
+
continue;
|
|
13735
|
+
}
|
|
13736
|
+
if (text[i] === "`")
|
|
13737
|
+
return;
|
|
13738
|
+
i += 1;
|
|
13739
|
+
continue;
|
|
13740
|
+
}
|
|
13741
|
+
const regexEnd = text[i] === "/" ? regexLiteralEnd(text, i) : undefined;
|
|
13742
|
+
if (regexEnd !== undefined) {
|
|
13743
|
+
i = regexEnd;
|
|
13744
|
+
continue;
|
|
13745
|
+
}
|
|
13746
|
+
if (text.startsWith("//", i)) {
|
|
13747
|
+
const newline = text.indexOf(`
|
|
13748
|
+
`, i);
|
|
13749
|
+
i = newline < 0 ? text.length : newline;
|
|
13750
|
+
continue;
|
|
13751
|
+
}
|
|
13752
|
+
if (text.startsWith("/*", i)) {
|
|
13753
|
+
const close = text.indexOf("*/", i + 2);
|
|
13754
|
+
if (close < 0)
|
|
13755
|
+
return;
|
|
13756
|
+
i = close + 2;
|
|
13757
|
+
continue;
|
|
13758
|
+
}
|
|
13759
|
+
if (text[i] === "{")
|
|
13760
|
+
depth += 1;
|
|
13761
|
+
else if (text[i] === "}")
|
|
13762
|
+
depth -= 1;
|
|
13763
|
+
i += 1;
|
|
13764
|
+
}
|
|
13765
|
+
continue;
|
|
13766
|
+
}
|
|
13767
|
+
if (text.startsWith(opener, i))
|
|
13768
|
+
return { value: text.slice(start + opener.length, i), end: i + opener.length };
|
|
13769
|
+
i += 1;
|
|
13770
|
+
}
|
|
13771
|
+
return;
|
|
13772
|
+
}
|
|
13773
|
+
var EXPRESSION_KEYWORDS = new Set([
|
|
13774
|
+
"return",
|
|
13775
|
+
"typeof",
|
|
13776
|
+
"instanceof",
|
|
13777
|
+
"in",
|
|
13778
|
+
"of",
|
|
13779
|
+
"new",
|
|
13780
|
+
"delete",
|
|
13781
|
+
"void",
|
|
13782
|
+
"throw",
|
|
13783
|
+
"case",
|
|
13784
|
+
"do",
|
|
13785
|
+
"else",
|
|
13786
|
+
"yield",
|
|
13787
|
+
"await"
|
|
13788
|
+
]);
|
|
13789
|
+
function endsWithOperand(text, end) {
|
|
13790
|
+
let i = end;
|
|
13791
|
+
while (i > 0 && /\s/.test(text[i - 1]))
|
|
13792
|
+
i -= 1;
|
|
13793
|
+
if (i === 0)
|
|
13794
|
+
return false;
|
|
13795
|
+
const char = text[i - 1];
|
|
13796
|
+
if (char === ")" || char === "]" || char === '"' || char === "'" || char === "`")
|
|
13797
|
+
return true;
|
|
13798
|
+
if (/[\w$]/.test(char)) {
|
|
13799
|
+
let wordStart = i;
|
|
13800
|
+
while (wordStart > 0 && /[\w$]/.test(text[wordStart - 1]))
|
|
13801
|
+
wordStart -= 1;
|
|
13802
|
+
const word = text.slice(wordStart, i);
|
|
13803
|
+
if (/^\d/.test(word))
|
|
13804
|
+
return true;
|
|
13805
|
+
let before = wordStart;
|
|
13806
|
+
while (before > 0 && /\s/.test(text[before - 1]))
|
|
13807
|
+
before -= 1;
|
|
13808
|
+
const isProperty = text[before - 1] === "." && text[before - 2] !== ".";
|
|
13809
|
+
return isProperty || !EXPRESSION_KEYWORDS.has(word);
|
|
13810
|
+
}
|
|
13811
|
+
if ((char === "+" || char === "-") && text[i - 2] === char)
|
|
13812
|
+
return endsWithOperand(text, i - 2);
|
|
13813
|
+
if (char === "!" && i >= 2 && /[\w$)\]]/.test(text[i - 2]))
|
|
13814
|
+
return endsWithOperand(text, i - 1);
|
|
13815
|
+
return false;
|
|
13816
|
+
}
|
|
13817
|
+
function regexLiteralEnd(text, start) {
|
|
13818
|
+
if (text[start + 1] === "/" || text[start + 1] === "*")
|
|
13819
|
+
return;
|
|
13820
|
+
if (endsWithOperand(text, start))
|
|
13821
|
+
return;
|
|
13822
|
+
let inClass = false;
|
|
13823
|
+
for (let i = start + 1;i < text.length; i += 1) {
|
|
13824
|
+
const char = text[i];
|
|
13825
|
+
if (char === `
|
|
13826
|
+
`)
|
|
13827
|
+
return;
|
|
13828
|
+
if (char === "\\") {
|
|
13829
|
+
i += 1;
|
|
13830
|
+
continue;
|
|
13831
|
+
}
|
|
13832
|
+
if (char === "[")
|
|
13833
|
+
inClass = true;
|
|
13834
|
+
else if (char === "]")
|
|
13835
|
+
inClass = false;
|
|
13836
|
+
else if (char === "/" && !inClass) {
|
|
13837
|
+
let end = i + 1;
|
|
13838
|
+
while (/[a-z]/i.test(text[end] ?? ""))
|
|
13839
|
+
end += 1;
|
|
13840
|
+
return end;
|
|
13841
|
+
}
|
|
13842
|
+
}
|
|
13843
|
+
return;
|
|
13844
|
+
}
|
|
13845
|
+
function readStringValue(text, offset) {
|
|
13846
|
+
let i = offset;
|
|
13847
|
+
const parts = [];
|
|
13848
|
+
let concatenated = false;
|
|
13849
|
+
let listed = false;
|
|
13850
|
+
for (;; ) {
|
|
13851
|
+
const opener = STRING_OPENER.exec(text.slice(i, i + 5));
|
|
13852
|
+
if (!opener)
|
|
13853
|
+
break;
|
|
13854
|
+
const literal = readStringLiteral(text, i + opener[0].length - opener[1].length);
|
|
13855
|
+
if (!literal)
|
|
13856
|
+
return;
|
|
13857
|
+
parts.push(literal.value);
|
|
13858
|
+
i = literal.end;
|
|
13859
|
+
const separator = /^[\s+,]*/.exec(text.slice(i))[0];
|
|
13860
|
+
if (!STRING_OPENER.test(text.slice(i + separator.length, i + separator.length + 5))) {
|
|
13861
|
+
if (separator.includes("+"))
|
|
13862
|
+
return;
|
|
13863
|
+
break;
|
|
13864
|
+
}
|
|
13865
|
+
if (separator.includes("+") && separator.includes(","))
|
|
13866
|
+
return;
|
|
13867
|
+
if (separator.includes(","))
|
|
13868
|
+
listed = true;
|
|
13869
|
+
else
|
|
13870
|
+
concatenated = true;
|
|
13871
|
+
i += separator.length;
|
|
13872
|
+
}
|
|
13873
|
+
if (parts.length === 0 || concatenated && listed)
|
|
13874
|
+
return;
|
|
13875
|
+
if (!listed)
|
|
13876
|
+
return parts.join("");
|
|
13877
|
+
const join9 = /^[\s,]*\]\s*\.join\(\s*(["'`])((?:\\.|(?!\1).)*)\1\s*\)/.exec(text.slice(i));
|
|
13878
|
+
const joinSeparator = join9 ? join9[2].replace(/\\n/g, `
|
|
13879
|
+
`).replace(/\\t/g, "\t") : `
|
|
13880
|
+
`;
|
|
13881
|
+
return parts.join(joinSeparator);
|
|
13882
|
+
}
|
|
13883
|
+
function textOffsetOfLine(lines, index) {
|
|
13884
|
+
let offset = 0;
|
|
13885
|
+
for (let i = 0;i < index; i += 1)
|
|
13886
|
+
offset += lines[i].length + 1;
|
|
13887
|
+
return offset;
|
|
13888
|
+
}
|
|
13889
|
+
function stringStart(rest) {
|
|
13890
|
+
let consumed = 0;
|
|
13891
|
+
let remaining = rest;
|
|
13892
|
+
for (let guard = 0;guard < 3; guard += 1) {
|
|
13893
|
+
const wrapper = VALUE_WRAPPERS.exec(remaining);
|
|
13894
|
+
if (!wrapper)
|
|
13895
|
+
break;
|
|
13896
|
+
consumed += wrapper[0].length;
|
|
13897
|
+
remaining = remaining.slice(wrapper[0].length);
|
|
13898
|
+
}
|
|
13899
|
+
return STRING_OPENER.test(remaining) ? consumed : -1;
|
|
13900
|
+
}
|
|
13901
|
+
function resolvePromptLiteralDefinition(lines, startLine) {
|
|
13902
|
+
const text = lines.join(`
|
|
13903
|
+
`);
|
|
13904
|
+
for (const index of [startLine - 1, startLine - 2]) {
|
|
13905
|
+
const line2 = lines[index];
|
|
13906
|
+
if (line2 === undefined)
|
|
13907
|
+
continue;
|
|
13908
|
+
const head = DEFINITION_HEAD.exec(line2);
|
|
13909
|
+
if (head) {
|
|
13910
|
+
const [, name, , colon, rest] = head;
|
|
13911
|
+
let valueOffset = -1;
|
|
13912
|
+
const inline = stringStart(rest);
|
|
13913
|
+
if (inline >= 0) {
|
|
13914
|
+
valueOffset = textOffsetOfLine(lines, index) + line2.length - rest.length + inline;
|
|
13915
|
+
} else if (/^(?:\(|\[|(?:textwrap\.)?dedent\(|)\s*$/.test(rest) && lines[index + 1] !== undefined) {
|
|
13916
|
+
const next = lines[index + 1];
|
|
13917
|
+
const nextStart = stringStart(next.trimStart());
|
|
13918
|
+
if (nextStart >= 0)
|
|
13919
|
+
valueOffset = textOffsetOfLine(lines, index + 1) + (next.length - next.trimStart().length) + nextStart;
|
|
13920
|
+
}
|
|
13921
|
+
if (valueOffset < 0 && colon) {
|
|
13922
|
+
const block = readYamlBlockScalar(lines, index, rest);
|
|
13923
|
+
if (block !== undefined)
|
|
13924
|
+
return { key: name, text: block, line: index + 1 };
|
|
13925
|
+
}
|
|
13926
|
+
if (valueOffset < 0)
|
|
13927
|
+
continue;
|
|
13928
|
+
let offset2 = valueOffset;
|
|
13929
|
+
while (!STRING_OPENER.test(text.slice(offset2, offset2 + 5)))
|
|
13930
|
+
offset2 += 1;
|
|
13931
|
+
const value2 = readStringValue(text, offset2);
|
|
13932
|
+
if (value2 === undefined)
|
|
13933
|
+
continue;
|
|
13934
|
+
return colon ? { key: name, text: value2, line: index + 1 } : { identifier: name, text: value2, line: index + 1 };
|
|
13935
|
+
}
|
|
13936
|
+
if (index !== startLine - 1)
|
|
13937
|
+
continue;
|
|
13938
|
+
const returned = /^\s*return\s+(.*)$/.exec(line2);
|
|
13939
|
+
if (!returned)
|
|
13940
|
+
continue;
|
|
13941
|
+
const start = stringStart(returned[1]);
|
|
13942
|
+
if (start < 0)
|
|
13943
|
+
continue;
|
|
13944
|
+
let offset = textOffsetOfLine(lines, index) + line2.length - returned[1].length + start;
|
|
13945
|
+
while (!STRING_OPENER.test(text.slice(offset, offset + 5)))
|
|
13946
|
+
offset += 1;
|
|
13947
|
+
const value = readStringValue(text, offset);
|
|
13948
|
+
if (value === undefined)
|
|
13949
|
+
continue;
|
|
13950
|
+
for (let i = index - 1;i >= Math.max(0, index - MAX_BUILDER_LOOKBEHIND_LINES); i -= 1) {
|
|
13951
|
+
const builder = BUILDER_HEAD.exec(lines[i]);
|
|
13952
|
+
if (builder)
|
|
13953
|
+
return { identifier: builder[1] ?? builder[2] ?? builder[3], text: value, line: index + 1 };
|
|
13954
|
+
}
|
|
13955
|
+
}
|
|
13956
|
+
const line = lines[startLine - 1];
|
|
13957
|
+
if (line === undefined)
|
|
13958
|
+
return;
|
|
13959
|
+
if (/^\s*(?:\/\/|\*(?!\/)|#)/.test(line))
|
|
13960
|
+
return;
|
|
13961
|
+
for (const match of line.matchAll(INLINE_PROMPT_KEY)) {
|
|
13962
|
+
if (endsInComment(line.slice(0, match.index)))
|
|
13963
|
+
break;
|
|
13964
|
+
const after = match.index + match[0].length;
|
|
13965
|
+
const start = stringStart(line.slice(after));
|
|
13966
|
+
if (start < 0)
|
|
13967
|
+
continue;
|
|
13968
|
+
let offset = textOffsetOfLine(lines, startLine - 1) + after + start;
|
|
13969
|
+
while (!STRING_OPENER.test(text.slice(offset, offset + 5)))
|
|
13970
|
+
offset += 1;
|
|
13971
|
+
const value = readStringValue(text, offset);
|
|
13972
|
+
if (value !== undefined)
|
|
13973
|
+
return { key: match[1], text: value, line: startLine };
|
|
13974
|
+
}
|
|
13975
|
+
return;
|
|
13976
|
+
}
|
|
13977
|
+
function endsInComment(prefix) {
|
|
13978
|
+
let quote;
|
|
13979
|
+
let inBlock = false;
|
|
13980
|
+
for (let i = 0;i < prefix.length; i += 1) {
|
|
13981
|
+
const char = prefix[i];
|
|
13982
|
+
if (inBlock) {
|
|
13983
|
+
if (prefix.startsWith("*/", i)) {
|
|
13984
|
+
inBlock = false;
|
|
13985
|
+
i += 1;
|
|
13986
|
+
}
|
|
13987
|
+
continue;
|
|
13988
|
+
}
|
|
13989
|
+
if (quote) {
|
|
13990
|
+
if (char === "\\")
|
|
13991
|
+
i += 1;
|
|
13992
|
+
else if (char === quote)
|
|
13993
|
+
quote = undefined;
|
|
13994
|
+
continue;
|
|
13995
|
+
}
|
|
13996
|
+
if (char === '"' || char === "'" || char === "`") {
|
|
13997
|
+
quote = char;
|
|
13998
|
+
continue;
|
|
13999
|
+
}
|
|
14000
|
+
const regexEnd = char === "/" ? regexLiteralEnd(prefix, i) : undefined;
|
|
14001
|
+
if (regexEnd !== undefined) {
|
|
14002
|
+
i = regexEnd - 1;
|
|
14003
|
+
continue;
|
|
14004
|
+
}
|
|
14005
|
+
if (prefix.startsWith("//", i))
|
|
14006
|
+
return true;
|
|
14007
|
+
else if (prefix.startsWith("/*", i)) {
|
|
14008
|
+
inBlock = true;
|
|
14009
|
+
i += 1;
|
|
14010
|
+
}
|
|
14011
|
+
}
|
|
14012
|
+
return inBlock;
|
|
14013
|
+
}
|
|
14014
|
+
function readYamlBlockScalar(lines, index, rest) {
|
|
14015
|
+
const indicator = /^([|>])([-+]?)\s*(?:#.*)?$/.exec(rest.trim());
|
|
14016
|
+
if (!indicator)
|
|
14017
|
+
return;
|
|
14018
|
+
const [, style, chomping] = indicator;
|
|
14019
|
+
const keyIndent = lines[index].length - lines[index].trimStart().length;
|
|
14020
|
+
const body = [];
|
|
14021
|
+
let blockIndent;
|
|
14022
|
+
for (let i = index + 1;i < lines.length; i += 1) {
|
|
14023
|
+
const line = lines[i];
|
|
14024
|
+
if (!line.trim()) {
|
|
14025
|
+
body.push("");
|
|
14026
|
+
continue;
|
|
14027
|
+
}
|
|
14028
|
+
const indent = line.length - line.trimStart().length;
|
|
14029
|
+
if (indent <= keyIndent)
|
|
14030
|
+
break;
|
|
14031
|
+
blockIndent ??= indent;
|
|
14032
|
+
if (indent < blockIndent)
|
|
14033
|
+
break;
|
|
14034
|
+
body.push(line.slice(blockIndent));
|
|
14035
|
+
}
|
|
14036
|
+
let trailingBlank = 0;
|
|
14037
|
+
while (body.length > 0 && body[body.length - 1] === "") {
|
|
14038
|
+
body.pop();
|
|
14039
|
+
trailingBlank += 1;
|
|
14040
|
+
}
|
|
14041
|
+
if (body.length === 0)
|
|
14042
|
+
return;
|
|
14043
|
+
let text;
|
|
14044
|
+
if (style === "|") {
|
|
14045
|
+
text = body.join(`
|
|
14046
|
+
`);
|
|
14047
|
+
} else {
|
|
14048
|
+
if (body.some((line) => /^\s/.test(line)))
|
|
14049
|
+
return;
|
|
14050
|
+
text = "";
|
|
14051
|
+
let blanks = 0;
|
|
14052
|
+
for (const [i, line] of body.entries()) {
|
|
14053
|
+
if (line === "") {
|
|
14054
|
+
blanks += 1;
|
|
14055
|
+
continue;
|
|
14056
|
+
}
|
|
14057
|
+
text += i === 0 || text === "" ? `
|
|
14058
|
+
`.repeat(blanks) + line : blanks > 0 ? `
|
|
14059
|
+
`.repeat(blanks) + line : ` ${line}`;
|
|
14060
|
+
blanks = 0;
|
|
14061
|
+
}
|
|
14062
|
+
}
|
|
14063
|
+
if (chomping === "-")
|
|
14064
|
+
return text;
|
|
14065
|
+
return chomping === "+" ? text + `
|
|
14066
|
+
`.repeat(trailingBlank + 1) : `${text}
|
|
14067
|
+
`;
|
|
14068
|
+
}
|
|
14069
|
+
function isCodeLikeContent(text) {
|
|
14070
|
+
return CODE_LIKE_CONTENT.some((pattern) => pattern.test(text));
|
|
14071
|
+
}
|
|
14072
|
+
var SOURCE_EXTENSION = /\.(?:[cm]?[jt]sx?|py)$/;
|
|
14073
|
+
function moduleStems(definitionPath) {
|
|
14074
|
+
const stem = definitionPath.replace(/\.[^./]+$/, "");
|
|
14075
|
+
const dir = /\/(?:index|__init__)$/.test(stem) ? stem.replace(/\/[^/]+$/, "") : undefined;
|
|
14076
|
+
return dir ? [stem, dir] : [stem];
|
|
14077
|
+
}
|
|
14078
|
+
function specifierResolvesTo(spec, importerPath, definitionPath, python) {
|
|
14079
|
+
const stems = moduleStems(definitionPath);
|
|
14080
|
+
const importerDir = posix.dirname(importerPath);
|
|
14081
|
+
let target;
|
|
14082
|
+
let exact = true;
|
|
14083
|
+
if (python) {
|
|
14084
|
+
const dots = /^\.*/.exec(spec)[0].length;
|
|
14085
|
+
const rest = spec.slice(dots).split(".").filter(Boolean).join("/");
|
|
14086
|
+
if (dots > 0) {
|
|
14087
|
+
let base = importerDir;
|
|
14088
|
+
for (let i = 1;i < dots; i += 1)
|
|
14089
|
+
base = posix.dirname(base);
|
|
14090
|
+
target = posix.normalize(posix.join(base, rest));
|
|
14091
|
+
} else if (!rest.includes("/")) {
|
|
14092
|
+
return stems.some((stem) => stem === rest || stem === posix.join(importerDir, rest));
|
|
14093
|
+
} else {
|
|
14094
|
+
target = rest;
|
|
14095
|
+
exact = false;
|
|
14096
|
+
}
|
|
14097
|
+
} else if (spec.startsWith(".")) {
|
|
14098
|
+
target = posix.normalize(posix.join(importerDir, spec)).replace(SOURCE_EXTENSION, "");
|
|
14099
|
+
} else {
|
|
14100
|
+
const segments = spec.replace(SOURCE_EXTENSION, "").split("/");
|
|
14101
|
+
if (segments.length > 0 && /^[@~#$]/.test(segments[0]))
|
|
14102
|
+
segments.shift();
|
|
14103
|
+
if (segments.length < 2)
|
|
14104
|
+
return false;
|
|
14105
|
+
target = segments.join("/");
|
|
14106
|
+
exact = false;
|
|
14107
|
+
}
|
|
14108
|
+
return stems.some((stem) => stem === target || !exact && stem.endsWith(`/${target}`));
|
|
14109
|
+
}
|
|
14110
|
+
function localNameIn(specifiers, identifier) {
|
|
14111
|
+
for (const raw of specifiers.replace(/#[^\n]*|\/\/[^\n]*/g, "").replace(/[()]/g, "").split(",")) {
|
|
14112
|
+
const match = /^\s*(?:type\s+)?([A-Za-z_$][\w$]*)(?:\s*(?:\bas\b|:)\s*([A-Za-z_$][\w$]*))?\s*$/.exec(raw);
|
|
14113
|
+
if (match?.[1] === identifier)
|
|
14114
|
+
return match[2] ?? identifier;
|
|
14115
|
+
}
|
|
14116
|
+
return;
|
|
14117
|
+
}
|
|
14118
|
+
function importedLocalName(importerPath, lines, identifier, definitionPath, exportsDefault = false) {
|
|
14119
|
+
const text = lines.join(`
|
|
14120
|
+
`);
|
|
14121
|
+
const python = extname7(importerPath) === ".py";
|
|
14122
|
+
if (python) {
|
|
14123
|
+
for (const match of text.matchAll(/^[ \t]*from\s+([.\w]+)\s+import\s+(\([^)]*\)|[^\n]*)/gm)) {
|
|
14124
|
+
if (!specifierResolvesTo(match[1], importerPath, definitionPath, true))
|
|
14125
|
+
continue;
|
|
14126
|
+
const local = localNameIn(match[2].replace(/\\\n/g, " "), identifier);
|
|
14127
|
+
if (local)
|
|
14128
|
+
return local;
|
|
14129
|
+
}
|
|
14130
|
+
for (const match of text.matchAll(/^[ \t]*import\s+([.\w]+)(?:\s+as\s+(\w+))?/gm)) {
|
|
14131
|
+
if (specifierResolvesTo(match[1], importerPath, definitionPath, true))
|
|
14132
|
+
return identifier;
|
|
14133
|
+
}
|
|
14134
|
+
return;
|
|
14135
|
+
}
|
|
14136
|
+
const statements = [
|
|
14137
|
+
/\bimport\s+(?:type\s+)?(?:[A-Za-z_$][\w$]*\s*,\s*)?\{([^}]*)\}\s*from\s*["']([^"']+)["']/g,
|
|
14138
|
+
/\b(?:const|let|var)\s*\{([^}]*)\}\s*=\s*(?:await\s+)?(?:require|import)\(\s*["']([^"']+)["']\s*\)/g
|
|
14139
|
+
];
|
|
14140
|
+
for (const pattern of statements) {
|
|
14141
|
+
for (const match of text.matchAll(pattern)) {
|
|
14142
|
+
if (!specifierResolvesTo(match[2], importerPath, definitionPath, false))
|
|
14143
|
+
continue;
|
|
14144
|
+
const local = localNameIn(match[1], identifier);
|
|
14145
|
+
if (local)
|
|
14146
|
+
return local;
|
|
14147
|
+
}
|
|
14148
|
+
}
|
|
14149
|
+
if (exportsDefault) {
|
|
14150
|
+
for (const match of text.matchAll(/\bimport\s+(?:type\s+)?([A-Za-z_$][\w$]*)\s*(?:,\s*(?:\{[^}]*\}|\*\s*as\s+[A-Za-z_$][\w$]*)\s*)?from\s*["']([^"']+)["']/g)) {
|
|
14151
|
+
if (specifierResolvesTo(match[2], importerPath, definitionPath, false))
|
|
14152
|
+
return match[1];
|
|
14153
|
+
}
|
|
14154
|
+
}
|
|
14155
|
+
for (const match of text.matchAll(/\bimport\s*\*\s*as\s+[A-Za-z_$][\w$]*\s+from\s*["']([^"']+)["']/g)) {
|
|
14156
|
+
if (specifierResolvesTo(match[1], importerPath, definitionPath, false))
|
|
14157
|
+
return identifier;
|
|
14158
|
+
}
|
|
14159
|
+
return;
|
|
14160
|
+
}
|
|
14161
|
+
function importStatementLines(lines) {
|
|
14162
|
+
const text = lines.join(`
|
|
14163
|
+
`);
|
|
14164
|
+
const covered = new Set;
|
|
14165
|
+
const statement = /^[ \t]*(?:import\b[^;]*?\bfrom\s*["'][^"'\n]+["']|export\s*(?:type\s*)?\{[^}]*\}\s*from\s*["'][^"'\n]+["']|from\s+[.\w]+\s+import\s*(?:\([^)]*\)|[^\n]*))/gm;
|
|
14166
|
+
for (const match of text.matchAll(statement)) {
|
|
14167
|
+
const first2 = text.slice(0, match.index).split(`
|
|
14168
|
+
`).length - 1;
|
|
14169
|
+
const last = first2 + match[0].split(`
|
|
14170
|
+
`).length - 1;
|
|
14171
|
+
for (let i = first2;i <= last; i += 1)
|
|
14172
|
+
covered.add(i);
|
|
14173
|
+
}
|
|
14174
|
+
return covered;
|
|
14175
|
+
}
|
|
14176
|
+
var MODEL_CALLEE = /model|llm|complet|generat|chat|invoke|infer|prompt|agent|judge|claude|gpt|openai|anthropic|gemini|\.create$/i;
|
|
14177
|
+
function calleeImportedFromModelFile(callee, path, lines, modelFiles) {
|
|
14178
|
+
const base = callee.split(".")[0];
|
|
14179
|
+
const text = lines.join(`
|
|
14180
|
+
`);
|
|
14181
|
+
const python = extname7(path) === ".py";
|
|
14182
|
+
const statements = python ? [/^[ \t]*from\s+([.\w]+)\s+import\s+(\([^)]*\)|[^\n]*)/gm] : [
|
|
14183
|
+
/\bimport\s+(?:type\s+)?(?:([A-Za-z_$][\w$]*)\s*,?\s*)?(?:\{([^}]*)\}|\*\s*as\s+([A-Za-z_$][\w$]*))?\s*from\s*["']([^"']+)["']/g,
|
|
14184
|
+
/\b(?:const|let|var)\s*\{([^}]*)\}\s*=\s*(?:await\s+)?(?:require|import)\(\s*["']([^"']+)["']\s*\)/g
|
|
14185
|
+
];
|
|
14186
|
+
for (const pattern of statements) {
|
|
14187
|
+
for (const match of text.matchAll(pattern)) {
|
|
14188
|
+
let spec;
|
|
14189
|
+
let names;
|
|
14190
|
+
if (python) {
|
|
14191
|
+
spec = match[1];
|
|
14192
|
+
names = match[2].replace(/[()]/g, "").split(",").map((part) => part.trim().split(/\s+as\s+/).pop() ?? "");
|
|
14193
|
+
} else if (match.length === 5) {
|
|
14194
|
+
spec = match[4];
|
|
14195
|
+
names = [match[1] ?? "", match[3] ?? "", ...(match[2] ?? "").split(",").map((part) => part.trim().split(/\s+as\s+/).pop() ?? "")];
|
|
14196
|
+
} else {
|
|
14197
|
+
spec = match[2];
|
|
14198
|
+
names = match[1].split(",").map((part) => part.trim().split(/\s*:\s*/).pop() ?? "");
|
|
14199
|
+
}
|
|
14200
|
+
if (!names.includes(base))
|
|
14201
|
+
continue;
|
|
14202
|
+
for (const modelPath of modelFiles) {
|
|
14203
|
+
if (specifierResolvesTo(spec, path, modelPath, python))
|
|
14204
|
+
return true;
|
|
14205
|
+
}
|
|
14206
|
+
}
|
|
14207
|
+
}
|
|
14208
|
+
return false;
|
|
14209
|
+
}
|
|
14210
|
+
var INSTRUCTION_KEY = /\b(instruction|instructions|task|brief|goal|message|query|question)["']?\s*[:=]\s*$/;
|
|
14211
|
+
var MODEL_CALL_IN_BODY = /\b[\w$.]*(?:model|llm|complet|generat|chat|claude|gpt|openai|anthropic|gemini)[\w$]*\s*\(|\brole\b\s*["']?\s*[:=]\s*["'](?:system|user|assistant)["']/i;
|
|
14212
|
+
var MAX_HELPER_BODY_LINES = 80;
|
|
14213
|
+
var MAX_CALL_CONTEXT_LINES = 25;
|
|
14214
|
+
var CALL_ROLE_WINDOW_LINES = 8;
|
|
14215
|
+
function localHelperCallsModel(callee, lines) {
|
|
14216
|
+
const ident = escapeRegExp(callee.split(".").pop() ?? callee);
|
|
14217
|
+
const head = new RegExp(`^\\s*(?:export\\s+)?(?:async\\s+)?(?:function\\s+${ident}\\s*[(<]|def\\s+${ident}\\s*\\(|(?:const|let|var)\\s+${ident}\\s*=\\s*(?:async\\s+)?(?:\\(|[A-Za-z_$][\\w$]*\\s*=>)|(?:(?:private|public|protected|static|async)\\s+)*${ident}\\s*\\([^)]*\\)?\\s*[:{])`);
|
|
14218
|
+
const start = lines.findIndex((line) => head.test(line));
|
|
14219
|
+
if (start < 0)
|
|
14220
|
+
return false;
|
|
14221
|
+
return lines.slice(start + 1, start + 1 + MAX_HELPER_BODY_LINES).some((line) => MODEL_CALL_IN_BODY.test(line));
|
|
14222
|
+
}
|
|
14223
|
+
function callCarriesChatMessages(lines, index) {
|
|
14224
|
+
for (let i = Math.max(0, index - CALL_ROLE_WINDOW_LINES);i < Math.min(lines.length, index + CALL_ROLE_WINDOW_LINES + 1); i += 1) {
|
|
14225
|
+
if (/\brole\b\s*["']?\s*[:=]\s*["'](?:system|user|human|assistant)["']/.test(lines[i]))
|
|
14226
|
+
return true;
|
|
14227
|
+
}
|
|
14228
|
+
return false;
|
|
14229
|
+
}
|
|
14230
|
+
function composingPromptName(lines, index, identifier) {
|
|
14231
|
+
for (let i = index;i >= Math.max(0, index - MAX_BUILDER_LOOKBEHIND_LINES); i -= 1) {
|
|
14232
|
+
const builder = BUILDER_HEAD.exec(lines[i]);
|
|
14233
|
+
const assignment = /^\s*(?:export\s+)?(?:(?:const|let|var)\s+)?([A-Za-z_$][\w$]*)\s*(?::[^=]+)?=(?![=>])/.exec(lines[i]);
|
|
14234
|
+
const name = builder ? builder[1] ?? builder[2] ?? builder[3] : assignment?.[1];
|
|
14235
|
+
if (name)
|
|
14236
|
+
return name !== identifier && PROMPT_NAMED_IDENTIFIER.test(name) ? name : undefined;
|
|
14237
|
+
}
|
|
14238
|
+
return;
|
|
14239
|
+
}
|
|
14240
|
+
var OUTPUT_CALLEE = /^(?:console\.\w+|(?:[\w$]+\.)*(?:log|logger|logging)\.\w+|print|log|alert|toast(?:\.\w+)?|(?:[\w$]+\.)*(?:write|writeFile|writeFileSync|appendFile|send|json|setState|set[A-Z]\w*))$/;
|
|
14241
|
+
function enclosingCallee(text, index) {
|
|
14242
|
+
let depth = 0;
|
|
14243
|
+
for (let i = index - 1;i >= 0; i -= 1) {
|
|
14244
|
+
const char = text[i];
|
|
14245
|
+
if (char === ")" || char === "]" || char === "}")
|
|
14246
|
+
depth += 1;
|
|
14247
|
+
else if (char === "[" || char === "{")
|
|
14248
|
+
depth = Math.max(0, depth - 1);
|
|
14249
|
+
else if (char === "(") {
|
|
14250
|
+
if (depth > 0) {
|
|
14251
|
+
depth -= 1;
|
|
14252
|
+
continue;
|
|
14253
|
+
}
|
|
14254
|
+
return /([A-Za-z_$][\w$.]*)\s*$/.exec(text.slice(Math.max(0, i - 200), i))?.[1];
|
|
14255
|
+
}
|
|
14256
|
+
}
|
|
14257
|
+
return;
|
|
14258
|
+
}
|
|
14259
|
+
function findModelInputUse(identifier, definition, files, rootDir, fileCache, options) {
|
|
14260
|
+
const scan = (path, lines, name) => {
|
|
14261
|
+
const ident = escapeRegExp(name);
|
|
14262
|
+
const keyed = new RegExp(`\\b(${MODEL_INPUT_KEYS.join("|")})["']?\\s*[:=]\\s*(?:await\\s+)?(?:(?:this|self)\\.)?(?:[A-Za-z_$][\\w$]*\\.)?${ident}\\b`);
|
|
14263
|
+
const messageCtor = new RegExp(`\\b(SystemMessage|HumanMessage|SystemMessagePromptTemplate\\.from_template|HumanMessagePromptTemplate\\.from_template|PromptTemplate\\.from_template|ChatPromptTemplate\\.from_template)\\s*\\(\\s*(?:content\\s*=\\s*)?${ident}\\b`);
|
|
14264
|
+
const roleTuple = new RegExp(`\\(\\s*["'](system|user|human)["']\\s*,\\s*${ident}\\b`);
|
|
14265
|
+
const interpolated = new RegExp(`\\b(${MODEL_INPUT_KEYS.join("|")})["']?\\s*[:=]\\s*[fF]?[\`"'][^\`"']*(?:\\$\\{|\\{)${ident}\\b`);
|
|
14266
|
+
const shorthand = DIRECT_PROMPT_KEYS.has(name) ? new RegExp(`[{,(]\\s*${ident}\\s*[,})]`) : undefined;
|
|
14267
|
+
const isModelFile = files.model.has(path);
|
|
14268
|
+
for (let i = 0;i < lines.length; i += 1) {
|
|
14269
|
+
if (path === definition.path && i === definition.line - 1)
|
|
14270
|
+
continue;
|
|
14271
|
+
const line = lines[i];
|
|
14272
|
+
if (line.length > 4000 || !line.includes(name))
|
|
14273
|
+
continue;
|
|
14274
|
+
const fixed = messageCtor.exec(line) ?? roleTuple.exec(line);
|
|
14275
|
+
if (fixed)
|
|
14276
|
+
return { path, line: i + 1, key: fixed[1] };
|
|
14277
|
+
const match = keyed.exec(line) ?? interpolated.exec(line);
|
|
14278
|
+
if (match && (isModelFile || DIRECT_PROMPT_KEYS.has(match[1]) || match[1] === "content" && hasNearbyRole(lines, i + 1))) {
|
|
14279
|
+
return { path, line: i + 1, key: match[1] };
|
|
14280
|
+
}
|
|
14281
|
+
if (shorthand?.test(line) && isModelFile)
|
|
14282
|
+
return { path, line: i + 1, key: name };
|
|
14283
|
+
}
|
|
14284
|
+
return;
|
|
14285
|
+
};
|
|
14286
|
+
const firstReference = (path, lines, name) => {
|
|
14287
|
+
const ident = escapeRegExp(name);
|
|
14288
|
+
const reference = new RegExp(`(?<![\\w$])(?:(?:this|self|[A-Za-z_$][\\w$]*)\\.)?${ident}(?![\\w$])`, "g");
|
|
14289
|
+
const jsxAttribute = new RegExp(`[\\w-]+=\\{\\s*${ident}\\s*\\}`);
|
|
14290
|
+
const jsxChild = /\.[jt]sx$/.test(path) ? new RegExp(`(?<!\\$)\\{\\s*${ident}\\s*\\}`) : undefined;
|
|
14291
|
+
const imports = importStatementLines(lines);
|
|
14292
|
+
const isModelFile = files.model.has(path);
|
|
14293
|
+
const declaration = new RegExp(`^\\s*(?:export\\s+)?(?:default\\s+)?(?:async\\s+)?(?:function\\s*\\*?\\s*|def\\s+|(?:const|let|var)\\s+)${ident}\\b`);
|
|
14294
|
+
for (let i = 0;i < lines.length; i += 1) {
|
|
14295
|
+
if (path === definition.path && i === definition.line - 1)
|
|
14296
|
+
continue;
|
|
14297
|
+
const line = lines[i];
|
|
14298
|
+
if (line.length > 4000 || !line.includes(name))
|
|
14299
|
+
continue;
|
|
14300
|
+
if (/^\s*(?:\/\/|#|\*|import\b|export\s*\{|from\s+\S+\s+import\b)/.test(line) || jsxAttribute.test(line) || jsxChild?.test(line))
|
|
14301
|
+
continue;
|
|
14302
|
+
const context = `${lines.slice(Math.max(0, i - MAX_CALL_CONTEXT_LINES), i).join(`
|
|
14303
|
+
`)}
|
|
14304
|
+
`;
|
|
14305
|
+
if (declaration.test(line) || imports.has(i))
|
|
14306
|
+
continue;
|
|
14307
|
+
for (const match of line.matchAll(reference)) {
|
|
14308
|
+
const callee = enclosingCallee(context + line, context.length + match.index);
|
|
14309
|
+
if (callee && OUTPUT_CALLEE.test(callee))
|
|
14310
|
+
continue;
|
|
14311
|
+
const before = (context + line).slice(0, context.length + match.index);
|
|
14312
|
+
const instructionKey = INSTRUCTION_KEY.exec(before)?.[1];
|
|
14313
|
+
const after = line.slice(match.index + match[0].length);
|
|
14314
|
+
const composed = /(?:\$\{\s*|\+\s*|[[,]\s*|^\s*|[^=!<>]=\s*|\breturn\s+|\bawait\s+)$/.test(before) && /^\s*(?:\}|\+|,|\]|;|\(|$)/.test(after);
|
|
14315
|
+
const composedInto = composed ? composingPromptName(lines, i, name) : undefined;
|
|
14316
|
+
const via = isModelFile ? "a file that calls a model" : instructionKey ? `the ${instructionKey} key of an agent call` : callee && MODEL_CALLEE.test(callee) ? `the model-call helper ${callee}` : callee && localHelperCallsModel(callee, lines) ? `the local helper ${callee}, which calls a model` : callee && calleeImportedFromModelFile(callee, path, lines, files.model) ? `${callee}, imported from a module that calls a model` : callee && callCarriesChatMessages(lines, i) ? `a ${callee} call that also carries chat messages` : composedInto && `composition into ${composedInto}`;
|
|
14317
|
+
if (via)
|
|
14318
|
+
return { path, line: i + 1, key: "reference", referenceOnly: true, via };
|
|
14319
|
+
}
|
|
14320
|
+
}
|
|
14321
|
+
return;
|
|
14322
|
+
};
|
|
14323
|
+
const own = readFileLines(rootDir, definition.path, fileCache);
|
|
14324
|
+
const local = own ? scan(definition.path, own, identifier) : undefined;
|
|
14325
|
+
if (local)
|
|
14326
|
+
return local;
|
|
14327
|
+
const importers = [];
|
|
14328
|
+
if (!GENERIC_IDENTIFIERS.has(identifier)) {
|
|
14329
|
+
const ident = escapeRegExp(identifier);
|
|
14330
|
+
const exportsDefault = own?.some((line) => new RegExp(`^\\s*export\\s+default\\s+${ident}\\s*;?\\s*$|\\bexport\\s*\\{[^}]*\\b${ident}\\s+as\\s+default\\b`).test(line)) ?? false;
|
|
14331
|
+
const moduleName = posix.basename(definition.path).replace(/\.[^.]+$/, "");
|
|
14332
|
+
for (const path of files.searchable) {
|
|
14333
|
+
if (path === definition.path)
|
|
14334
|
+
continue;
|
|
14335
|
+
const lines = readFileLines(rootDir, path, fileCache);
|
|
14336
|
+
if (!lines || !lines.some((line) => line.includes(identifier) || exportsDefault && line.includes(moduleName)))
|
|
14337
|
+
continue;
|
|
14338
|
+
const name = importedLocalName(path, lines, identifier, definition.path, exportsDefault);
|
|
14339
|
+
if (!name)
|
|
14340
|
+
continue;
|
|
14341
|
+
const use = scan(path, lines, name);
|
|
14342
|
+
if (use)
|
|
14343
|
+
return use;
|
|
14344
|
+
importers.push({ path, lines, name });
|
|
14345
|
+
}
|
|
14346
|
+
}
|
|
14347
|
+
if (!options.allowReference)
|
|
14348
|
+
return;
|
|
14349
|
+
if (own) {
|
|
14350
|
+
const use = firstReference(definition.path, own, identifier);
|
|
14351
|
+
if (use)
|
|
14352
|
+
return use;
|
|
14353
|
+
}
|
|
14354
|
+
for (const importer of importers) {
|
|
14355
|
+
const use = firstReference(importer.path, importer.lines, importer.name);
|
|
14356
|
+
if (use)
|
|
14357
|
+
return use;
|
|
14358
|
+
}
|
|
14359
|
+
return;
|
|
14360
|
+
}
|
|
14361
|
+
function readsAsInstructions(identifier, text) {
|
|
14362
|
+
const score = instructionScore(text);
|
|
14363
|
+
const secondPerson = SECOND_PERSON_OPENING.test(text);
|
|
14364
|
+
if (PROMPT_NAMED_IDENTIFIER.test(identifier))
|
|
14365
|
+
return score >= 2 || secondPerson;
|
|
14366
|
+
return secondPerson && score >= 2 && text.length >= MIN_UNNAMED_REFERENCED_PROMPT_CHARS;
|
|
14367
|
+
}
|
|
14368
|
+
function hasNearbyRole(lines, line) {
|
|
14369
|
+
for (let i = Math.max(0, line - 4);i < Math.min(lines.length, line + 3); i += 1) {
|
|
14370
|
+
if (/\brole\b\s*["']?\s*[:=]/.test(lines[i]))
|
|
14371
|
+
return true;
|
|
14372
|
+
}
|
|
14373
|
+
return false;
|
|
14374
|
+
}
|
|
14375
|
+
function isDirectModelInput(key, value, path, lines, line, modelFiles) {
|
|
14376
|
+
if (CONFIG_EXTENSIONS.has(extname7(path).toLowerCase())) {
|
|
14377
|
+
return DIRECT_PROMPT_KEYS.has(key) && value.length >= MIN_CONFIG_PROMPT_CHARS;
|
|
14378
|
+
}
|
|
14379
|
+
if (modelFiles.has(path)) {
|
|
14380
|
+
return DIRECT_PROMPT_KEYS.has(key) || key === "content" && hasNearbyRole(lines, line);
|
|
14381
|
+
}
|
|
14382
|
+
return DIRECT_PROMPT_KEYS.has(key) && instructionScore(value) >= 2;
|
|
14383
|
+
}
|
|
14384
|
+
function promotePromptLiteralCandidate(candidate, rootDir, confidence2, fileCache, files) {
|
|
13645
14385
|
const lines = readFileLines(rootDir, candidate.path, fileCache);
|
|
13646
|
-
|
|
14386
|
+
if (!lines)
|
|
14387
|
+
return;
|
|
14388
|
+
const definition = resolvePromptLiteralDefinition(lines, candidate.startLine);
|
|
14389
|
+
if (!definition)
|
|
14390
|
+
return;
|
|
14391
|
+
const value = definition.text.trim();
|
|
14392
|
+
const literalText = value.replace(/\$\{[^}]*\}|\{[A-Za-z_][\w.]*\}/g, "").trim();
|
|
14393
|
+
if (literalText.length < MIN_RESOLVED_PROMPT_CHARS || isCodeLikeContent(value))
|
|
14394
|
+
return;
|
|
14395
|
+
const key = definition.key ?? (definition.identifier && DIRECT_PROMPT_KEYS.has(definition.identifier) ? definition.identifier : undefined);
|
|
14396
|
+
let use;
|
|
14397
|
+
if (key && isDirectModelInput(key, value, candidate.path, lines, definition.line, files.model)) {
|
|
14398
|
+
use = { path: candidate.path, line: definition.line, key };
|
|
14399
|
+
}
|
|
14400
|
+
if (!use && definition.identifier) {
|
|
14401
|
+
use = findModelInputUse(definition.identifier, { path: candidate.path, line: definition.line }, files, rootDir, fileCache, {
|
|
14402
|
+
allowReference: readsAsInstructions(definition.identifier, value)
|
|
14403
|
+
});
|
|
14404
|
+
}
|
|
14405
|
+
if (!use)
|
|
14406
|
+
return;
|
|
14407
|
+
const name = definition.identifier ?? definition.key;
|
|
14408
|
+
const evidence = [{ path: candidate.path, line: definition.line, reason: `deterministic detector ${candidate.signal}` }];
|
|
14409
|
+
const sameSite = use.path === candidate.path && use.line === definition.line;
|
|
14410
|
+
if (!sameSite) {
|
|
14411
|
+
evidence.push({
|
|
14412
|
+
path: use.path,
|
|
14413
|
+
line: use.line,
|
|
14414
|
+
reason: use.referenceOnly ? "prompt-named literal referenced here (positional or composed model input)" : `passed to a model call as ${use.key}`
|
|
14415
|
+
});
|
|
14416
|
+
}
|
|
13647
14417
|
return {
|
|
13648
|
-
id: stableId("prompt", `${pathStem(candidate.path)}:L${
|
|
14418
|
+
id: stableId("prompt", `${pathStem(candidate.path)}:L${definition.line}`),
|
|
13649
14419
|
type: "prompt",
|
|
13650
|
-
name:
|
|
14420
|
+
name: name ? titleFromId(name) : `Inline Prompt (${candidate.path}:${definition.line})`,
|
|
13651
14421
|
scope: "shared",
|
|
13652
14422
|
usedByAgentIds: [],
|
|
13653
|
-
confidence: confidence2,
|
|
13654
|
-
|
|
14423
|
+
confidence: use.referenceOnly ? Math.min(confidence2, REFERENCED_PROMPT_CONFIDENCE) : confidence2,
|
|
14424
|
+
confidenceReason: use.referenceOnly ? `Deterministic: instruction-like literal ${name} is referenced at ${use.path}:${use.line} through ${use.via}, but no prompt key (system, instructions, content) was found at the call.` : sameSite ? `Deterministic: string literal written under the ${use.key} key at ${candidate.path}:${definition.line}.` : `Deterministic: string literal ${name} passed to a model call as ${use.key} at ${use.path}:${use.line}.`,
|
|
14425
|
+
evidence,
|
|
14426
|
+
body: definition.text
|
|
13655
14427
|
};
|
|
13656
14428
|
}
|
|
13657
14429
|
function promoteModelConfigCandidate(candidate, rootDir, confidence2, fileCache) {
|
|
@@ -13683,6 +14455,10 @@ function mergePromotedDuplicate(existing, next) {
|
|
|
13683
14455
|
function promoteHarnessCandidates(report, rootDir) {
|
|
13684
14456
|
const fileCache = new Map;
|
|
13685
14457
|
const byId = new Map;
|
|
14458
|
+
const files = {
|
|
14459
|
+
model: new Set(report.candidates.filter((candidate) => candidate.kind === "llm_call_site" || candidate.kind === "framework_construct").map((candidate) => candidate.path)),
|
|
14460
|
+
searchable: new Set(report.files.map((file) => file.path))
|
|
14461
|
+
};
|
|
13686
14462
|
for (const candidate of report.candidates) {
|
|
13687
14463
|
const confidence2 = PROMOTED_CONFIDENCE[candidate.confidence];
|
|
13688
14464
|
if (confidence2 === undefined)
|
|
@@ -13693,11 +14469,13 @@ function promoteHarnessCandidates(report, rootDir) {
|
|
|
13693
14469
|
artifact = promoteToolCandidate(candidate, rootDir, confidence2, fileCache);
|
|
13694
14470
|
break;
|
|
13695
14471
|
case "prompt_file":
|
|
14472
|
+
if (candidate.signal === "prompt_module.name_hint")
|
|
14473
|
+
break;
|
|
13696
14474
|
artifact = promotePromptFileCandidate(candidate, confidence2);
|
|
13697
14475
|
break;
|
|
13698
14476
|
case "prompt_literal":
|
|
13699
14477
|
if (candidate.confidence === "high") {
|
|
13700
|
-
artifact = promotePromptLiteralCandidate(candidate, rootDir, confidence2, fileCache);
|
|
14478
|
+
artifact = promotePromptLiteralCandidate(candidate, rootDir, confidence2, fileCache, files);
|
|
13701
14479
|
}
|
|
13702
14480
|
break;
|
|
13703
14481
|
case "model_config":
|
|
@@ -13763,6 +14541,7 @@ var HARNESS_FAMILY_FLAGS = [
|
|
|
13763
14541
|
"offset",
|
|
13764
14542
|
"out",
|
|
13765
14543
|
"path",
|
|
14544
|
+
"promote",
|
|
13766
14545
|
"remote",
|
|
13767
14546
|
"report",
|
|
13768
14547
|
"run",
|
|
@@ -14049,7 +14828,7 @@ async function runHarnessCommand(context) {
|
|
|
14049
14828
|
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.");
|
|
14050
14829
|
}
|
|
14051
14830
|
if (context.flags["github-actions"] === "true") {
|
|
14052
|
-
const { runGithubActionsAnalyze } = await import("./harness-github-actions-
|
|
14831
|
+
const { runGithubActionsAnalyze } = await import("./harness-github-actions-p3g8cjf2.js");
|
|
14053
14832
|
const result = await runGithubActionsAnalyze(rootDir, {
|
|
14054
14833
|
writeReport: (report2) => {
|
|
14055
14834
|
const normalized = normalizeHarnessReport(report2);
|
|
@@ -14184,6 +14963,28 @@ async function runHarnessCommand(context) {
|
|
|
14184
14963
|
message: "Scan this project for static harness candidates?"
|
|
14185
14964
|
});
|
|
14186
14965
|
writeHumanProgress(context, "Harness candidates: static pre-pass (no LLM, no network)...");
|
|
14966
|
+
if (context.flags.promote !== undefined) {
|
|
14967
|
+
const promote = context.flags.promote === "true" ? "all" : context.flags.promote.trim().toLowerCase();
|
|
14968
|
+
if (promote !== "all" && !HARNESS_ANALYZE_CONCERNS.includes(promote)) {
|
|
14969
|
+
throw new CliInputError(`Unknown --promote value "${context.flags.promote}".`, `Use --promote=all or one of: ${HARNESS_ANALYZE_CONCERNS.join(", ")}.`);
|
|
14970
|
+
}
|
|
14971
|
+
const promoteOut = context.flags.out;
|
|
14972
|
+
if (promoteOut === "true") {
|
|
14973
|
+
throw new CliInputError("Missing output path for --out.", "Usage: moda harness candidates --promote=<concern|all> --out=<file>");
|
|
14974
|
+
}
|
|
14975
|
+
const artifacts = deterministicArtifacts(rootDir, promote === "all" ? undefined : promote);
|
|
14976
|
+
const promoted = { concern: promote, artifacts };
|
|
14977
|
+
const promoteWritten = [];
|
|
14978
|
+
if (promoteOut && !context.dryRun) {
|
|
14979
|
+
const target = resolve10(context.cwd, promoteOut);
|
|
14980
|
+
mkdirSync5(dirname7(target), { recursive: true });
|
|
14981
|
+
writeFileSync5(target, `${JSON.stringify(promoted, null, 2)}
|
|
14982
|
+
`, "utf8");
|
|
14983
|
+
promoteWritten.push(target);
|
|
14984
|
+
}
|
|
14985
|
+
context.output.writeData({ scanPlan, ...promoted, written: promoteWritten, dryRun: context.dryRun });
|
|
14986
|
+
return { exitCode: 0 };
|
|
14987
|
+
}
|
|
14187
14988
|
const report = detectHarnessCandidates(rootDir);
|
|
14188
14989
|
const written = [];
|
|
14189
14990
|
const outFlag = context.flags.out;
|
|
@@ -14656,7 +15457,7 @@ function extractHarnessReportFromText(output, rootDir, concern) {
|
|
|
14656
15457
|
}
|
|
14657
15458
|
function reportJsonCandidates(output) {
|
|
14658
15459
|
const candidates = [];
|
|
14659
|
-
const markerPattern = new RegExp(`${
|
|
15460
|
+
const markerPattern = new RegExp(`${escapeRegExp2(REPORT_JSON_BEGIN)}\\s*([\\s\\S]*?)\\s*${escapeRegExp2(REPORT_JSON_END)}`, "g");
|
|
14660
15461
|
for (const match of output.matchAll(markerPattern)) {
|
|
14661
15462
|
if (match[1])
|
|
14662
15463
|
candidates.push(match[1]);
|
|
@@ -14702,6 +15503,17 @@ function applyResolvedPromptSource(artifact, source) {
|
|
|
14702
15503
|
artifact.sourcePath = source.sourcePath;
|
|
14703
15504
|
artifact.contentHash = source.sourceDefinition.sourceHash;
|
|
14704
15505
|
}
|
|
15506
|
+
function isToolGroupPlaceholder(name) {
|
|
15507
|
+
const trimmed = (name ?? "").trim();
|
|
15508
|
+
if (!trimmed)
|
|
15509
|
+
return false;
|
|
15510
|
+
if (trimmed.includes("*"))
|
|
15511
|
+
return true;
|
|
15512
|
+
return /\s(?:tools|toolkits?|toolsets?)$/i.test(trimmed);
|
|
15513
|
+
}
|
|
15514
|
+
function isDetectedToolDefinitionReason(reason) {
|
|
15515
|
+
return typeof reason === "string" && (reason.startsWith("deterministic detector ") || reason.startsWith("Tool definition detected"));
|
|
15516
|
+
}
|
|
14705
15517
|
function removeArtifacts(report, ids) {
|
|
14706
15518
|
const graph = report.graph;
|
|
14707
15519
|
const keep = (id) => typeof id !== "string" || !ids.has(id);
|
|
@@ -14751,6 +15563,33 @@ function repairExternalAnalystReport(report, rootDir, options = {}) {
|
|
|
14751
15563
|
normalized.graph.unknowns.push({ id: `unresolved_${artifact.id}`, question: error instanceof Error ? error.message : String(error), candidateIds: [artifact.id], evidence: artifact.evidence });
|
|
14752
15564
|
}
|
|
14753
15565
|
}
|
|
15566
|
+
for (const artifact of normalized.graph.artifacts) {
|
|
15567
|
+
if (artifact.type !== "tool" || unverified.has(artifact.id) || !isToolGroupPlaceholder(artifact.name))
|
|
15568
|
+
continue;
|
|
15569
|
+
if (artifact.evidence.some((entry) => isDetectedToolDefinitionReason(entry.reason)))
|
|
15570
|
+
continue;
|
|
15571
|
+
unverified.add(artifact.id);
|
|
15572
|
+
normalized.graph.unknowns.push({
|
|
15573
|
+
id: `unresolved_${artifact.id}`,
|
|
15574
|
+
question: `"${artifact.name}" is a dynamic tool source (a group of tools resolved at runtime), not a single tool definition, so its tools are not enumerated in the harness.`,
|
|
15575
|
+
candidateIds: [artifact.id],
|
|
15576
|
+
evidence: artifact.evidence
|
|
15577
|
+
});
|
|
15578
|
+
}
|
|
15579
|
+
for (const artifact of normalized.graph.artifacts) {
|
|
15580
|
+
if (artifact.type !== "model_config" || unverified.has(artifact.id))
|
|
15581
|
+
continue;
|
|
15582
|
+
const paths = artifact.evidence.map((entry) => entry.path).filter((path) => typeof path === "string" && path.length > 0);
|
|
15583
|
+
if (paths.length === 0 || !paths.every((path) => TEST_PATH2.test(path)))
|
|
15584
|
+
continue;
|
|
15585
|
+
unverified.add(artifact.id);
|
|
15586
|
+
normalized.graph.unknowns.push({
|
|
15587
|
+
id: `unresolved_${artifact.id}`,
|
|
15588
|
+
question: `Model ${artifact.name ?? artifact.id} is cited only from test or fixture files, so it is a test input rather than the harness's model configuration.`,
|
|
15589
|
+
candidateIds: [artifact.id],
|
|
15590
|
+
evidence: artifact.evidence
|
|
15591
|
+
});
|
|
15592
|
+
}
|
|
14754
15593
|
for (const artifact of normalized.graph.artifacts) {
|
|
14755
15594
|
if (unverified.has(artifact.id) || !requiresArtifactBody(artifact.type))
|
|
14756
15595
|
continue;
|
|
@@ -14834,6 +15673,12 @@ var CONCERN_PROMOTED_ARTIFACT_TYPES = {
|
|
|
14834
15673
|
prompts: new Set(["prompt"]),
|
|
14835
15674
|
evals: new Set(["model_config"])
|
|
14836
15675
|
};
|
|
15676
|
+
function deterministicArtifacts(rootDir, concern) {
|
|
15677
|
+
const graph = { artifacts: [], unknowns: [] };
|
|
15678
|
+
mergeDeterministicArtifacts(graph, rootDir, { concern });
|
|
15679
|
+
hydratePromptAndToolBodies(graph, rootDir);
|
|
15680
|
+
return graph.artifacts;
|
|
15681
|
+
}
|
|
14837
15682
|
function mergeDeterministicArtifacts(graph, rootDir, options = {}) {
|
|
14838
15683
|
if (process.env.MODA_HARNESS_DETERMINISTIC_MERGE === "0")
|
|
14839
15684
|
return { added: 0 };
|
|
@@ -15064,7 +15909,7 @@ function extractTextFromAgentEvent(event) {
|
|
|
15064
15909
|
return textParts.length > 0 ? textParts.join(`
|
|
15065
15910
|
`) : undefined;
|
|
15066
15911
|
}
|
|
15067
|
-
function
|
|
15912
|
+
function escapeRegExp2(value) {
|
|
15068
15913
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
15069
15914
|
}
|
|
15070
15915
|
var EVENT_CARD_MAX = 100;
|
|
@@ -15818,6 +16663,10 @@ function renderExternalHarnessAnalystPrompt(options) {
|
|
|
15818
16663
|
"- unknowns: report-level open questions with id, question, and citationIds",
|
|
15819
16664
|
"",
|
|
15820
16665
|
'Use exact field names and numeric confidence values from 0 to 1. Do not write string confidence values like "high". Do not use confidence >= 0.90 unless the claim is direct evidence from the cited line(s).',
|
|
16666
|
+
`Name each runtime agent after the class or exported symbol that defines it, adding the role in parentheses when helpful, e.g. "AutonomousPlanWorkflow (weekly planner)"; a Cloudflare Workflow or Durable Object class keeps its class name. Never emit an agent whose class is not defined or exported in this source tree: a binding to another worker's class (e.g. a wrangler script_name binding) is a deployment detail, not an agent of this repo.`,
|
|
16667
|
+
'A `tool` artifact is one tool definition. Never emit a group of tools ("MCP server tools", "composio_*", "worker tools") as a tool; record a dynamic tool source (MCP servers, Composio, webhooks) as a graph unknown that cites where the tools are loaded.',
|
|
16668
|
+
"Ignore any checked-in .moda/ directory: it is the output of an earlier Moda run and is often stale. Never cite it or reuse its entities.",
|
|
16669
|
+
'Every graph item with confidence below 0.85 must also carry confidenceReason: one sentence naming what held confidence down, e.g. "Inferred from AGENTS.md:231-232 only; no source file defines this agent." or "Entrypoint read, but the tool registry was outside the snapshot."',
|
|
15821
16670
|
"Each graph item with evidence must use evidence: [{ path, reason }], not citationIds/citations.",
|
|
15822
16671
|
...spec ? spec.contractLines : [
|
|
15823
16672
|
'Runtime agents must include id, name, kind:"runtime_agent", root, entrypointIds, channelAdapterIds, artifactIds, identityNamespaceIds, deploymentIds, frameworkIds, modelProviderIds, confidence, evidence.',
|
|
@@ -18221,4 +19070,4 @@ function hashText(text) {
|
|
|
18221
19070
|
return createHash5("sha256").update(text).digest("hex");
|
|
18222
19071
|
}
|
|
18223
19072
|
|
|
18224
|
-
export { startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, runHarnessCommand, writeHarnessAnalyzeResult, emitWrittenArtifacts, analyzeHarnessPrompts, repairExternalAnalystReport, deriveRelationshipsFromGraph, mergeDeterministicArtifacts, analystRefutations, describeCodingAgentEvent, analystEventProgress, isRetryableExternalAnalystFailure, sleep, summarizeInvalidAnalystReport, isDeterministicLocalAnalyst, resolveHarnessAnalyzeConcern, detectAvailableCodingAgents, codingAgentDisplayName, runCodingAgent, resolveAnalystModel, renderExternalHarnessAnalystPrompt, CONCERN_CANDIDATE_KINDS, SEED_CANDIDATE_KIND_LABELS, renderAnalystCandidateLines, renderAnalystSeedLines, truncateText, scanHarness, summarizeHarness, buildSourceSnapshot, writeHumanProgress, describeSyncIdentity, describeSyncTenantLabel, findFresherHarnessReports, writeHarnessArtifacts, assertHarnessGraphSyncQuality, graphForSync, inventoryFiles, numericEnv, numericEnvAllowZero, computeDeterministicFloor, stableId, titleFromId, promptNameFromPath };
|
|
19073
|
+
export { startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, runHarnessCommand, writeHarnessAnalyzeResult, emitWrittenArtifacts, analyzeHarnessPrompts, isToolGroupPlaceholder, repairExternalAnalystReport, deriveRelationshipsFromGraph, deterministicArtifacts, mergeDeterministicArtifacts, analystRefutations, describeCodingAgentEvent, analystEventProgress, isRetryableExternalAnalystFailure, sleep, summarizeInvalidAnalystReport, isDeterministicLocalAnalyst, resolveHarnessAnalyzeConcern, detectAvailableCodingAgents, codingAgentDisplayName, runCodingAgent, resolveAnalystModel, renderExternalHarnessAnalystPrompt, CONCERN_CANDIDATE_KINDS, SEED_CANDIDATE_KIND_LABELS, renderAnalystCandidateLines, renderAnalystSeedLines, truncateText, scanHarness, summarizeHarness, buildSourceSnapshot, writeHumanProgress, describeSyncIdentity, describeSyncTenantLabel, findFresherHarnessReports, writeHarnessArtifacts, assertHarnessGraphSyncQuality, graphForSync, inventoryFiles, numericEnv, numericEnvAllowZero, computeDeterministicFloor, stableId, titleFromId, promptNameFromPath };
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./cli-rdh9jjr2.js";
|
|
5
5
|
import {
|
|
6
6
|
inspectPromptManifest
|
|
7
|
-
} from "./cli-
|
|
7
|
+
} from "./cli-arze1hgb.js";
|
|
8
8
|
import {
|
|
9
9
|
readHarnessSyncState,
|
|
10
10
|
renderDoctorHuman,
|
|
@@ -395,7 +395,7 @@ async function harnessCurrentCheck(cwd, manifestPath, manifestExists, tenantId)
|
|
|
395
395
|
};
|
|
396
396
|
}
|
|
397
397
|
try {
|
|
398
|
-
const { scanHarness } = await import("./harness-
|
|
398
|
+
const { scanHarness } = await import("./harness-t2xjak6g.js");
|
|
399
399
|
const current = scanHarness({
|
|
400
400
|
rootDir: cwd,
|
|
401
401
|
scannerVersion: "doctor",
|
package/dist/cli.js
CHANGED
|
@@ -2145,9 +2145,10 @@ var HARNESS_SUBCOMMAND_HELP = [
|
|
|
2145
2145
|
{
|
|
2146
2146
|
name: "candidates",
|
|
2147
2147
|
description: "Static pre-pass listing likely agents, prompts, and tools (local; no LLM, no network)",
|
|
2148
|
-
usage: "moda harness candidates [--path=<dir>] [--out=<file>] [--dry-run] [--yes]",
|
|
2148
|
+
usage: "moda harness candidates [--path=<dir>] [--out=<file>] [--promote=<concern|all>] [--dry-run] [--yes]",
|
|
2149
2149
|
flags: [
|
|
2150
2150
|
HARNESS_PATH_FLAG,
|
|
2151
|
+
{ name: "--promote=<concern|all>", description: "Print the deterministic artifacts (tools, prompts, model configs) for one concern (topology, tools, prompts, evals) or all, with bodies, instead of the raw candidates." },
|
|
2151
2152
|
{ name: "--out=<file>", description: "Also write the candidates report to a file." },
|
|
2152
2153
|
{ name: "--dry-run", description: "Do not write --out." },
|
|
2153
2154
|
{ name: "--yes", description: "Approve a broad scan without the prompt." }
|
|
@@ -2967,25 +2968,25 @@ function leafManifestFields(leaf, commands) {
|
|
|
2967
2968
|
import { fileURLToPath } from "url";
|
|
2968
2969
|
import { realpathSync } from "fs";
|
|
2969
2970
|
async function runPromptsCommand(...args) {
|
|
2970
|
-
return (await import("./prompts-
|
|
2971
|
+
return (await import("./prompts-z2v4k4q7.js")).runPromptsCommand(...args);
|
|
2971
2972
|
}
|
|
2972
2973
|
async function runSkillsCommand(...args) {
|
|
2973
2974
|
return (await import("./skills-mwftqzyk.js")).runSkillsCommand(...args);
|
|
2974
2975
|
}
|
|
2975
2976
|
async function runHarnessCommand(...args) {
|
|
2976
|
-
return (await import("./harness-
|
|
2977
|
+
return (await import("./harness-t2xjak6g.js")).runHarnessCommand(...args);
|
|
2977
2978
|
}
|
|
2978
2979
|
async function runSyncCommand(...args) {
|
|
2979
|
-
return (await import("./sync-
|
|
2980
|
+
return (await import("./sync-tzvrgzqs.js")).runSyncCommand(...args);
|
|
2980
2981
|
}
|
|
2981
2982
|
async function runRegistryCommand(...args) {
|
|
2982
2983
|
return (await import("./registry-tv8fktxc.js")).runRegistryCommand(...args);
|
|
2983
2984
|
}
|
|
2984
2985
|
async function runDoctorCommand(...args) {
|
|
2985
|
-
return (await import("./doctor-
|
|
2986
|
+
return (await import("./doctor-66qe8hq9.js")).runDoctorCommand(...args);
|
|
2986
2987
|
}
|
|
2987
2988
|
async function runStatusCommand(...args) {
|
|
2988
|
-
return (await import("./doctor-
|
|
2989
|
+
return (await import("./doctor-66qe8hq9.js")).runStatusCommand(...args);
|
|
2989
2990
|
}
|
|
2990
2991
|
async function runAuthCommand(...args) {
|
|
2991
2992
|
return (await import("./profile-commands-nbaec4y9.js")).runAuthCommand(...args);
|
|
@@ -2997,7 +2998,7 @@ async function runProfilesCommand(...args) {
|
|
|
2997
2998
|
return (await import("./profile-commands-nbaec4y9.js")).runProfilesCommand(...args);
|
|
2998
2999
|
}
|
|
2999
3000
|
async function runAgentCommand(...args) {
|
|
3000
|
-
return (await import("./agent-
|
|
3001
|
+
return (await import("./agent-nxn5df1w.js")).runAgentCommand(...args);
|
|
3001
3002
|
}
|
|
3002
3003
|
async function runProductionCommand(...args) {
|
|
3003
3004
|
return (await import("./production-intelligence-zek0rkzj.js")).runProductionCommand(...args);
|
|
@@ -6761,7 +6762,7 @@ var commandRegistry = createCommandRegistry([
|
|
|
6761
6762
|
resetApiRequestCountBeforeRun: true,
|
|
6762
6763
|
telemetry: "result-and-error",
|
|
6763
6764
|
handler: async (context) => {
|
|
6764
|
-
const { runInit } = await import("./index-
|
|
6765
|
+
const { runInit } = await import("./index-tt5rmqyq.js");
|
|
6765
6766
|
if (context.outputMode === "agent-stream") {
|
|
6766
6767
|
context.output.writeEvent({
|
|
6767
6768
|
event: "started",
|
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
promptsDiscoveredCheck,
|
|
4
4
|
runDoctorCommand,
|
|
5
5
|
runStatusCommand
|
|
6
|
-
} from "./cli-
|
|
6
|
+
} from "./cli-zgmxsmbt.js";
|
|
7
7
|
import"./cli-rdh9jjr2.js";
|
|
8
|
-
import"./cli-
|
|
8
|
+
import"./cli-arze1hgb.js";
|
|
9
9
|
import"./cli-mm48br00.js";
|
|
10
10
|
import"./cli-xq45etg1.js";
|
|
11
11
|
import"./cli-gtke9wrw.js";
|
|
@@ -13,12 +13,14 @@ import {
|
|
|
13
13
|
describeSyncIdentity,
|
|
14
14
|
describeSyncTenantLabel,
|
|
15
15
|
detectAvailableCodingAgents,
|
|
16
|
+
deterministicArtifacts,
|
|
16
17
|
emitWrittenArtifacts,
|
|
17
18
|
findFresherHarnessReports,
|
|
18
19
|
graphForSync,
|
|
19
20
|
inventoryFiles,
|
|
20
21
|
isDeterministicLocalAnalyst,
|
|
21
22
|
isRetryableExternalAnalystFailure,
|
|
23
|
+
isToolGroupPlaceholder,
|
|
22
24
|
mergeDeterministicArtifacts,
|
|
23
25
|
numericEnv,
|
|
24
26
|
numericEnvAllowZero,
|
|
@@ -41,7 +43,7 @@ import {
|
|
|
41
43
|
writeHarnessAnalyzeResult,
|
|
42
44
|
writeHarnessArtifacts,
|
|
43
45
|
writeHumanProgress
|
|
44
|
-
} from "./cli-
|
|
46
|
+
} from "./cli-xx73daeb.js";
|
|
45
47
|
import"./cli-97fnztpy.js";
|
|
46
48
|
import"./cli-xq45etg1.js";
|
|
47
49
|
import"./cli-gtke9wrw.js";
|
|
@@ -80,12 +82,14 @@ export {
|
|
|
80
82
|
numericEnvAllowZero,
|
|
81
83
|
numericEnv,
|
|
82
84
|
mergeDeterministicArtifacts,
|
|
85
|
+
isToolGroupPlaceholder,
|
|
83
86
|
isRetryableExternalAnalystFailure,
|
|
84
87
|
isDeterministicLocalAnalyst,
|
|
85
88
|
inventoryFiles,
|
|
86
89
|
graphForSync,
|
|
87
90
|
findFresherHarnessReports,
|
|
88
91
|
emitWrittenArtifacts,
|
|
92
|
+
deterministicArtifacts,
|
|
89
93
|
detectAvailableCodingAgents,
|
|
90
94
|
describeSyncTenantLabel,
|
|
91
95
|
describeSyncIdentity,
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
} from "./cli-hcwdz9sd.js";
|
|
22
22
|
import {
|
|
23
23
|
buildDoctorReport
|
|
24
|
-
} from "./cli-
|
|
24
|
+
} from "./cli-zgmxsmbt.js";
|
|
25
25
|
import {
|
|
26
26
|
ConnectCodeError,
|
|
27
27
|
connectWithCode,
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
import {
|
|
33
33
|
initPrompts,
|
|
34
34
|
runPromptSync
|
|
35
|
-
} from "./cli-
|
|
35
|
+
} from "./cli-arze1hgb.js";
|
|
36
36
|
import"./cli-mm48br00.js";
|
|
37
37
|
import {
|
|
38
38
|
codingAgentDisplayName,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
runCodingAgent,
|
|
47
47
|
runHarnessCommand,
|
|
48
48
|
startRemoteAnalyze
|
|
49
|
-
} from "./cli-
|
|
49
|
+
} from "./cli-xx73daeb.js";
|
|
50
50
|
import {
|
|
51
51
|
stripAnsi
|
|
52
52
|
} from "./cli-97fnztpy.js";
|
|
@@ -6,11 +6,11 @@ import"./cli-rjav0vj1.js";
|
|
|
6
6
|
import"./cli-hcwdz9sd.js";
|
|
7
7
|
import {
|
|
8
8
|
runPromptsCommand
|
|
9
|
-
} from "./cli-
|
|
9
|
+
} from "./cli-arze1hgb.js";
|
|
10
10
|
import"./cli-mm48br00.js";
|
|
11
11
|
import {
|
|
12
12
|
runHarnessCommand
|
|
13
|
-
} from "./cli-
|
|
13
|
+
} from "./cli-xx73daeb.js";
|
|
14
14
|
import"./cli-97fnztpy.js";
|
|
15
15
|
import"./cli-xq45etg1.js";
|
|
16
16
|
import"./cli-gtke9wrw.js";
|
package/package.json
CHANGED