@moda-ai/cli 1.55.73 → 1.55.75
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-nqykfqm0.js → agent-g42xvr5e.js} +3 -3
- package/dist/{cli-zyg6v6vq.js → cli-3yz57mqd.js} +2 -2
- package/dist/{cli-h5ar0v9v.js → cli-8bc55erh.js} +1378 -392
- package/dist/{cli-4bmxk8z9.js → cli-ec42ynvj.js} +3 -3
- package/dist/cli.js +7 -7
- package/dist/{doctor-180rzz99.js → doctor-epyjq11e.js} +2 -2
- package/dist/{harness-defgbftj.js → harness-ew65z05z.js} +1 -1
- package/dist/{harness-github-actions-p4011crc.js → harness-github-actions-d0rb1wmk.js} +1 -1
- package/dist/{index-4z7h9mam.js → index-2rhvz7fa.js} +3 -1
- package/dist/{index-femt9s00.js → index-dk98sc3s.js} +1 -1
- package/dist/{index-6ycqrx13.js → index-xqssm1xh.js} +3 -3
- package/dist/{prompt-attribution-1s253fra.js → prompt-attribution-e1zhhr1b.js} +1 -1
- package/dist/prompt-source-mcp.js +1 -1
- package/dist/{prompts-gmdscxhk.js → prompts-4vxn04ht.js} +1 -1
- package/dist/{sync-asf3zmmn.js → sync-j6csmvpx.js} +2 -2
- package/package.json +1 -1
- package/skills/integration/index.json +2 -2
|
@@ -109,10 +109,10 @@ import {
|
|
|
109
109
|
} from "./cli-0v6na3yp.js";
|
|
110
110
|
|
|
111
111
|
// src/harness-extract/enumerators/agents.ts
|
|
112
|
-
var
|
|
112
|
+
var import_typescript14 = __toESM(require_typescript(), 1);
|
|
113
113
|
|
|
114
114
|
// src/harness-extract/index.ts
|
|
115
|
-
var
|
|
115
|
+
var import_typescript13 = __toESM(require_typescript(), 1);
|
|
116
116
|
import { resolve as resolve13 } from "node:path";
|
|
117
117
|
|
|
118
118
|
// src/harness-extract/ast.ts
|
|
@@ -1307,8 +1307,11 @@ function selectKey(tree, key, missing) {
|
|
|
1307
1307
|
if (member.key === "...") {
|
|
1308
1308
|
const fromSpread = selectKey(member, key, missing);
|
|
1309
1309
|
if (fromSpread !== missing) {
|
|
1310
|
-
|
|
1310
|
+
const mayLack = hasWhere(fromSpread, (node) => node === missing);
|
|
1311
|
+
if (mayLack || fromSpread.resolution === "unresolved") {
|
|
1311
1312
|
const prior = selectKey({ ...tree, children: members.slice(0, index) }, key, missing);
|
|
1313
|
+
if (prior !== missing && mayLack)
|
|
1314
|
+
return substituteWhere(fromSpread, (node) => node === missing, prior);
|
|
1312
1315
|
if (prior !== missing)
|
|
1313
1316
|
return { ...fromSpread, kind: "oneOf", children: [prior, fromSpread], resolution: "partial", note: "unknown spread may override property" };
|
|
1314
1317
|
}
|
|
@@ -1354,16 +1357,14 @@ function leaves(tree) {
|
|
|
1354
1357
|
return flow.length > 0 && tree.kind !== "template" ? flow.flatMap(leaves) : [tree];
|
|
1355
1358
|
}
|
|
1356
1359
|
function hasWhere(tree, match) {
|
|
1357
|
-
return match(tree) || valueChildren(tree).some((child) => hasWhere(child, match));
|
|
1360
|
+
return match(tree) || FLOW_KINDS.has(tree.kind) && valueChildren(tree).some((child) => hasWhere(child, match));
|
|
1358
1361
|
}
|
|
1359
1362
|
function substituteWhere(tree, match, replacement) {
|
|
1360
1363
|
if (match(tree))
|
|
1361
1364
|
return tree.key !== undefined ? { ...replacement, key: tree.key } : replacement;
|
|
1362
1365
|
if (!hasWhere(tree, match))
|
|
1363
1366
|
return tree;
|
|
1364
|
-
|
|
1365
|
-
return mapFlow(tree, (child) => substituteWhere(child, match, replacement));
|
|
1366
|
-
return { ...tree, children: (tree.children ?? []).map((child) => substituteWhere(child, match, replacement)) };
|
|
1367
|
+
return mapFlow(tree, (child) => substituteWhere(child, match, replacement));
|
|
1367
1368
|
}
|
|
1368
1369
|
function allValues(tree) {
|
|
1369
1370
|
if (tree.kind === "object" || tree.kind === "array" || tree.kind === "assembled" && tree.text === "array") {
|
|
@@ -1610,7 +1611,7 @@ class CallIndex {
|
|
|
1610
1611
|
this.byName ??= this.build();
|
|
1611
1612
|
const out = this.direct(name, limit, (declaration) => declares(declaration, fn));
|
|
1612
1613
|
if (isDefaultExport(fn) && name !== "default" && out.length < limit)
|
|
1613
|
-
out.push(...this.direct("default", limit - out.length, (declaration) => declares(declaration, fn)));
|
|
1614
|
+
out.push(...this.direct("default", limit - out.length, (declaration) => declares(declaration, fn), new Set(out)));
|
|
1614
1615
|
for (const alias of this.aliases.get(name) ?? []) {
|
|
1615
1616
|
if (out.length >= limit)
|
|
1616
1617
|
break;
|
|
@@ -1711,11 +1712,13 @@ class CallIndex {
|
|
|
1711
1712
|
this.checkingDefaults.delete(declaration);
|
|
1712
1713
|
}
|
|
1713
1714
|
}
|
|
1714
|
-
direct(name, limit, matches) {
|
|
1715
|
+
direct(name, limit, matches, found) {
|
|
1715
1716
|
const candidates = this.byName.get(name) ?? [];
|
|
1716
1717
|
const out = [];
|
|
1717
1718
|
let checked = 0;
|
|
1718
1719
|
for (const call of candidates) {
|
|
1720
|
+
if (found?.has(call))
|
|
1721
|
+
continue;
|
|
1719
1722
|
if (out.length >= limit || checked >= limit * 20)
|
|
1720
1723
|
break;
|
|
1721
1724
|
checked += 1;
|
|
@@ -17641,6 +17644,103 @@ function hasDirective(text) {
|
|
|
17641
17644
|
const plain = text.replace(/\{\{[^}]*\}\}/g, " ").trim();
|
|
17642
17645
|
return DIRECTIVE_ANYWHERE.test(plain) || DIRECTIVE_VERB.test(plain);
|
|
17643
17646
|
}
|
|
17647
|
+
var ERROR_TEXT = /^\s*(?:error\b|failed\b|could not\b|couldn't\b|cannot\b|can't\b|unable to\b|invalid\b|unknown\b|missing\b|not found\b)/i;
|
|
17648
|
+
function toolResultIsPrompt(owner, pieces) {
|
|
17649
|
+
if (!owner)
|
|
17650
|
+
return false;
|
|
17651
|
+
if (import_typescript8.default.isShorthandPropertyAssignment(owner) || import_typescript8.default.isPropertyAssignment(owner) && !isNamedTableEntry(owner))
|
|
17652
|
+
return false;
|
|
17653
|
+
const own = pieces.map((piece) => piece.trim()).filter(Boolean);
|
|
17654
|
+
if (own.length === 0)
|
|
17655
|
+
return false;
|
|
17656
|
+
const text = withoutLabels(own.join(`
|
|
17657
|
+
`));
|
|
17658
|
+
if (own.every((piece) => ERROR_TEXT.test(piece)) && !IMPERATIVE.test(text))
|
|
17659
|
+
return false;
|
|
17660
|
+
if (!hasDirective(text) && !IMPERATIVE.test(text))
|
|
17661
|
+
return false;
|
|
17662
|
+
const fn = import_typescript8.default.isFunctionLike(owner) ? owner : import_typescript8.default.isVariableDeclaration(owner) && owner.initializer && import_typescript8.default.isFunctionLike(unwrapNode(owner.initializer)) ? unwrapNode(owner.initializer) : undefined;
|
|
17663
|
+
return !fn || isTextBuilder(fn);
|
|
17664
|
+
}
|
|
17665
|
+
function isNamedTableEntry(property) {
|
|
17666
|
+
const object = property.parent;
|
|
17667
|
+
if (object.properties.some((entry) => entry.name && import_typescript8.default.isIdentifier(entry.name) && entry.name.text === "type"))
|
|
17668
|
+
return false;
|
|
17669
|
+
let node = object;
|
|
17670
|
+
while (import_typescript8.default.isObjectLiteralExpression(node) || import_typescript8.default.isPropertyAssignment(node) || import_typescript8.default.isParenthesizedExpression(node) || import_typescript8.default.isAsExpression(node) || import_typescript8.default.isSatisfiesExpression(node) || import_typescript8.default.isTypeAssertionExpression(node)) {
|
|
17671
|
+
node = node.parent;
|
|
17672
|
+
}
|
|
17673
|
+
return import_typescript8.default.isVariableDeclaration(node) || import_typescript8.default.isPropertyDeclaration(node) || import_typescript8.default.isExportAssignment(node);
|
|
17674
|
+
}
|
|
17675
|
+
function withoutLabels(text) {
|
|
17676
|
+
return text.replace(/\{\{[^}]*\}\}/g, " ").replace(/(^|[.!?\n]\s*)[A-Za-z][\w -]{0,24}:(?=\s)/g, "$1");
|
|
17677
|
+
}
|
|
17678
|
+
var IMPERATIVE_VERBS = "keep|write|reply|respond|return|answer|use|include|output|list|describe|summari[sz]e|explain|decide|pick|choose|rate|score|label|extract|generate|draft|revise|rewrite|translate|tell|ask|call|check|verify|follow|format|limit|stop|continue|focus|consider|act|identify|compare|judge|review|repair|fix|plan|propose|suggest|recommend|find|search|read|treat|cite|flag|mark|rank|group|merge|drop|skip|wait|confirm|send|offer|share|re-share|lean|vary|retry|resend|retell|replace|unschedule|reschedule|reconnect|connect|attach|pass|move|open|try|run|re-run|rerun|load|save|update|delete|remove|add|create|edit|post|publish|schedule|mention|note|let|give|show|present|announce|surface|ping|text|message|forward|route|hand|escalate|report|log";
|
|
17679
|
+
var IMPERATIVE = new RegExp(`(?:^|[.!?:;\\n]\\s*|\\bif\\b[^.!?\\n]{0,160},\\s*)(?:then\\s+)?(?:${IMPERATIVE_VERBS})\\b`, "i");
|
|
17680
|
+
function unwrapNode(node) {
|
|
17681
|
+
let current = node;
|
|
17682
|
+
while (import_typescript8.default.isParenthesizedExpression(current) || import_typescript8.default.isAsExpression(current) || import_typescript8.default.isSatisfiesExpression(current))
|
|
17683
|
+
current = current.expression;
|
|
17684
|
+
return current;
|
|
17685
|
+
}
|
|
17686
|
+
function isTextBuilder(fn) {
|
|
17687
|
+
const modifiers = import_typescript8.default.canHaveModifiers(fn) ? import_typescript8.default.getModifiers(fn) ?? [] : [];
|
|
17688
|
+
if (modifiers.some((modifier) => modifier.kind === import_typescript8.default.SyntaxKind.AsyncKeyword))
|
|
17689
|
+
return false;
|
|
17690
|
+
const declared = fn.type?.getText().replace(/\s+/g, "");
|
|
17691
|
+
if (declared && !/^(?:Promise<)?(?:(?:readonly)?string(?:\[\])?|null|undefined)(?:\|(?:(?:readonly)?string(?:\[\])?|null|undefined))*>?$/.test(declared))
|
|
17692
|
+
return false;
|
|
17693
|
+
let builder = true;
|
|
17694
|
+
let returns = 0;
|
|
17695
|
+
let failures = 0;
|
|
17696
|
+
const visit = (node) => {
|
|
17697
|
+
if (!builder)
|
|
17698
|
+
return;
|
|
17699
|
+
if (node !== fn && import_typescript8.default.isFunctionLike(node))
|
|
17700
|
+
return;
|
|
17701
|
+
if (import_typescript8.default.isAwaitExpression(node))
|
|
17702
|
+
builder = false;
|
|
17703
|
+
else if (import_typescript8.default.isReturnStatement(node) && node.expression) {
|
|
17704
|
+
if (returnsRecord(node.expression))
|
|
17705
|
+
builder = false;
|
|
17706
|
+
returns += 1;
|
|
17707
|
+
if (ERROR_TEXT.test(leadingText(node.expression)))
|
|
17708
|
+
failures += 1;
|
|
17709
|
+
import_typescript8.default.forEachChild(node, visit);
|
|
17710
|
+
} else
|
|
17711
|
+
import_typescript8.default.forEachChild(node, visit);
|
|
17712
|
+
};
|
|
17713
|
+
const body = fn.body;
|
|
17714
|
+
if (body && !import_typescript8.default.isBlock(body))
|
|
17715
|
+
return !returnsRecord(body);
|
|
17716
|
+
if (body)
|
|
17717
|
+
import_typescript8.default.forEachChild(body, visit);
|
|
17718
|
+
return builder && !(returns > 1 && failures > 0 && takesContext(fn));
|
|
17719
|
+
}
|
|
17720
|
+
function takesContext(fn) {
|
|
17721
|
+
return fn.parameters.some((parameter) => {
|
|
17722
|
+
const name = import_typescript8.default.isIdentifier(parameter.name) ? parameter.name.text : "";
|
|
17723
|
+
return /^(?:ctx|context|env|sql|db|tx)$/.test(name) || /(?:Context|Env)\b/.test(parameter.type?.getText() ?? "");
|
|
17724
|
+
});
|
|
17725
|
+
}
|
|
17726
|
+
function leadingText(expr) {
|
|
17727
|
+
const value = unwrapNode(expr);
|
|
17728
|
+
if (import_typescript8.default.isStringLiteral(value) || import_typescript8.default.isNoSubstitutionTemplateLiteral(value))
|
|
17729
|
+
return value.text;
|
|
17730
|
+
if (import_typescript8.default.isTemplateExpression(value))
|
|
17731
|
+
return value.head.text;
|
|
17732
|
+
if (import_typescript8.default.isBinaryExpression(value) && value.operatorToken.kind === import_typescript8.default.SyntaxKind.PlusToken)
|
|
17733
|
+
return leadingText(value.left);
|
|
17734
|
+
return "";
|
|
17735
|
+
}
|
|
17736
|
+
function returnsRecord(expr) {
|
|
17737
|
+
const value = unwrapNode(expr);
|
|
17738
|
+
if (import_typescript8.default.isObjectLiteralExpression(value))
|
|
17739
|
+
return true;
|
|
17740
|
+
if (import_typescript8.default.isConditionalExpression(value))
|
|
17741
|
+
return returnsRecord(value.whenTrue) || returnsRecord(value.whenFalse);
|
|
17742
|
+
return value.kind === import_typescript8.default.SyntaxKind.TrueKeyword || value.kind === import_typescript8.default.SyntaxKind.FalseKeyword || import_typescript8.default.isNumericLiteral(value);
|
|
17743
|
+
}
|
|
17644
17744
|
function isInstructionDescription(text) {
|
|
17645
17745
|
if (text.length >= 2000)
|
|
17646
17746
|
return true;
|
|
@@ -17792,7 +17892,7 @@ class PromptResolver {
|
|
|
17792
17892
|
const line = `${ref.path}:${ref.line}`;
|
|
17793
17893
|
firstOnLine.set(line, Math.min(firstOnLine.get(line) ?? Infinity, ref.start));
|
|
17794
17894
|
}
|
|
17795
|
-
const refs = [...this.refs.values()].map(({ pieces, start, ...ref }) => {
|
|
17895
|
+
const refs = [...this.refs.values()].filter((ref) => this.keepAll || ref.role !== "tool-result" || toolResultIsPrompt(ref.ownerNode, [...ref.pieces.values()])).map(({ pieces, start, ownerNode: _owner, ...ref }) => {
|
|
17796
17896
|
const later = start > firstOnLine.get(`${ref.path}:${ref.line}`);
|
|
17797
17897
|
const column = later ? this.columnOf(ref.path, start) : undefined;
|
|
17798
17898
|
return {
|
|
@@ -18369,7 +18469,8 @@ class PromptResolver {
|
|
|
18369
18469
|
hops: walk.hops,
|
|
18370
18470
|
via: [...walk.flags],
|
|
18371
18471
|
pieces: new Map,
|
|
18372
|
-
start: anchor.getStart(sf)
|
|
18472
|
+
start: anchor.getStart(sf),
|
|
18473
|
+
...owner ? { ownerNode: owner.node } : {}
|
|
18373
18474
|
};
|
|
18374
18475
|
this.refs.set(key, ref);
|
|
18375
18476
|
}
|
|
@@ -18390,6 +18491,15 @@ class PromptResolver {
|
|
|
18390
18491
|
return;
|
|
18391
18492
|
return this.relative(resolvePath(dirname7(statement.getSourceFile().fileName), spec.replace(/\?raw$/, "")));
|
|
18392
18493
|
}
|
|
18494
|
+
preferModelRole(ref, walk) {
|
|
18495
|
+
const toolPath = walk.role === "tool-result" || walk.role === "tool-description";
|
|
18496
|
+
if (ref.role === "tool-result" && !toolPath) {
|
|
18497
|
+
ref.role = walk.role;
|
|
18498
|
+
ref.hops = walk.hops;
|
|
18499
|
+
ref.via = [...walk.flags];
|
|
18500
|
+
}
|
|
18501
|
+
return ref.role === "tool-result" || walk.role !== "tool-result";
|
|
18502
|
+
}
|
|
18393
18503
|
fileRef(path, walk) {
|
|
18394
18504
|
if (TEST_SOURCE.test(path))
|
|
18395
18505
|
return;
|
|
@@ -18399,9 +18509,11 @@ class PromptResolver {
|
|
|
18399
18509
|
ref = { id, path, line: 1, endLine: 1, start: 0, kind: "file", role: walk.role, text: "", callSiteIds: [], hops: walk.hops, via: [...walk.flags], pieces: new Map };
|
|
18400
18510
|
this.refs.set(id, ref);
|
|
18401
18511
|
}
|
|
18512
|
+
const counts = this.preferModelRole(ref, walk);
|
|
18402
18513
|
if (!ref.callSiteIds.includes(walk.site.id))
|
|
18403
18514
|
ref.callSiteIds.push(walk.site.id);
|
|
18404
|
-
|
|
18515
|
+
if (counts)
|
|
18516
|
+
ref.via = ref.via.filter((f) => walk.flags.includes(f));
|
|
18405
18517
|
}
|
|
18406
18518
|
markUnresolved(node, reason, walk) {
|
|
18407
18519
|
const sf = node.getSourceFile();
|
|
@@ -19037,7 +19149,7 @@ async function runHarnessCommand(context) {
|
|
|
19037
19149
|
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.");
|
|
19038
19150
|
}
|
|
19039
19151
|
if (context.flags["github-actions"] === "true") {
|
|
19040
|
-
const { runGithubActionsAnalyze } = await import("./harness-github-actions-
|
|
19152
|
+
const { runGithubActionsAnalyze } = await import("./harness-github-actions-d0rb1wmk.js");
|
|
19041
19153
|
const result = await runGithubActionsAnalyze(rootDir, {
|
|
19042
19154
|
writeReport: (report2) => {
|
|
19043
19155
|
const normalized = normalizeHarnessReport(report2);
|
|
@@ -19183,8 +19295,8 @@ async function runHarnessCommand(context) {
|
|
|
19183
19295
|
}
|
|
19184
19296
|
const { artifacts, unknowns } = deterministicGraphItems(rootDir, promote === "all" ? undefined : promote);
|
|
19185
19297
|
tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
|
|
19186
|
-
const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-
|
|
19187
|
-
const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-
|
|
19298
|
+
const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-2rhvz7fa.js");
|
|
19299
|
+
const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-dk98sc3s.js");
|
|
19188
19300
|
let components = { runtimeAgents: [], artifacts: [], warnings: [] };
|
|
19189
19301
|
if (promote === "all" || promote === "topology" || promote === "tools") {
|
|
19190
19302
|
const { result, ctx } = extractHarnessWithContext2(rootDir);
|
|
@@ -19218,8 +19330,8 @@ async function runHarnessCommand(context) {
|
|
|
19218
19330
|
}
|
|
19219
19331
|
case "extract": {
|
|
19220
19332
|
writeHumanProgress(context, "Harness extract: tracing model call sites (no LLM, no network)...");
|
|
19221
|
-
const { extractHarnessWithContext: extractHarnessWithContext2, serializeExtractResult } = await import("./index-
|
|
19222
|
-
const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-
|
|
19333
|
+
const { extractHarnessWithContext: extractHarnessWithContext2, serializeExtractResult } = await import("./index-2rhvz7fa.js");
|
|
19334
|
+
const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-dk98sc3s.js");
|
|
19223
19335
|
const { result, ctx } = extractHarnessWithContext2(rootDir, { fresh: true });
|
|
19224
19336
|
const artifacts = deterministicArtifacts(rootDir);
|
|
19225
19337
|
tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
|
|
@@ -26642,164 +26754,1129 @@ function collectModelLiterals(rootDir) {
|
|
|
26642
26754
|
return { literals: [...found].sort(), truncated: capped || skipped };
|
|
26643
26755
|
}
|
|
26644
26756
|
|
|
26645
|
-
// src/harness-extract/
|
|
26646
|
-
var
|
|
26647
|
-
|
|
26648
|
-
|
|
26649
|
-
|
|
26650
|
-
|
|
26651
|
-
|
|
26652
|
-
|
|
26653
|
-
|
|
26654
|
-
|
|
26655
|
-
|
|
26656
|
-
|
|
26657
|
-
|
|
26658
|
-
|
|
26659
|
-
|
|
26660
|
-
if (
|
|
26661
|
-
return
|
|
26662
|
-
|
|
26663
|
-
|
|
26664
|
-
|
|
26665
|
-
|
|
26666
|
-
|
|
26667
|
-
|
|
26668
|
-
|
|
26669
|
-
|
|
26670
|
-
|
|
26671
|
-
|
|
26672
|
-
|
|
26673
|
-
|
|
26674
|
-
|
|
26675
|
-
|
|
26676
|
-
|
|
26677
|
-
|
|
26678
|
-
const fnObject = fn ? objectsOf(fn)[0] : undefined;
|
|
26679
|
-
const fnName = fnObject ? singleLiteral2(member(fnObject, "name")) : undefined;
|
|
26680
|
-
if (fnName && fnObject)
|
|
26681
|
-
return { name: fnName, path: fnObject.path, line: fnObject.line, via: "function.name" };
|
|
26682
|
-
const nameNode = member(tree, "name");
|
|
26683
|
-
const name = singleLiteral2(nameNode);
|
|
26684
|
-
const keys = (tree.children ?? []).map((child) => child.key ?? "");
|
|
26685
|
-
if (name && nameNode && keys.some((key) => DEFINITION_KEYS.has(key)))
|
|
26686
|
-
return { name, path: nameNode.path, line: nameNode.line, via: "name" };
|
|
26687
|
-
return;
|
|
26688
|
-
}
|
|
26689
|
-
function toolNamesOf(tree) {
|
|
26690
|
-
const out = { names: [], unresolved: [] };
|
|
26691
|
-
const visit = (node, inArray, names) => {
|
|
26692
|
-
if (node.kind === "array" || node.kind === "assembled" && node.text === "array") {
|
|
26693
|
-
for (const child of node.children ?? [])
|
|
26694
|
-
visit(child, true, names);
|
|
26695
|
-
return;
|
|
26696
|
-
}
|
|
26697
|
-
if (node.kind === "object") {
|
|
26698
|
-
const definition = definitionName(node);
|
|
26699
|
-
if (definition) {
|
|
26700
|
-
names.push(definition);
|
|
26701
|
-
return;
|
|
26702
|
-
}
|
|
26703
|
-
if (inArray) {
|
|
26704
|
-
out.unresolved.push({ ...node, note: "tool object without a literal name" });
|
|
26705
|
-
return;
|
|
26757
|
+
// src/harness-extract/emit-tools.ts
|
|
26758
|
+
var import_typescript12 = __toESM(require_typescript(), 1);
|
|
26759
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
26760
|
+
import { join as join14, posix as posix3 } from "node:path";
|
|
26761
|
+
|
|
26762
|
+
// src/harness-extract/enumerators/common.ts
|
|
26763
|
+
var import_typescript10 = __toESM(require_typescript(), 1);
|
|
26764
|
+
import { readdirSync as readdirSync8, readFileSync as readFileSync15 } from "node:fs";
|
|
26765
|
+
import { dirname as dirname10, join as join13, posix as posix2, relative as relative10 } from "node:path";
|
|
26766
|
+
var cache = new WeakMap;
|
|
26767
|
+
var SKIP = new Set(["node_modules", "dist", "build", "out", "vendor", "coverage", "__pycache__"]);
|
|
26768
|
+
var TEST_PATH4 = /(?:^|\/)(?:test|tests|__tests__|test-fixtures|fixtures?|__fixtures__|__mocks__|e2e)\/|\.(?:test|spec)\.[cm]?[jt]sx?$/i;
|
|
26769
|
+
var EVAL_PATH2 = /(?:^|\/)evals?\/|\.evals?\.[cm]?[jt]sx?$/i;
|
|
26770
|
+
function enumerationRepository(ctx) {
|
|
26771
|
+
const existing = cache.get(ctx);
|
|
26772
|
+
if (existing)
|
|
26773
|
+
return existing;
|
|
26774
|
+
const files = [];
|
|
26775
|
+
const walk = (dir) => {
|
|
26776
|
+
for (const entry of readdirSync8(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
26777
|
+
const abs = join13(dir, entry.name);
|
|
26778
|
+
if (entry.isDirectory()) {
|
|
26779
|
+
if (!entry.name.startsWith(".") && !SKIP.has(entry.name))
|
|
26780
|
+
walk(abs);
|
|
26781
|
+
} else if (entry.isFile() && /\.(?:[cm]?[jt]sx?|py|jsonc?|toml)$/.test(entry.name) && !/\.d\.[cm]?ts$/.test(entry.name)) {
|
|
26782
|
+
const path = relative10(ctx.rootDir, abs).split("\\").join("/");
|
|
26783
|
+
try {
|
|
26784
|
+
const text = readFileSync15(abs, "utf8");
|
|
26785
|
+
if (text.length > 1024 * 1024)
|
|
26786
|
+
continue;
|
|
26787
|
+
const source = ctx.programFor(path)?.getSourceFile(abs) ?? import_typescript10.default.createSourceFile(abs, text, import_typescript10.default.ScriptTarget.Latest, true, path.endsWith("tsx") ? import_typescript10.default.ScriptKind.TSX : import_typescript10.default.ScriptKind.TS);
|
|
26788
|
+
files.push({ path, text, source });
|
|
26789
|
+
} catch {}
|
|
26706
26790
|
}
|
|
26707
|
-
|
|
26708
|
-
|
|
26709
|
-
|
|
26710
|
-
|
|
26711
|
-
|
|
26712
|
-
|
|
26713
|
-
|
|
26714
|
-
|
|
26715
|
-
|
|
26716
|
-
|
|
26717
|
-
|
|
26718
|
-
|
|
26719
|
-
|
|
26791
|
+
}
|
|
26792
|
+
};
|
|
26793
|
+
walk(ctx.rootDir);
|
|
26794
|
+
const workers = [];
|
|
26795
|
+
const paths = new Set(files.map((file) => file.path));
|
|
26796
|
+
const closure = (main) => {
|
|
26797
|
+
const found = new Set, pending = [main];
|
|
26798
|
+
for (let index = 0;index < pending.length; index++) {
|
|
26799
|
+
const path = pending[index];
|
|
26800
|
+
if (found.has(path))
|
|
26801
|
+
continue;
|
|
26802
|
+
found.add(path);
|
|
26803
|
+
const file = files.find((entry) => entry.path === path);
|
|
26804
|
+
if (!file)
|
|
26805
|
+
continue;
|
|
26806
|
+
for (const ref of import_typescript10.default.preProcessFile(file.text, true, true).importedFiles) {
|
|
26807
|
+
if (!ref.fileName.startsWith("."))
|
|
26808
|
+
continue;
|
|
26809
|
+
const base = posix2.normalize(posix2.join(posix2.dirname(path), ref.fileName)).replace(/\.[cm]?js$/, "");
|
|
26810
|
+
const target = [base, ...[".ts", ".tsx", ".js", ".mjs", "/index.ts", "/index.js"].map((suffix) => base + suffix)].find((candidate) => paths.has(candidate));
|
|
26811
|
+
if (target)
|
|
26812
|
+
pending.push(target);
|
|
26720
26813
|
}
|
|
26721
|
-
names.push(...record.values());
|
|
26722
|
-
return;
|
|
26723
26814
|
}
|
|
26724
|
-
|
|
26725
|
-
|
|
26726
|
-
|
|
26727
|
-
|
|
26815
|
+
return found;
|
|
26816
|
+
};
|
|
26817
|
+
for (const file of files)
|
|
26818
|
+
if (/(?:^|\/)wrangler(?:\.[\w.-]+)?\.(?:jsonc?|toml)$/.test(file.path)) {
|
|
26819
|
+
try {
|
|
26820
|
+
const config2 = file.path.endsWith(".toml") ? parse(file.text) : JSON.parse(stripJsonc(file.text));
|
|
26821
|
+
const variants = [["default", config2], ...Object.entries(config2.env ?? {}).map(([name, section]) => [name, { ...config2, ...section, queues: section.queues, workflows: section.workflows }])];
|
|
26822
|
+
for (const [environment, section] of variants) {
|
|
26823
|
+
if (typeof section.main !== "string" || isTestWorkerConfig({ path: file.path, name: section.name, mains: [section.main] }))
|
|
26824
|
+
continue;
|
|
26825
|
+
const main = posix2.normalize(posix2.join(dirname10(file.path), section.main));
|
|
26826
|
+
workers.push({ id: `${file.path}#${environment}`, main, cron: Boolean(section.triggers?.crons?.length), queueBindings: new Set((section.queues?.producers ?? []).flatMap((producer) => typeof producer.binding === "string" ? [producer.binding] : [])), workflowClasses: (section.workflows ?? []).flatMap((binding) => typeof binding.class_name === "string" && !binding.script_name ? [binding.class_name] : []), files: closure(main) });
|
|
26827
|
+
}
|
|
26828
|
+
} catch {}
|
|
26728
26829
|
}
|
|
26729
|
-
|
|
26830
|
+
const queueBindingsFor = (path) => {
|
|
26831
|
+
const owners = workers.filter((worker) => worker.files.has(path));
|
|
26832
|
+
return new Set(owners[0] ? [...owners[0].queueBindings].filter((binding) => owners.every((worker) => worker.queueBindings.has(binding))) : []);
|
|
26730
26833
|
};
|
|
26731
|
-
|
|
26732
|
-
|
|
26834
|
+
const reach = buildImportGraphReachability(ctx.rootDir);
|
|
26835
|
+
const repo = { files, workers, queueBindingsFor, cronEntrypoints: new Set(workers.filter((worker) => worker.cron).map((worker) => worker.main)), deployedFiles: reach.inProd, status: (path) => reach.inProd.has(path) || reach.reachable.has(path) ? "reachable" : "defined_only" };
|
|
26836
|
+
cache.set(ctx, repo);
|
|
26837
|
+
return repo;
|
|
26733
26838
|
}
|
|
26734
|
-
|
|
26735
|
-
|
|
26736
|
-
var PROMPT_ROLES = new Set(["system", "user", "messages", "prompt", "instructions", "questions"]);
|
|
26737
|
-
var MAX_HELPER_CALLERS = 200;
|
|
26738
|
-
var MAX_DERIVED = 5000;
|
|
26739
|
-
var MAX_CALLER_CHAIN = 3;
|
|
26740
|
-
var cache = new Map;
|
|
26741
|
-
function clearExtractCache() {
|
|
26742
|
-
cache.clear();
|
|
26839
|
+
function lineOf5(node) {
|
|
26840
|
+
return node.getSourceFile().getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
26743
26841
|
}
|
|
26744
|
-
function
|
|
26745
|
-
|
|
26842
|
+
function nameOf(node) {
|
|
26843
|
+
if (!node)
|
|
26844
|
+
return;
|
|
26845
|
+
if (import_typescript10.default.isComputedPropertyName(node) && import_typescript10.default.isStringLiteralLike(node.expression))
|
|
26846
|
+
return node.expression.text;
|
|
26847
|
+
return import_typescript10.default.isIdentifier(node) || import_typescript10.default.isStringLiteralLike(node) || import_typescript10.default.isNumericLiteral(node) ? node.text : undefined;
|
|
26746
26848
|
}
|
|
26747
|
-
function
|
|
26748
|
-
|
|
26749
|
-
|
|
26750
|
-
const key = `${root}\x00${JSON.stringify(rest)}`;
|
|
26751
|
-
const fingerprint = sourceFingerprint(root, rest);
|
|
26752
|
-
const cached = fresh ? undefined : cache.get(key);
|
|
26753
|
-
if (cached && cached.fingerprint === fingerprint)
|
|
26754
|
-
return cached.output;
|
|
26755
|
-
const output = runExtract(root, options);
|
|
26756
|
-
cache.set(key, { output, fingerprint });
|
|
26757
|
-
return output;
|
|
26849
|
+
function visit(node, fn) {
|
|
26850
|
+
fn(node);
|
|
26851
|
+
import_typescript10.default.forEachChild(node, (child) => visit(child, fn));
|
|
26758
26852
|
}
|
|
26759
|
-
function
|
|
26760
|
-
|
|
26761
|
-
const ref = { path: relPath(rootDir, source.fileName), start: node.getStart(source), end: node.getEnd(), line: lineOf(node) };
|
|
26762
|
-
if (key !== undefined)
|
|
26763
|
-
ref.key = key;
|
|
26764
|
-
Object.defineProperty(ref, "node", { value: node, enumerable: false });
|
|
26765
|
-
return ref;
|
|
26853
|
+
function componentId(kind, path, name) {
|
|
26854
|
+
return `${kind}:${path}:${name}`;
|
|
26766
26855
|
}
|
|
26767
|
-
function
|
|
26768
|
-
|
|
26769
|
-
const name = functionName(fn);
|
|
26770
|
-
if (name)
|
|
26771
|
-
return { fn, name };
|
|
26772
|
-
}
|
|
26773
|
-
return;
|
|
26856
|
+
function artifact(type, name, file, node, reason, status) {
|
|
26857
|
+
return { id: componentId(type, file.path, name), type, name, scope: "shared", sourcePath: file.path, usedByAgentIds: [], confidence: 1, evidence: [{ path: file.path, line: lineOf5(node), reason }], status };
|
|
26774
26858
|
}
|
|
26775
|
-
function
|
|
26776
|
-
|
|
26777
|
-
const owner = cls && (fn.parent === cls || fn.parent && fn.parent.parent === cls) ? className(cls) : undefined;
|
|
26778
|
-
return owner ? `${owner}.${name}` : name;
|
|
26859
|
+
function agent(name, file, node, reason, status) {
|
|
26860
|
+
return { id: componentId("agent", file.path, name), name, kind: "runtime_agent", root: ".", entrypointIds: [], channelAdapterIds: [], artifactIds: [], identityNamespaceIds: [], deploymentIds: [], frameworkIds: [], modelProviderIds: [], confidence: 1, evidence: [{ path: file.path, line: lineOf5(node), reason }], status };
|
|
26779
26861
|
}
|
|
26780
|
-
function
|
|
26781
|
-
|
|
26782
|
-
const object = objectLiteralOf2(fn);
|
|
26783
|
-
if (object) {
|
|
26784
|
-
const holder = object.parent && import_typescript10.default.isVariableDeclaration(object.parent) && import_typescript10.default.isIdentifier(object.parent.name) ? object.parent.name.text : `L${lineOf(object)}`;
|
|
26785
|
-
parts.unshift(holder);
|
|
26786
|
-
}
|
|
26787
|
-
for (let outer = namedEnclosingFunction(object ?? fn);outer; outer = namedEnclosingFunction(outer.fn))
|
|
26788
|
-
parts.unshift(qualifiedName(outer.fn, outer.name));
|
|
26789
|
-
return `${relPath(rootDir, fn.getSourceFile().fileName)}#${parts.join(".")}`;
|
|
26862
|
+
function emptyResult() {
|
|
26863
|
+
return { runtimeAgents: [], artifacts: [], warnings: [] };
|
|
26790
26864
|
}
|
|
26791
|
-
function
|
|
26792
|
-
const
|
|
26793
|
-
return
|
|
26865
|
+
function stableResult(result) {
|
|
26866
|
+
const unique2 = (values) => [...new Map(values.map((x) => [x.id, x])).values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
26867
|
+
return { runtimeAgents: unique2(result.runtimeAgents), artifacts: unique2(result.artifacts), warnings: [...new Set(result.warnings)].sort() };
|
|
26794
26868
|
}
|
|
26795
|
-
|
|
26796
|
-
|
|
26797
|
-
|
|
26798
|
-
|
|
26799
|
-
|
|
26800
|
-
|
|
26801
|
-
|
|
26802
|
-
|
|
26869
|
+
|
|
26870
|
+
// src/harness-extract/tool-owners.ts
|
|
26871
|
+
var import_typescript11 = __toESM(require_typescript(), 1);
|
|
26872
|
+
var AGENT_BASES3 = new Set(["Think", "Agent", "AIChatAgent"]);
|
|
26873
|
+
var ROLE_FIELD = /^(?:role|roleId|roleName|kind|type|id|slug|agentRole|subagentRole)$/i;
|
|
26874
|
+
var MAX_HOPS = 10;
|
|
26875
|
+
var MIN_ALLOWLIST = 3;
|
|
26876
|
+
var TOOL_LIST_PARAM = /^(?:allow(?:list|ed)?|allowedTools|toolNames|tools|requested)$/i;
|
|
26877
|
+
var ALLOWLIST_SHARE = 0.6;
|
|
26878
|
+
function sourceFilesOf(ctx) {
|
|
26879
|
+
const out = [];
|
|
26880
|
+
for (const program of ctx.programs) {
|
|
26881
|
+
for (const source of program.getSourceFiles()) {
|
|
26882
|
+
if (source.isDeclarationFile || /[\\/]node_modules[\\/]/.test(source.fileName))
|
|
26883
|
+
continue;
|
|
26884
|
+
const rel2 = relPath(ctx.rootDir, source.fileName);
|
|
26885
|
+
if (rel2.startsWith(".."))
|
|
26886
|
+
continue;
|
|
26887
|
+
if (ctx.programFor(source.fileName) !== program)
|
|
26888
|
+
continue;
|
|
26889
|
+
out.push({ program, source, rel: rel2 });
|
|
26890
|
+
}
|
|
26891
|
+
}
|
|
26892
|
+
return out;
|
|
26893
|
+
}
|
|
26894
|
+
function isOneOffScript(rel2, reach) {
|
|
26895
|
+
if (!/^scripts\//.test(rel2))
|
|
26896
|
+
return false;
|
|
26897
|
+
return !reach?.inProd.has(rel2);
|
|
26898
|
+
}
|
|
26899
|
+
|
|
26900
|
+
class ToolOwners {
|
|
26901
|
+
ctx;
|
|
26902
|
+
classes = [];
|
|
26903
|
+
byDeclaration = new Map;
|
|
26904
|
+
references = new Map;
|
|
26905
|
+
edges = new Map;
|
|
26906
|
+
allowlists;
|
|
26907
|
+
constructor(ctx) {
|
|
26908
|
+
this.ctx = ctx;
|
|
26909
|
+
const memo = createFrameworkMemo();
|
|
26910
|
+
for (const { program, source, rel: rel2 } of sourceFilesOf(ctx)) {
|
|
26911
|
+
if (isTestPath(rel2))
|
|
26912
|
+
continue;
|
|
26913
|
+
const checker = program.getTypeChecker();
|
|
26914
|
+
const visit2 = (node) => {
|
|
26915
|
+
if ((import_typescript11.default.isClassDeclaration(node) || import_typescript11.default.isClassExpression(node)) && node.name) {
|
|
26916
|
+
let info;
|
|
26917
|
+
try {
|
|
26918
|
+
info = frameworkBaseOf(node, checker, memo);
|
|
26919
|
+
} catch {
|
|
26920
|
+
info = undefined;
|
|
26921
|
+
}
|
|
26922
|
+
if (info?.base && AGENT_BASES3.has(info.base)) {
|
|
26923
|
+
const agent2 = {
|
|
26924
|
+
name: node.name.text,
|
|
26925
|
+
path: rel2,
|
|
26926
|
+
line: lineOf(node.name),
|
|
26927
|
+
abstract: Boolean(import_typescript11.default.getCombinedModifierFlags(node) & import_typescript11.default.ModifierFlags.Abstract),
|
|
26928
|
+
base: info.base,
|
|
26929
|
+
baseModule: info.module,
|
|
26930
|
+
parent: superclassOf(node, checker),
|
|
26931
|
+
declaration: node,
|
|
26932
|
+
fields: classFields(node),
|
|
26933
|
+
methods: new Set(node.members.filter((member) => import_typescript11.default.isMethodDeclaration(member) || import_typescript11.default.isGetAccessorDeclaration(member)).map((member) => propertyNameText(member.name) ?? ""))
|
|
26934
|
+
};
|
|
26935
|
+
this.classes.push(agent2);
|
|
26936
|
+
this.byDeclaration.set(node, agent2);
|
|
26937
|
+
}
|
|
26938
|
+
}
|
|
26939
|
+
import_typescript11.default.forEachChild(node, visit2);
|
|
26940
|
+
};
|
|
26941
|
+
visit2(source);
|
|
26942
|
+
}
|
|
26943
|
+
}
|
|
26944
|
+
concrete() {
|
|
26945
|
+
return this.classes.filter((agent2) => !agent2.abstract);
|
|
26946
|
+
}
|
|
26947
|
+
fieldOf(name, field) {
|
|
26948
|
+
let current = this.classes.find((agent2) => agent2.name === name);
|
|
26949
|
+
for (let hops = 0;current && hops < 10; hops += 1) {
|
|
26950
|
+
if (field in current.fields)
|
|
26951
|
+
return current.fields[field];
|
|
26952
|
+
current = current.parent ? this.byDeclaration.get(current.parent) : undefined;
|
|
26953
|
+
}
|
|
26954
|
+
return;
|
|
26955
|
+
}
|
|
26956
|
+
inheritors(owner, method) {
|
|
26957
|
+
const out = [];
|
|
26958
|
+
for (const agent2 of this.classes) {
|
|
26959
|
+
if (agent2.abstract)
|
|
26960
|
+
continue;
|
|
26961
|
+
let current = agent2;
|
|
26962
|
+
let ok = false;
|
|
26963
|
+
for (let hops = 0;current && hops < 10; hops += 1) {
|
|
26964
|
+
if (current === owner) {
|
|
26965
|
+
ok = true;
|
|
26966
|
+
break;
|
|
26967
|
+
}
|
|
26968
|
+
if (method && current.methods.has(method))
|
|
26969
|
+
break;
|
|
26970
|
+
current = current.parent ? this.byDeclaration.get(current.parent) : undefined;
|
|
26971
|
+
}
|
|
26972
|
+
if (ok)
|
|
26973
|
+
out.push(agent2.name);
|
|
26974
|
+
}
|
|
26975
|
+
return out;
|
|
26976
|
+
}
|
|
26977
|
+
ownersOf(node, program) {
|
|
26978
|
+
const sets = { direct: new Set, rpc: new Set, open: new Set };
|
|
26979
|
+
const start = this.positionOf(node, program);
|
|
26980
|
+
if (!start)
|
|
26981
|
+
return { direct: [], rpc: [], open: [] };
|
|
26982
|
+
const seen = new Set;
|
|
26983
|
+
let frontier = [{ position: start, via: "direct" }];
|
|
26984
|
+
for (let hops = 0;frontier.length > 0 && hops <= MAX_HOPS; hops += 1) {
|
|
26985
|
+
const next = [];
|
|
26986
|
+
for (const { position, via } of frontier) {
|
|
26987
|
+
for (const agent2 of position.agents)
|
|
26988
|
+
sets[via].add(agent2);
|
|
26989
|
+
const key = `${position.id}|${via}`;
|
|
26990
|
+
if (seen.has(key))
|
|
26991
|
+
continue;
|
|
26992
|
+
seen.add(key);
|
|
26993
|
+
for (const edge of this.edgesOf(position, program))
|
|
26994
|
+
next.push({ position: edge.position, via: combineVia(via, edge.via) });
|
|
26995
|
+
}
|
|
26996
|
+
frontier = next;
|
|
26997
|
+
}
|
|
26998
|
+
const direct = [...sets.direct].sort();
|
|
26999
|
+
return {
|
|
27000
|
+
direct,
|
|
27001
|
+
rpc: [...sets.rpc].filter((name) => !sets.direct.has(name)).sort(),
|
|
27002
|
+
open: [...sets.open].filter((name) => !sets.direct.has(name)).sort()
|
|
27003
|
+
};
|
|
27004
|
+
}
|
|
27005
|
+
positionOf(node, program) {
|
|
27006
|
+
let method;
|
|
27007
|
+
for (let current = node;current; current = current.parent) {
|
|
27008
|
+
if ((import_typescript11.default.isMethodDeclaration(current) || import_typescript11.default.isGetAccessorDeclaration(current) || import_typescript11.default.isPropertyDeclaration(current)) && import_typescript11.default.isClassLike(current.parent) && import_typescript11.default.isIdentifier(current.name)) {
|
|
27009
|
+
method = current.name;
|
|
27010
|
+
}
|
|
27011
|
+
if (import_typescript11.default.isClassLike(current)) {
|
|
27012
|
+
const agent2 = this.byDeclaration.get(current);
|
|
27013
|
+
if (!agent2)
|
|
27014
|
+
return current.name ? this.holderPosition(current.name, program) : undefined;
|
|
27015
|
+
const guards = fieldGuards(node, current);
|
|
27016
|
+
const agents = this.inheritors(agent2, method?.text).filter((name) => guards.every((guard) => guard.holds(this.fieldOf(name, guard.field))));
|
|
27017
|
+
const anchor = method ?? current;
|
|
27018
|
+
return { id: nodeId(anchor), anchor, agents, agent: agent2, method };
|
|
27019
|
+
}
|
|
27020
|
+
}
|
|
27021
|
+
const holder = holderName(node);
|
|
27022
|
+
return holder ? this.holderPosition(holder, program) : undefined;
|
|
27023
|
+
}
|
|
27024
|
+
holderPosition(name, program) {
|
|
27025
|
+
const target = valueDeclaration(resolvedSymbol(name, program.getTypeChecker())) ?? name.parent;
|
|
27026
|
+
return { id: nodeId(target), anchor: target, agents: [], holder: name };
|
|
27027
|
+
}
|
|
27028
|
+
edgesOf(position, program) {
|
|
27029
|
+
const cached = this.edges.get(position.id);
|
|
27030
|
+
if (cached)
|
|
27031
|
+
return cached;
|
|
27032
|
+
const out = [];
|
|
27033
|
+
this.edges.set(position.id, out);
|
|
27034
|
+
const checker = program.getTypeChecker();
|
|
27035
|
+
if (position.holder) {
|
|
27036
|
+
for (const reference of this.referencesOf(program, position.holder.text)) {
|
|
27037
|
+
if (reference === position.holder || isDeclarationName(reference))
|
|
27038
|
+
continue;
|
|
27039
|
+
if (valueDeclaration(resolvedSymbol(reference, checker)) !== position.anchor)
|
|
27040
|
+
continue;
|
|
27041
|
+
const next = this.positionOf(reference, program);
|
|
27042
|
+
if (next)
|
|
27043
|
+
out.push({ position: next, via: "direct" });
|
|
27044
|
+
}
|
|
27045
|
+
} else if (position.agent && position.method) {
|
|
27046
|
+
const owner = position.agent;
|
|
27047
|
+
const name = position.method.text;
|
|
27048
|
+
const unique2 = this.classes.filter((agent2) => agent2.methods.has(name)).length === 1 && owner.methods.has(name);
|
|
27049
|
+
const declaration = position.method.parent;
|
|
27050
|
+
const takesToolList = import_typescript11.default.isMethodDeclaration(declaration) && declaration.parameters.some((param) => import_typescript11.default.isIdentifier(param.name) && TOOL_LIST_PARAM.test(param.name.text));
|
|
27051
|
+
for (const reference of this.referencesOf(program, name)) {
|
|
27052
|
+
const access = reference.parent;
|
|
27053
|
+
if (!access || !import_typescript11.default.isPropertyAccessExpression(access) || access.name !== reference)
|
|
27054
|
+
continue;
|
|
27055
|
+
if (access.expression.kind === import_typescript11.default.SyntaxKind.ThisKeyword) {
|
|
27056
|
+
if (!isWithin3(reference, owner.declaration))
|
|
27057
|
+
continue;
|
|
27058
|
+
const next2 = this.positionOf(reference, program);
|
|
27059
|
+
if (next2)
|
|
27060
|
+
out.push({ position: { ...next2, agents: [] }, via: "direct" });
|
|
27061
|
+
continue;
|
|
27062
|
+
}
|
|
27063
|
+
if (!unique2 || !import_typescript11.default.isCallExpression(access.parent) || access.parent.expression !== access)
|
|
27064
|
+
continue;
|
|
27065
|
+
const resolved = valueDeclaration(resolvedSymbol(reference, checker));
|
|
27066
|
+
if (resolved && resolved.parent !== owner.declaration)
|
|
27067
|
+
continue;
|
|
27068
|
+
const next = this.positionOf(reference, program);
|
|
27069
|
+
if (next)
|
|
27070
|
+
out.push({ position: next, via: takesToolList ? "open" : "rpc" });
|
|
27071
|
+
}
|
|
27072
|
+
}
|
|
27073
|
+
return out;
|
|
27074
|
+
}
|
|
27075
|
+
referencesOf(program, name) {
|
|
27076
|
+
let index = this.references.get(program);
|
|
27077
|
+
if (!index) {
|
|
27078
|
+
index = new Map;
|
|
27079
|
+
for (const source of program.getSourceFiles()) {
|
|
27080
|
+
if (source.isDeclarationFile || /[\\/]node_modules[\\/]/.test(source.fileName))
|
|
27081
|
+
continue;
|
|
27082
|
+
if (isTestPath(relPath(this.ctx.rootDir, source.fileName)))
|
|
27083
|
+
continue;
|
|
27084
|
+
const visit2 = (node) => {
|
|
27085
|
+
if (import_typescript11.default.isIdentifier(node)) {
|
|
27086
|
+
const list = index.get(node.text);
|
|
27087
|
+
if (list)
|
|
27088
|
+
list.push(node);
|
|
27089
|
+
else
|
|
27090
|
+
index.set(node.text, [node]);
|
|
27091
|
+
}
|
|
27092
|
+
import_typescript11.default.forEachChild(node, visit2);
|
|
27093
|
+
};
|
|
27094
|
+
visit2(source);
|
|
27095
|
+
}
|
|
27096
|
+
this.references.set(program, index);
|
|
27097
|
+
}
|
|
27098
|
+
return index.get(name) ?? [];
|
|
27099
|
+
}
|
|
27100
|
+
indexAllowlists(knownTools) {
|
|
27101
|
+
this.allowlists = [];
|
|
27102
|
+
for (const { program, source, rel: rel2 } of sourceFilesOf(this.ctx)) {
|
|
27103
|
+
if (isTestPath(rel2))
|
|
27104
|
+
continue;
|
|
27105
|
+
const checker = program.getTypeChecker();
|
|
27106
|
+
const visit2 = (node) => {
|
|
27107
|
+
if (import_typescript11.default.isArrayLiteralExpression(node) && (!node.parent || !import_typescript11.default.isSpreadElement(node.parent))) {
|
|
27108
|
+
const entries = stringEntries(node, checker);
|
|
27109
|
+
const named = entries.filter((entry) => knownTools.has(entry) || entry.endsWith("*") && entry.length > 2);
|
|
27110
|
+
if (entries.length >= MIN_ALLOWLIST && named.length / entries.length >= ALLOWLIST_SHARE) {
|
|
27111
|
+
const agents = this.allowlistOwners(node, program);
|
|
27112
|
+
if (agents.length > 0)
|
|
27113
|
+
this.allowlists.push({ entries, agents, path: rel2 });
|
|
27114
|
+
}
|
|
27115
|
+
}
|
|
27116
|
+
import_typescript11.default.forEachChild(node, visit2);
|
|
27117
|
+
};
|
|
27118
|
+
visit2(source);
|
|
27119
|
+
}
|
|
27120
|
+
}
|
|
27121
|
+
allowlisted() {
|
|
27122
|
+
return new Set((this.allowlists ?? []).flatMap((list) => list.agents));
|
|
27123
|
+
}
|
|
27124
|
+
agentsFor(tool, owners, allowlistApplies = () => true) {
|
|
27125
|
+
const restricted = this.allowlisted();
|
|
27126
|
+
const out = new Set([...owners.direct, ...owners.open, ...owners.rpc.filter((agent2) => !restricted.has(agent2)), ...this.allowlistAgents(tool, allowlistApplies)]);
|
|
27127
|
+
return [...out].sort();
|
|
27128
|
+
}
|
|
27129
|
+
allowlistAgents(tool, applies = () => true) {
|
|
27130
|
+
const out = new Set;
|
|
27131
|
+
for (const list of this.allowlists ?? []) {
|
|
27132
|
+
if (!applies(list.path))
|
|
27133
|
+
continue;
|
|
27134
|
+
if (list.entries.some((entry) => entry === tool || entry.endsWith("*") && tool.startsWith(entry.slice(0, -1)))) {
|
|
27135
|
+
for (const agent2 of list.agents)
|
|
27136
|
+
out.add(agent2);
|
|
27137
|
+
}
|
|
27138
|
+
}
|
|
27139
|
+
return [...out].sort();
|
|
27140
|
+
}
|
|
27141
|
+
allowlistOwners(list, program) {
|
|
27142
|
+
const keys = new Set;
|
|
27143
|
+
const direct = new Set;
|
|
27144
|
+
const checker = program.getTypeChecker();
|
|
27145
|
+
const visited = new Set;
|
|
27146
|
+
const walk = (node, hops) => {
|
|
27147
|
+
if (hops > 4 || visited.has(node))
|
|
27148
|
+
return;
|
|
27149
|
+
visited.add(node);
|
|
27150
|
+
for (let current = node.parent;current; current = current.parent) {
|
|
27151
|
+
if (import_typescript11.default.isClassLike(current)) {
|
|
27152
|
+
const agent2 = this.byDeclaration.get(current);
|
|
27153
|
+
if (agent2)
|
|
27154
|
+
for (const name of this.inheritors(agent2, undefined))
|
|
27155
|
+
direct.add(name);
|
|
27156
|
+
return;
|
|
27157
|
+
}
|
|
27158
|
+
if (import_typescript11.default.isFunctionLike(current))
|
|
27159
|
+
return;
|
|
27160
|
+
if (import_typescript11.default.isPropertyAssignment(current) || import_typescript11.default.isShorthandPropertyAssignment(current)) {
|
|
27161
|
+
const key = propertyNameText(current.name);
|
|
27162
|
+
if (key)
|
|
27163
|
+
keys.add(key);
|
|
27164
|
+
}
|
|
27165
|
+
if (import_typescript11.default.isObjectLiteralExpression(current)) {
|
|
27166
|
+
for (const property of current.properties) {
|
|
27167
|
+
if (!import_typescript11.default.isPropertyAssignment(property) || !ROLE_FIELD.test(propertyNameText(property.name) ?? ""))
|
|
27168
|
+
continue;
|
|
27169
|
+
const value = unwrap(property.initializer);
|
|
27170
|
+
if (import_typescript11.default.isStringLiteral(value))
|
|
27171
|
+
keys.add(value.text);
|
|
27172
|
+
}
|
|
27173
|
+
}
|
|
27174
|
+
if (import_typescript11.default.isVariableDeclaration(current) && import_typescript11.default.isIdentifier(current.name)) {
|
|
27175
|
+
const target = current;
|
|
27176
|
+
for (const reference of this.referencesOf(program, current.name.text)) {
|
|
27177
|
+
if (reference === current.name || isDeclarationName(reference))
|
|
27178
|
+
continue;
|
|
27179
|
+
if (valueDeclaration(resolvedSymbol(reference, checker)) !== target)
|
|
27180
|
+
continue;
|
|
27181
|
+
walk(reference, hops + 1);
|
|
27182
|
+
}
|
|
27183
|
+
return;
|
|
27184
|
+
}
|
|
27185
|
+
}
|
|
27186
|
+
};
|
|
27187
|
+
walk(list, 0);
|
|
27188
|
+
for (const agent2 of this.concrete()) {
|
|
27189
|
+
if (Object.entries(agent2.fields).some(([field, value]) => ROLE_FIELD.test(field) && keys.has(value)))
|
|
27190
|
+
direct.add(agent2.name);
|
|
27191
|
+
}
|
|
27192
|
+
return [...direct].sort();
|
|
27193
|
+
}
|
|
27194
|
+
}
|
|
27195
|
+
function combineVia(current, edge) {
|
|
27196
|
+
if (current === "open" || edge === "open")
|
|
27197
|
+
return "open";
|
|
27198
|
+
if (current === "rpc" || edge === "rpc")
|
|
27199
|
+
return "rpc";
|
|
27200
|
+
return "direct";
|
|
27201
|
+
}
|
|
27202
|
+
function nodeId(node) {
|
|
27203
|
+
return `${node.getSourceFile().fileName}:${node.getStart()}`;
|
|
27204
|
+
}
|
|
27205
|
+
function fieldGuards(node, cls) {
|
|
27206
|
+
const out = [];
|
|
27207
|
+
let child = node;
|
|
27208
|
+
for (let current = node.parent;current && current !== cls; child = current, current = current.parent) {
|
|
27209
|
+
let condition;
|
|
27210
|
+
let whenTrue;
|
|
27211
|
+
if (import_typescript11.default.isConditionalExpression(current) && child !== current.condition) {
|
|
27212
|
+
condition = current.condition;
|
|
27213
|
+
whenTrue = child === current.whenTrue;
|
|
27214
|
+
} else if (import_typescript11.default.isIfStatement(current) && child !== current.expression) {
|
|
27215
|
+
condition = current.expression;
|
|
27216
|
+
whenTrue = child === current.thenStatement;
|
|
27217
|
+
}
|
|
27218
|
+
if (!condition || whenTrue === undefined)
|
|
27219
|
+
continue;
|
|
27220
|
+
const test = unwrap(condition);
|
|
27221
|
+
if (!import_typescript11.default.isBinaryExpression(test))
|
|
27222
|
+
continue;
|
|
27223
|
+
const op = test.operatorToken.kind;
|
|
27224
|
+
const equal = op === import_typescript11.default.SyntaxKind.EqualsEqualsEqualsToken || op === import_typescript11.default.SyntaxKind.EqualsEqualsToken;
|
|
27225
|
+
const notEqual = op === import_typescript11.default.SyntaxKind.ExclamationEqualsEqualsToken || op === import_typescript11.default.SyntaxKind.ExclamationEqualsToken;
|
|
27226
|
+
if (!equal && !notEqual)
|
|
27227
|
+
continue;
|
|
27228
|
+
const sides = [unwrap(test.left), unwrap(test.right)];
|
|
27229
|
+
const access = sides.find((side) => import_typescript11.default.isPropertyAccessExpression(side) && side.expression.kind === import_typescript11.default.SyntaxKind.ThisKeyword);
|
|
27230
|
+
const literal = sides.find((side) => import_typescript11.default.isStringLiteral(side));
|
|
27231
|
+
if (!access || !literal)
|
|
27232
|
+
continue;
|
|
27233
|
+
const wantEqual = equal === whenTrue;
|
|
27234
|
+
const value = literal.text;
|
|
27235
|
+
out.push({ field: access.name.text, holds: (actual) => actual === undefined || actual === value === wantEqual });
|
|
27236
|
+
}
|
|
27237
|
+
return out;
|
|
27238
|
+
}
|
|
27239
|
+
function isWithin3(node, container) {
|
|
27240
|
+
for (let current = node;current; current = current.parent)
|
|
27241
|
+
if (current === container)
|
|
27242
|
+
return true;
|
|
27243
|
+
return false;
|
|
27244
|
+
}
|
|
27245
|
+
function superclassOf(node, checker) {
|
|
27246
|
+
const heritage = node.heritageClauses?.find((clause) => clause.token === import_typescript11.default.SyntaxKind.ExtendsKeyword)?.types[0];
|
|
27247
|
+
if (!heritage)
|
|
27248
|
+
return;
|
|
27249
|
+
const expression = unwrap(heritage.expression);
|
|
27250
|
+
const declaration = valueDeclaration(resolvedSymbol(import_typescript11.default.isPropertyAccessExpression(expression) ? expression.name : expression, checker));
|
|
27251
|
+
return declaration && (import_typescript11.default.isClassDeclaration(declaration) || import_typescript11.default.isClassExpression(declaration)) ? declaration : undefined;
|
|
27252
|
+
}
|
|
27253
|
+
function classFields(node) {
|
|
27254
|
+
const fields = {};
|
|
27255
|
+
for (const member of node.members) {
|
|
27256
|
+
if (!import_typescript11.default.isPropertyDeclaration(member) || !member.initializer)
|
|
27257
|
+
continue;
|
|
27258
|
+
const name = propertyNameText(member.name);
|
|
27259
|
+
if (!name)
|
|
27260
|
+
continue;
|
|
27261
|
+
const value = unwrap(member.initializer);
|
|
27262
|
+
if (import_typescript11.default.isStringLiteral(value) || import_typescript11.default.isNoSubstitutionTemplateLiteral(value))
|
|
27263
|
+
fields[name] = value.text;
|
|
27264
|
+
else if (value.kind === import_typescript11.default.SyntaxKind.TrueKeyword)
|
|
27265
|
+
fields[name] = "true";
|
|
27266
|
+
else if (value.kind === import_typescript11.default.SyntaxKind.FalseKeyword)
|
|
27267
|
+
fields[name] = "false";
|
|
27268
|
+
}
|
|
27269
|
+
return fields;
|
|
27270
|
+
}
|
|
27271
|
+
function holderName(node) {
|
|
27272
|
+
let found;
|
|
27273
|
+
for (let current = node.parent;current; current = current.parent) {
|
|
27274
|
+
if (import_typescript11.default.isFunctionDeclaration(current) && current.name)
|
|
27275
|
+
return current.name;
|
|
27276
|
+
if (import_typescript11.default.isVariableDeclaration(current) && import_typescript11.default.isIdentifier(current.name)) {
|
|
27277
|
+
found = current.name;
|
|
27278
|
+
const statement = current.parent?.parent;
|
|
27279
|
+
if (statement && import_typescript11.default.isVariableStatement(statement) && import_typescript11.default.isSourceFile(statement.parent))
|
|
27280
|
+
return found;
|
|
27281
|
+
const init = current.initializer ? unwrap(current.initializer) : undefined;
|
|
27282
|
+
if (init && (import_typescript11.default.isArrowFunction(init) || import_typescript11.default.isFunctionExpression(init)))
|
|
27283
|
+
return found;
|
|
27284
|
+
}
|
|
27285
|
+
}
|
|
27286
|
+
return found;
|
|
27287
|
+
}
|
|
27288
|
+
function isDeclarationName(identifier) {
|
|
27289
|
+
const parent = identifier.parent;
|
|
27290
|
+
if (!parent)
|
|
27291
|
+
return false;
|
|
27292
|
+
if (import_typescript11.default.isImportSpecifier(parent) || import_typescript11.default.isImportClause(parent) || import_typescript11.default.isNamespaceImport(parent) || import_typescript11.default.isExportSpecifier(parent))
|
|
27293
|
+
return true;
|
|
27294
|
+
return (import_typescript11.default.isVariableDeclaration(parent) || import_typescript11.default.isFunctionDeclaration(parent) || import_typescript11.default.isClassDeclaration(parent) || import_typescript11.default.isParameter(parent) || import_typescript11.default.isPropertyDeclaration(parent) || import_typescript11.default.isMethodDeclaration(parent)) && parent.name === identifier;
|
|
27295
|
+
}
|
|
27296
|
+
function stringEntries(expression, checker, depth = 0) {
|
|
27297
|
+
if (depth > 4)
|
|
27298
|
+
return [];
|
|
27299
|
+
const value = unwrap(expression);
|
|
27300
|
+
if (import_typescript11.default.isIdentifier(value)) {
|
|
27301
|
+
const declaration = valueDeclaration(resolvedSymbol(value, checker));
|
|
27302
|
+
return declaration && import_typescript11.default.isVariableDeclaration(declaration) && declaration.initializer ? stringEntries(declaration.initializer, checker, depth + 1) : [];
|
|
27303
|
+
}
|
|
27304
|
+
if (!import_typescript11.default.isArrayLiteralExpression(value))
|
|
27305
|
+
return [];
|
|
27306
|
+
const out = [];
|
|
27307
|
+
for (const element of value.elements) {
|
|
27308
|
+
if (import_typescript11.default.isSpreadElement(element)) {
|
|
27309
|
+
out.push(...stringEntries(element.expression, checker, depth + 1));
|
|
27310
|
+
continue;
|
|
27311
|
+
}
|
|
27312
|
+
const text = constantString(element, checker, depth);
|
|
27313
|
+
if (text !== undefined)
|
|
27314
|
+
out.push(text);
|
|
27315
|
+
}
|
|
27316
|
+
return out;
|
|
27317
|
+
}
|
|
27318
|
+
function constantString(expression, checker, depth) {
|
|
27319
|
+
const value = unwrap(expression);
|
|
27320
|
+
if (import_typescript11.default.isStringLiteral(value) || import_typescript11.default.isNoSubstitutionTemplateLiteral(value))
|
|
27321
|
+
return value.text;
|
|
27322
|
+
if (depth > 4)
|
|
27323
|
+
return;
|
|
27324
|
+
if (import_typescript11.default.isIdentifier(value)) {
|
|
27325
|
+
const declaration = valueDeclaration(resolvedSymbol(value, checker));
|
|
27326
|
+
return declaration && import_typescript11.default.isVariableDeclaration(declaration) && declaration.initializer ? constantString(declaration.initializer, checker, depth + 1) : undefined;
|
|
27327
|
+
}
|
|
27328
|
+
if (import_typescript11.default.isTemplateExpression(value)) {
|
|
27329
|
+
let text = value.head.text;
|
|
27330
|
+
for (const span of value.templateSpans) {
|
|
27331
|
+
const part = constantString(span.expression, checker, depth + 1);
|
|
27332
|
+
if (part === undefined)
|
|
27333
|
+
return;
|
|
27334
|
+
text += part + span.literal.text;
|
|
27335
|
+
}
|
|
27336
|
+
return text;
|
|
27337
|
+
}
|
|
27338
|
+
return;
|
|
27339
|
+
}
|
|
27340
|
+
|
|
27341
|
+
// src/harness-extract/tools.ts
|
|
27342
|
+
var PASS_THROUGH2 = new Set(["ref", "call", "param", "oneOf", "lookup"]);
|
|
27343
|
+
var DEFINITION_KEYS = new Set(["description", "input_schema", "inputSchema", "parameters", "schema", "execute", "type", "strict"]);
|
|
27344
|
+
function member(tree, key) {
|
|
27345
|
+
const members = tree.children ?? [];
|
|
27346
|
+
for (let index = members.length - 1;index >= 0; index -= 1)
|
|
27347
|
+
if (members[index].key === key)
|
|
27348
|
+
return members[index];
|
|
27349
|
+
return;
|
|
27350
|
+
}
|
|
27351
|
+
function singleLiteral2(tree) {
|
|
27352
|
+
if (!tree)
|
|
27353
|
+
return;
|
|
27354
|
+
if (tree.kind === "literal")
|
|
27355
|
+
return tree.text;
|
|
27356
|
+
if (PASS_THROUGH2.has(tree.kind)) {
|
|
27357
|
+
const flow = valueChildren(tree);
|
|
27358
|
+
if (flow.length === 1)
|
|
27359
|
+
return singleLiteral2(flow[0]);
|
|
27360
|
+
}
|
|
27361
|
+
return;
|
|
27362
|
+
}
|
|
27363
|
+
function objectsOf(tree) {
|
|
27364
|
+
if (tree.kind === "object")
|
|
27365
|
+
return [tree];
|
|
27366
|
+
if (PASS_THROUGH2.has(tree.kind))
|
|
27367
|
+
return valueChildren(tree).flatMap(objectsOf);
|
|
27368
|
+
return [];
|
|
27369
|
+
}
|
|
27370
|
+
function definitionName(tree) {
|
|
27371
|
+
const fn = member(tree, "function");
|
|
27372
|
+
const fnObject = fn ? objectsOf(fn)[0] : undefined;
|
|
27373
|
+
const fnName = fnObject ? singleLiteral2(member(fnObject, "name")) : undefined;
|
|
27374
|
+
if (fnName && fnObject)
|
|
27375
|
+
return { name: fnName, path: fnObject.path, line: fnObject.line, via: "function.name" };
|
|
27376
|
+
const nameNode = member(tree, "name");
|
|
27377
|
+
const name = singleLiteral2(nameNode);
|
|
27378
|
+
const keys = (tree.children ?? []).map((child) => child.key ?? "");
|
|
27379
|
+
if (name && nameNode && keys.some((key) => DEFINITION_KEYS.has(key)))
|
|
27380
|
+
return { name, path: nameNode.path, line: nameNode.line, via: "name" };
|
|
27381
|
+
return;
|
|
27382
|
+
}
|
|
27383
|
+
function toolNamesOf(tree) {
|
|
27384
|
+
const out = { names: [], unresolved: [] };
|
|
27385
|
+
const visit2 = (node, inArray, names) => {
|
|
27386
|
+
if (node.kind === "array" || node.kind === "assembled" && node.text === "array") {
|
|
27387
|
+
for (const child of node.children ?? [])
|
|
27388
|
+
visit2(child, true, names);
|
|
27389
|
+
return;
|
|
27390
|
+
}
|
|
27391
|
+
if (node.kind === "object") {
|
|
27392
|
+
const definition = definitionName(node);
|
|
27393
|
+
if (definition) {
|
|
27394
|
+
names.push(definition);
|
|
27395
|
+
return;
|
|
27396
|
+
}
|
|
27397
|
+
if (inArray) {
|
|
27398
|
+
out.unresolved.push({ ...node, note: "tool object without a literal name" });
|
|
27399
|
+
return;
|
|
27400
|
+
}
|
|
27401
|
+
const record = new Map;
|
|
27402
|
+
const set = (hit) => {
|
|
27403
|
+
record.delete(hit.name);
|
|
27404
|
+
record.set(hit.name, hit);
|
|
27405
|
+
};
|
|
27406
|
+
for (const child of node.children ?? []) {
|
|
27407
|
+
if (child.key === "...") {
|
|
27408
|
+
const spread = [];
|
|
27409
|
+
visit2(child, false, spread);
|
|
27410
|
+
spread.forEach(set);
|
|
27411
|
+
} else if (child.key) {
|
|
27412
|
+
set({ name: child.key, path: child.path, line: child.line, via: "key" });
|
|
27413
|
+
}
|
|
27414
|
+
}
|
|
27415
|
+
names.push(...record.values());
|
|
27416
|
+
return;
|
|
27417
|
+
}
|
|
27418
|
+
if (PASS_THROUGH2.has(node.kind) && valueChildren(node).length > 0) {
|
|
27419
|
+
for (const child of valueChildren(node))
|
|
27420
|
+
visit2(child, inArray, names);
|
|
27421
|
+
return;
|
|
27422
|
+
}
|
|
27423
|
+
out.unresolved.push(node);
|
|
27424
|
+
};
|
|
27425
|
+
visit2(tree, false, out.names);
|
|
27426
|
+
return out;
|
|
27427
|
+
}
|
|
27428
|
+
|
|
27429
|
+
// src/harness-extract/emit-tools.ts
|
|
27430
|
+
var SCHEMA_KEYS = ["input_schema", "inputSchema", "parameters", "output_schema"];
|
|
27431
|
+
var TOOL_BODY_KEYS = ["execute", "handler"];
|
|
27432
|
+
var TOOL_FACTORY = /^(?:tool|dynamicTool|agentTool|createTool|defineTool)$/;
|
|
27433
|
+
var TOOL_MODULE = /^(?:ai|agents(?:\/.*)?|@cloudflare\/[\w-]+(?:\/.*)?|@mastra\/[\w-]+|@ai-sdk\/[\w-]+|@openai\/agents(?:-core)?|@langchain\/[\w-]+)$/;
|
|
27434
|
+
var MODEL_FACING_NAME = /^[A-Za-z_][\w.:-]{0,127}$/;
|
|
27435
|
+
var MAX_NAMES_PER_SITE = 64;
|
|
27436
|
+
var MAX_TOOLS = 1e4;
|
|
27437
|
+
var MAX_EVIDENCE_PER_TOOL = 64;
|
|
27438
|
+
var MAX_DEFINITIONS_PER_TOOL = 64;
|
|
27439
|
+
var MAX_DEFINITION_BYTES = 8 * 1024 * 1024;
|
|
27440
|
+
var MAX_BODY_BYTES = 64000;
|
|
27441
|
+
function emitTools(result, ctx, options = {}) {
|
|
27442
|
+
const owners = options.owners ?? new ToolOwners(ctx);
|
|
27443
|
+
const agentForScope = createAgentScopeResolver(result, ctx);
|
|
27444
|
+
let reach;
|
|
27445
|
+
try {
|
|
27446
|
+
reach = buildImportGraphReachability(ctx.rootDir);
|
|
27447
|
+
} catch {
|
|
27448
|
+
reach = undefined;
|
|
27449
|
+
}
|
|
27450
|
+
const skipPath = (rel2) => isTestPath(rel2) || isOneOffScript(rel2, reach);
|
|
27451
|
+
const tracers = new Map;
|
|
27452
|
+
const tracerFor = (program) => {
|
|
27453
|
+
let tracer = tracers.get(program);
|
|
27454
|
+
if (!tracer) {
|
|
27455
|
+
const checker = program.getTypeChecker();
|
|
27456
|
+
tracer = new ValueTracer(ctx.rootDir, checker, new CallIndex(program, checker), { maxDepth: 8, maxNodes: 400, maxCallers: 8 });
|
|
27457
|
+
tracers.set(program, tracer);
|
|
27458
|
+
}
|
|
27459
|
+
return tracer;
|
|
27460
|
+
};
|
|
27461
|
+
const packageOf = workspacePackages(ctx.rootDir);
|
|
27462
|
+
const found = new Map;
|
|
27463
|
+
const ownersByTool = new Map;
|
|
27464
|
+
let definitionBytes = 0;
|
|
27465
|
+
const limit = () => {
|
|
27466
|
+
const warning = "tools: bounded tool catalog budget reached; some evidence or bodies omitted";
|
|
27467
|
+
if (!result.warnings.includes(warning))
|
|
27468
|
+
result.warnings.push(warning);
|
|
27469
|
+
};
|
|
27470
|
+
const add = (name, via, evidence, toolOwners, definition, displayName, enclosing) => {
|
|
27471
|
+
if (!MODEL_FACING_NAME.test(name))
|
|
27472
|
+
return;
|
|
27473
|
+
const pkg = packageOf(evidence.path);
|
|
27474
|
+
const key = name;
|
|
27475
|
+
let tool = found.get(key);
|
|
27476
|
+
if (!tool) {
|
|
27477
|
+
if (found.size >= MAX_TOOLS) {
|
|
27478
|
+
limit();
|
|
27479
|
+
return;
|
|
27480
|
+
}
|
|
27481
|
+
tool = { name, status: enumerationRepository(ctx).status(evidence.path) === "defined_only" ? "defined_only" : "reachable", ...pkg ? { package: pkg } : {}, via, evidence: [], agents: [], calledFrom: [], definitions: [] };
|
|
27482
|
+
found.set(key, tool);
|
|
27483
|
+
ownersByTool.set(key, { direct: [], rpc: [], open: [] });
|
|
27484
|
+
}
|
|
27485
|
+
if (enumerationRepository(ctx).status(evidence.path) !== "defined_only")
|
|
27486
|
+
tool.status = "reachable";
|
|
27487
|
+
if (tool.evidence.length < MAX_EVIDENCE_PER_TOOL && !tool.evidence.some((other) => other.path === evidence.path && other.line === evidence.line)) {
|
|
27488
|
+
tool.evidence.push(evidence);
|
|
27489
|
+
tool.calledFrom.push({ path: evidence.path, line: evidence.line, ...enclosing ? { enclosing } : {} });
|
|
27490
|
+
}
|
|
27491
|
+
if (definition) {
|
|
27492
|
+
const source = definition.getSourceFile();
|
|
27493
|
+
const path = relPath(ctx.rootDir, source.fileName), start = definition.getStart(source);
|
|
27494
|
+
if (tool.definitions.length < MAX_DEFINITIONS_PER_TOOL && !tool.definitions.some((other) => other.path === path && other.start === start)) {
|
|
27495
|
+
const text = Buffer.from(definition.getText(source));
|
|
27496
|
+
if (text.length > MAX_BODY_BYTES) {
|
|
27497
|
+
const warning = `tools: ${name} definition at ${path}:${lineOf(definition)} exceeds ${MAX_BODY_BYTES} bytes; its body is truncated`;
|
|
27498
|
+
if (!result.warnings.includes(warning))
|
|
27499
|
+
result.warnings.push(warning);
|
|
27500
|
+
}
|
|
27501
|
+
const body = text.subarray(0, Math.max(0, Math.min(MAX_BODY_BYTES, MAX_DEFINITION_BYTES - definitionBytes))).toString("utf8");
|
|
27502
|
+
definitionBytes += Buffer.byteLength(body);
|
|
27503
|
+
if (definitionBytes >= MAX_DEFINITION_BYTES)
|
|
27504
|
+
limit();
|
|
27505
|
+
tool.definitions.push({ path, start, end: definition.getEnd(), line: lineOf(definition), scope: scopeOf(ctx.rootDir, definition), body });
|
|
27506
|
+
}
|
|
27507
|
+
}
|
|
27508
|
+
const merged = ownersByTool.get(key);
|
|
27509
|
+
for (const agent2 of toolOwners.direct)
|
|
27510
|
+
if (!merged.direct.includes(agent2))
|
|
27511
|
+
merged.direct.push(agent2);
|
|
27512
|
+
for (const agent2 of toolOwners.rpc)
|
|
27513
|
+
if (!merged.rpc.includes(agent2))
|
|
27514
|
+
merged.rpc.push(agent2);
|
|
27515
|
+
for (const agent2 of toolOwners.open)
|
|
27516
|
+
if (!merged.open.includes(agent2))
|
|
27517
|
+
merged.open.push(agent2);
|
|
27518
|
+
tool.displayName ??= displayName;
|
|
27519
|
+
};
|
|
27520
|
+
for (const { program, source, rel: rel2 } of sourceFilesOf(ctx)) {
|
|
27521
|
+
if (skipPath(rel2))
|
|
27522
|
+
continue;
|
|
27523
|
+
const checker = program.getTypeChecker();
|
|
27524
|
+
const tracer = tracerFor(program);
|
|
27525
|
+
const names = (expression) => literalStrings(expression, tracer).slice(0, MAX_NAMES_PER_SITE);
|
|
27526
|
+
const at = (node, reason) => ({ path: rel2, line: lineOf(node), reason });
|
|
27527
|
+
const visitObject = (object) => {
|
|
27528
|
+
const keys = object.properties.map((property) => propertyNameText(property.name) ?? "");
|
|
27529
|
+
const nameExpr = propertyValue(object, "name");
|
|
27530
|
+
if (nameExpr && SCHEMA_KEYS.some((key) => keys.includes(key)) && !isSchemaProperty(object)) {
|
|
27531
|
+
const list = names(nameExpr);
|
|
27532
|
+
if (list.length > 0) {
|
|
27533
|
+
const span = registryEntryOf(object);
|
|
27534
|
+
const agents = owners.ownersOf(span, program);
|
|
27535
|
+
for (const name of list)
|
|
27536
|
+
add(name, "definition", at(nameExpr, "tool definition (name beside its input schema)"), agents, span, displayNameOf(object, tracer), enclosingName(object));
|
|
27537
|
+
}
|
|
27538
|
+
}
|
|
27539
|
+
const toolNameExpr = propertyValue(object, "toolName");
|
|
27540
|
+
if (toolNameExpr && keys.includes("description")) {
|
|
27541
|
+
const list = names(toolNameExpr);
|
|
27542
|
+
if (list.length > 0) {
|
|
27543
|
+
const agents = owners.ownersOf(object, program);
|
|
27544
|
+
for (const name of list)
|
|
27545
|
+
add(name, "role-table", at(toolNameExpr, "role table row naming the tool the model sees"), agents, object, displayNameOf(object, tracer), enclosingName(object));
|
|
27546
|
+
}
|
|
27547
|
+
}
|
|
27548
|
+
for (const property of object.properties) {
|
|
27549
|
+
if (!import_typescript12.default.isPropertyAssignment(property) || !isToolValue(property.initializer, checker))
|
|
27550
|
+
continue;
|
|
27551
|
+
const list = import_typescript12.default.isComputedPropertyName(property.name) ? names(property.name.expression) : [propertyNameText(property.name)].filter((key) => Boolean(key));
|
|
27552
|
+
if (list.length === 0)
|
|
27553
|
+
continue;
|
|
27554
|
+
const agents = owners.ownersOf(property, program);
|
|
27555
|
+
const options2 = toolOptions(property.initializer);
|
|
27556
|
+
const definition = definitionNode(property.initializer, checker);
|
|
27557
|
+
for (const name of list)
|
|
27558
|
+
add(name, "record", at(property, "tools record key"), agents, definition, options2 ? displayNameOf(options2, tracer) : undefined, enclosingName(property));
|
|
27559
|
+
}
|
|
27560
|
+
};
|
|
27561
|
+
const visit2 = (node) => {
|
|
27562
|
+
try {
|
|
27563
|
+
if (import_typescript12.default.isObjectLiteralExpression(node)) {
|
|
27564
|
+
visitObject(node);
|
|
27565
|
+
} else if (import_typescript12.default.isBinaryExpression(node) && node.operatorToken.kind === import_typescript12.default.SyntaxKind.EqualsToken && import_typescript12.default.isElementAccessExpression(node.left) && isToolValue(node.right, checker)) {
|
|
27566
|
+
const list = names(node.left.argumentExpression);
|
|
27567
|
+
if (list.length > 0) {
|
|
27568
|
+
const agents = owners.ownersOf(node, program);
|
|
27569
|
+
const options2 = toolOptions(node.right);
|
|
27570
|
+
const definition = definitionNode(node.right, checker);
|
|
27571
|
+
for (const name of list)
|
|
27572
|
+
add(name, "record", at(node, "tool stored under this key"), agents, definition, options2 ? displayNameOf(options2, tracer) : undefined, enclosingName(node));
|
|
27573
|
+
}
|
|
27574
|
+
}
|
|
27575
|
+
} catch {}
|
|
27576
|
+
import_typescript12.default.forEachChild(node, visit2);
|
|
27577
|
+
};
|
|
27578
|
+
visit2(source);
|
|
27579
|
+
}
|
|
27580
|
+
for (const role of result.roles) {
|
|
27581
|
+
if (role.role !== "tools" || role.sink.isTest || skipPath(role.sink.path))
|
|
27582
|
+
continue;
|
|
27583
|
+
const program = ctx.programFor(role.sink.path);
|
|
27584
|
+
const siteOwners = program ? ownersAtSite(owners, program, role.sink.path, role.sink.line) : { direct: [], rpc: [], open: [] };
|
|
27585
|
+
for (const hit of toolNamesOf(role.tree).names) {
|
|
27586
|
+
if (skipPath(hit.path))
|
|
27587
|
+
continue;
|
|
27588
|
+
add(hit.name, "tools-arg", { path: hit.path, line: hit.line, reason: `named in the tools argument of ${role.sink.callee} at ${role.sink.path}:${role.sink.line}` }, siteOwners, undefined, undefined, role.sink.enclosing);
|
|
27589
|
+
}
|
|
27590
|
+
}
|
|
27591
|
+
owners.indexAllowlists(new Set([...found.values()].map((tool) => tool.name)));
|
|
27592
|
+
const callOwners = new Map;
|
|
27593
|
+
for (const role of result.roles) {
|
|
27594
|
+
if (role.role !== "tools" || role.sink.isTest || skipPath(role.sink.path))
|
|
27595
|
+
continue;
|
|
27596
|
+
const ids = agentForScope(role.sink.scope);
|
|
27597
|
+
for (const hit of toolNamesOf(role.tree).names) {
|
|
27598
|
+
let owners2 = callOwners.get(hit.name);
|
|
27599
|
+
if (!owners2)
|
|
27600
|
+
callOwners.set(hit.name, owners2 = new Set);
|
|
27601
|
+
for (const id of ids)
|
|
27602
|
+
owners2.add(id);
|
|
27603
|
+
}
|
|
27604
|
+
}
|
|
27605
|
+
for (const [key, tool] of found) {
|
|
27606
|
+
const ids = new Set;
|
|
27607
|
+
for (const name of owners.agentsFor(tool.name, ownersByTool.get(key))) {
|
|
27608
|
+
const classes = owners.classes.filter((entry) => entry.name === name);
|
|
27609
|
+
if (classes.length === 1)
|
|
27610
|
+
for (const id of agentForScope(`${classes[0].path}#${name}`))
|
|
27611
|
+
ids.add(id);
|
|
27612
|
+
}
|
|
27613
|
+
for (const id of callOwners.get(tool.name) ?? [])
|
|
27614
|
+
ids.add(id);
|
|
27615
|
+
tool.agents = [...ids].sort();
|
|
27616
|
+
}
|
|
27617
|
+
return [...found.values()].sort((a, b) => a.name.localeCompare(b.name) || (a.package ?? "").localeCompare(b.package ?? ""));
|
|
27618
|
+
}
|
|
27619
|
+
function registryEntryOf(object) {
|
|
27620
|
+
const parent = object.parent;
|
|
27621
|
+
if (parent && import_typescript12.default.isPropertyAssignment(parent) && propertyNameText(parent.name) === "definition" && import_typescript12.default.isObjectLiteralExpression(parent.parent)) {
|
|
27622
|
+
return parent.parent;
|
|
27623
|
+
}
|
|
27624
|
+
return object;
|
|
27625
|
+
}
|
|
27626
|
+
function definitionNode(expression, checker, depth = 0) {
|
|
27627
|
+
const value = unwrap(expression);
|
|
27628
|
+
if (import_typescript12.default.isCallExpression(value) || import_typescript12.default.isObjectLiteralExpression(value))
|
|
27629
|
+
return value;
|
|
27630
|
+
if (import_typescript12.default.isIdentifier(value) && depth < 2) {
|
|
27631
|
+
const declaration = valueDeclaration(resolvedSymbol(value, checker));
|
|
27632
|
+
if (declaration && import_typescript12.default.isVariableDeclaration(declaration) && declaration.initializer)
|
|
27633
|
+
return definitionNode(declaration.initializer, checker, depth + 1);
|
|
27634
|
+
}
|
|
27635
|
+
return;
|
|
27636
|
+
}
|
|
27637
|
+
function ownersAtSite(owners, program, path, line) {
|
|
27638
|
+
const source = program.getSourceFiles().find((file) => file.fileName.endsWith(`/${path}`) || file.fileName === path);
|
|
27639
|
+
if (!source)
|
|
27640
|
+
return { direct: [], rpc: [], open: [] };
|
|
27641
|
+
const position = source.getPositionOfLineAndCharacter(Math.max(0, line - 1), 0);
|
|
27642
|
+
let node = source;
|
|
27643
|
+
const descend = (current) => {
|
|
27644
|
+
for (const child of current.getChildren(source)) {
|
|
27645
|
+
if (child.getStart(source) <= position && position < child.getEnd()) {
|
|
27646
|
+
node = child;
|
|
27647
|
+
descend(child);
|
|
27648
|
+
return;
|
|
27649
|
+
}
|
|
27650
|
+
}
|
|
27651
|
+
};
|
|
27652
|
+
descend(source);
|
|
27653
|
+
return owners.ownersOf(node, program);
|
|
27654
|
+
}
|
|
27655
|
+
function literalStrings(expression, tracer) {
|
|
27656
|
+
const value = unwrap(expression);
|
|
27657
|
+
if (import_typescript12.default.isStringLiteral(value) || import_typescript12.default.isNoSubstitutionTemplateLiteral(value))
|
|
27658
|
+
return [value.text];
|
|
27659
|
+
let tree;
|
|
27660
|
+
try {
|
|
27661
|
+
tree = tracer.trace(value);
|
|
27662
|
+
} catch {
|
|
27663
|
+
return [];
|
|
27664
|
+
}
|
|
27665
|
+
return [...new Set(renderings(tree, MAX_NAMES_PER_SITE).filter((text) => text.length > 0 && !text.includes("${...}")))];
|
|
27666
|
+
}
|
|
27667
|
+
function displayNameOf(object, tracer) {
|
|
27668
|
+
for (const key of ["displayName", "title"]) {
|
|
27669
|
+
const value = propertyValue(object, key);
|
|
27670
|
+
if (!value)
|
|
27671
|
+
continue;
|
|
27672
|
+
const [text] = literalStrings(value, tracer);
|
|
27673
|
+
if (text)
|
|
27674
|
+
return text;
|
|
27675
|
+
}
|
|
27676
|
+
return;
|
|
27677
|
+
}
|
|
27678
|
+
function toolOptions(expression) {
|
|
27679
|
+
const value = unwrap(expression);
|
|
27680
|
+
if (import_typescript12.default.isObjectLiteralExpression(value))
|
|
27681
|
+
return value;
|
|
27682
|
+
if (import_typescript12.default.isCallExpression(value)) {
|
|
27683
|
+
for (const argument of value.arguments) {
|
|
27684
|
+
const inner = unwrap(argument);
|
|
27685
|
+
if (import_typescript12.default.isObjectLiteralExpression(inner))
|
|
27686
|
+
return inner;
|
|
27687
|
+
}
|
|
27688
|
+
}
|
|
27689
|
+
return;
|
|
27690
|
+
}
|
|
27691
|
+
function enclosingName(node) {
|
|
27692
|
+
const parts = [];
|
|
27693
|
+
for (let current = node.parent;current; current = current.parent) {
|
|
27694
|
+
if ((import_typescript12.default.isFunctionDeclaration(current) || import_typescript12.default.isMethodDeclaration(current)) && current.name && parts.length === 0) {
|
|
27695
|
+
parts.unshift(propertyNameText(current.name) ?? "");
|
|
27696
|
+
} else if (import_typescript12.default.isVariableDeclaration(current) && import_typescript12.default.isIdentifier(current.name) && parts.length === 0) {
|
|
27697
|
+
parts.unshift(current.name.text);
|
|
27698
|
+
} else if (import_typescript12.default.isClassLike(current) && current.name) {
|
|
27699
|
+
parts.unshift(current.name.text);
|
|
27700
|
+
break;
|
|
27701
|
+
}
|
|
27702
|
+
}
|
|
27703
|
+
const joined = parts.filter(Boolean).join(".");
|
|
27704
|
+
return joined || undefined;
|
|
27705
|
+
}
|
|
27706
|
+
function isSchemaProperty(object) {
|
|
27707
|
+
const parent = object.parent;
|
|
27708
|
+
if (!parent || !import_typescript12.default.isPropertyAssignment(parent))
|
|
27709
|
+
return false;
|
|
27710
|
+
const holder = parent.parent;
|
|
27711
|
+
return import_typescript12.default.isObjectLiteralExpression(holder) && import_typescript12.default.isPropertyAssignment(holder.parent) && propertyNameText(holder.parent.name) === "properties";
|
|
27712
|
+
}
|
|
27713
|
+
function isToolValue(expression, checker, depth = 0) {
|
|
27714
|
+
const value = unwrap(expression);
|
|
27715
|
+
if (import_typescript12.default.isCallExpression(value)) {
|
|
27716
|
+
const callee = unwrap(value.expression);
|
|
27717
|
+
const name = import_typescript12.default.isIdentifier(callee) ? callee : import_typescript12.default.isPropertyAccessExpression(callee) ? callee.name : undefined;
|
|
27718
|
+
if (!name)
|
|
27719
|
+
return false;
|
|
27720
|
+
if (TOOL_FACTORY.test(name.text))
|
|
27721
|
+
return true;
|
|
27722
|
+
if (import_typescript12.default.isIdentifier(callee)) {
|
|
27723
|
+
const origin = importOrigin(callee, checker);
|
|
27724
|
+
if (origin && TOOL_MODULE.test(origin.module) && /tool/i.test(origin.imported))
|
|
27725
|
+
return true;
|
|
27726
|
+
}
|
|
27727
|
+
return false;
|
|
27728
|
+
}
|
|
27729
|
+
if (import_typescript12.default.isObjectLiteralExpression(value)) {
|
|
27730
|
+
const keys = value.properties.map((property) => propertyNameText(property.name) ?? "");
|
|
27731
|
+
return SCHEMA_KEYS.some((key) => keys.includes(key)) && TOOL_BODY_KEYS.some((key) => keys.includes(key)) && keys.includes("description") && !keys.includes("name");
|
|
27732
|
+
}
|
|
27733
|
+
if (import_typescript12.default.isIdentifier(value) && depth < 2) {
|
|
27734
|
+
const declaration = valueDeclaration(resolvedSymbol(value, checker));
|
|
27735
|
+
if (declaration && import_typescript12.default.isVariableDeclaration(declaration) && declaration.initializer && declaration.parent.flags & import_typescript12.default.NodeFlags.Const) {
|
|
27736
|
+
return isToolValue(declaration.initializer, checker, depth + 1);
|
|
27737
|
+
}
|
|
27738
|
+
}
|
|
27739
|
+
return false;
|
|
27740
|
+
}
|
|
27741
|
+
var emitted = new WeakMap;
|
|
27742
|
+
function emitToolsCached(result, ctx) {
|
|
27743
|
+
let tools = emitted.get(result);
|
|
27744
|
+
if (!tools) {
|
|
27745
|
+
tools = emitTools(result, ctx);
|
|
27746
|
+
emitted.set(result, tools);
|
|
27747
|
+
}
|
|
27748
|
+
return tools;
|
|
27749
|
+
}
|
|
27750
|
+
function toolArtifactId(name, pkg) {
|
|
27751
|
+
const slug2 = (text) => text.replace(/[^A-Za-z0-9_.:-]+/g, "_");
|
|
27752
|
+
return `tool.extract.${slug2(name)}`;
|
|
27753
|
+
}
|
|
27754
|
+
function workspacePackages(rootDir) {
|
|
27755
|
+
const cache2 = new Map;
|
|
27756
|
+
const lookup = (dir) => {
|
|
27757
|
+
if (dir === "" || dir === ".")
|
|
27758
|
+
return "";
|
|
27759
|
+
const cached = cache2.get(dir);
|
|
27760
|
+
if (cached !== undefined)
|
|
27761
|
+
return cached;
|
|
27762
|
+
const found = existsSync9(join14(rootDir, dir, "package.json")) ? dir : lookup(posix3.dirname(dir) === "." ? "" : posix3.dirname(dir));
|
|
27763
|
+
cache2.set(dir, found);
|
|
27764
|
+
return found;
|
|
27765
|
+
};
|
|
27766
|
+
return (rel2) => lookup(posix3.dirname(rel2) === "." ? "" : posix3.dirname(rel2));
|
|
27767
|
+
}
|
|
27768
|
+
function toolDefinitionRefs(tools) {
|
|
27769
|
+
const out = [];
|
|
27770
|
+
for (const tool of tools) {
|
|
27771
|
+
const definition = tool.definitions[0];
|
|
27772
|
+
if (!definition)
|
|
27773
|
+
continue;
|
|
27774
|
+
out.push({
|
|
27775
|
+
toolId: toolArtifactId(tool.name, tool.package),
|
|
27776
|
+
name: tool.name,
|
|
27777
|
+
definition: { path: definition.path, start: definition.start, end: definition.end, line: definition.line },
|
|
27778
|
+
...tool.agents.length > 0 ? { agentIds: [...tool.agents] } : {},
|
|
27779
|
+
scope: definition.scope
|
|
27780
|
+
});
|
|
27781
|
+
}
|
|
27782
|
+
return out;
|
|
27783
|
+
}
|
|
27784
|
+
function toolArtifacts(tools, runtimeAgents = []) {
|
|
27785
|
+
const knownIds = new Set(runtimeAgents.map((agent2) => agent2.id));
|
|
27786
|
+
return tools.map((tool) => {
|
|
27787
|
+
const usedByAgentIds = [...new Set(tool.agents.filter((id) => knownIds.has(id)))];
|
|
27788
|
+
const artifact2 = {
|
|
27789
|
+
id: toolArtifactId(tool.name, tool.package),
|
|
27790
|
+
type: "tool",
|
|
27791
|
+
name: tool.name,
|
|
27792
|
+
status: tool.status,
|
|
27793
|
+
scope: usedByAgentIds.length === 1 ? "agent" : "shared",
|
|
27794
|
+
...tool.definitions[0] ? { sourcePath: tool.definitions[0].path } : {},
|
|
27795
|
+
...tool.definitions[0] ? { body: tool.definitions[0].body } : {},
|
|
27796
|
+
...tool.definitions.length > 1 ? { definitionVariants: tool.definitions.map((definition) => ({ sourcePath: definition.path, body: definition.body, evidence: [{ path: definition.path, line: definition.line }] })) } : {},
|
|
27797
|
+
usedByAgentIds,
|
|
27798
|
+
confidence: 0.9,
|
|
27799
|
+
confidenceReason: `Deterministic: model-facing tool name read from ${tool.via === "tools-arg" ? "a traced tools argument" : "its definition"} (call-site extractor).`,
|
|
27800
|
+
evidence: tool.evidence.map((entry) => ({ path: entry.path, line: entry.line, reason: entry.reason })),
|
|
27801
|
+
calledFrom: tool.calledFrom,
|
|
27802
|
+
agentClasses: [...tool.agents],
|
|
27803
|
+
...tool.displayName ? { displayName: tool.displayName } : {}
|
|
27804
|
+
};
|
|
27805
|
+
return artifact2;
|
|
27806
|
+
});
|
|
27807
|
+
}
|
|
27808
|
+
|
|
27809
|
+
// src/harness-extract/types.ts
|
|
27810
|
+
var EXTRACT_SCHEMA_VERSION = 1;
|
|
27811
|
+
|
|
27812
|
+
// src/harness-extract/index.ts
|
|
27813
|
+
var PROMPT_ROLES = new Set(["system", "user", "messages", "prompt", "instructions", "questions"]);
|
|
27814
|
+
var MAX_HELPER_CALLERS = 200;
|
|
27815
|
+
var MAX_DERIVED = 5000;
|
|
27816
|
+
var MAX_CALLER_CHAIN = 3;
|
|
27817
|
+
var cache2 = new Map;
|
|
27818
|
+
function clearExtractCache() {
|
|
27819
|
+
cache2.clear();
|
|
27820
|
+
}
|
|
27821
|
+
function extractHarness(rootDir, options = {}) {
|
|
27822
|
+
return extractHarnessWithContext(rootDir, options).result;
|
|
27823
|
+
}
|
|
27824
|
+
function extractHarnessWithContext(rootDir, options = {}) {
|
|
27825
|
+
const root = resolve13(rootDir);
|
|
27826
|
+
const { fresh, ...rest } = options;
|
|
27827
|
+
const key = `${root}\x00${JSON.stringify(rest)}`;
|
|
27828
|
+
const fingerprint = sourceFingerprint(root, rest);
|
|
27829
|
+
const cached = fresh ? undefined : cache2.get(key);
|
|
27830
|
+
if (cached && cached.fingerprint === fingerprint)
|
|
27831
|
+
return cached.output;
|
|
27832
|
+
const output = runExtract(root, options);
|
|
27833
|
+
cache2.set(key, { output, fingerprint });
|
|
27834
|
+
return output;
|
|
27835
|
+
}
|
|
27836
|
+
function argRef(rootDir, node, key) {
|
|
27837
|
+
const source = node.getSourceFile();
|
|
27838
|
+
const ref = { path: relPath(rootDir, source.fileName), start: node.getStart(source), end: node.getEnd(), line: lineOf(node) };
|
|
27839
|
+
if (key !== undefined)
|
|
27840
|
+
ref.key = key;
|
|
27841
|
+
Object.defineProperty(ref, "node", { value: node, enumerable: false });
|
|
27842
|
+
return ref;
|
|
27843
|
+
}
|
|
27844
|
+
function namedEnclosingFunction(node) {
|
|
27845
|
+
for (let fn = enclosingFunction(node);fn; fn = enclosingFunction(fn)) {
|
|
27846
|
+
const name = functionName(fn);
|
|
27847
|
+
if (name)
|
|
27848
|
+
return { fn, name };
|
|
27849
|
+
}
|
|
27850
|
+
return;
|
|
27851
|
+
}
|
|
27852
|
+
function qualifiedName(fn, name) {
|
|
27853
|
+
const cls = enclosingClass(fn);
|
|
27854
|
+
const owner = cls && (fn.parent === cls || fn.parent && fn.parent.parent === cls) ? className(cls) : undefined;
|
|
27855
|
+
return owner ? `${owner}.${name}` : name;
|
|
27856
|
+
}
|
|
27857
|
+
function functionScope(rootDir, fn, name) {
|
|
27858
|
+
const parts = [qualifiedName(fn, name)];
|
|
27859
|
+
const object = objectLiteralOf2(fn);
|
|
27860
|
+
if (object) {
|
|
27861
|
+
const holder = object.parent && import_typescript13.default.isVariableDeclaration(object.parent) && import_typescript13.default.isIdentifier(object.parent.name) ? object.parent.name.text : `L${lineOf(object)}`;
|
|
27862
|
+
parts.unshift(holder);
|
|
27863
|
+
}
|
|
27864
|
+
for (let outer = namedEnclosingFunction(object ?? fn);outer; outer = namedEnclosingFunction(outer.fn))
|
|
27865
|
+
parts.unshift(qualifiedName(outer.fn, outer.name));
|
|
27866
|
+
return `${relPath(rootDir, fn.getSourceFile().fileName)}#${parts.join(".")}`;
|
|
27867
|
+
}
|
|
27868
|
+
function objectLiteralOf2(fn) {
|
|
27869
|
+
const member2 = import_typescript13.default.isMethodDeclaration(fn) || import_typescript13.default.isGetAccessorDeclaration(fn) || import_typescript13.default.isSetAccessorDeclaration(fn) ? fn : import_typescript13.default.isPropertyAssignment(fn.parent) ? fn.parent : undefined;
|
|
27870
|
+
return member2 && import_typescript13.default.isObjectLiteralExpression(member2.parent) ? member2.parent : undefined;
|
|
27871
|
+
}
|
|
27872
|
+
function scopeOf(rootDir, node) {
|
|
27873
|
+
const named = namedEnclosingFunction(node);
|
|
27874
|
+
if (named)
|
|
27875
|
+
return functionScope(rootDir, named.fn, named.name);
|
|
27876
|
+
const path = relPath(rootDir, node.getSourceFile().fileName);
|
|
27877
|
+
let outermost;
|
|
27878
|
+
for (let fn = enclosingFunction(node);fn; fn = enclosingFunction(fn))
|
|
27879
|
+
outermost = fn;
|
|
26803
27880
|
return outermost ? `${path}#L${lineOf(outermost)}` : path;
|
|
26804
27881
|
}
|
|
26805
27882
|
function callerChain(rootDir, anchor, calls, memo) {
|
|
@@ -26828,15 +27905,15 @@ function findAgentClasses(program, checker, memo) {
|
|
|
26828
27905
|
for (const source of program.getSourceFiles()) {
|
|
26829
27906
|
if (source.isDeclarationFile || /[\\/]node_modules[\\/]/.test(source.fileName))
|
|
26830
27907
|
continue;
|
|
26831
|
-
const
|
|
26832
|
-
if ((
|
|
27908
|
+
const visit2 = (node) => {
|
|
27909
|
+
if ((import_typescript13.default.isClassDeclaration(node) || import_typescript13.default.isClassExpression(node)) && node.heritageClauses) {
|
|
26833
27910
|
const base = frameworkBaseOf(node, checker, memo).base;
|
|
26834
27911
|
if (base && AGENT_CLASS_BASES.has(base))
|
|
26835
27912
|
out.push(node);
|
|
26836
27913
|
}
|
|
26837
|
-
|
|
27914
|
+
import_typescript13.default.forEachChild(node, visit2);
|
|
26838
27915
|
};
|
|
26839
|
-
|
|
27916
|
+
visit2(source);
|
|
26840
27917
|
}
|
|
26841
27918
|
return out;
|
|
26842
27919
|
}
|
|
@@ -26878,35 +27955,35 @@ function siteFields(sources, rootDir) {
|
|
|
26878
27955
|
return out;
|
|
26879
27956
|
}
|
|
26880
27957
|
function paramFlow(node, fn, checker, hops = 0) {
|
|
26881
|
-
if (!
|
|
27958
|
+
if (!import_typescript13.default.isExpression(node) || hops > 2)
|
|
26882
27959
|
return;
|
|
26883
27960
|
const expr = unwrap(node);
|
|
26884
|
-
if (
|
|
27961
|
+
if (import_typescript13.default.isBinaryExpression(expr) && (expr.operatorToken.kind === import_typescript13.default.SyntaxKind.QuestionQuestionToken || expr.operatorToken.kind === import_typescript13.default.SyntaxKind.BarBarToken)) {
|
|
26885
27962
|
return paramFlow(expr.left, fn, checker, hops);
|
|
26886
27963
|
}
|
|
26887
|
-
if (
|
|
27964
|
+
if (import_typescript13.default.isPropertyAccessExpression(expr) && import_typescript13.default.isIdentifier(unwrap(expr.expression))) {
|
|
26888
27965
|
const inner = paramFlow(expr.expression, fn, checker, hops);
|
|
26889
27966
|
return inner && inner.key === undefined ? { param: inner.param, key: expr.name.text } : undefined;
|
|
26890
27967
|
}
|
|
26891
|
-
if (!
|
|
27968
|
+
if (!import_typescript13.default.isIdentifier(expr))
|
|
26892
27969
|
return;
|
|
26893
27970
|
const declaration = valueDeclaration(resolvedSymbol(expr, checker));
|
|
26894
27971
|
if (!declaration)
|
|
26895
27972
|
return;
|
|
26896
|
-
if (
|
|
27973
|
+
if (import_typescript13.default.isParameter(declaration) && declaration.parent === fn && !declaration.dotDotDotToken)
|
|
26897
27974
|
return { param: declaration };
|
|
26898
|
-
if (
|
|
27975
|
+
if (import_typescript13.default.isBindingElement(declaration) && import_typescript13.default.isObjectBindingPattern(declaration.parent) && import_typescript13.default.isParameter(declaration.parent.parent) && declaration.parent.parent.parent === fn && !declaration.dotDotDotToken) {
|
|
26899
27976
|
const key = propertyNameText(declaration.propertyName ?? declaration.name);
|
|
26900
27977
|
return key ? { param: declaration.parent.parent, key } : undefined;
|
|
26901
27978
|
}
|
|
26902
|
-
if (
|
|
27979
|
+
if (import_typescript13.default.isVariableDeclaration(declaration) && declaration.initializer && enclosingFunction(declaration) === fn && declaration.parent.flags & import_typescript13.default.NodeFlags.Const) {
|
|
26903
27980
|
return paramFlow(declaration.initializer, fn, checker, hops + 1);
|
|
26904
27981
|
}
|
|
26905
27982
|
return;
|
|
26906
27983
|
}
|
|
26907
27984
|
function roleParamFlow(arg, fn, checker) {
|
|
26908
27985
|
const object = unwrap(arg.node);
|
|
26909
|
-
if (arg.key !== undefined && !arg.key.includes(".") &&
|
|
27986
|
+
if (arg.key !== undefined && !arg.key.includes(".") && import_typescript13.default.isObjectLiteralExpression(object)) {
|
|
26910
27987
|
const value = propertyValue(object, arg.key);
|
|
26911
27988
|
const flow = value ? paramFlow(value, fn, checker) : undefined;
|
|
26912
27989
|
return flow ? { ...flow, viaProperty: true } : undefined;
|
|
@@ -26918,9 +27995,9 @@ function descendArg(argument, path) {
|
|
|
26918
27995
|
let index = 0;
|
|
26919
27996
|
for (;index < path.length; index += 1) {
|
|
26920
27997
|
let value = unwrap(node);
|
|
26921
|
-
if (
|
|
27998
|
+
if (import_typescript13.default.isCallExpression(value) && value.expression.getText() === "JSON.stringify" && value.arguments[0])
|
|
26922
27999
|
value = unwrap(value.arguments[0]);
|
|
26923
|
-
const next =
|
|
28000
|
+
const next = import_typescript13.default.isObjectLiteralExpression(value) ? propertyValue(value, path[index]) : undefined;
|
|
26924
28001
|
if (!next)
|
|
26925
28002
|
break;
|
|
26926
28003
|
node = next;
|
|
@@ -26997,8 +28074,8 @@ function runExtract(rootDir, options) {
|
|
|
26997
28074
|
};
|
|
26998
28075
|
sites.push({ site, entry, anchor, sources, level: 0 });
|
|
26999
28076
|
};
|
|
27000
|
-
const
|
|
27001
|
-
if (
|
|
28077
|
+
const visit2 = (node) => {
|
|
28078
|
+
if (import_typescript13.default.isCallExpression(node) || import_typescript13.default.isNewExpression(node)) {
|
|
27002
28079
|
for (const recognizer of CALL_SINKS) {
|
|
27003
28080
|
let match;
|
|
27004
28081
|
const begin = performance.now();
|
|
@@ -27013,7 +28090,7 @@ function runExtract(rootDir, options) {
|
|
|
27013
28090
|
break;
|
|
27014
28091
|
}
|
|
27015
28092
|
}
|
|
27016
|
-
} else if (
|
|
28093
|
+
} else if (import_typescript13.default.isClassDeclaration(node) || import_typescript13.default.isClassExpression(node)) {
|
|
27017
28094
|
for (const recognizer of classRecognizers) {
|
|
27018
28095
|
try {
|
|
27019
28096
|
for (const match of recognizer.match(node, ctx2))
|
|
@@ -27023,9 +28100,9 @@ function runExtract(rootDir, options) {
|
|
|
27023
28100
|
}
|
|
27024
28101
|
}
|
|
27025
28102
|
}
|
|
27026
|
-
|
|
28103
|
+
import_typescript13.default.forEachChild(node, visit2);
|
|
27027
28104
|
};
|
|
27028
|
-
|
|
28105
|
+
visit2(source);
|
|
27029
28106
|
}
|
|
27030
28107
|
} catch (error) {
|
|
27031
28108
|
warnings.push(`sinks ${entry.configPath ?? "(fallback)"}: ${error.message}`);
|
|
@@ -27075,7 +28152,7 @@ function runExtract(rootDir, options) {
|
|
|
27075
28152
|
const sources = [];
|
|
27076
28153
|
for (const { source: role, flow } of flowing) {
|
|
27077
28154
|
const argument = call.arguments[named.fn.parameters.indexOf(flow.param)];
|
|
27078
|
-
if (!argument ||
|
|
28155
|
+
if (!argument || import_typescript13.default.isSpreadElement(argument))
|
|
27079
28156
|
continue;
|
|
27080
28157
|
const arg = descendArg(argument, [flow.key, flow.viaProperty ? undefined : role.arg.key].filter((part) => Boolean(part)));
|
|
27081
28158
|
sources.push({ ...role, bindings: extendBindings(role.bindings, callerBindings), arg });
|
|
@@ -27204,11 +28281,21 @@ function runExtract(rootDir, options) {
|
|
|
27204
28281
|
timings.models = Date.now() - begin;
|
|
27205
28282
|
result.durationMs = Date.now() - started;
|
|
27206
28283
|
}
|
|
28284
|
+
if (options.tools ?? true) {
|
|
28285
|
+
const begin = Date.now();
|
|
28286
|
+
try {
|
|
28287
|
+
result.toolDefinitions = toolDefinitionRefs(emitToolsCached(result, ctx));
|
|
28288
|
+
} catch (error) {
|
|
28289
|
+
warnings.push(`tools: ${error.message}`);
|
|
28290
|
+
}
|
|
28291
|
+
timings.tools = Date.now() - begin;
|
|
28292
|
+
result.durationMs = Date.now() - started;
|
|
28293
|
+
}
|
|
27207
28294
|
return { result, ctx };
|
|
27208
28295
|
}
|
|
27209
28296
|
function nodeSpanning(source, start, end) {
|
|
27210
28297
|
let best;
|
|
27211
|
-
const
|
|
28298
|
+
const visit2 = (node) => {
|
|
27212
28299
|
const nodeStart = node.getStart(source);
|
|
27213
28300
|
if (nodeStart > start || node.getEnd() < end)
|
|
27214
28301
|
return;
|
|
@@ -27217,9 +28304,9 @@ function nodeSpanning(source, start, end) {
|
|
|
27217
28304
|
return;
|
|
27218
28305
|
}
|
|
27219
28306
|
best = node;
|
|
27220
|
-
|
|
28307
|
+
import_typescript13.default.forEachChild(node, visit2);
|
|
27221
28308
|
};
|
|
27222
|
-
|
|
28309
|
+
visit2(source);
|
|
27223
28310
|
return best;
|
|
27224
28311
|
}
|
|
27225
28312
|
function serializeExtractResult(result) {
|
|
@@ -27263,114 +28350,6 @@ function assignAgentIds(result, agentForScope) {
|
|
|
27263
28350
|
}
|
|
27264
28351
|
}
|
|
27265
28352
|
|
|
27266
|
-
// src/harness-extract/enumerators/common.ts
|
|
27267
|
-
var import_typescript11 = __toESM(require_typescript(), 1);
|
|
27268
|
-
import { readdirSync as readdirSync8, readFileSync as readFileSync15 } from "node:fs";
|
|
27269
|
-
import { dirname as dirname10, join as join13, posix as posix2, relative as relative10 } from "node:path";
|
|
27270
|
-
var cache2 = new WeakMap;
|
|
27271
|
-
var SKIP = new Set(["node_modules", "dist", "build", "out", "vendor", "coverage", "__pycache__"]);
|
|
27272
|
-
var TEST_PATH4 = /(?:^|\/)(?:test|tests|__tests__|test-fixtures|fixtures?|__fixtures__|__mocks__|e2e)\/|\.(?:test|spec)\.[cm]?[jt]sx?$/i;
|
|
27273
|
-
var EVAL_PATH2 = /(?:^|\/)evals?\/|\.evals?\.[cm]?[jt]sx?$/i;
|
|
27274
|
-
function enumerationRepository(ctx) {
|
|
27275
|
-
const existing = cache2.get(ctx);
|
|
27276
|
-
if (existing)
|
|
27277
|
-
return existing;
|
|
27278
|
-
const files = [];
|
|
27279
|
-
const walk = (dir) => {
|
|
27280
|
-
for (const entry of readdirSync8(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
27281
|
-
const abs = join13(dir, entry.name);
|
|
27282
|
-
if (entry.isDirectory()) {
|
|
27283
|
-
if (!entry.name.startsWith(".") && !SKIP.has(entry.name))
|
|
27284
|
-
walk(abs);
|
|
27285
|
-
} else if (entry.isFile() && /\.(?:[cm]?[jt]sx?|py|jsonc?|toml)$/.test(entry.name) && !/\.d\.[cm]?ts$/.test(entry.name)) {
|
|
27286
|
-
const path = relative10(ctx.rootDir, abs).split("\\").join("/");
|
|
27287
|
-
try {
|
|
27288
|
-
const text = readFileSync15(abs, "utf8");
|
|
27289
|
-
if (text.length > 1024 * 1024)
|
|
27290
|
-
continue;
|
|
27291
|
-
const source = ctx.programFor(path)?.getSourceFile(abs) ?? import_typescript11.default.createSourceFile(abs, text, import_typescript11.default.ScriptTarget.Latest, true, path.endsWith("tsx") ? import_typescript11.default.ScriptKind.TSX : import_typescript11.default.ScriptKind.TS);
|
|
27292
|
-
files.push({ path, text, source });
|
|
27293
|
-
} catch {}
|
|
27294
|
-
}
|
|
27295
|
-
}
|
|
27296
|
-
};
|
|
27297
|
-
walk(ctx.rootDir);
|
|
27298
|
-
const workers = [];
|
|
27299
|
-
const paths = new Set(files.map((file) => file.path));
|
|
27300
|
-
const closure = (main) => {
|
|
27301
|
-
const found = new Set, pending = [main];
|
|
27302
|
-
for (let index = 0;index < pending.length; index++) {
|
|
27303
|
-
const path = pending[index];
|
|
27304
|
-
if (found.has(path))
|
|
27305
|
-
continue;
|
|
27306
|
-
found.add(path);
|
|
27307
|
-
const file = files.find((entry) => entry.path === path);
|
|
27308
|
-
if (!file)
|
|
27309
|
-
continue;
|
|
27310
|
-
for (const ref of import_typescript11.default.preProcessFile(file.text, true, true).importedFiles) {
|
|
27311
|
-
if (!ref.fileName.startsWith("."))
|
|
27312
|
-
continue;
|
|
27313
|
-
const base = posix2.normalize(posix2.join(posix2.dirname(path), ref.fileName)).replace(/\.[cm]?js$/, "");
|
|
27314
|
-
const target = [base, ...[".ts", ".tsx", ".js", ".mjs", "/index.ts", "/index.js"].map((suffix) => base + suffix)].find((candidate) => paths.has(candidate));
|
|
27315
|
-
if (target)
|
|
27316
|
-
pending.push(target);
|
|
27317
|
-
}
|
|
27318
|
-
}
|
|
27319
|
-
return found;
|
|
27320
|
-
};
|
|
27321
|
-
for (const file of files)
|
|
27322
|
-
if (/(?:^|\/)wrangler(?:\.[\w.-]+)?\.(?:jsonc?|toml)$/.test(file.path)) {
|
|
27323
|
-
try {
|
|
27324
|
-
const config2 = file.path.endsWith(".toml") ? parse(file.text) : JSON.parse(stripJsonc(file.text));
|
|
27325
|
-
const variants = [["default", config2], ...Object.entries(config2.env ?? {}).map(([name, section]) => [name, { ...config2, ...section, queues: section.queues, workflows: section.workflows }])];
|
|
27326
|
-
for (const [environment, section] of variants) {
|
|
27327
|
-
if (typeof section.main !== "string" || isTestWorkerConfig({ path: file.path, name: section.name, mains: [section.main] }))
|
|
27328
|
-
continue;
|
|
27329
|
-
const main = posix2.normalize(posix2.join(dirname10(file.path), section.main));
|
|
27330
|
-
workers.push({ id: `${file.path}#${environment}`, main, cron: Boolean(section.triggers?.crons?.length), queueBindings: new Set((section.queues?.producers ?? []).flatMap((producer) => typeof producer.binding === "string" ? [producer.binding] : [])), workflowClasses: (section.workflows ?? []).flatMap((binding) => typeof binding.class_name === "string" && !binding.script_name ? [binding.class_name] : []), files: closure(main) });
|
|
27331
|
-
}
|
|
27332
|
-
} catch {}
|
|
27333
|
-
}
|
|
27334
|
-
const queueBindingsFor = (path) => {
|
|
27335
|
-
const owners = workers.filter((worker) => worker.files.has(path));
|
|
27336
|
-
return new Set(owners[0] ? [...owners[0].queueBindings].filter((binding) => owners.every((worker) => worker.queueBindings.has(binding))) : []);
|
|
27337
|
-
};
|
|
27338
|
-
const reach = buildImportGraphReachability(ctx.rootDir);
|
|
27339
|
-
const repo = { files, workers, queueBindingsFor, cronEntrypoints: new Set(workers.filter((worker) => worker.cron).map((worker) => worker.main)), deployedFiles: reach.inProd, status: (path) => reach.inProd.has(path) || reach.reachable.has(path) ? "reachable" : "defined_only" };
|
|
27340
|
-
cache2.set(ctx, repo);
|
|
27341
|
-
return repo;
|
|
27342
|
-
}
|
|
27343
|
-
function lineOf5(node) {
|
|
27344
|
-
return node.getSourceFile().getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
27345
|
-
}
|
|
27346
|
-
function nameOf(node) {
|
|
27347
|
-
if (!node)
|
|
27348
|
-
return;
|
|
27349
|
-
if (import_typescript11.default.isComputedPropertyName(node) && import_typescript11.default.isStringLiteralLike(node.expression))
|
|
27350
|
-
return node.expression.text;
|
|
27351
|
-
return import_typescript11.default.isIdentifier(node) || import_typescript11.default.isStringLiteralLike(node) || import_typescript11.default.isNumericLiteral(node) ? node.text : undefined;
|
|
27352
|
-
}
|
|
27353
|
-
function visit(node, fn) {
|
|
27354
|
-
fn(node);
|
|
27355
|
-
import_typescript11.default.forEachChild(node, (child) => visit(child, fn));
|
|
27356
|
-
}
|
|
27357
|
-
function componentId(kind, path, name) {
|
|
27358
|
-
return `${kind}:${path}:${name}`;
|
|
27359
|
-
}
|
|
27360
|
-
function artifact(type, name, file, node, reason, status) {
|
|
27361
|
-
return { id: componentId(type, file.path, name), type, name, scope: "shared", sourcePath: file.path, usedByAgentIds: [], confidence: 1, evidence: [{ path: file.path, line: lineOf5(node), reason }], status };
|
|
27362
|
-
}
|
|
27363
|
-
function agent(name, file, node, reason, status) {
|
|
27364
|
-
return { id: componentId("agent", file.path, name), name, kind: "runtime_agent", root: ".", entrypointIds: [], channelAdapterIds: [], artifactIds: [], identityNamespaceIds: [], deploymentIds: [], frameworkIds: [], modelProviderIds: [], confidence: 1, evidence: [{ path: file.path, line: lineOf5(node), reason }], status };
|
|
27365
|
-
}
|
|
27366
|
-
function emptyResult() {
|
|
27367
|
-
return { runtimeAgents: [], artifacts: [], warnings: [] };
|
|
27368
|
-
}
|
|
27369
|
-
function stableResult(result) {
|
|
27370
|
-
const unique2 = (values) => [...new Map(values.map((x) => [x.id, x])).values()].sort((a, b) => a.id.localeCompare(b.id));
|
|
27371
|
-
return { runtimeAgents: unique2(result.runtimeAgents), artifacts: unique2(result.artifacts), warnings: [...new Set(result.warnings)].sort() };
|
|
27372
|
-
}
|
|
27373
|
-
|
|
27374
28353
|
// src/harness-extract/enumerators/agents.ts
|
|
27375
28354
|
function agentForScope(scope, enumeration) {
|
|
27376
28355
|
return enumeration.agentForScope(scope);
|
|
@@ -27379,15 +28358,15 @@ function createAgentScopeResolver(result, ctx) {
|
|
|
27379
28358
|
return enumerateAgents(result, ctx).agentForScope;
|
|
27380
28359
|
}
|
|
27381
28360
|
var enumerations = new WeakMap;
|
|
27382
|
-
var
|
|
28361
|
+
var AGENT_BASES4 = new Set(["Think", "Agent", "AIChatAgent", "McpAgent"]);
|
|
27383
28362
|
var HTTP_METHODS2 = new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]);
|
|
27384
28363
|
function routeOf(fn, file) {
|
|
27385
28364
|
const name = functionName(fn);
|
|
27386
28365
|
if (name && HTTP_METHODS2.has(name) && /(?:^|\/)(?:route|\+server)\.[cm]?[jt]sx?$/.test(file.path))
|
|
27387
28366
|
return `${name} ${file.path}`;
|
|
27388
28367
|
const parent = fn.parent;
|
|
27389
|
-
if (parent &&
|
|
27390
|
-
const path = parent.arguments.find(
|
|
28368
|
+
if (parent && import_typescript14.default.isCallExpression(parent) && import_typescript14.default.isPropertyAccessExpression(parent.expression) && /^(get|post|put|patch|delete|all|on)$/.test(parent.expression.name.text)) {
|
|
28369
|
+
const path = parent.arguments.find(import_typescript14.default.isStringLiteralLike);
|
|
27391
28370
|
if (path)
|
|
27392
28371
|
return `${parent.expression.name.text.toUpperCase()} ${path.text} (${file.path})`;
|
|
27393
28372
|
}
|
|
@@ -27409,19 +28388,19 @@ function enumerateAgents(result, ctx) {
|
|
|
27409
28388
|
continue;
|
|
27410
28389
|
const checker = ctx.checkerFor(file.path);
|
|
27411
28390
|
visit(file.source, (node) => {
|
|
27412
|
-
if ((
|
|
28391
|
+
if ((import_typescript14.default.isClassDeclaration(node) || import_typescript14.default.isClassExpression(node)) && node.name) {
|
|
27413
28392
|
const name2 = node.name.text;
|
|
27414
28393
|
const info = checker ? frameworkBaseOf(node, checker, memo) : undefined;
|
|
27415
28394
|
const directBase = node.heritageClauses?.flatMap((h) => h.types).map((x) => x.expression.getText()) ?? [];
|
|
27416
28395
|
const protocolEvents = new Set;
|
|
27417
28396
|
visit(node, (member2) => {
|
|
27418
|
-
if (
|
|
28397
|
+
if (import_typescript14.default.isStringLiteralLike(member2))
|
|
27419
28398
|
protocolEvents.add(member2.text);
|
|
27420
28399
|
});
|
|
27421
28400
|
const realtime = protocolEvents.has("session.update") && protocolEvents.has("response.create") && [...protocolEvents].some((event) => event.includes("function_call"));
|
|
27422
|
-
const exported =
|
|
27423
|
-
const abstract =
|
|
27424
|
-
if (!abstract && (exported || bound.has(name2)) && (info?.base &&
|
|
28401
|
+
const exported = import_typescript14.default.getCombinedModifierFlags(node) & import_typescript14.default.ModifierFlags.Export;
|
|
28402
|
+
const abstract = import_typescript14.default.getCombinedModifierFlags(node) & import_typescript14.default.ModifierFlags.Abstract;
|
|
28403
|
+
if (!abstract && (exported || bound.has(name2)) && (info?.base && AGENT_BASES4.has(info.base) || directBase.some((x) => AGENT_BASES4.has(x)) || exported && realtime)) {
|
|
27425
28404
|
classes.push({ file, node, name: name2, chain: info?.chain ?? [name2, ...directBase] });
|
|
27426
28405
|
}
|
|
27427
28406
|
}
|
|
@@ -27458,10 +28437,10 @@ function enumerateAgents(result, ctx) {
|
|
|
27458
28437
|
};
|
|
27459
28438
|
if (name) {
|
|
27460
28439
|
const parts = [qualified(node, name)];
|
|
27461
|
-
const member2 =
|
|
27462
|
-
const object = member2 &&
|
|
28440
|
+
const member2 = import_typescript14.default.isMethodDeclaration(node) || import_typescript14.default.isGetAccessorDeclaration(node) || import_typescript14.default.isSetAccessorDeclaration(node) ? node : import_typescript14.default.isPropertyAssignment(node.parent) ? node.parent : undefined;
|
|
28441
|
+
const object = member2 && import_typescript14.default.isObjectLiteralExpression(member2.parent) ? member2.parent : undefined;
|
|
27463
28442
|
if (object)
|
|
27464
|
-
parts.unshift(
|
|
28443
|
+
parts.unshift(import_typescript14.default.isVariableDeclaration(object.parent) && import_typescript14.default.isIdentifier(object.parent.name) ? object.parent.name.text : `L${lineOf5(object)}`);
|
|
27465
28444
|
for (let outer = (object ?? node).parent;outer; outer = outer.parent) {
|
|
27466
28445
|
if (isFunctionLike(outer)) {
|
|
27467
28446
|
const outerName = functionName(outer);
|
|
@@ -27483,7 +28462,7 @@ function enumerateAgents(result, ctx) {
|
|
|
27483
28462
|
const checker = ctx.checkerFor(node.getSourceFile().fileName.slice(ctx.rootDir.length + 1));
|
|
27484
28463
|
const bases = node.heritageClauses?.flatMap((clause) => clause.types).flatMap((base) => {
|
|
27485
28464
|
const declaration = checker && valueDeclaration(resolvedSymbol(base.expression, checker));
|
|
27486
|
-
return declaration &&
|
|
28465
|
+
return declaration && import_typescript14.default.isClassLike(declaration) ? classChain(declaration, seen) : [];
|
|
27487
28466
|
}) ?? [];
|
|
27488
28467
|
return [node, ...bases];
|
|
27489
28468
|
};
|
|
@@ -27499,32 +28478,32 @@ function enumerateAgents(result, ctx) {
|
|
|
27499
28478
|
return;
|
|
27500
28479
|
};
|
|
27501
28480
|
const bindingTruth = (condition, worker) => {
|
|
27502
|
-
if (condition.kind ===
|
|
28481
|
+
if (condition.kind === import_typescript14.default.SyntaxKind.TrueKeyword)
|
|
27503
28482
|
return true;
|
|
27504
|
-
if (condition.kind ===
|
|
28483
|
+
if (condition.kind === import_typescript14.default.SyntaxKind.FalseKeyword)
|
|
27505
28484
|
return false;
|
|
27506
|
-
if (
|
|
28485
|
+
if (import_typescript14.default.isPrefixUnaryExpression(condition) && condition.operator === import_typescript14.default.SyntaxKind.ExclamationToken) {
|
|
27507
28486
|
const value = bindingTruth(condition.operand, worker);
|
|
27508
28487
|
return value === undefined ? undefined : !value;
|
|
27509
28488
|
}
|
|
27510
|
-
if (
|
|
28489
|
+
if (import_typescript14.default.isPropertyAccessExpression(condition) && /^(?:this\.)?env$/.test(condition.expression.getText()) && (worker ? repo.workers.find((entry) => entry.id === worker)?.queueBindings : repo.queueBindingsFor(condition.getSourceFile().fileName.slice(ctx.rootDir.length + 1)))?.has(condition.name.text))
|
|
27511
28490
|
return true;
|
|
27512
28491
|
return;
|
|
27513
28492
|
};
|
|
27514
|
-
const returns = (node) => Boolean(node && (
|
|
28493
|
+
const returns = (node) => Boolean(node && (import_typescript14.default.isReturnStatement(node) || import_typescript14.default.isBlock(node) && node.statements.length && import_typescript14.default.isReturnStatement(node.statements[node.statements.length - 1])));
|
|
27515
28494
|
const deployed = (node, worker) => {
|
|
27516
28495
|
for (let current = node;current.parent; current = current.parent) {
|
|
27517
28496
|
const parent = current.parent;
|
|
27518
|
-
if (
|
|
28497
|
+
if (import_typescript14.default.isIfStatement(parent)) {
|
|
27519
28498
|
const truth = bindingTruth(parent.expression, worker);
|
|
27520
28499
|
if (truth !== undefined && (current === parent.thenStatement ? !truth : current === parent.elseStatement ? truth : false))
|
|
27521
28500
|
return false;
|
|
27522
28501
|
}
|
|
27523
|
-
if (
|
|
28502
|
+
if (import_typescript14.default.isBlock(parent))
|
|
27524
28503
|
for (const prior of parent.statements) {
|
|
27525
28504
|
if (prior.getStart() >= current.getStart())
|
|
27526
28505
|
break;
|
|
27527
|
-
if (
|
|
28506
|
+
if (import_typescript14.default.isIfStatement(prior)) {
|
|
27528
28507
|
const truth = bindingTruth(prior.expression, worker);
|
|
27529
28508
|
if (truth !== undefined && returns(truth ? prior.thenStatement : prior.elseStatement))
|
|
27530
28509
|
return false;
|
|
@@ -27550,7 +28529,7 @@ function enumerateAgents(result, ctx) {
|
|
|
27550
28529
|
const descend = (node) => {
|
|
27551
28530
|
if (node.getStart() <= offset && node.getEnd() >= offset) {
|
|
27552
28531
|
anchor = node;
|
|
27553
|
-
|
|
28532
|
+
import_typescript14.default.forEachChild(node, descend);
|
|
27554
28533
|
}
|
|
27555
28534
|
};
|
|
27556
28535
|
descend(file.source);
|
|
@@ -27559,21 +28538,21 @@ function enumerateAgents(result, ctx) {
|
|
|
27559
28538
|
continue;
|
|
27560
28539
|
markModel(scope, anchor);
|
|
27561
28540
|
const tools = site.toolsArg ? ctx.nodeAt(site.toolsArg) : undefined;
|
|
27562
|
-
scope.hasTools ||= Boolean(tools && !(
|
|
28541
|
+
scope.hasTools ||= Boolean(tools && !(import_typescript14.default.isObjectLiteralExpression(tools) && tools.properties.length === 0) && !(import_typescript14.default.isArrayLiteralExpression(tools) && tools.elements.length === 0));
|
|
27563
28542
|
scope.aliases.push(site.scope);
|
|
27564
28543
|
}
|
|
27565
28544
|
const targetsOf = (node, file) => {
|
|
27566
28545
|
const checker = ctx.checkerFor(file.path);
|
|
27567
28546
|
if (!checker)
|
|
27568
28547
|
return [];
|
|
27569
|
-
const at =
|
|
28548
|
+
const at = import_typescript14.default.isPropertyAccessExpression(node) ? node.name : node;
|
|
27570
28549
|
const declaration = valueDeclaration(resolvedSymbol(at, checker));
|
|
27571
28550
|
if (!declaration)
|
|
27572
28551
|
return [];
|
|
27573
28552
|
const direct = byNode.get(declaration) ?? scopes.get(keyOf(declaration));
|
|
27574
28553
|
if (direct)
|
|
27575
28554
|
return [direct];
|
|
27576
|
-
if (
|
|
28555
|
+
if (import_typescript14.default.isVariableDeclaration(declaration) && declaration.initializer) {
|
|
27577
28556
|
const fn = byNode.get(declaration.initializer) ?? scopes.get(keyOf(declaration.initializer));
|
|
27578
28557
|
if (fn)
|
|
27579
28558
|
return [fn];
|
|
@@ -27585,19 +28564,19 @@ function enumerateAgents(result, ctx) {
|
|
|
27585
28564
|
if (node !== scope.node && isFunctionLike(node)) {
|
|
27586
28565
|
return;
|
|
27587
28566
|
}
|
|
27588
|
-
if (
|
|
28567
|
+
if (import_typescript14.default.isWhileStatement(node) || import_typescript14.default.isDoStatement(node) || import_typescript14.default.isForStatement(node) || import_typescript14.default.isForOfStatement(node))
|
|
27589
28568
|
scope.hasLoop = true;
|
|
27590
|
-
if ((
|
|
28569
|
+
if ((import_typescript14.default.isIdentifier(node) || import_typescript14.default.isStringLiteralLike(node)) && /^(?:tool_calls|toolCalls|tool_use|tool_result|tool_results|toolResults)$/.test(node.text)) {
|
|
27591
28570
|
scope.hasTools = true;
|
|
27592
28571
|
scope.toolFeedback = true;
|
|
27593
28572
|
}
|
|
27594
|
-
if (
|
|
27595
|
-
const fields = new Map(node.properties.filter(
|
|
28573
|
+
if (import_typescript14.default.isObjectLiteralExpression(node)) {
|
|
28574
|
+
const fields = new Map(node.properties.filter(import_typescript14.default.isPropertyAssignment).map((p2) => [nameOf(p2.name), p2.initializer]));
|
|
27596
28575
|
const type = fields.get("type");
|
|
27597
|
-
if (type &&
|
|
28576
|
+
if (type && import_typescript14.default.isStringLiteralLike(type) && type.text === "tool" && fields.has("name"))
|
|
27598
28577
|
scope.forcedOutput = true;
|
|
27599
28578
|
}
|
|
27600
|
-
if (
|
|
28579
|
+
if (import_typescript14.default.isCallExpression(node) || import_typescript14.default.isNewExpression(node)) {
|
|
27601
28580
|
const callee = node.expression.getText();
|
|
27602
28581
|
if (/(?:chat\.)?completions\.create$|messages\.(?:create|stream)$|responses\.(?:create|stream)$/.test(callee))
|
|
27603
28582
|
markModel(scope, node);
|
|
@@ -27605,7 +28584,7 @@ function enumerateAgents(result, ctx) {
|
|
|
27605
28584
|
markModel(scope, node);
|
|
27606
28585
|
const connect = (at) => {
|
|
27607
28586
|
for (const target of byNode.has(at) ? [byNode.get(at)] : targetsOf(at, scope.file)) {
|
|
27608
|
-
if (
|
|
28587
|
+
if (import_typescript14.default.isPropertyAccessExpression(at) && at.expression.kind === import_typescript14.default.SyntaxKind.ThisKeyword) {
|
|
27609
28588
|
virtualEdges.set(`${scope.key}|${target.key}`, at.name.text);
|
|
27610
28589
|
scope.virtualCalls.set(target.key, at.name.text);
|
|
27611
28590
|
}
|
|
@@ -27624,30 +28603,30 @@ function enumerateAgents(result, ctx) {
|
|
|
27624
28603
|
connect(at);
|
|
27625
28604
|
return;
|
|
27626
28605
|
}
|
|
27627
|
-
if (
|
|
28606
|
+
if (import_typescript14.default.isIdentifier(at) || import_typescript14.default.isPropertyAccessExpression(at))
|
|
27628
28607
|
connect(at);
|
|
27629
|
-
|
|
28608
|
+
import_typescript14.default.forEachChild(at, connectArgument);
|
|
27630
28609
|
};
|
|
27631
28610
|
for (const argument of node.arguments ?? [])
|
|
27632
28611
|
connectArgument(argument);
|
|
27633
28612
|
for (const argument of node.arguments ?? [])
|
|
27634
|
-
if (
|
|
28613
|
+
if (import_typescript14.default.isObjectLiteralExpression(argument)) {
|
|
27635
28614
|
const fields = new Set(argument.properties.map((p2) => nameOf(p2.name)));
|
|
27636
28615
|
if (fields.has("model") && fields.has("messages") && fields.has("tools")) {
|
|
27637
28616
|
markModel(scope, node);
|
|
27638
28617
|
scope.hasTools = true;
|
|
27639
28618
|
}
|
|
27640
28619
|
}
|
|
27641
|
-
if (/(?:^|\.)(?:stepCountIs|isStepCount)$/.test(node.expression.getText()) && node.arguments?.[0] &&
|
|
28620
|
+
if (/(?:^|\.)(?:stepCountIs|isStepCount)$/.test(node.expression.getText()) && node.arguments?.[0] && import_typescript14.default.isNumericLiteral(node.arguments?.[0]) && Number(node.arguments?.[0].text) > 1) {
|
|
27642
28621
|
scope.hasLoop = true;
|
|
27643
28622
|
scope.configuredSteps = true;
|
|
27644
28623
|
}
|
|
27645
28624
|
}
|
|
27646
|
-
if (
|
|
28625
|
+
if (import_typescript14.default.isPropertyAssignment(node) && nameOf(node.name) === "maxSteps" && import_typescript14.default.isNumericLiteral(node.initializer) && Number(node.initializer.text) > 1) {
|
|
27647
28626
|
scope.hasLoop = true;
|
|
27648
28627
|
scope.configuredSteps = true;
|
|
27649
28628
|
}
|
|
27650
|
-
|
|
28629
|
+
import_typescript14.default.forEachChild(node, inspect);
|
|
27651
28630
|
};
|
|
27652
28631
|
inspect(scope.node);
|
|
27653
28632
|
}
|
|
@@ -27672,19 +28651,19 @@ function enumerateAgents(result, ctx) {
|
|
|
27672
28651
|
values.add(id);
|
|
27673
28652
|
};
|
|
27674
28653
|
for (const cls of classes) {
|
|
27675
|
-
const
|
|
27676
|
-
agents.set(
|
|
28654
|
+
const emitted2 = agent(cls.name, cls.file, cls.node, "Concrete agent/framework class or realtime model/tool bridge", repo.status(cls.file.path));
|
|
28655
|
+
agents.set(emitted2.id, emitted2);
|
|
27677
28656
|
}
|
|
27678
28657
|
for (const scope of scopes.values()) {
|
|
27679
28658
|
let nestedInFunction = false;
|
|
27680
|
-
for (let parent = scope.node.parent;parent && !
|
|
28659
|
+
for (let parent = scope.node.parent;parent && !import_typescript14.default.isClassLike(parent); parent = parent.parent)
|
|
27681
28660
|
if (isFunctionLike(parent)) {
|
|
27682
28661
|
nestedInFunction = true;
|
|
27683
28662
|
break;
|
|
27684
28663
|
}
|
|
27685
28664
|
if (scope.className && !nestedInFunction) {
|
|
27686
28665
|
let member2 = scope.node;
|
|
27687
|
-
while (member2.parent && !
|
|
28666
|
+
while (member2.parent && !import_typescript14.default.isClassLike(member2.parent))
|
|
27688
28667
|
member2 = member2.parent;
|
|
27689
28668
|
const memberName = "name" in member2 ? nameOf(member2.name) : undefined;
|
|
27690
28669
|
for (const cls of classes) {
|
|
@@ -27709,9 +28688,9 @@ function enumerateAgents(result, ctx) {
|
|
|
27709
28688
|
const name = boundary.route ?? functionName(boundary.node);
|
|
27710
28689
|
if (!name)
|
|
27711
28690
|
continue;
|
|
27712
|
-
const
|
|
27713
|
-
agents.set(
|
|
27714
|
-
assign(boundary.key,
|
|
28691
|
+
const emitted2 = agent(name, boundary.file, scope.node, "Function or route owns a multi-step model/tool feedback loop", repo.status(boundary.file.path));
|
|
28692
|
+
agents.set(emitted2.id, emitted2);
|
|
28693
|
+
assign(boundary.key, emitted2.id);
|
|
27715
28694
|
}
|
|
27716
28695
|
}
|
|
27717
28696
|
let changed = true;
|
|
@@ -27778,7 +28757,7 @@ function enumerateAgents(result, ctx) {
|
|
|
27778
28757
|
}
|
|
27779
28758
|
|
|
27780
28759
|
// src/harness-extract/enumerators/workflows.ts
|
|
27781
|
-
var
|
|
28760
|
+
var import_typescript15 = __toESM(require_typescript(), 1);
|
|
27782
28761
|
function enumerateWorkflows(result, ctx) {
|
|
27783
28762
|
const output = emptyResult();
|
|
27784
28763
|
const repo = enumerationRepository(ctx);
|
|
@@ -27791,10 +28770,10 @@ function enumerateWorkflows(result, ctx) {
|
|
|
27791
28770
|
continue;
|
|
27792
28771
|
for (const name of worker.workflowClasses) {
|
|
27793
28772
|
let exported = checker.getExportsOfModule(module).find((symbol) => symbol.name === name);
|
|
27794
|
-
if (exported && exported.flags &
|
|
28773
|
+
if (exported && exported.flags & import_typescript15.default.SymbolFlags.Alias)
|
|
27795
28774
|
exported = checker.getAliasedSymbol(exported);
|
|
27796
28775
|
const declaration = exported && valueDeclaration(exported);
|
|
27797
|
-
if (declaration &&
|
|
28776
|
+
if (declaration && import_typescript15.default.isClassDeclaration(declaration))
|
|
27798
28777
|
bindings.add(nodeKey(declaration));
|
|
27799
28778
|
}
|
|
27800
28779
|
}
|
|
@@ -27803,7 +28782,7 @@ function enumerateWorkflows(result, ctx) {
|
|
|
27803
28782
|
if (!/\.[cm]?[jt]sx?$/.test(file.path) || TEST_PATH4.test(file.path) || EVAL_PATH2.test(file.path))
|
|
27804
28783
|
continue;
|
|
27805
28784
|
visit(file.source, (node) => {
|
|
27806
|
-
if (!
|
|
28785
|
+
if (!import_typescript15.default.isClassDeclaration(node) || !node.name || import_typescript15.default.getCombinedModifierFlags(node) & import_typescript15.default.ModifierFlags.Abstract)
|
|
27807
28786
|
return;
|
|
27808
28787
|
const checker = ctx.checkerFor(file.path);
|
|
27809
28788
|
const base = checker ? frameworkBaseOf(node, checker, memo)?.base : undefined;
|
|
@@ -27828,7 +28807,7 @@ function enumerateWorkflows(result, ctx) {
|
|
|
27828
28807
|
if (!cls || !workerClasses.has(nodeKey(cls)))
|
|
27829
28808
|
return calls;
|
|
27830
28809
|
const member2 = scope.node.parent === cls ? scope.node : scope.node.parent;
|
|
27831
|
-
if (
|
|
28810
|
+
if (import_typescript15.default.getCombinedModifierFlags(member2) & import_typescript15.default.ModifierFlags.Static)
|
|
27832
28811
|
return calls;
|
|
27833
28812
|
return new Set([...calls].map((key) => {
|
|
27834
28813
|
const method = scope.virtualCalls.get(key);
|
|
@@ -27842,24 +28821,24 @@ function enumerateWorkflows(result, ctx) {
|
|
|
27842
28821
|
if (!node || visited.has(node))
|
|
27843
28822
|
return;
|
|
27844
28823
|
visited.add(node);
|
|
27845
|
-
if (
|
|
28824
|
+
if (import_typescript15.default.isParenthesizedExpression(node) || import_typescript15.default.isAsExpression(node) || import_typescript15.default.isSatisfiesExpression(node) || import_typescript15.default.isNonNullExpression(node)) {
|
|
27846
28825
|
resolveWorker(node.expression);
|
|
27847
28826
|
return;
|
|
27848
28827
|
}
|
|
27849
|
-
if (
|
|
28828
|
+
if (import_typescript15.default.isCallExpression(node) && /(?:^|\.)withSentry$/.test(node.expression.getText())) {
|
|
27850
28829
|
for (const argument of node.arguments)
|
|
27851
28830
|
resolveWorker(argument);
|
|
27852
28831
|
return;
|
|
27853
28832
|
}
|
|
27854
|
-
if (
|
|
28833
|
+
if (import_typescript15.default.isExportAssignment(node)) {
|
|
27855
28834
|
resolveWorker(node.expression);
|
|
27856
28835
|
return;
|
|
27857
28836
|
}
|
|
27858
|
-
if (
|
|
28837
|
+
if (import_typescript15.default.isVariableDeclaration(node)) {
|
|
27859
28838
|
resolveWorker(node.initializer);
|
|
27860
28839
|
return;
|
|
27861
28840
|
}
|
|
27862
|
-
if (
|
|
28841
|
+
if (import_typescript15.default.isIdentifier(node) && checker) {
|
|
27863
28842
|
resolveWorker(valueDeclaration(resolvedSymbol(node, checker)));
|
|
27864
28843
|
return;
|
|
27865
28844
|
}
|
|
@@ -27867,17 +28846,17 @@ function enumerateWorkflows(result, ctx) {
|
|
|
27867
28846
|
};
|
|
27868
28847
|
const module = mainFile && checker?.getSymbolAtLocation(mainFile.source);
|
|
27869
28848
|
const exported = module && checker?.getExportsOfModule(module).find((symbol2) => symbol2.name === "default");
|
|
27870
|
-
const symbol = exported && checker && (exported.flags &
|
|
28849
|
+
const symbol = exported && checker && (exported.flags & import_typescript15.default.SymbolFlags.Alias ? checker.getAliasedSymbol(exported) : exported);
|
|
27871
28850
|
resolveWorker(symbol && valueDeclaration(symbol));
|
|
27872
28851
|
const collectImplementations = (node) => {
|
|
27873
|
-
if (!
|
|
28852
|
+
if (!import_typescript15.default.isClassLike(node) || workerClasses.has(nodeKey(node)))
|
|
27874
28853
|
return;
|
|
27875
28854
|
workerClasses.add(nodeKey(node));
|
|
27876
28855
|
for (const member2 of node.members) {
|
|
27877
|
-
if (
|
|
28856
|
+
if (import_typescript15.default.getCombinedModifierFlags(member2) & import_typescript15.default.ModifierFlags.Static)
|
|
27878
28857
|
continue;
|
|
27879
28858
|
const name = nameOf(member2.name);
|
|
27880
|
-
const implementation = byKey.get(nodeKey(member2)) ?? (
|
|
28859
|
+
const implementation = byKey.get(nodeKey(member2)) ?? (import_typescript15.default.isPropertyDeclaration(member2) && member2.initializer ? byKey.get(nodeKey(member2.initializer)) : undefined);
|
|
27881
28860
|
if (name && !implementations.has(name))
|
|
27882
28861
|
implementations.set(name, implementation?.key ?? "(non-callable override)");
|
|
27883
28862
|
}
|
|
@@ -27904,19 +28883,19 @@ function enumerateWorkflows(result, ctx) {
|
|
|
27904
28883
|
if (!node || seen2.has(node))
|
|
27905
28884
|
return;
|
|
27906
28885
|
seen2.add(node);
|
|
27907
|
-
if (
|
|
28886
|
+
if (import_typescript15.default.isIdentifier(node) && checker) {
|
|
27908
28887
|
resolveScheduled(valueDeclaration(resolvedSymbol(node, checker)), seen2);
|
|
27909
28888
|
return;
|
|
27910
28889
|
}
|
|
27911
|
-
if (
|
|
28890
|
+
if (import_typescript15.default.isVariableDeclaration(node) || import_typescript15.default.isPropertyAssignment(node) || import_typescript15.default.isPropertyDeclaration(node)) {
|
|
27912
28891
|
resolveScheduled(node.initializer, seen2);
|
|
27913
28892
|
return;
|
|
27914
28893
|
}
|
|
27915
|
-
if (
|
|
28894
|
+
if (import_typescript15.default.isShorthandPropertyAssignment(node)) {
|
|
27916
28895
|
resolveScheduled(checker && valueDeclaration(checker.getShorthandAssignmentValueSymbol(node)), seen2);
|
|
27917
28896
|
return;
|
|
27918
28897
|
}
|
|
27919
|
-
if (
|
|
28898
|
+
if (import_typescript15.default.isParenthesizedExpression(node) || import_typescript15.default.isAsExpression(node) || import_typescript15.default.isSatisfiesExpression(node) || import_typescript15.default.isNonNullExpression(node)) {
|
|
27920
28899
|
resolveScheduled(node.expression, seen2);
|
|
27921
28900
|
return;
|
|
27922
28901
|
}
|
|
@@ -27926,11 +28905,11 @@ function enumerateWorkflows(result, ctx) {
|
|
|
27926
28905
|
if (seen2.has(node))
|
|
27927
28906
|
return;
|
|
27928
28907
|
seen2.add(node);
|
|
27929
|
-
const members =
|
|
27930
|
-
const handlers = members.filter((member2) => nameOf(member2.name) === "scheduled" && !(
|
|
28908
|
+
const members = import_typescript15.default.isObjectLiteralExpression(node) ? node.properties : import_typescript15.default.isClassLike(node) ? node.members : [];
|
|
28909
|
+
const handlers = members.filter((member2) => nameOf(member2.name) === "scheduled" && !(import_typescript15.default.getCombinedModifierFlags(member2) & import_typescript15.default.ModifierFlags.Static));
|
|
27931
28910
|
for (const member2 of handlers)
|
|
27932
28911
|
resolveScheduled(member2);
|
|
27933
|
-
if (!handlers.length &&
|
|
28912
|
+
if (!handlers.length && import_typescript15.default.isClassLike(node) && checker)
|
|
27934
28913
|
for (const base of node.heritageClauses?.flatMap((clause) => clause.types) ?? []) {
|
|
27935
28914
|
const declaration = valueDeclaration(resolvedSymbol(base.expression, checker));
|
|
27936
28915
|
if (declaration)
|
|
@@ -27976,7 +28955,7 @@ function enumerateWorkflows(result, ctx) {
|
|
|
27976
28955
|
}
|
|
27977
28956
|
|
|
27978
28957
|
// src/harness-extract/enumerators/catalog.ts
|
|
27979
|
-
var
|
|
28958
|
+
var import_typescript16 = __toESM(require_typescript(), 1);
|
|
27980
28959
|
var THINK_WORKSPACE_TOOLS = ["read", "write", "edit", "list", "find", "grep", "delete"];
|
|
27981
28960
|
function strings(expression, checker, seen = new Set) {
|
|
27982
28961
|
if (!expression)
|
|
@@ -27985,35 +28964,35 @@ function strings(expression, checker, seen = new Set) {
|
|
|
27985
28964
|
if (seen.has(node))
|
|
27986
28965
|
return [];
|
|
27987
28966
|
seen.add(node);
|
|
27988
|
-
if (
|
|
28967
|
+
if (import_typescript16.default.isIdentifier(node)) {
|
|
27989
28968
|
const declaration = checker && valueDeclaration(resolvedSymbol(node, checker));
|
|
27990
|
-
if (!declaration || !
|
|
28969
|
+
if (!declaration || !import_typescript16.default.isVariableDeclaration(declaration))
|
|
27991
28970
|
return [];
|
|
27992
28971
|
return strings(declaration.initializer, checker, seen);
|
|
27993
28972
|
}
|
|
27994
|
-
if (
|
|
27995
|
-
return node.elements.flatMap((entry) =>
|
|
27996
|
-
if (
|
|
28973
|
+
if (import_typescript16.default.isArrayLiteralExpression(node))
|
|
28974
|
+
return node.elements.flatMap((entry) => import_typescript16.default.isSpreadElement(entry) ? strings(entry.expression, checker, seen) : strings(entry, checker, seen));
|
|
28975
|
+
if (import_typescript16.default.isStringLiteralLike(node))
|
|
27997
28976
|
return [{ name: node.text, node }];
|
|
27998
|
-
if (
|
|
28977
|
+
if (import_typescript16.default.isNewExpression(node) && node.expression.getText() === "Set")
|
|
27999
28978
|
return strings(node.arguments?.[0], checker, seen);
|
|
28000
28979
|
return [];
|
|
28001
28980
|
}
|
|
28002
28981
|
function property(object, name) {
|
|
28003
28982
|
const entry = object.properties.find((item) => item.name && nameOf(item.name) === name);
|
|
28004
|
-
return entry &&
|
|
28983
|
+
return entry && import_typescript16.default.isPropertyAssignment(entry) ? entry.initializer : entry && import_typescript16.default.isShorthandPropertyAssignment(entry) ? entry.name : undefined;
|
|
28005
28984
|
}
|
|
28006
28985
|
function inheritedTrue(node, propertyName2, checker, seen = new Set) {
|
|
28007
28986
|
if (seen.has(node))
|
|
28008
28987
|
return false;
|
|
28009
28988
|
seen.add(node);
|
|
28010
28989
|
const own = node.members.find((member2) => nameOf(member2.name) === propertyName2);
|
|
28011
|
-
if (own &&
|
|
28012
|
-
return unwrap(own.initializer).kind ===
|
|
28990
|
+
if (own && import_typescript16.default.isPropertyDeclaration(own) && own.initializer)
|
|
28991
|
+
return unwrap(own.initializer).kind === import_typescript16.default.SyntaxKind.TrueKeyword;
|
|
28013
28992
|
if (checker)
|
|
28014
28993
|
for (const base of node.heritageClauses?.flatMap((h) => h.types) ?? []) {
|
|
28015
28994
|
const declaration = valueDeclaration(resolvedSymbol(base.expression, checker));
|
|
28016
|
-
if (declaration && (
|
|
28995
|
+
if (declaration && (import_typescript16.default.isClassDeclaration(declaration) || import_typescript16.default.isClassExpression(declaration)))
|
|
28017
28996
|
return inheritedTrue(declaration, propertyName2, checker, seen);
|
|
28018
28997
|
}
|
|
28019
28998
|
return false;
|
|
@@ -28028,10 +29007,10 @@ function enumerateToolCatalog(result, ctx) {
|
|
|
28028
29007
|
if (!owners.length || !checker)
|
|
28029
29008
|
continue;
|
|
28030
29009
|
visit(scope.node, (node) => {
|
|
28031
|
-
if (!
|
|
29010
|
+
if (!import_typescript16.default.isIdentifier(node) || !/ALLOW|MCP_NAME/.test(node.text))
|
|
28032
29011
|
return;
|
|
28033
29012
|
const declaration = valueDeclaration(resolvedSymbol(node, checker));
|
|
28034
|
-
if (!declaration || !
|
|
29013
|
+
if (!declaration || !import_typescript16.default.isVariableDeclaration(declaration) || !import_typescript16.default.isIdentifier(declaration.name))
|
|
28035
29014
|
return;
|
|
28036
29015
|
const key = `${declaration.getSourceFile().fileName}:${declaration.name.text}`;
|
|
28037
29016
|
let existing = symbolOwners.get(key);
|
|
@@ -28052,7 +29031,7 @@ function enumerateToolCatalog(result, ctx) {
|
|
|
28052
29031
|
if (!file || !checker)
|
|
28053
29032
|
continue;
|
|
28054
29033
|
visit(file.source, (node) => {
|
|
28055
|
-
if ((
|
|
29034
|
+
if ((import_typescript16.default.isClassDeclaration(node) || import_typescript16.default.isClassExpression(node)) && node.name?.text === runtime.name && frameworkBaseOf(node, checker, memo)?.base === "Think")
|
|
28056
29035
|
thinkIds.add(runtime.id);
|
|
28057
29036
|
});
|
|
28058
29037
|
}
|
|
@@ -28069,11 +29048,11 @@ function enumerateToolCatalog(result, ctx) {
|
|
|
28069
29048
|
continue;
|
|
28070
29049
|
const checker = ctx.checkerFor(file.path), declarations = new Map;
|
|
28071
29050
|
visit(file.source, (node) => {
|
|
28072
|
-
if (
|
|
29051
|
+
if (import_typescript16.default.isVariableDeclaration(node) && import_typescript16.default.isIdentifier(node.name) && node.initializer)
|
|
28073
29052
|
declarations.set(node.name.text, node.initializer);
|
|
28074
29053
|
});
|
|
28075
29054
|
visit(file.source, (node) => {
|
|
28076
|
-
if ((
|
|
29055
|
+
if ((import_typescript16.default.isClassDeclaration(node) || import_typescript16.default.isClassExpression(node)) && node.name && agentByName.has(node.name.text)) {
|
|
28077
29056
|
const info = checker ? frameworkBaseOf(node, checker, memo) : undefined;
|
|
28078
29057
|
const directThink = node.heritageClauses?.some((h) => h.types.some((t) => t.expression.getText() === "Think"));
|
|
28079
29058
|
if (info?.base === "Think" || directThink) {
|
|
@@ -28085,37 +29064,37 @@ function enumerateToolCatalog(result, ctx) {
|
|
|
28085
29064
|
add(name, file, node, "think", "Think workspace tool inherited by this concrete agent", owners2);
|
|
28086
29065
|
}
|
|
28087
29066
|
}
|
|
28088
|
-
if (
|
|
29067
|
+
if (import_typescript16.default.isPropertyAccessExpression(node) && node.name.text === "activate_skill" || import_typescript16.default.isPropertyAssignment(node) && nameOf(node.name) === "activate_skill") {
|
|
28089
29068
|
const owner = ownersAt(node, file.path);
|
|
28090
29069
|
add("activate_skill", file, node, "think", "Source explicitly exposes Think skill activation", owner);
|
|
28091
29070
|
}
|
|
28092
|
-
if (
|
|
29071
|
+
if (import_typescript16.default.isCallExpression(node) && import_typescript16.default.isPropertyAccessExpression(node.expression) && /^(?:registerTool|tool)$/.test(node.expression.name.text) && checker) {
|
|
28093
29072
|
const receiver = valueDeclaration(resolvedSymbol(node.expression.expression, checker));
|
|
28094
|
-
const init = receiver &&
|
|
28095
|
-
const origin = init &&
|
|
29073
|
+
const init = receiver && import_typescript16.default.isVariableDeclaration(receiver) && receiver.initializer ? unwrap(receiver.initializer) : undefined;
|
|
29074
|
+
const origin = init && import_typescript16.default.isNewExpression(init) && import_typescript16.default.isIdentifier(init.expression) ? importOrigin(init.expression, checker) : undefined;
|
|
28096
29075
|
const name = node.arguments[0];
|
|
28097
|
-
if (origin?.module.startsWith("@modelcontextprotocol/sdk/") && origin.imported === "McpServer" && name &&
|
|
29076
|
+
if (origin?.module.startsWith("@modelcontextprotocol/sdk/") && origin.imported === "McpServer" && name && import_typescript16.default.isStringLiteralLike(name)) {
|
|
28098
29077
|
add(name.text, file, name, "mcp_server", "MCP SDK server explicitly registers this model-facing tool name", ownersAt(node, file.path));
|
|
28099
29078
|
}
|
|
28100
29079
|
}
|
|
28101
|
-
if (
|
|
29080
|
+
if (import_typescript16.default.isCallExpression(node) && import_typescript16.default.isPropertyAccessExpression(node.expression) && node.expression.expression.getText() === "Output" && node.expression.name.text === "object") {
|
|
28102
29081
|
const owners2 = ownersAt(node, file.path).filter((id) => thinkIds.has(id));
|
|
28103
|
-
if (owners2.length && checker &&
|
|
29082
|
+
if (owners2.length && checker && import_typescript16.default.isIdentifier(node.expression.expression) && ["ai", "@cloudflare/think"].includes(importOrigin(node.expression.expression, checker)?.module ?? ""))
|
|
28104
29083
|
add("think_final_answer", file, node, "think", "Think structured output is offered as the framework final-answer tool", owners2);
|
|
28105
29084
|
}
|
|
28106
|
-
if (
|
|
29085
|
+
if (import_typescript16.default.isCallExpression(node) && import_typescript16.default.isIdentifier(node.expression) && node.expression.text === "createExecuteRuntime") {
|
|
28107
29086
|
const owners2 = ownersAt(node, file.path).filter((id) => thinkIds.has(id));
|
|
28108
29087
|
if (owners2.length && checker && importOrigin(node.expression, checker)?.module.startsWith("@cloudflare/think"))
|
|
28109
29088
|
add("execute", file, node, "think", "Think Code Mode runtime explicitly enabled for this agent", owners2);
|
|
28110
29089
|
}
|
|
28111
|
-
if (!
|
|
29090
|
+
if (!import_typescript16.default.isObjectLiteralExpression(node))
|
|
28112
29091
|
return;
|
|
28113
29092
|
const serverNames = strings(property(node, "name"), checker), allow = property(node, "allow");
|
|
28114
29093
|
if (serverNames.length !== 1 || !allow || !property(node, "url"))
|
|
28115
29094
|
return;
|
|
28116
29095
|
const server = serverNames[0].name;
|
|
28117
29096
|
const owners = ownersAt(node, file.path);
|
|
28118
|
-
if (
|
|
29097
|
+
if (import_typescript16.default.isStringLiteralLike(unwrap(allow)) && unwrap(allow).text === "all") {
|
|
28119
29098
|
const entry = add(`${server} dynamic MCP tools`, file, allow, "mcp_dynamic_group", "Server schemas are admitted dynamically as one bounded catalog group", owners);
|
|
28120
29099
|
entry.serverName = server;
|
|
28121
29100
|
entry.dynamicGroup = true;
|
|
@@ -28166,23 +29145,30 @@ function enumerateToolCatalog(result, ctx) {
|
|
|
28166
29145
|
var ENUMERATORS = [
|
|
28167
29146
|
{ id: "agents", enumerate: ({ result }, ctx) => ({ runtimeAgents: enumerateAgents(result, ctx).runtimeAgents }) },
|
|
28168
29147
|
{ id: "workflows", enumerate: ({ result }, ctx) => enumerateWorkflows(result, ctx) },
|
|
28169
|
-
{ id: "framework-mcp-catalog", enumerate: ({ result }, ctx) => enumerateToolCatalog(result, ctx) }
|
|
29148
|
+
{ id: "framework-mcp-catalog", enumerate: ({ result }, ctx) => enumerateToolCatalog(result, ctx) },
|
|
29149
|
+
{ id: "tool-registry", enumerate: ({ result }, ctx) => ({ artifacts: toolArtifacts(emitToolsCached(result, ctx), enumerateAgents(result, ctx).runtimeAgents) }) }
|
|
28170
29150
|
];
|
|
28171
29151
|
function enumerateHarnessComponents(result, ctx) {
|
|
28172
29152
|
const agents = enumerateAgents(result, ctx), workflows = enumerateWorkflows(result, ctx), catalog = enumerateToolCatalog(result, ctx);
|
|
28173
|
-
return stableResult({ runtimeAgents: agents.runtimeAgents, artifacts: [...workflows.artifacts, ...catalog.artifacts], warnings: [...workflows.warnings, ...catalog.warnings] });
|
|
29153
|
+
return stableResult({ runtimeAgents: agents.runtimeAgents, artifacts: [...workflows.artifacts, ...toolArtifacts(emitToolsCached(result, ctx), agents.runtimeAgents), ...catalog.artifacts], warnings: [...workflows.warnings, ...catalog.warnings] });
|
|
28174
29154
|
}
|
|
28175
29155
|
function mergeEnumeratedComponents(artifacts, components) {
|
|
28176
29156
|
const merged = new Map;
|
|
28177
29157
|
const definitions = new Map;
|
|
28178
|
-
|
|
29158
|
+
const registry = components.artifacts.filter((item) => item.type === "tool" && item.id.startsWith("tool.extract."));
|
|
29159
|
+
for (const item of [...registry, ...artifacts, ...components.artifacts.filter((item2) => !registry.includes(item2))]) {
|
|
28179
29160
|
const key = item.type === "tool" ? `tool:${item.name}` : item.id;
|
|
28180
|
-
if (item.type === "tool"
|
|
29161
|
+
if (item.type === "tool") {
|
|
29162
|
+
const own = item.definitionVariants ?? (item.body ? [{ sourcePath: item.sourcePath, body: item.body, evidence: item.evidence }] : []);
|
|
28181
29163
|
let variants = definitions.get(key);
|
|
28182
|
-
|
|
28183
|
-
|
|
28184
|
-
|
|
28185
|
-
variants
|
|
29164
|
+
for (const variant of own) {
|
|
29165
|
+
if (!variant.body)
|
|
29166
|
+
continue;
|
|
29167
|
+
if (!variants)
|
|
29168
|
+
definitions.set(key, variants = []);
|
|
29169
|
+
if (!variants.some((entry) => entry.id === item.id && entry.sourcePath === variant.sourcePath && entry.body === variant.body))
|
|
29170
|
+
variants.push({ id: item.id, sourcePath: variant.sourcePath, body: variant.body, evidence: [...variant.evidence ?? item.evidence], usedByAgentIds: [...item.usedByAgentIds] });
|
|
29171
|
+
}
|
|
28186
29172
|
}
|
|
28187
29173
|
const previous = merged.get(key);
|
|
28188
29174
|
if (!previous) {
|
|
@@ -28213,4 +29199,4 @@ function mergeEnumeratedComponents(artifacts, components) {
|
|
|
28213
29199
|
return { runtimeAgents, artifacts: output };
|
|
28214
29200
|
}
|
|
28215
29201
|
|
|
28216
|
-
export { startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, valueChildren, selectKey, allValues, renderings, CALL_SINKS, registerCallSink, registerClassSink, isModelId, collectModels, modelArtifacts, modelUnknowns, collectModelLiterals,
|
|
29202
|
+
export { startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, valueChildren, selectKey, allValues, renderings, CALL_SINKS, registerCallSink, registerClassSink, isModelId, collectModels, modelArtifacts, modelUnknowns, collectModelLiterals, agentForScope, createAgentScopeResolver, enumerateAgents, toolNamesOf, EXTRACT_SCHEMA_VERSION, enumerateWorkflows, enumerateToolCatalog, ENUMERATORS, enumerateHarnessComponents, mergeEnumeratedComponents, clearExtractCache, extractHarness, extractHarnessWithContext, scopeOf, serializeExtractResult, runEnumerators, assignAgentIds, runHarnessCommand, writeHarnessAnalyzeResult, emitWrittenArtifacts, analyzeHarnessPrompts, isToolGroupPlaceholder, repairExternalAnalystReport, deriveRelationshipsFromGraph, deterministicArtifacts, deterministicGraphItems, mergeDeterministicArtifacts, analystRefutations, describeCodingAgentEvent, analystEventProgress, isRetryableExternalAnalystFailure, sleep, summarizeInvalidAnalystReport, isDeterministicLocalAnalyst, resolveHarnessAnalyzeConcern, resolveExternalHarnessAnalystInvocation, detectAvailableCodingAgents, codingAgentDisplayName, runCodingAgent, readOnlyClaudeExtraArgs, 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 };
|