@moda-ai/cli 1.55.72 → 1.55.74

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.
@@ -18,10 +18,12 @@ import {
18
18
  artifactHasBody,
19
19
  buildImportGraphReachability,
20
20
  createHarnessReport,
21
+ detectBoundRuntimeClasses,
21
22
  firstEvidencePath,
22
23
  graphForReport,
23
24
  hashHarnessReport,
24
25
  hashStableJson,
26
+ isTestWorkerConfig,
25
27
  loadHarnessReportForSync,
26
28
  mergeBoundRuntimeClasses,
27
29
  normalizeHarnessReport,
@@ -29,14 +31,11 @@ import {
29
31
  requiresArtifactBody,
30
32
  resolveHarnessReportPath,
31
33
  stampRemoteSnapshotTruncation,
34
+ stripJsonc,
32
35
  tagComponentStatus,
33
36
  validateHarnessReport,
34
37
  writeHarnessReportArtifacts
35
- } from "./cli-9ww72mrd.js";
36
- import {
37
- createCommandContext,
38
- stringOption
39
- } from "./cli-5ms8rw8x.js";
38
+ } from "./cli-y333w08f.js";
40
39
  import {
41
40
  assertFlags,
42
41
  assertPositionals,
@@ -46,6 +45,10 @@ import {
46
45
  ApiError,
47
46
  callControlAPI
48
47
  } from "./cli-87xy1evx.js";
48
+ import {
49
+ createCommandContext,
50
+ stringOption
51
+ } from "./cli-5ms8rw8x.js";
49
52
  import {
50
53
  EXIT_DEGRADED,
51
54
  embeddedTenantIdFromApiKey,
@@ -105,8 +108,11 @@ import {
105
108
  __toESM
106
109
  } from "./cli-0v6na3yp.js";
107
110
 
111
+ // src/harness-extract/enumerators/agents.ts
112
+ var import_typescript14 = __toESM(require_typescript(), 1);
113
+
108
114
  // src/harness-extract/index.ts
109
- var import_typescript10 = __toESM(require_typescript(), 1);
115
+ var import_typescript13 = __toESM(require_typescript(), 1);
110
116
  import { resolve as resolve13 } from "node:path";
111
117
 
112
118
  // src/harness-extract/ast.ts
@@ -9140,7 +9146,7 @@ function isUnder2(path, root) {
9140
9146
  return true;
9141
9147
  return path === root || path.startsWith(`${root}/`);
9142
9148
  }
9143
- function stripJsonc(text) {
9149
+ function stripJsonc2(text) {
9144
9150
  let out = "";
9145
9151
  let i = 0;
9146
9152
  let inString = false;
@@ -9184,7 +9190,7 @@ function stripJsonc(text) {
9184
9190
  }
9185
9191
  function parseJsonLoose(text) {
9186
9192
  try {
9187
- return JSON.parse(stripJsonc(text));
9193
+ return JSON.parse(stripJsonc2(text));
9188
9194
  } catch {
9189
9195
  return;
9190
9196
  }
@@ -17635,6 +17641,103 @@ function hasDirective(text) {
17635
17641
  const plain = text.replace(/\{\{[^}]*\}\}/g, " ").trim();
17636
17642
  return DIRECTIVE_ANYWHERE.test(plain) || DIRECTIVE_VERB.test(plain);
17637
17643
  }
17644
+ 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;
17645
+ function toolResultIsPrompt(owner, pieces) {
17646
+ if (!owner)
17647
+ return false;
17648
+ if (import_typescript8.default.isShorthandPropertyAssignment(owner) || import_typescript8.default.isPropertyAssignment(owner) && !isNamedTableEntry(owner))
17649
+ return false;
17650
+ const own = pieces.map((piece) => piece.trim()).filter(Boolean);
17651
+ if (own.length === 0)
17652
+ return false;
17653
+ const text = withoutLabels(own.join(`
17654
+ `));
17655
+ if (own.every((piece) => ERROR_TEXT.test(piece)) && !IMPERATIVE.test(text))
17656
+ return false;
17657
+ if (!hasDirective(text) && !IMPERATIVE.test(text))
17658
+ return false;
17659
+ 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;
17660
+ return !fn || isTextBuilder(fn);
17661
+ }
17662
+ function isNamedTableEntry(property) {
17663
+ const object = property.parent;
17664
+ if (object.properties.some((entry) => entry.name && import_typescript8.default.isIdentifier(entry.name) && entry.name.text === "type"))
17665
+ return false;
17666
+ let node = object;
17667
+ 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)) {
17668
+ node = node.parent;
17669
+ }
17670
+ return import_typescript8.default.isVariableDeclaration(node) || import_typescript8.default.isPropertyDeclaration(node) || import_typescript8.default.isExportAssignment(node);
17671
+ }
17672
+ function withoutLabels(text) {
17673
+ return text.replace(/\{\{[^}]*\}\}/g, " ").replace(/(^|[.!?\n]\s*)[A-Za-z][\w -]{0,24}:(?=\s)/g, "$1");
17674
+ }
17675
+ 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";
17676
+ var IMPERATIVE = new RegExp(`(?:^|[.!?:;\\n]\\s*|\\bif\\b[^.!?\\n]{0,160},\\s*)(?:then\\s+)?(?:${IMPERATIVE_VERBS})\\b`, "i");
17677
+ function unwrapNode(node) {
17678
+ let current = node;
17679
+ while (import_typescript8.default.isParenthesizedExpression(current) || import_typescript8.default.isAsExpression(current) || import_typescript8.default.isSatisfiesExpression(current))
17680
+ current = current.expression;
17681
+ return current;
17682
+ }
17683
+ function isTextBuilder(fn) {
17684
+ const modifiers = import_typescript8.default.canHaveModifiers(fn) ? import_typescript8.default.getModifiers(fn) ?? [] : [];
17685
+ if (modifiers.some((modifier) => modifier.kind === import_typescript8.default.SyntaxKind.AsyncKeyword))
17686
+ return false;
17687
+ const declared = fn.type?.getText().replace(/\s+/g, "");
17688
+ if (declared && !/^(?:Promise<)?(?:(?:readonly)?string(?:\[\])?|null|undefined)(?:\|(?:(?:readonly)?string(?:\[\])?|null|undefined))*>?$/.test(declared))
17689
+ return false;
17690
+ let builder = true;
17691
+ let returns = 0;
17692
+ let failures = 0;
17693
+ const visit = (node) => {
17694
+ if (!builder)
17695
+ return;
17696
+ if (node !== fn && import_typescript8.default.isFunctionLike(node))
17697
+ return;
17698
+ if (import_typescript8.default.isAwaitExpression(node))
17699
+ builder = false;
17700
+ else if (import_typescript8.default.isReturnStatement(node) && node.expression) {
17701
+ if (returnsRecord(node.expression))
17702
+ builder = false;
17703
+ returns += 1;
17704
+ if (ERROR_TEXT.test(leadingText(node.expression)))
17705
+ failures += 1;
17706
+ import_typescript8.default.forEachChild(node, visit);
17707
+ } else
17708
+ import_typescript8.default.forEachChild(node, visit);
17709
+ };
17710
+ const body = fn.body;
17711
+ if (body && !import_typescript8.default.isBlock(body))
17712
+ return !returnsRecord(body);
17713
+ if (body)
17714
+ import_typescript8.default.forEachChild(body, visit);
17715
+ return builder && !(returns > 1 && failures > 0 && takesContext(fn));
17716
+ }
17717
+ function takesContext(fn) {
17718
+ return fn.parameters.some((parameter) => {
17719
+ const name = import_typescript8.default.isIdentifier(parameter.name) ? parameter.name.text : "";
17720
+ return /^(?:ctx|context|env|sql|db|tx)$/.test(name) || /(?:Context|Env)\b/.test(parameter.type?.getText() ?? "");
17721
+ });
17722
+ }
17723
+ function leadingText(expr) {
17724
+ const value = unwrapNode(expr);
17725
+ if (import_typescript8.default.isStringLiteral(value) || import_typescript8.default.isNoSubstitutionTemplateLiteral(value))
17726
+ return value.text;
17727
+ if (import_typescript8.default.isTemplateExpression(value))
17728
+ return value.head.text;
17729
+ if (import_typescript8.default.isBinaryExpression(value) && value.operatorToken.kind === import_typescript8.default.SyntaxKind.PlusToken)
17730
+ return leadingText(value.left);
17731
+ return "";
17732
+ }
17733
+ function returnsRecord(expr) {
17734
+ const value = unwrapNode(expr);
17735
+ if (import_typescript8.default.isObjectLiteralExpression(value))
17736
+ return true;
17737
+ if (import_typescript8.default.isConditionalExpression(value))
17738
+ return returnsRecord(value.whenTrue) || returnsRecord(value.whenFalse);
17739
+ return value.kind === import_typescript8.default.SyntaxKind.TrueKeyword || value.kind === import_typescript8.default.SyntaxKind.FalseKeyword || import_typescript8.default.isNumericLiteral(value);
17740
+ }
17638
17741
  function isInstructionDescription(text) {
17639
17742
  if (text.length >= 2000)
17640
17743
  return true;
@@ -17786,7 +17889,7 @@ class PromptResolver {
17786
17889
  const line = `${ref.path}:${ref.line}`;
17787
17890
  firstOnLine.set(line, Math.min(firstOnLine.get(line) ?? Infinity, ref.start));
17788
17891
  }
17789
- const refs = [...this.refs.values()].map(({ pieces, start, ...ref }) => {
17892
+ 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 }) => {
17790
17893
  const later = start > firstOnLine.get(`${ref.path}:${ref.line}`);
17791
17894
  const column = later ? this.columnOf(ref.path, start) : undefined;
17792
17895
  return {
@@ -18363,7 +18466,8 @@ class PromptResolver {
18363
18466
  hops: walk.hops,
18364
18467
  via: [...walk.flags],
18365
18468
  pieces: new Map,
18366
- start: anchor.getStart(sf)
18469
+ start: anchor.getStart(sf),
18470
+ ...owner ? { ownerNode: owner.node } : {}
18367
18471
  };
18368
18472
  this.refs.set(key, ref);
18369
18473
  }
@@ -18384,6 +18488,15 @@ class PromptResolver {
18384
18488
  return;
18385
18489
  return this.relative(resolvePath(dirname7(statement.getSourceFile().fileName), spec.replace(/\?raw$/, "")));
18386
18490
  }
18491
+ preferModelRole(ref, walk) {
18492
+ const toolPath = walk.role === "tool-result" || walk.role === "tool-description";
18493
+ if (ref.role === "tool-result" && !toolPath) {
18494
+ ref.role = walk.role;
18495
+ ref.hops = walk.hops;
18496
+ ref.via = [...walk.flags];
18497
+ }
18498
+ return ref.role === "tool-result" || walk.role !== "tool-result";
18499
+ }
18387
18500
  fileRef(path, walk) {
18388
18501
  if (TEST_SOURCE.test(path))
18389
18502
  return;
@@ -18393,9 +18506,11 @@ class PromptResolver {
18393
18506
  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 };
18394
18507
  this.refs.set(id, ref);
18395
18508
  }
18509
+ const counts = this.preferModelRole(ref, walk);
18396
18510
  if (!ref.callSiteIds.includes(walk.site.id))
18397
18511
  ref.callSiteIds.push(walk.site.id);
18398
- ref.via = ref.via.filter((f) => walk.flags.includes(f));
18512
+ if (counts)
18513
+ ref.via = ref.via.filter((f) => walk.flags.includes(f));
18399
18514
  }
18400
18515
  markUnresolved(node, reason, walk) {
18401
18516
  const sf = node.getSourceFile();
@@ -19031,7 +19146,7 @@ async function runHarnessCommand(context) {
19031
19146
  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.");
19032
19147
  }
19033
19148
  if (context.flags["github-actions"] === "true") {
19034
- const { runGithubActionsAnalyze } = await import("./harness-github-actions-awcd5ns1.js");
19149
+ const { runGithubActionsAnalyze } = await import("./harness-github-actions-m26tapfj.js");
19035
19150
  const result = await runGithubActionsAnalyze(rootDir, {
19036
19151
  writeReport: (report2) => {
19037
19152
  const normalized = normalizeHarnessReport(report2);
@@ -19177,7 +19292,15 @@ async function runHarnessCommand(context) {
19177
19292
  }
19178
19293
  const { artifacts, unknowns } = deterministicGraphItems(rootDir, promote === "all" ? undefined : promote);
19179
19294
  tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
19180
- const promoted = { concern: promote, artifacts, unknowns };
19295
+ const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-cpz85prt.js");
19296
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-0wm7157z.js");
19297
+ let components = { runtimeAgents: [], artifacts: [], warnings: [] };
19298
+ if (promote === "all" || promote === "topology" || promote === "tools") {
19299
+ const { result, ctx } = extractHarnessWithContext2(rootDir);
19300
+ const found = enumerateHarnessComponents(result, ctx);
19301
+ components = promote === "tools" ? { ...found, artifacts: found.artifacts.filter((entry) => entry.type === "tool") } : promote === "topology" ? { ...found, artifacts: found.artifacts.filter((entry) => entry.type !== "tool") } : found;
19302
+ }
19303
+ const promoted = { concern: promote, unknowns, ...mergeEnumeratedComponents(artifacts, components) };
19181
19304
  const promoteWritten = [];
19182
19305
  if (promoteOut && !context.dryRun) {
19183
19306
  const target = resolve9(context.cwd, promoteOut);
@@ -19204,10 +19327,14 @@ async function runHarnessCommand(context) {
19204
19327
  }
19205
19328
  case "extract": {
19206
19329
  writeHumanProgress(context, "Harness extract: tracing model call sites (no LLM, no network)...");
19207
- const { extractHarness: extractHarness2, serializeExtractResult } = await import("./index-tpwztst3.js");
19208
- const result = extractHarness2(rootDir, { fresh: true });
19330
+ const { extractHarnessWithContext: extractHarnessWithContext2, serializeExtractResult } = await import("./index-cpz85prt.js");
19331
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-0wm7157z.js");
19332
+ const { result, ctx } = extractHarnessWithContext2(rootDir, { fresh: true });
19333
+ const artifacts = deterministicArtifacts(rootDir);
19334
+ tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
19335
+ const graph = mergeEnumeratedComponents(artifacts, enumerateHarnessComponents(result, ctx));
19209
19336
  writeHumanProgress(context, `Harness extract: ${result.callSites.length} call sites, ${result.roles.length} traced roles across ${result.files} files (${result.programs} programs, ${result.durationMs.toLocaleString()} ms).`);
19210
- context.output.writeData(serializeExtractResult(result), {
19337
+ context.output.writeData({ ...serializeExtractResult(result), graph }, {
19211
19338
  status: result.warnings.length > 0 ? "degraded" : "success",
19212
19339
  ...result.warnings.length > 0 ? { warnings: result.warnings } : {}
19213
19340
  });
@@ -19987,18 +20114,19 @@ function deterministicGraphItems(rootDir, concern) {
19987
20114
  hydratePromptAndToolBodies(graph, rootDir);
19988
20115
  return { artifacts: graph.artifacts, unknowns: graph.unknowns };
19989
20116
  }
19990
- var extractedModelsCache = new Map;
20117
+ var extractedModelsCache = new WeakMap;
19991
20118
  function extractedModelItems(rootDir) {
19992
20119
  const empty = { artifacts: [], unknowns: [], rewritten: new Set, enabled: false };
19993
20120
  if (process.env.MODA_HARNESS_EXTRACT === "0")
19994
20121
  return empty;
19995
20122
  const key = resolve9(rootDir);
19996
- const cached = extractedModelsCache.get(key);
19997
- if (cached)
19998
- return cached;
19999
20123
  let items = { ...empty, enabled: true };
20000
20124
  try {
20001
- const result = extractHarness(key);
20125
+ const { result, ctx } = extractHarnessWithContext(key);
20126
+ createAgentScopeResolver(result, ctx);
20127
+ const cached = extractedModelsCache.get(result);
20128
+ if (cached)
20129
+ return cached;
20002
20130
  for (const warning of result.warnings)
20003
20131
  process.stderr.write(`warning: harness extraction incomplete; ${warning}
20004
20132
  `);
@@ -20008,11 +20136,11 @@ function extractedModelItems(rootDir) {
20008
20136
  rewritten: new Set((result.rewrittenModels ?? []).map((entry) => normalizedModelId(entry.id))),
20009
20137
  enabled: true
20010
20138
  };
20139
+ extractedModelsCache.set(result, items);
20011
20140
  } catch (error) {
20012
20141
  process.stderr.write(`warning: harness extraction failed; model artifacts come from the candidate pre-pass only (${error instanceof Error ? error.message : String(error)})
20013
20142
  `);
20014
20143
  }
20015
- extractedModelsCache.set(key, items);
20016
20144
  return items;
20017
20145
  }
20018
20146
  var normalizedModelId = (name) => String(name ?? "").trim().toLowerCase();
@@ -20180,7 +20308,7 @@ function withCallSitePrompts(rootDir, promoted) {
20180
20308
  const { result, ctx } = extractHarnessWithContext(rootDir);
20181
20309
  const sites = result.callSites.filter((site) => !site.isTest);
20182
20310
  const toolDefinitions = result.toolDefinitions ?? [];
20183
- return promptArtifactsFromCallSites(sites, ctx, promoted, { toolDefinitions }).artifacts;
20311
+ return promptArtifactsFromCallSites(sites, ctx, promoted, { toolDefinitions, agentForScope: createAgentScopeResolver(result, ctx) }).artifacts;
20184
20312
  } catch {
20185
20313
  return promoted;
20186
20314
  }
@@ -26390,25 +26518,29 @@ var REASON = {
26390
26518
  config: "model id in model configuration next to a model call"
26391
26519
  };
26392
26520
  function modelArtifacts(result) {
26393
- return (result.models ?? []).map((model) => ({
26394
- id: `model_config_${slug(model.id)}_${createHash9("sha256").update(model.id).digest("hex").slice(0, 8)}`,
26395
- type: "model_config",
26396
- name: model.id,
26397
- scope: "shared",
26398
- usedByAgentIds: [],
26399
- confidence: CONFIDENCE[model.resolution],
26400
- confidenceReason: model.resolution === "config" ? "Read from a model-named setting in source; no call site passes it directly." : "Traced from a model call site's model argument to this literal.",
26401
- evidence: [
26402
- { path: model.definition.path, line: model.definition.line, reason: REASON[model.resolution] },
26403
- ...model.calledFrom.slice(0, MAX_CALL_SITE_EVIDENCE).map((site) => ({
26404
- path: site.path,
26405
- line: site.line,
26406
- reason: `model call site${site.enclosing ? ` in ${site.enclosing}` : ""} (${site.callee})`
26407
- }))
26408
- ],
26409
- calledFrom: model.calledFrom.map((site) => ({ path: site.path, line: site.line, ...site.enclosing ? { enclosing: site.enclosing } : {} })),
26410
- resolution: model.resolution
26411
- }));
26521
+ const owners = new Map(result.callSites.map((site) => [site.id, site.agentIds ?? []]));
26522
+ return (result.models ?? []).map((model) => {
26523
+ const agentIds = [...new Set(model.calledFrom.flatMap((site) => owners.get(site.callSite) ?? []))].sort();
26524
+ return {
26525
+ id: `model_config_${slug(model.id)}_${createHash9("sha256").update(model.id).digest("hex").slice(0, 8)}`,
26526
+ type: "model_config",
26527
+ name: model.id,
26528
+ scope: agentIds.length === 1 ? "agent" : "shared",
26529
+ usedByAgentIds: agentIds,
26530
+ confidence: CONFIDENCE[model.resolution],
26531
+ confidenceReason: model.resolution === "config" ? "Read from a model-named setting in source; no call site passes it directly." : "Traced from a model call site's model argument to this literal.",
26532
+ evidence: [
26533
+ { path: model.definition.path, line: model.definition.line, reason: REASON[model.resolution] },
26534
+ ...model.calledFrom.slice(0, MAX_CALL_SITE_EVIDENCE).map((site) => ({
26535
+ path: site.path,
26536
+ line: site.line,
26537
+ reason: `model call site${site.enclosing ? ` in ${site.enclosing}` : ""} (${site.callee})`
26538
+ }))
26539
+ ],
26540
+ calledFrom: model.calledFrom.map((site) => ({ path: site.path, line: site.line, ...site.enclosing ? { enclosing: site.enclosing } : {} })),
26541
+ resolution: model.resolution
26542
+ };
26543
+ });
26412
26544
  }
26413
26545
  function describeSource(source) {
26414
26546
  const [kind, ...rest] = source.split(":");
@@ -26619,210 +26751,1173 @@ function collectModelLiterals(rootDir) {
26619
26751
  return { literals: [...found].sort(), truncated: capped || skipped };
26620
26752
  }
26621
26753
 
26622
- // src/harness-extract/types.ts
26623
- var EXTRACT_SCHEMA_VERSION = 1;
26624
- // src/harness-extract/enumerators/index.ts
26625
- var ENUMERATORS = [];
26626
- // src/harness-extract/tools.ts
26627
- var PASS_THROUGH2 = new Set(["ref", "call", "param", "oneOf", "lookup"]);
26628
- var DEFINITION_KEYS = new Set(["description", "input_schema", "inputSchema", "parameters", "schema", "execute", "type", "strict"]);
26629
- function member(tree, key) {
26630
- const members = tree.children ?? [];
26631
- for (let index = members.length - 1;index >= 0; index -= 1)
26632
- if (members[index].key === key)
26633
- return members[index];
26634
- return;
26635
- }
26636
- function singleLiteral2(tree) {
26637
- if (!tree)
26638
- return;
26639
- if (tree.kind === "literal")
26640
- return tree.text;
26641
- if (PASS_THROUGH2.has(tree.kind)) {
26642
- const flow = valueChildren(tree);
26643
- if (flow.length === 1)
26644
- return singleLiteral2(flow[0]);
26645
- }
26646
- return;
26647
- }
26648
- function objectsOf(tree) {
26649
- if (tree.kind === "object")
26650
- return [tree];
26651
- if (PASS_THROUGH2.has(tree.kind))
26652
- return valueChildren(tree).flatMap(objectsOf);
26653
- return [];
26654
- }
26655
- function definitionName(tree) {
26656
- const fn = member(tree, "function");
26657
- const fnObject = fn ? objectsOf(fn)[0] : undefined;
26658
- const fnName = fnObject ? singleLiteral2(member(fnObject, "name")) : undefined;
26659
- if (fnName && fnObject)
26660
- return { name: fnName, path: fnObject.path, line: fnObject.line, via: "function.name" };
26661
- const nameNode = member(tree, "name");
26662
- const name = singleLiteral2(nameNode);
26663
- const keys = (tree.children ?? []).map((child) => child.key ?? "");
26664
- if (name && nameNode && keys.some((key) => DEFINITION_KEYS.has(key)))
26665
- return { name, path: nameNode.path, line: nameNode.line, via: "name" };
26666
- return;
26667
- }
26668
- function toolNamesOf(tree) {
26669
- const out = { names: [], unresolved: [] };
26670
- const visit = (node, inArray, names) => {
26671
- if (node.kind === "array" || node.kind === "assembled" && node.text === "array") {
26672
- for (const child of node.children ?? [])
26673
- visit(child, true, names);
26674
- return;
26675
- }
26676
- if (node.kind === "object") {
26677
- const definition = definitionName(node);
26678
- if (definition) {
26679
- names.push(definition);
26680
- return;
26681
- }
26682
- if (inArray) {
26683
- out.unresolved.push({ ...node, note: "tool object without a literal name" });
26684
- return;
26754
+ // src/harness-extract/emit-tools.ts
26755
+ var import_typescript12 = __toESM(require_typescript(), 1);
26756
+ import { existsSync as existsSync9 } from "node:fs";
26757
+ import { join as join14, posix as posix3 } from "node:path";
26758
+
26759
+ // src/harness-extract/enumerators/common.ts
26760
+ var import_typescript10 = __toESM(require_typescript(), 1);
26761
+ import { readdirSync as readdirSync8, readFileSync as readFileSync15 } from "node:fs";
26762
+ import { dirname as dirname10, join as join13, posix as posix2, relative as relative10 } from "node:path";
26763
+ var cache = new WeakMap;
26764
+ var SKIP = new Set(["node_modules", "dist", "build", "out", "vendor", "coverage", "__pycache__"]);
26765
+ var TEST_PATH4 = /(?:^|\/)(?:test|tests|__tests__|test-fixtures|fixtures?|__fixtures__|__mocks__|e2e)\/|\.(?:test|spec)\.[cm]?[jt]sx?$/i;
26766
+ var EVAL_PATH2 = /(?:^|\/)evals?\/|\.evals?\.[cm]?[jt]sx?$/i;
26767
+ function enumerationRepository(ctx) {
26768
+ const existing = cache.get(ctx);
26769
+ if (existing)
26770
+ return existing;
26771
+ const files = [];
26772
+ const walk = (dir) => {
26773
+ for (const entry of readdirSync8(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
26774
+ const abs = join13(dir, entry.name);
26775
+ if (entry.isDirectory()) {
26776
+ if (!entry.name.startsWith(".") && !SKIP.has(entry.name))
26777
+ walk(abs);
26778
+ } else if (entry.isFile() && /\.(?:[cm]?[jt]sx?|py|jsonc?|toml)$/.test(entry.name) && !/\.d\.[cm]?ts$/.test(entry.name)) {
26779
+ const path = relative10(ctx.rootDir, abs).split("\\").join("/");
26780
+ try {
26781
+ const text = readFileSync15(abs, "utf8");
26782
+ if (text.length > 1024 * 1024)
26783
+ continue;
26784
+ 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);
26785
+ files.push({ path, text, source });
26786
+ } catch {}
26685
26787
  }
26686
- const record = new Map;
26687
- const set = (hit) => {
26688
- record.delete(hit.name);
26689
- record.set(hit.name, hit);
26690
- };
26691
- for (const child of node.children ?? []) {
26692
- if (child.key === "...") {
26693
- const spread = [];
26694
- visit(child, false, spread);
26695
- spread.forEach(set);
26696
- } else if (child.key) {
26697
- set({ name: child.key, path: child.path, line: child.line, via: "key" });
26698
- }
26788
+ }
26789
+ };
26790
+ walk(ctx.rootDir);
26791
+ const workers = [];
26792
+ const paths = new Set(files.map((file) => file.path));
26793
+ const closure = (main) => {
26794
+ const found = new Set, pending = [main];
26795
+ for (let index = 0;index < pending.length; index++) {
26796
+ const path = pending[index];
26797
+ if (found.has(path))
26798
+ continue;
26799
+ found.add(path);
26800
+ const file = files.find((entry) => entry.path === path);
26801
+ if (!file)
26802
+ continue;
26803
+ for (const ref of import_typescript10.default.preProcessFile(file.text, true, true).importedFiles) {
26804
+ if (!ref.fileName.startsWith("."))
26805
+ continue;
26806
+ const base = posix2.normalize(posix2.join(posix2.dirname(path), ref.fileName)).replace(/\.[cm]?js$/, "");
26807
+ const target = [base, ...[".ts", ".tsx", ".js", ".mjs", "/index.ts", "/index.js"].map((suffix) => base + suffix)].find((candidate) => paths.has(candidate));
26808
+ if (target)
26809
+ pending.push(target);
26699
26810
  }
26700
- names.push(...record.values());
26701
- return;
26702
26811
  }
26703
- if (PASS_THROUGH2.has(node.kind) && valueChildren(node).length > 0) {
26704
- for (const child of valueChildren(node))
26705
- visit(child, inArray, names);
26706
- return;
26812
+ return found;
26813
+ };
26814
+ for (const file of files)
26815
+ if (/(?:^|\/)wrangler(?:\.[\w.-]+)?\.(?:jsonc?|toml)$/.test(file.path)) {
26816
+ try {
26817
+ const config2 = file.path.endsWith(".toml") ? parse(file.text) : JSON.parse(stripJsonc(file.text));
26818
+ const variants = [["default", config2], ...Object.entries(config2.env ?? {}).map(([name, section]) => [name, { ...config2, ...section, queues: section.queues, workflows: section.workflows }])];
26819
+ for (const [environment, section] of variants) {
26820
+ if (typeof section.main !== "string" || isTestWorkerConfig({ path: file.path, name: section.name, mains: [section.main] }))
26821
+ continue;
26822
+ const main = posix2.normalize(posix2.join(dirname10(file.path), section.main));
26823
+ 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) });
26824
+ }
26825
+ } catch {}
26707
26826
  }
26708
- out.unresolved.push(node);
26827
+ const queueBindingsFor = (path) => {
26828
+ const owners = workers.filter((worker) => worker.files.has(path));
26829
+ return new Set(owners[0] ? [...owners[0].queueBindings].filter((binding) => owners.every((worker) => worker.queueBindings.has(binding))) : []);
26709
26830
  };
26710
- visit(tree, false, out.names);
26711
- return out;
26712
- }
26713
-
26714
- // src/harness-extract/index.ts
26715
- var PROMPT_ROLES = new Set(["system", "user", "messages", "prompt", "instructions", "questions"]);
26716
- var MAX_HELPER_CALLERS = 200;
26717
- var MAX_DERIVED = 5000;
26718
- var MAX_CALLER_CHAIN = 3;
26719
- var cache = new Map;
26720
- function clearExtractCache() {
26721
- cache.clear();
26831
+ const reach = buildImportGraphReachability(ctx.rootDir);
26832
+ 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" };
26833
+ cache.set(ctx, repo);
26834
+ return repo;
26722
26835
  }
26723
- function extractHarness(rootDir, options = {}) {
26724
- return extractHarnessWithContext(rootDir, options).result;
26725
- }
26726
- function extractHarnessWithContext(rootDir, options = {}) {
26727
- const root = resolve13(rootDir);
26728
- const { fresh, ...rest } = options;
26729
- const key = `${root}\x00${JSON.stringify(rest)}`;
26730
- const fingerprint = sourceFingerprint(root, rest);
26731
- const cached = fresh ? undefined : cache.get(key);
26732
- if (cached && cached.fingerprint === fingerprint)
26733
- return cached.output;
26734
- const output = runExtract(root, options);
26735
- cache.set(key, { output, fingerprint });
26736
- return output;
26836
+ function lineOf5(node) {
26837
+ return node.getSourceFile().getLineAndCharacterOfPosition(node.getStart()).line + 1;
26737
26838
  }
26738
- function argRef(rootDir, node, key) {
26739
- const source = node.getSourceFile();
26740
- const ref = { path: relPath(rootDir, source.fileName), start: node.getStart(source), end: node.getEnd(), line: lineOf(node) };
26741
- if (key !== undefined)
26742
- ref.key = key;
26743
- Object.defineProperty(ref, "node", { value: node, enumerable: false });
26744
- return ref;
26839
+ function nameOf(node) {
26840
+ if (!node)
26841
+ return;
26842
+ if (import_typescript10.default.isComputedPropertyName(node) && import_typescript10.default.isStringLiteralLike(node.expression))
26843
+ return node.expression.text;
26844
+ return import_typescript10.default.isIdentifier(node) || import_typescript10.default.isStringLiteralLike(node) || import_typescript10.default.isNumericLiteral(node) ? node.text : undefined;
26745
26845
  }
26746
- function namedEnclosingFunction(node) {
26747
- for (let fn = enclosingFunction(node);fn; fn = enclosingFunction(fn)) {
26748
- const name = functionName(fn);
26749
- if (name)
26750
- return { fn, name };
26751
- }
26752
- return;
26846
+ function visit(node, fn) {
26847
+ fn(node);
26848
+ import_typescript10.default.forEachChild(node, (child) => visit(child, fn));
26753
26849
  }
26754
- function qualifiedName(fn, name) {
26755
- const cls = enclosingClass(fn);
26756
- const owner = cls && (fn.parent === cls || fn.parent && fn.parent.parent === cls) ? className(cls) : undefined;
26757
- return owner ? `${owner}.${name}` : name;
26850
+ function componentId(kind, path, name) {
26851
+ return `${kind}:${path}:${name}`;
26758
26852
  }
26759
- function functionScope(rootDir, fn, name) {
26760
- const parts = [qualifiedName(fn, name)];
26761
- const object = objectLiteralOf2(fn);
26762
- if (object) {
26763
- const holder = object.parent && import_typescript10.default.isVariableDeclaration(object.parent) && import_typescript10.default.isIdentifier(object.parent.name) ? object.parent.name.text : `L${lineOf(object)}`;
26764
- parts.unshift(holder);
26765
- }
26766
- for (let outer = namedEnclosingFunction(object ?? fn);outer; outer = namedEnclosingFunction(outer.fn))
26767
- parts.unshift(qualifiedName(outer.fn, outer.name));
26768
- return `${relPath(rootDir, fn.getSourceFile().fileName)}#${parts.join(".")}`;
26853
+ function artifact(type, name, file, node, reason, status) {
26854
+ 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 };
26769
26855
  }
26770
- function objectLiteralOf2(fn) {
26771
- const member2 = import_typescript10.default.isMethodDeclaration(fn) || import_typescript10.default.isGetAccessorDeclaration(fn) || import_typescript10.default.isSetAccessorDeclaration(fn) ? fn : import_typescript10.default.isPropertyAssignment(fn.parent) ? fn.parent : undefined;
26772
- return member2 && import_typescript10.default.isObjectLiteralExpression(member2.parent) ? member2.parent : undefined;
26856
+ function agent(name, file, node, reason, status) {
26857
+ 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 };
26773
26858
  }
26774
- function scopeOf(rootDir, node) {
26775
- const named = namedEnclosingFunction(node);
26776
- if (named)
26777
- return functionScope(rootDir, named.fn, named.name);
26778
- const path = relPath(rootDir, node.getSourceFile().fileName);
26779
- let outermost;
26780
- for (let fn = enclosingFunction(node);fn; fn = enclosingFunction(fn))
26781
- outermost = fn;
26782
- return outermost ? `${path}#L${lineOf(outermost)}` : path;
26859
+ function emptyResult() {
26860
+ return { runtimeAgents: [], artifacts: [], warnings: [] };
26783
26861
  }
26784
- function callerChain(rootDir, anchor, calls, memo) {
26785
- const start = namedEnclosingFunction(anchor);
26786
- if (!start)
26787
- return { callers: [], callerScopes: [] };
26788
- const cached = memo.get(start.fn);
26789
- if (cached)
26790
- return cached;
26791
- const chain = { callers: [], callerScopes: [] };
26792
- const seen = new Set;
26793
- let current = start;
26794
- while (current && !seen.has(current.fn) && chain.callers.length <= MAX_CALLER_CHAIN) {
26795
- seen.add(current.fn);
26796
- chain.callers.unshift(qualifiedName(current.fn, current.name));
26797
- chain.callerScopes.unshift(functionScope(rootDir, current.fn, current.name));
26798
- const caller = calls.callersOf(current.fn, current.name, 1)[0];
26799
- current = caller ? namedEnclosingFunction(caller) : undefined;
26800
- }
26801
- memo.set(start.fn, chain);
26802
- return chain;
26862
+ function stableResult(result) {
26863
+ const unique2 = (values) => [...new Map(values.map((x) => [x.id, x])).values()].sort((a, b) => a.id.localeCompare(b.id));
26864
+ return { runtimeAgents: unique2(result.runtimeAgents), artifacts: unique2(result.artifacts), warnings: [...new Set(result.warnings)].sort() };
26803
26865
  }
26804
- var AGENT_CLASS_BASES = new Set(["Think", "Agent", "AIChatAgent"]);
26805
- function findAgentClasses(program, checker, memo) {
26866
+
26867
+ // src/harness-extract/tool-owners.ts
26868
+ var import_typescript11 = __toESM(require_typescript(), 1);
26869
+ var AGENT_BASES3 = new Set(["Think", "Agent", "AIChatAgent"]);
26870
+ var ROLE_FIELD = /^(?:role|roleId|roleName|kind|type|id|slug|agentRole|subagentRole)$/i;
26871
+ var MAX_HOPS = 10;
26872
+ var MIN_ALLOWLIST = 3;
26873
+ var TOOL_LIST_PARAM = /^(?:allow(?:list|ed)?|allowedTools|toolNames|tools|requested)$/i;
26874
+ var ALLOWLIST_SHARE = 0.6;
26875
+ function sourceFilesOf(ctx) {
26806
26876
  const out = [];
26807
- for (const source of program.getSourceFiles()) {
26808
- if (source.isDeclarationFile || /[\\/]node_modules[\\/]/.test(source.fileName))
26809
- continue;
26810
- const visit = (node) => {
26811
- if ((import_typescript10.default.isClassDeclaration(node) || import_typescript10.default.isClassExpression(node)) && node.heritageClauses) {
26812
- const base = frameworkBaseOf(node, checker, memo).base;
26813
- if (base && AGENT_CLASS_BASES.has(base))
26814
- out.push(node);
26815
- }
26816
- import_typescript10.default.forEachChild(node, visit);
26817
- };
26818
- visit(source);
26877
+ for (const program of ctx.programs) {
26878
+ for (const source of program.getSourceFiles()) {
26879
+ if (source.isDeclarationFile || /[\\/]node_modules[\\/]/.test(source.fileName))
26880
+ continue;
26881
+ const rel2 = relPath(ctx.rootDir, source.fileName);
26882
+ if (rel2.startsWith(".."))
26883
+ continue;
26884
+ if (ctx.programFor(source.fileName) !== program)
26885
+ continue;
26886
+ out.push({ program, source, rel: rel2 });
26887
+ }
26819
26888
  }
26820
26889
  return out;
26821
26890
  }
26822
- function describeEnclosing(rootDir, anchor, checker, memo, ownClass) {
26823
- const fn = ownClass ? undefined : namedEnclosingFunction(anchor);
26824
- const cls = ownClass ?? enclosingClass(anchor);
26825
- let enclosingCls;
26891
+ function isOneOffScript(rel2, reach) {
26892
+ if (!/^scripts\//.test(rel2))
26893
+ return false;
26894
+ return !reach?.inProd.has(rel2);
26895
+ }
26896
+
26897
+ class ToolOwners {
26898
+ ctx;
26899
+ classes = [];
26900
+ byDeclaration = new Map;
26901
+ references = new Map;
26902
+ edges = new Map;
26903
+ allowlists;
26904
+ constructor(ctx) {
26905
+ this.ctx = ctx;
26906
+ const memo = createFrameworkMemo();
26907
+ for (const { program, source, rel: rel2 } of sourceFilesOf(ctx)) {
26908
+ if (isTestPath(rel2))
26909
+ continue;
26910
+ const checker = program.getTypeChecker();
26911
+ const visit2 = (node) => {
26912
+ if ((import_typescript11.default.isClassDeclaration(node) || import_typescript11.default.isClassExpression(node)) && node.name) {
26913
+ let info;
26914
+ try {
26915
+ info = frameworkBaseOf(node, checker, memo);
26916
+ } catch {
26917
+ info = undefined;
26918
+ }
26919
+ if (info?.base && AGENT_BASES3.has(info.base)) {
26920
+ const agent2 = {
26921
+ name: node.name.text,
26922
+ path: rel2,
26923
+ line: lineOf(node.name),
26924
+ abstract: Boolean(import_typescript11.default.getCombinedModifierFlags(node) & import_typescript11.default.ModifierFlags.Abstract),
26925
+ base: info.base,
26926
+ baseModule: info.module,
26927
+ parent: superclassOf(node, checker),
26928
+ declaration: node,
26929
+ fields: classFields(node),
26930
+ methods: new Set(node.members.filter((member) => import_typescript11.default.isMethodDeclaration(member) || import_typescript11.default.isGetAccessorDeclaration(member)).map((member) => propertyNameText(member.name) ?? ""))
26931
+ };
26932
+ this.classes.push(agent2);
26933
+ this.byDeclaration.set(node, agent2);
26934
+ }
26935
+ }
26936
+ import_typescript11.default.forEachChild(node, visit2);
26937
+ };
26938
+ visit2(source);
26939
+ }
26940
+ }
26941
+ concrete() {
26942
+ return this.classes.filter((agent2) => !agent2.abstract);
26943
+ }
26944
+ fieldOf(name, field) {
26945
+ let current = this.classes.find((agent2) => agent2.name === name);
26946
+ for (let hops = 0;current && hops < 10; hops += 1) {
26947
+ if (field in current.fields)
26948
+ return current.fields[field];
26949
+ current = current.parent ? this.byDeclaration.get(current.parent) : undefined;
26950
+ }
26951
+ return;
26952
+ }
26953
+ inheritors(owner, method) {
26954
+ const out = [];
26955
+ for (const agent2 of this.classes) {
26956
+ if (agent2.abstract)
26957
+ continue;
26958
+ let current = agent2;
26959
+ let ok = false;
26960
+ for (let hops = 0;current && hops < 10; hops += 1) {
26961
+ if (current === owner) {
26962
+ ok = true;
26963
+ break;
26964
+ }
26965
+ if (method && current.methods.has(method))
26966
+ break;
26967
+ current = current.parent ? this.byDeclaration.get(current.parent) : undefined;
26968
+ }
26969
+ if (ok)
26970
+ out.push(agent2.name);
26971
+ }
26972
+ return out;
26973
+ }
26974
+ ownersOf(node, program) {
26975
+ const sets = { direct: new Set, rpc: new Set, open: new Set };
26976
+ const start = this.positionOf(node, program);
26977
+ if (!start)
26978
+ return { direct: [], rpc: [], open: [] };
26979
+ const seen = new Set;
26980
+ let frontier = [{ position: start, via: "direct" }];
26981
+ for (let hops = 0;frontier.length > 0 && hops <= MAX_HOPS; hops += 1) {
26982
+ const next = [];
26983
+ for (const { position, via } of frontier) {
26984
+ for (const agent2 of position.agents)
26985
+ sets[via].add(agent2);
26986
+ const key = `${position.id}|${via}`;
26987
+ if (seen.has(key))
26988
+ continue;
26989
+ seen.add(key);
26990
+ for (const edge of this.edgesOf(position, program))
26991
+ next.push({ position: edge.position, via: combineVia(via, edge.via) });
26992
+ }
26993
+ frontier = next;
26994
+ }
26995
+ const direct = [...sets.direct].sort();
26996
+ return {
26997
+ direct,
26998
+ rpc: [...sets.rpc].filter((name) => !sets.direct.has(name)).sort(),
26999
+ open: [...sets.open].filter((name) => !sets.direct.has(name)).sort()
27000
+ };
27001
+ }
27002
+ positionOf(node, program) {
27003
+ let method;
27004
+ for (let current = node;current; current = current.parent) {
27005
+ 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)) {
27006
+ method = current.name;
27007
+ }
27008
+ if (import_typescript11.default.isClassLike(current)) {
27009
+ const agent2 = this.byDeclaration.get(current);
27010
+ if (!agent2)
27011
+ return current.name ? this.holderPosition(current.name, program) : undefined;
27012
+ const guards = fieldGuards(node, current);
27013
+ const agents = this.inheritors(agent2, method?.text).filter((name) => guards.every((guard) => guard.holds(this.fieldOf(name, guard.field))));
27014
+ const anchor = method ?? current;
27015
+ return { id: nodeId(anchor), anchor, agents, agent: agent2, method };
27016
+ }
27017
+ }
27018
+ const holder = holderName(node);
27019
+ return holder ? this.holderPosition(holder, program) : undefined;
27020
+ }
27021
+ holderPosition(name, program) {
27022
+ const target = valueDeclaration(resolvedSymbol(name, program.getTypeChecker())) ?? name.parent;
27023
+ return { id: nodeId(target), anchor: target, agents: [], holder: name };
27024
+ }
27025
+ edgesOf(position, program) {
27026
+ const cached = this.edges.get(position.id);
27027
+ if (cached)
27028
+ return cached;
27029
+ const out = [];
27030
+ this.edges.set(position.id, out);
27031
+ const checker = program.getTypeChecker();
27032
+ if (position.holder) {
27033
+ for (const reference of this.referencesOf(program, position.holder.text)) {
27034
+ if (reference === position.holder || isDeclarationName(reference))
27035
+ continue;
27036
+ if (valueDeclaration(resolvedSymbol(reference, checker)) !== position.anchor)
27037
+ continue;
27038
+ const next = this.positionOf(reference, program);
27039
+ if (next)
27040
+ out.push({ position: next, via: "direct" });
27041
+ }
27042
+ } else if (position.agent && position.method) {
27043
+ const owner = position.agent;
27044
+ const name = position.method.text;
27045
+ const unique2 = this.classes.filter((agent2) => agent2.methods.has(name)).length === 1 && owner.methods.has(name);
27046
+ const declaration = position.method.parent;
27047
+ const takesToolList = import_typescript11.default.isMethodDeclaration(declaration) && declaration.parameters.some((param) => import_typescript11.default.isIdentifier(param.name) && TOOL_LIST_PARAM.test(param.name.text));
27048
+ for (const reference of this.referencesOf(program, name)) {
27049
+ const access = reference.parent;
27050
+ if (!access || !import_typescript11.default.isPropertyAccessExpression(access) || access.name !== reference)
27051
+ continue;
27052
+ if (access.expression.kind === import_typescript11.default.SyntaxKind.ThisKeyword) {
27053
+ if (!isWithin3(reference, owner.declaration))
27054
+ continue;
27055
+ const next2 = this.positionOf(reference, program);
27056
+ if (next2)
27057
+ out.push({ position: { ...next2, agents: [] }, via: "direct" });
27058
+ continue;
27059
+ }
27060
+ if (!unique2 || !import_typescript11.default.isCallExpression(access.parent) || access.parent.expression !== access)
27061
+ continue;
27062
+ const resolved = valueDeclaration(resolvedSymbol(reference, checker));
27063
+ if (resolved && resolved.parent !== owner.declaration)
27064
+ continue;
27065
+ const next = this.positionOf(reference, program);
27066
+ if (next)
27067
+ out.push({ position: next, via: takesToolList ? "open" : "rpc" });
27068
+ }
27069
+ }
27070
+ return out;
27071
+ }
27072
+ referencesOf(program, name) {
27073
+ let index = this.references.get(program);
27074
+ if (!index) {
27075
+ index = new Map;
27076
+ for (const source of program.getSourceFiles()) {
27077
+ if (source.isDeclarationFile || /[\\/]node_modules[\\/]/.test(source.fileName))
27078
+ continue;
27079
+ if (isTestPath(relPath(this.ctx.rootDir, source.fileName)))
27080
+ continue;
27081
+ const visit2 = (node) => {
27082
+ if (import_typescript11.default.isIdentifier(node)) {
27083
+ const list = index.get(node.text);
27084
+ if (list)
27085
+ list.push(node);
27086
+ else
27087
+ index.set(node.text, [node]);
27088
+ }
27089
+ import_typescript11.default.forEachChild(node, visit2);
27090
+ };
27091
+ visit2(source);
27092
+ }
27093
+ this.references.set(program, index);
27094
+ }
27095
+ return index.get(name) ?? [];
27096
+ }
27097
+ indexAllowlists(knownTools) {
27098
+ this.allowlists = [];
27099
+ for (const { program, source, rel: rel2 } of sourceFilesOf(this.ctx)) {
27100
+ if (isTestPath(rel2))
27101
+ continue;
27102
+ const checker = program.getTypeChecker();
27103
+ const visit2 = (node) => {
27104
+ if (import_typescript11.default.isArrayLiteralExpression(node) && (!node.parent || !import_typescript11.default.isSpreadElement(node.parent))) {
27105
+ const entries = stringEntries(node, checker);
27106
+ const named = entries.filter((entry) => knownTools.has(entry) || entry.endsWith("*") && entry.length > 2);
27107
+ if (entries.length >= MIN_ALLOWLIST && named.length / entries.length >= ALLOWLIST_SHARE) {
27108
+ const agents = this.allowlistOwners(node, program);
27109
+ if (agents.length > 0)
27110
+ this.allowlists.push({ entries, agents, path: rel2 });
27111
+ }
27112
+ }
27113
+ import_typescript11.default.forEachChild(node, visit2);
27114
+ };
27115
+ visit2(source);
27116
+ }
27117
+ }
27118
+ allowlisted() {
27119
+ return new Set((this.allowlists ?? []).flatMap((list) => list.agents));
27120
+ }
27121
+ agentsFor(tool, owners, allowlistApplies = () => true) {
27122
+ const restricted = this.allowlisted();
27123
+ const out = new Set([...owners.direct, ...owners.open, ...owners.rpc.filter((agent2) => !restricted.has(agent2)), ...this.allowlistAgents(tool, allowlistApplies)]);
27124
+ return [...out].sort();
27125
+ }
27126
+ allowlistAgents(tool, applies = () => true) {
27127
+ const out = new Set;
27128
+ for (const list of this.allowlists ?? []) {
27129
+ if (!applies(list.path))
27130
+ continue;
27131
+ if (list.entries.some((entry) => entry === tool || entry.endsWith("*") && tool.startsWith(entry.slice(0, -1)))) {
27132
+ for (const agent2 of list.agents)
27133
+ out.add(agent2);
27134
+ }
27135
+ }
27136
+ return [...out].sort();
27137
+ }
27138
+ allowlistOwners(list, program) {
27139
+ const keys = new Set;
27140
+ const direct = new Set;
27141
+ const checker = program.getTypeChecker();
27142
+ const visited = new Set;
27143
+ const walk = (node, hops) => {
27144
+ if (hops > 4 || visited.has(node))
27145
+ return;
27146
+ visited.add(node);
27147
+ for (let current = node.parent;current; current = current.parent) {
27148
+ if (import_typescript11.default.isClassLike(current)) {
27149
+ const agent2 = this.byDeclaration.get(current);
27150
+ if (agent2)
27151
+ for (const name of this.inheritors(agent2, undefined))
27152
+ direct.add(name);
27153
+ return;
27154
+ }
27155
+ if (import_typescript11.default.isFunctionLike(current))
27156
+ return;
27157
+ if (import_typescript11.default.isPropertyAssignment(current) || import_typescript11.default.isShorthandPropertyAssignment(current)) {
27158
+ const key = propertyNameText(current.name);
27159
+ if (key)
27160
+ keys.add(key);
27161
+ }
27162
+ if (import_typescript11.default.isObjectLiteralExpression(current)) {
27163
+ for (const property of current.properties) {
27164
+ if (!import_typescript11.default.isPropertyAssignment(property) || !ROLE_FIELD.test(propertyNameText(property.name) ?? ""))
27165
+ continue;
27166
+ const value = unwrap(property.initializer);
27167
+ if (import_typescript11.default.isStringLiteral(value))
27168
+ keys.add(value.text);
27169
+ }
27170
+ }
27171
+ if (import_typescript11.default.isVariableDeclaration(current) && import_typescript11.default.isIdentifier(current.name)) {
27172
+ const target = current;
27173
+ for (const reference of this.referencesOf(program, current.name.text)) {
27174
+ if (reference === current.name || isDeclarationName(reference))
27175
+ continue;
27176
+ if (valueDeclaration(resolvedSymbol(reference, checker)) !== target)
27177
+ continue;
27178
+ walk(reference, hops + 1);
27179
+ }
27180
+ return;
27181
+ }
27182
+ }
27183
+ };
27184
+ walk(list, 0);
27185
+ for (const agent2 of this.concrete()) {
27186
+ if (Object.entries(agent2.fields).some(([field, value]) => ROLE_FIELD.test(field) && keys.has(value)))
27187
+ direct.add(agent2.name);
27188
+ }
27189
+ return [...direct].sort();
27190
+ }
27191
+ }
27192
+ function combineVia(current, edge) {
27193
+ if (current === "open" || edge === "open")
27194
+ return "open";
27195
+ if (current === "rpc" || edge === "rpc")
27196
+ return "rpc";
27197
+ return "direct";
27198
+ }
27199
+ function nodeId(node) {
27200
+ return `${node.getSourceFile().fileName}:${node.getStart()}`;
27201
+ }
27202
+ function fieldGuards(node, cls) {
27203
+ const out = [];
27204
+ let child = node;
27205
+ for (let current = node.parent;current && current !== cls; child = current, current = current.parent) {
27206
+ let condition;
27207
+ let whenTrue;
27208
+ if (import_typescript11.default.isConditionalExpression(current) && child !== current.condition) {
27209
+ condition = current.condition;
27210
+ whenTrue = child === current.whenTrue;
27211
+ } else if (import_typescript11.default.isIfStatement(current) && child !== current.expression) {
27212
+ condition = current.expression;
27213
+ whenTrue = child === current.thenStatement;
27214
+ }
27215
+ if (!condition || whenTrue === undefined)
27216
+ continue;
27217
+ const test = unwrap(condition);
27218
+ if (!import_typescript11.default.isBinaryExpression(test))
27219
+ continue;
27220
+ const op = test.operatorToken.kind;
27221
+ const equal = op === import_typescript11.default.SyntaxKind.EqualsEqualsEqualsToken || op === import_typescript11.default.SyntaxKind.EqualsEqualsToken;
27222
+ const notEqual = op === import_typescript11.default.SyntaxKind.ExclamationEqualsEqualsToken || op === import_typescript11.default.SyntaxKind.ExclamationEqualsToken;
27223
+ if (!equal && !notEqual)
27224
+ continue;
27225
+ const sides = [unwrap(test.left), unwrap(test.right)];
27226
+ const access = sides.find((side) => import_typescript11.default.isPropertyAccessExpression(side) && side.expression.kind === import_typescript11.default.SyntaxKind.ThisKeyword);
27227
+ const literal = sides.find((side) => import_typescript11.default.isStringLiteral(side));
27228
+ if (!access || !literal)
27229
+ continue;
27230
+ const wantEqual = equal === whenTrue;
27231
+ const value = literal.text;
27232
+ out.push({ field: access.name.text, holds: (actual) => actual === undefined || actual === value === wantEqual });
27233
+ }
27234
+ return out;
27235
+ }
27236
+ function isWithin3(node, container) {
27237
+ for (let current = node;current; current = current.parent)
27238
+ if (current === container)
27239
+ return true;
27240
+ return false;
27241
+ }
27242
+ function superclassOf(node, checker) {
27243
+ const heritage = node.heritageClauses?.find((clause) => clause.token === import_typescript11.default.SyntaxKind.ExtendsKeyword)?.types[0];
27244
+ if (!heritage)
27245
+ return;
27246
+ const expression = unwrap(heritage.expression);
27247
+ const declaration = valueDeclaration(resolvedSymbol(import_typescript11.default.isPropertyAccessExpression(expression) ? expression.name : expression, checker));
27248
+ return declaration && (import_typescript11.default.isClassDeclaration(declaration) || import_typescript11.default.isClassExpression(declaration)) ? declaration : undefined;
27249
+ }
27250
+ function classFields(node) {
27251
+ const fields = {};
27252
+ for (const member of node.members) {
27253
+ if (!import_typescript11.default.isPropertyDeclaration(member) || !member.initializer)
27254
+ continue;
27255
+ const name = propertyNameText(member.name);
27256
+ if (!name)
27257
+ continue;
27258
+ const value = unwrap(member.initializer);
27259
+ if (import_typescript11.default.isStringLiteral(value) || import_typescript11.default.isNoSubstitutionTemplateLiteral(value))
27260
+ fields[name] = value.text;
27261
+ else if (value.kind === import_typescript11.default.SyntaxKind.TrueKeyword)
27262
+ fields[name] = "true";
27263
+ else if (value.kind === import_typescript11.default.SyntaxKind.FalseKeyword)
27264
+ fields[name] = "false";
27265
+ }
27266
+ return fields;
27267
+ }
27268
+ function holderName(node) {
27269
+ let found;
27270
+ for (let current = node.parent;current; current = current.parent) {
27271
+ if (import_typescript11.default.isFunctionDeclaration(current) && current.name)
27272
+ return current.name;
27273
+ if (import_typescript11.default.isVariableDeclaration(current) && import_typescript11.default.isIdentifier(current.name)) {
27274
+ found = current.name;
27275
+ const statement = current.parent?.parent;
27276
+ if (statement && import_typescript11.default.isVariableStatement(statement) && import_typescript11.default.isSourceFile(statement.parent))
27277
+ return found;
27278
+ const init = current.initializer ? unwrap(current.initializer) : undefined;
27279
+ if (init && (import_typescript11.default.isArrowFunction(init) || import_typescript11.default.isFunctionExpression(init)))
27280
+ return found;
27281
+ }
27282
+ }
27283
+ return found;
27284
+ }
27285
+ function isDeclarationName(identifier) {
27286
+ const parent = identifier.parent;
27287
+ if (!parent)
27288
+ return false;
27289
+ if (import_typescript11.default.isImportSpecifier(parent) || import_typescript11.default.isImportClause(parent) || import_typescript11.default.isNamespaceImport(parent) || import_typescript11.default.isExportSpecifier(parent))
27290
+ return true;
27291
+ 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;
27292
+ }
27293
+ function stringEntries(expression, checker, depth = 0) {
27294
+ if (depth > 4)
27295
+ return [];
27296
+ const value = unwrap(expression);
27297
+ if (import_typescript11.default.isIdentifier(value)) {
27298
+ const declaration = valueDeclaration(resolvedSymbol(value, checker));
27299
+ return declaration && import_typescript11.default.isVariableDeclaration(declaration) && declaration.initializer ? stringEntries(declaration.initializer, checker, depth + 1) : [];
27300
+ }
27301
+ if (!import_typescript11.default.isArrayLiteralExpression(value))
27302
+ return [];
27303
+ const out = [];
27304
+ for (const element of value.elements) {
27305
+ if (import_typescript11.default.isSpreadElement(element)) {
27306
+ out.push(...stringEntries(element.expression, checker, depth + 1));
27307
+ continue;
27308
+ }
27309
+ const text = constantString(element, checker, depth);
27310
+ if (text !== undefined)
27311
+ out.push(text);
27312
+ }
27313
+ return out;
27314
+ }
27315
+ function constantString(expression, checker, depth) {
27316
+ const value = unwrap(expression);
27317
+ if (import_typescript11.default.isStringLiteral(value) || import_typescript11.default.isNoSubstitutionTemplateLiteral(value))
27318
+ return value.text;
27319
+ if (depth > 4)
27320
+ return;
27321
+ if (import_typescript11.default.isIdentifier(value)) {
27322
+ const declaration = valueDeclaration(resolvedSymbol(value, checker));
27323
+ return declaration && import_typescript11.default.isVariableDeclaration(declaration) && declaration.initializer ? constantString(declaration.initializer, checker, depth + 1) : undefined;
27324
+ }
27325
+ if (import_typescript11.default.isTemplateExpression(value)) {
27326
+ let text = value.head.text;
27327
+ for (const span of value.templateSpans) {
27328
+ const part = constantString(span.expression, checker, depth + 1);
27329
+ if (part === undefined)
27330
+ return;
27331
+ text += part + span.literal.text;
27332
+ }
27333
+ return text;
27334
+ }
27335
+ return;
27336
+ }
27337
+
27338
+ // src/harness-extract/tools.ts
27339
+ var PASS_THROUGH2 = new Set(["ref", "call", "param", "oneOf", "lookup"]);
27340
+ var DEFINITION_KEYS = new Set(["description", "input_schema", "inputSchema", "parameters", "schema", "execute", "type", "strict"]);
27341
+ function member(tree, key) {
27342
+ const members = tree.children ?? [];
27343
+ for (let index = members.length - 1;index >= 0; index -= 1)
27344
+ if (members[index].key === key)
27345
+ return members[index];
27346
+ return;
27347
+ }
27348
+ function singleLiteral2(tree) {
27349
+ if (!tree)
27350
+ return;
27351
+ if (tree.kind === "literal")
27352
+ return tree.text;
27353
+ if (PASS_THROUGH2.has(tree.kind)) {
27354
+ const flow = valueChildren(tree);
27355
+ if (flow.length === 1)
27356
+ return singleLiteral2(flow[0]);
27357
+ }
27358
+ return;
27359
+ }
27360
+ function objectsOf(tree) {
27361
+ if (tree.kind === "object")
27362
+ return [tree];
27363
+ if (PASS_THROUGH2.has(tree.kind))
27364
+ return valueChildren(tree).flatMap(objectsOf);
27365
+ return [];
27366
+ }
27367
+ function definitionName(tree) {
27368
+ const fn = member(tree, "function");
27369
+ const fnObject = fn ? objectsOf(fn)[0] : undefined;
27370
+ const fnName = fnObject ? singleLiteral2(member(fnObject, "name")) : undefined;
27371
+ if (fnName && fnObject)
27372
+ return { name: fnName, path: fnObject.path, line: fnObject.line, via: "function.name" };
27373
+ const nameNode = member(tree, "name");
27374
+ const name = singleLiteral2(nameNode);
27375
+ const keys = (tree.children ?? []).map((child) => child.key ?? "");
27376
+ if (name && nameNode && keys.some((key) => DEFINITION_KEYS.has(key)))
27377
+ return { name, path: nameNode.path, line: nameNode.line, via: "name" };
27378
+ return;
27379
+ }
27380
+ function toolNamesOf(tree) {
27381
+ const out = { names: [], unresolved: [] };
27382
+ const visit2 = (node, inArray, names) => {
27383
+ if (node.kind === "array" || node.kind === "assembled" && node.text === "array") {
27384
+ for (const child of node.children ?? [])
27385
+ visit2(child, true, names);
27386
+ return;
27387
+ }
27388
+ if (node.kind === "object") {
27389
+ const definition = definitionName(node);
27390
+ if (definition) {
27391
+ names.push(definition);
27392
+ return;
27393
+ }
27394
+ if (inArray) {
27395
+ out.unresolved.push({ ...node, note: "tool object without a literal name" });
27396
+ return;
27397
+ }
27398
+ const record = new Map;
27399
+ const set = (hit) => {
27400
+ record.delete(hit.name);
27401
+ record.set(hit.name, hit);
27402
+ };
27403
+ for (const child of node.children ?? []) {
27404
+ if (child.key === "...") {
27405
+ const spread = [];
27406
+ visit2(child, false, spread);
27407
+ spread.forEach(set);
27408
+ } else if (child.key) {
27409
+ set({ name: child.key, path: child.path, line: child.line, via: "key" });
27410
+ }
27411
+ }
27412
+ names.push(...record.values());
27413
+ return;
27414
+ }
27415
+ if (PASS_THROUGH2.has(node.kind) && valueChildren(node).length > 0) {
27416
+ for (const child of valueChildren(node))
27417
+ visit2(child, inArray, names);
27418
+ return;
27419
+ }
27420
+ out.unresolved.push(node);
27421
+ };
27422
+ visit2(tree, false, out.names);
27423
+ return out;
27424
+ }
27425
+
27426
+ // src/harness-extract/emit-tools.ts
27427
+ var SCHEMA_KEYS = ["input_schema", "inputSchema", "parameters", "output_schema"];
27428
+ var TOOL_BODY_KEYS = ["execute", "handler"];
27429
+ var TOOL_FACTORY = /^(?:tool|dynamicTool|agentTool|createTool|defineTool)$/;
27430
+ var TOOL_MODULE = /^(?:ai|agents(?:\/.*)?|@cloudflare\/[\w-]+(?:\/.*)?|@mastra\/[\w-]+|@ai-sdk\/[\w-]+|@openai\/agents(?:-core)?|@langchain\/[\w-]+)$/;
27431
+ var MODEL_FACING_NAME = /^[A-Za-z_][\w.:-]{0,127}$/;
27432
+ var MAX_NAMES_PER_SITE = 64;
27433
+ var MAX_TOOLS = 1e4;
27434
+ var MAX_EVIDENCE_PER_TOOL = 64;
27435
+ var MAX_DEFINITIONS_PER_TOOL = 64;
27436
+ var MAX_DEFINITION_BYTES = 8 * 1024 * 1024;
27437
+ var MAX_BODY_BYTES = 64000;
27438
+ function emitTools(result, ctx, options = {}) {
27439
+ const owners = options.owners ?? new ToolOwners(ctx);
27440
+ const agentForScope = createAgentScopeResolver(result, ctx);
27441
+ let reach;
27442
+ try {
27443
+ reach = buildImportGraphReachability(ctx.rootDir);
27444
+ } catch {
27445
+ reach = undefined;
27446
+ }
27447
+ const skipPath = (rel2) => isTestPath(rel2) || isOneOffScript(rel2, reach);
27448
+ const tracers = new Map;
27449
+ const tracerFor = (program) => {
27450
+ let tracer = tracers.get(program);
27451
+ if (!tracer) {
27452
+ const checker = program.getTypeChecker();
27453
+ tracer = new ValueTracer(ctx.rootDir, checker, new CallIndex(program, checker), { maxDepth: 8, maxNodes: 400, maxCallers: 8 });
27454
+ tracers.set(program, tracer);
27455
+ }
27456
+ return tracer;
27457
+ };
27458
+ const packageOf = workspacePackages(ctx.rootDir);
27459
+ const found = new Map;
27460
+ const ownersByTool = new Map;
27461
+ let definitionBytes = 0;
27462
+ const limit = () => {
27463
+ const warning = "tools: bounded tool catalog budget reached; some evidence or bodies omitted";
27464
+ if (!result.warnings.includes(warning))
27465
+ result.warnings.push(warning);
27466
+ };
27467
+ const add = (name, via, evidence, toolOwners, definition, displayName, enclosing) => {
27468
+ if (!MODEL_FACING_NAME.test(name))
27469
+ return;
27470
+ const pkg = packageOf(evidence.path);
27471
+ const key = name;
27472
+ let tool = found.get(key);
27473
+ if (!tool) {
27474
+ if (found.size >= MAX_TOOLS) {
27475
+ limit();
27476
+ return;
27477
+ }
27478
+ tool = { name, status: enumerationRepository(ctx).status(evidence.path) === "defined_only" ? "defined_only" : "reachable", ...pkg ? { package: pkg } : {}, via, evidence: [], agents: [], calledFrom: [], definitions: [] };
27479
+ found.set(key, tool);
27480
+ ownersByTool.set(key, { direct: [], rpc: [], open: [] });
27481
+ }
27482
+ if (enumerationRepository(ctx).status(evidence.path) !== "defined_only")
27483
+ tool.status = "reachable";
27484
+ if (tool.evidence.length < MAX_EVIDENCE_PER_TOOL && !tool.evidence.some((other) => other.path === evidence.path && other.line === evidence.line)) {
27485
+ tool.evidence.push(evidence);
27486
+ tool.calledFrom.push({ path: evidence.path, line: evidence.line, ...enclosing ? { enclosing } : {} });
27487
+ }
27488
+ if (definition) {
27489
+ const source = definition.getSourceFile();
27490
+ const path = relPath(ctx.rootDir, source.fileName), start = definition.getStart(source);
27491
+ if (tool.definitions.length < MAX_DEFINITIONS_PER_TOOL && !tool.definitions.some((other) => other.path === path && other.start === start)) {
27492
+ const text = Buffer.from(definition.getText(source));
27493
+ if (text.length > MAX_BODY_BYTES) {
27494
+ const warning = `tools: ${name} definition at ${path}:${lineOf(definition)} exceeds ${MAX_BODY_BYTES} bytes; its body is truncated`;
27495
+ if (!result.warnings.includes(warning))
27496
+ result.warnings.push(warning);
27497
+ }
27498
+ const body = text.subarray(0, Math.max(0, Math.min(MAX_BODY_BYTES, MAX_DEFINITION_BYTES - definitionBytes))).toString("utf8");
27499
+ definitionBytes += Buffer.byteLength(body);
27500
+ if (definitionBytes >= MAX_DEFINITION_BYTES)
27501
+ limit();
27502
+ tool.definitions.push({ path, start, end: definition.getEnd(), line: lineOf(definition), scope: scopeOf(ctx.rootDir, definition), body });
27503
+ }
27504
+ }
27505
+ const merged = ownersByTool.get(key);
27506
+ for (const agent2 of toolOwners.direct)
27507
+ if (!merged.direct.includes(agent2))
27508
+ merged.direct.push(agent2);
27509
+ for (const agent2 of toolOwners.rpc)
27510
+ if (!merged.rpc.includes(agent2))
27511
+ merged.rpc.push(agent2);
27512
+ for (const agent2 of toolOwners.open)
27513
+ if (!merged.open.includes(agent2))
27514
+ merged.open.push(agent2);
27515
+ tool.displayName ??= displayName;
27516
+ };
27517
+ for (const { program, source, rel: rel2 } of sourceFilesOf(ctx)) {
27518
+ if (skipPath(rel2))
27519
+ continue;
27520
+ const checker = program.getTypeChecker();
27521
+ const tracer = tracerFor(program);
27522
+ const names = (expression) => literalStrings(expression, tracer).slice(0, MAX_NAMES_PER_SITE);
27523
+ const at = (node, reason) => ({ path: rel2, line: lineOf(node), reason });
27524
+ const visitObject = (object) => {
27525
+ const keys = object.properties.map((property) => propertyNameText(property.name) ?? "");
27526
+ const nameExpr = propertyValue(object, "name");
27527
+ if (nameExpr && SCHEMA_KEYS.some((key) => keys.includes(key)) && !isSchemaProperty(object)) {
27528
+ const list = names(nameExpr);
27529
+ if (list.length > 0) {
27530
+ const span = registryEntryOf(object);
27531
+ const agents = owners.ownersOf(span, program);
27532
+ for (const name of list)
27533
+ add(name, "definition", at(nameExpr, "tool definition (name beside its input schema)"), agents, span, displayNameOf(object, tracer), enclosingName(object));
27534
+ }
27535
+ }
27536
+ const toolNameExpr = propertyValue(object, "toolName");
27537
+ if (toolNameExpr && keys.includes("description")) {
27538
+ const list = names(toolNameExpr);
27539
+ if (list.length > 0) {
27540
+ const agents = owners.ownersOf(object, program);
27541
+ for (const name of list)
27542
+ add(name, "role-table", at(toolNameExpr, "role table row naming the tool the model sees"), agents, object, displayNameOf(object, tracer), enclosingName(object));
27543
+ }
27544
+ }
27545
+ for (const property of object.properties) {
27546
+ if (!import_typescript12.default.isPropertyAssignment(property) || !isToolValue(property.initializer, checker))
27547
+ continue;
27548
+ const list = import_typescript12.default.isComputedPropertyName(property.name) ? names(property.name.expression) : [propertyNameText(property.name)].filter((key) => Boolean(key));
27549
+ if (list.length === 0)
27550
+ continue;
27551
+ const agents = owners.ownersOf(property, program);
27552
+ const options2 = toolOptions(property.initializer);
27553
+ const definition = definitionNode(property.initializer, checker);
27554
+ for (const name of list)
27555
+ add(name, "record", at(property, "tools record key"), agents, definition, options2 ? displayNameOf(options2, tracer) : undefined, enclosingName(property));
27556
+ }
27557
+ };
27558
+ const visit2 = (node) => {
27559
+ try {
27560
+ if (import_typescript12.default.isObjectLiteralExpression(node)) {
27561
+ visitObject(node);
27562
+ } 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)) {
27563
+ const list = names(node.left.argumentExpression);
27564
+ if (list.length > 0) {
27565
+ const agents = owners.ownersOf(node, program);
27566
+ const options2 = toolOptions(node.right);
27567
+ const definition = definitionNode(node.right, checker);
27568
+ for (const name of list)
27569
+ add(name, "record", at(node, "tool stored under this key"), agents, definition, options2 ? displayNameOf(options2, tracer) : undefined, enclosingName(node));
27570
+ }
27571
+ }
27572
+ } catch {}
27573
+ import_typescript12.default.forEachChild(node, visit2);
27574
+ };
27575
+ visit2(source);
27576
+ }
27577
+ for (const role of result.roles) {
27578
+ if (role.role !== "tools" || role.sink.isTest || skipPath(role.sink.path))
27579
+ continue;
27580
+ const program = ctx.programFor(role.sink.path);
27581
+ const siteOwners = program ? ownersAtSite(owners, program, role.sink.path, role.sink.line) : { direct: [], rpc: [], open: [] };
27582
+ for (const hit of toolNamesOf(role.tree).names) {
27583
+ if (skipPath(hit.path))
27584
+ continue;
27585
+ 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);
27586
+ }
27587
+ }
27588
+ owners.indexAllowlists(new Set([...found.values()].map((tool) => tool.name)));
27589
+ const callOwners = new Map;
27590
+ for (const role of result.roles) {
27591
+ if (role.role !== "tools" || role.sink.isTest || skipPath(role.sink.path))
27592
+ continue;
27593
+ const ids = agentForScope(role.sink.scope);
27594
+ for (const hit of toolNamesOf(role.tree).names) {
27595
+ let owners2 = callOwners.get(hit.name);
27596
+ if (!owners2)
27597
+ callOwners.set(hit.name, owners2 = new Set);
27598
+ for (const id of ids)
27599
+ owners2.add(id);
27600
+ }
27601
+ }
27602
+ for (const [key, tool] of found) {
27603
+ const ids = new Set;
27604
+ for (const name of owners.agentsFor(tool.name, ownersByTool.get(key))) {
27605
+ const classes = owners.classes.filter((entry) => entry.name === name);
27606
+ if (classes.length === 1)
27607
+ for (const id of agentForScope(`${classes[0].path}#${name}`))
27608
+ ids.add(id);
27609
+ }
27610
+ for (const id of callOwners.get(tool.name) ?? [])
27611
+ ids.add(id);
27612
+ tool.agents = [...ids].sort();
27613
+ }
27614
+ return [...found.values()].sort((a, b) => a.name.localeCompare(b.name) || (a.package ?? "").localeCompare(b.package ?? ""));
27615
+ }
27616
+ function registryEntryOf(object) {
27617
+ const parent = object.parent;
27618
+ if (parent && import_typescript12.default.isPropertyAssignment(parent) && propertyNameText(parent.name) === "definition" && import_typescript12.default.isObjectLiteralExpression(parent.parent)) {
27619
+ return parent.parent;
27620
+ }
27621
+ return object;
27622
+ }
27623
+ function definitionNode(expression, checker, depth = 0) {
27624
+ const value = unwrap(expression);
27625
+ if (import_typescript12.default.isCallExpression(value) || import_typescript12.default.isObjectLiteralExpression(value))
27626
+ return value;
27627
+ if (import_typescript12.default.isIdentifier(value) && depth < 2) {
27628
+ const declaration = valueDeclaration(resolvedSymbol(value, checker));
27629
+ if (declaration && import_typescript12.default.isVariableDeclaration(declaration) && declaration.initializer)
27630
+ return definitionNode(declaration.initializer, checker, depth + 1);
27631
+ }
27632
+ return;
27633
+ }
27634
+ function ownersAtSite(owners, program, path, line) {
27635
+ const source = program.getSourceFiles().find((file) => file.fileName.endsWith(`/${path}`) || file.fileName === path);
27636
+ if (!source)
27637
+ return { direct: [], rpc: [], open: [] };
27638
+ const position = source.getPositionOfLineAndCharacter(Math.max(0, line - 1), 0);
27639
+ let node = source;
27640
+ const descend = (current) => {
27641
+ for (const child of current.getChildren(source)) {
27642
+ if (child.getStart(source) <= position && position < child.getEnd()) {
27643
+ node = child;
27644
+ descend(child);
27645
+ return;
27646
+ }
27647
+ }
27648
+ };
27649
+ descend(source);
27650
+ return owners.ownersOf(node, program);
27651
+ }
27652
+ function literalStrings(expression, tracer) {
27653
+ const value = unwrap(expression);
27654
+ if (import_typescript12.default.isStringLiteral(value) || import_typescript12.default.isNoSubstitutionTemplateLiteral(value))
27655
+ return [value.text];
27656
+ let tree;
27657
+ try {
27658
+ tree = tracer.trace(value);
27659
+ } catch {
27660
+ return [];
27661
+ }
27662
+ return [...new Set(renderings(tree, MAX_NAMES_PER_SITE).filter((text) => text.length > 0 && !text.includes("${...}")))];
27663
+ }
27664
+ function displayNameOf(object, tracer) {
27665
+ for (const key of ["displayName", "title"]) {
27666
+ const value = propertyValue(object, key);
27667
+ if (!value)
27668
+ continue;
27669
+ const [text] = literalStrings(value, tracer);
27670
+ if (text)
27671
+ return text;
27672
+ }
27673
+ return;
27674
+ }
27675
+ function toolOptions(expression) {
27676
+ const value = unwrap(expression);
27677
+ if (import_typescript12.default.isObjectLiteralExpression(value))
27678
+ return value;
27679
+ if (import_typescript12.default.isCallExpression(value)) {
27680
+ for (const argument of value.arguments) {
27681
+ const inner = unwrap(argument);
27682
+ if (import_typescript12.default.isObjectLiteralExpression(inner))
27683
+ return inner;
27684
+ }
27685
+ }
27686
+ return;
27687
+ }
27688
+ function enclosingName(node) {
27689
+ const parts = [];
27690
+ for (let current = node.parent;current; current = current.parent) {
27691
+ if ((import_typescript12.default.isFunctionDeclaration(current) || import_typescript12.default.isMethodDeclaration(current)) && current.name && parts.length === 0) {
27692
+ parts.unshift(propertyNameText(current.name) ?? "");
27693
+ } else if (import_typescript12.default.isVariableDeclaration(current) && import_typescript12.default.isIdentifier(current.name) && parts.length === 0) {
27694
+ parts.unshift(current.name.text);
27695
+ } else if (import_typescript12.default.isClassLike(current) && current.name) {
27696
+ parts.unshift(current.name.text);
27697
+ break;
27698
+ }
27699
+ }
27700
+ const joined = parts.filter(Boolean).join(".");
27701
+ return joined || undefined;
27702
+ }
27703
+ function isSchemaProperty(object) {
27704
+ const parent = object.parent;
27705
+ if (!parent || !import_typescript12.default.isPropertyAssignment(parent))
27706
+ return false;
27707
+ const holder = parent.parent;
27708
+ return import_typescript12.default.isObjectLiteralExpression(holder) && import_typescript12.default.isPropertyAssignment(holder.parent) && propertyNameText(holder.parent.name) === "properties";
27709
+ }
27710
+ function isToolValue(expression, checker, depth = 0) {
27711
+ const value = unwrap(expression);
27712
+ if (import_typescript12.default.isCallExpression(value)) {
27713
+ const callee = unwrap(value.expression);
27714
+ const name = import_typescript12.default.isIdentifier(callee) ? callee : import_typescript12.default.isPropertyAccessExpression(callee) ? callee.name : undefined;
27715
+ if (!name)
27716
+ return false;
27717
+ if (TOOL_FACTORY.test(name.text))
27718
+ return true;
27719
+ if (import_typescript12.default.isIdentifier(callee)) {
27720
+ const origin = importOrigin(callee, checker);
27721
+ if (origin && TOOL_MODULE.test(origin.module) && /tool/i.test(origin.imported))
27722
+ return true;
27723
+ }
27724
+ return false;
27725
+ }
27726
+ if (import_typescript12.default.isObjectLiteralExpression(value)) {
27727
+ const keys = value.properties.map((property) => propertyNameText(property.name) ?? "");
27728
+ return SCHEMA_KEYS.some((key) => keys.includes(key)) && TOOL_BODY_KEYS.some((key) => keys.includes(key)) && keys.includes("description") && !keys.includes("name");
27729
+ }
27730
+ if (import_typescript12.default.isIdentifier(value) && depth < 2) {
27731
+ const declaration = valueDeclaration(resolvedSymbol(value, checker));
27732
+ if (declaration && import_typescript12.default.isVariableDeclaration(declaration) && declaration.initializer && declaration.parent.flags & import_typescript12.default.NodeFlags.Const) {
27733
+ return isToolValue(declaration.initializer, checker, depth + 1);
27734
+ }
27735
+ }
27736
+ return false;
27737
+ }
27738
+ var emitted = new WeakMap;
27739
+ function emitToolsCached(result, ctx) {
27740
+ let tools = emitted.get(result);
27741
+ if (!tools) {
27742
+ tools = emitTools(result, ctx);
27743
+ emitted.set(result, tools);
27744
+ }
27745
+ return tools;
27746
+ }
27747
+ function toolArtifactId(name, pkg) {
27748
+ const slug2 = (text) => text.replace(/[^A-Za-z0-9_.:-]+/g, "_");
27749
+ return `tool.extract.${slug2(name)}`;
27750
+ }
27751
+ function workspacePackages(rootDir) {
27752
+ const cache2 = new Map;
27753
+ const lookup = (dir) => {
27754
+ if (dir === "" || dir === ".")
27755
+ return "";
27756
+ const cached = cache2.get(dir);
27757
+ if (cached !== undefined)
27758
+ return cached;
27759
+ const found = existsSync9(join14(rootDir, dir, "package.json")) ? dir : lookup(posix3.dirname(dir) === "." ? "" : posix3.dirname(dir));
27760
+ cache2.set(dir, found);
27761
+ return found;
27762
+ };
27763
+ return (rel2) => lookup(posix3.dirname(rel2) === "." ? "" : posix3.dirname(rel2));
27764
+ }
27765
+ function toolDefinitionRefs(tools) {
27766
+ const out = [];
27767
+ for (const tool of tools) {
27768
+ const definition = tool.definitions[0];
27769
+ if (!definition)
27770
+ continue;
27771
+ out.push({
27772
+ toolId: toolArtifactId(tool.name, tool.package),
27773
+ name: tool.name,
27774
+ definition: { path: definition.path, start: definition.start, end: definition.end, line: definition.line },
27775
+ ...tool.agents.length > 0 ? { agentIds: [...tool.agents] } : {},
27776
+ scope: definition.scope
27777
+ });
27778
+ }
27779
+ return out;
27780
+ }
27781
+ function toolArtifacts(tools, runtimeAgents = []) {
27782
+ const knownIds = new Set(runtimeAgents.map((agent2) => agent2.id));
27783
+ return tools.map((tool) => {
27784
+ const usedByAgentIds = [...new Set(tool.agents.filter((id) => knownIds.has(id)))];
27785
+ const artifact2 = {
27786
+ id: toolArtifactId(tool.name, tool.package),
27787
+ type: "tool",
27788
+ name: tool.name,
27789
+ status: tool.status,
27790
+ scope: usedByAgentIds.length === 1 ? "agent" : "shared",
27791
+ ...tool.definitions[0] ? { sourcePath: tool.definitions[0].path } : {},
27792
+ ...tool.definitions[0] ? { body: tool.definitions[0].body } : {},
27793
+ ...tool.definitions.length > 1 ? { definitionVariants: tool.definitions.map((definition) => ({ sourcePath: definition.path, body: definition.body, evidence: [{ path: definition.path, line: definition.line }] })) } : {},
27794
+ usedByAgentIds,
27795
+ confidence: 0.9,
27796
+ confidenceReason: `Deterministic: model-facing tool name read from ${tool.via === "tools-arg" ? "a traced tools argument" : "its definition"} (call-site extractor).`,
27797
+ evidence: tool.evidence.map((entry) => ({ path: entry.path, line: entry.line, reason: entry.reason })),
27798
+ calledFrom: tool.calledFrom,
27799
+ agentClasses: [...tool.agents],
27800
+ ...tool.displayName ? { displayName: tool.displayName } : {}
27801
+ };
27802
+ return artifact2;
27803
+ });
27804
+ }
27805
+
27806
+ // src/harness-extract/types.ts
27807
+ var EXTRACT_SCHEMA_VERSION = 1;
27808
+
27809
+ // src/harness-extract/index.ts
27810
+ var PROMPT_ROLES = new Set(["system", "user", "messages", "prompt", "instructions", "questions"]);
27811
+ var MAX_HELPER_CALLERS = 200;
27812
+ var MAX_DERIVED = 5000;
27813
+ var MAX_CALLER_CHAIN = 3;
27814
+ var cache2 = new Map;
27815
+ function clearExtractCache() {
27816
+ cache2.clear();
27817
+ }
27818
+ function extractHarness(rootDir, options = {}) {
27819
+ return extractHarnessWithContext(rootDir, options).result;
27820
+ }
27821
+ function extractHarnessWithContext(rootDir, options = {}) {
27822
+ const root = resolve13(rootDir);
27823
+ const { fresh, ...rest } = options;
27824
+ const key = `${root}\x00${JSON.stringify(rest)}`;
27825
+ const fingerprint = sourceFingerprint(root, rest);
27826
+ const cached = fresh ? undefined : cache2.get(key);
27827
+ if (cached && cached.fingerprint === fingerprint)
27828
+ return cached.output;
27829
+ const output = runExtract(root, options);
27830
+ cache2.set(key, { output, fingerprint });
27831
+ return output;
27832
+ }
27833
+ function argRef(rootDir, node, key) {
27834
+ const source = node.getSourceFile();
27835
+ const ref = { path: relPath(rootDir, source.fileName), start: node.getStart(source), end: node.getEnd(), line: lineOf(node) };
27836
+ if (key !== undefined)
27837
+ ref.key = key;
27838
+ Object.defineProperty(ref, "node", { value: node, enumerable: false });
27839
+ return ref;
27840
+ }
27841
+ function namedEnclosingFunction(node) {
27842
+ for (let fn = enclosingFunction(node);fn; fn = enclosingFunction(fn)) {
27843
+ const name = functionName(fn);
27844
+ if (name)
27845
+ return { fn, name };
27846
+ }
27847
+ return;
27848
+ }
27849
+ function qualifiedName(fn, name) {
27850
+ const cls = enclosingClass(fn);
27851
+ const owner = cls && (fn.parent === cls || fn.parent && fn.parent.parent === cls) ? className(cls) : undefined;
27852
+ return owner ? `${owner}.${name}` : name;
27853
+ }
27854
+ function functionScope(rootDir, fn, name) {
27855
+ const parts = [qualifiedName(fn, name)];
27856
+ const object = objectLiteralOf2(fn);
27857
+ if (object) {
27858
+ const holder = object.parent && import_typescript13.default.isVariableDeclaration(object.parent) && import_typescript13.default.isIdentifier(object.parent.name) ? object.parent.name.text : `L${lineOf(object)}`;
27859
+ parts.unshift(holder);
27860
+ }
27861
+ for (let outer = namedEnclosingFunction(object ?? fn);outer; outer = namedEnclosingFunction(outer.fn))
27862
+ parts.unshift(qualifiedName(outer.fn, outer.name));
27863
+ return `${relPath(rootDir, fn.getSourceFile().fileName)}#${parts.join(".")}`;
27864
+ }
27865
+ function objectLiteralOf2(fn) {
27866
+ 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;
27867
+ return member2 && import_typescript13.default.isObjectLiteralExpression(member2.parent) ? member2.parent : undefined;
27868
+ }
27869
+ function scopeOf(rootDir, node) {
27870
+ const named = namedEnclosingFunction(node);
27871
+ if (named)
27872
+ return functionScope(rootDir, named.fn, named.name);
27873
+ const path = relPath(rootDir, node.getSourceFile().fileName);
27874
+ let outermost;
27875
+ for (let fn = enclosingFunction(node);fn; fn = enclosingFunction(fn))
27876
+ outermost = fn;
27877
+ return outermost ? `${path}#L${lineOf(outermost)}` : path;
27878
+ }
27879
+ function callerChain(rootDir, anchor, calls, memo) {
27880
+ const start = namedEnclosingFunction(anchor);
27881
+ if (!start)
27882
+ return { callers: [], callerScopes: [] };
27883
+ const cached = memo.get(start.fn);
27884
+ if (cached)
27885
+ return cached;
27886
+ const chain = { callers: [], callerScopes: [] };
27887
+ const seen = new Set;
27888
+ let current = start;
27889
+ while (current && !seen.has(current.fn) && chain.callers.length <= MAX_CALLER_CHAIN) {
27890
+ seen.add(current.fn);
27891
+ chain.callers.unshift(qualifiedName(current.fn, current.name));
27892
+ chain.callerScopes.unshift(functionScope(rootDir, current.fn, current.name));
27893
+ const caller = calls.callersOf(current.fn, current.name, 1)[0];
27894
+ current = caller ? namedEnclosingFunction(caller) : undefined;
27895
+ }
27896
+ memo.set(start.fn, chain);
27897
+ return chain;
27898
+ }
27899
+ var AGENT_CLASS_BASES = new Set(["Think", "Agent", "AIChatAgent"]);
27900
+ function findAgentClasses(program, checker, memo) {
27901
+ const out = [];
27902
+ for (const source of program.getSourceFiles()) {
27903
+ if (source.isDeclarationFile || /[\\/]node_modules[\\/]/.test(source.fileName))
27904
+ continue;
27905
+ const visit2 = (node) => {
27906
+ if ((import_typescript13.default.isClassDeclaration(node) || import_typescript13.default.isClassExpression(node)) && node.heritageClauses) {
27907
+ const base = frameworkBaseOf(node, checker, memo).base;
27908
+ if (base && AGENT_CLASS_BASES.has(base))
27909
+ out.push(node);
27910
+ }
27911
+ import_typescript13.default.forEachChild(node, visit2);
27912
+ };
27913
+ visit2(source);
27914
+ }
27915
+ return out;
27916
+ }
27917
+ function describeEnclosing(rootDir, anchor, checker, memo, ownClass) {
27918
+ const fn = ownClass ? undefined : namedEnclosingFunction(anchor);
27919
+ const cls = ownClass ?? enclosingClass(anchor);
27920
+ let enclosingCls;
26826
27921
  if (cls) {
26827
27922
  const info = frameworkBaseOf(cls, checker, memo);
26828
27923
  const at = cls.name ?? cls;
@@ -26857,35 +27952,35 @@ function siteFields(sources, rootDir) {
26857
27952
  return out;
26858
27953
  }
26859
27954
  function paramFlow(node, fn, checker, hops = 0) {
26860
- if (!import_typescript10.default.isExpression(node) || hops > 2)
27955
+ if (!import_typescript13.default.isExpression(node) || hops > 2)
26861
27956
  return;
26862
27957
  const expr = unwrap(node);
26863
- if (import_typescript10.default.isBinaryExpression(expr) && (expr.operatorToken.kind === import_typescript10.default.SyntaxKind.QuestionQuestionToken || expr.operatorToken.kind === import_typescript10.default.SyntaxKind.BarBarToken)) {
27958
+ if (import_typescript13.default.isBinaryExpression(expr) && (expr.operatorToken.kind === import_typescript13.default.SyntaxKind.QuestionQuestionToken || expr.operatorToken.kind === import_typescript13.default.SyntaxKind.BarBarToken)) {
26864
27959
  return paramFlow(expr.left, fn, checker, hops);
26865
27960
  }
26866
- if (import_typescript10.default.isPropertyAccessExpression(expr) && import_typescript10.default.isIdentifier(unwrap(expr.expression))) {
27961
+ if (import_typescript13.default.isPropertyAccessExpression(expr) && import_typescript13.default.isIdentifier(unwrap(expr.expression))) {
26867
27962
  const inner = paramFlow(expr.expression, fn, checker, hops);
26868
27963
  return inner && inner.key === undefined ? { param: inner.param, key: expr.name.text } : undefined;
26869
27964
  }
26870
- if (!import_typescript10.default.isIdentifier(expr))
27965
+ if (!import_typescript13.default.isIdentifier(expr))
26871
27966
  return;
26872
27967
  const declaration = valueDeclaration(resolvedSymbol(expr, checker));
26873
27968
  if (!declaration)
26874
27969
  return;
26875
- if (import_typescript10.default.isParameter(declaration) && declaration.parent === fn && !declaration.dotDotDotToken)
27970
+ if (import_typescript13.default.isParameter(declaration) && declaration.parent === fn && !declaration.dotDotDotToken)
26876
27971
  return { param: declaration };
26877
- if (import_typescript10.default.isBindingElement(declaration) && import_typescript10.default.isObjectBindingPattern(declaration.parent) && import_typescript10.default.isParameter(declaration.parent.parent) && declaration.parent.parent.parent === fn && !declaration.dotDotDotToken) {
27972
+ 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) {
26878
27973
  const key = propertyNameText(declaration.propertyName ?? declaration.name);
26879
27974
  return key ? { param: declaration.parent.parent, key } : undefined;
26880
27975
  }
26881
- if (import_typescript10.default.isVariableDeclaration(declaration) && declaration.initializer && enclosingFunction(declaration) === fn && declaration.parent.flags & import_typescript10.default.NodeFlags.Const) {
27976
+ if (import_typescript13.default.isVariableDeclaration(declaration) && declaration.initializer && enclosingFunction(declaration) === fn && declaration.parent.flags & import_typescript13.default.NodeFlags.Const) {
26882
27977
  return paramFlow(declaration.initializer, fn, checker, hops + 1);
26883
27978
  }
26884
27979
  return;
26885
27980
  }
26886
27981
  function roleParamFlow(arg, fn, checker) {
26887
27982
  const object = unwrap(arg.node);
26888
- if (arg.key !== undefined && !arg.key.includes(".") && import_typescript10.default.isObjectLiteralExpression(object)) {
27983
+ if (arg.key !== undefined && !arg.key.includes(".") && import_typescript13.default.isObjectLiteralExpression(object)) {
26889
27984
  const value = propertyValue(object, arg.key);
26890
27985
  const flow = value ? paramFlow(value, fn, checker) : undefined;
26891
27986
  return flow ? { ...flow, viaProperty: true } : undefined;
@@ -26897,9 +27992,9 @@ function descendArg(argument, path) {
26897
27992
  let index = 0;
26898
27993
  for (;index < path.length; index += 1) {
26899
27994
  let value = unwrap(node);
26900
- if (import_typescript10.default.isCallExpression(value) && value.expression.getText() === "JSON.stringify" && value.arguments[0])
27995
+ if (import_typescript13.default.isCallExpression(value) && value.expression.getText() === "JSON.stringify" && value.arguments[0])
26901
27996
  value = unwrap(value.arguments[0]);
26902
- const next = import_typescript10.default.isObjectLiteralExpression(value) ? propertyValue(value, path[index]) : undefined;
27997
+ const next = import_typescript13.default.isObjectLiteralExpression(value) ? propertyValue(value, path[index]) : undefined;
26903
27998
  if (!next)
26904
27999
  break;
26905
28000
  node = next;
@@ -26976,8 +28071,8 @@ function runExtract(rootDir, options) {
26976
28071
  };
26977
28072
  sites.push({ site, entry, anchor, sources, level: 0 });
26978
28073
  };
26979
- const visit = (node) => {
26980
- if (import_typescript10.default.isCallExpression(node) || import_typescript10.default.isNewExpression(node)) {
28074
+ const visit2 = (node) => {
28075
+ if (import_typescript13.default.isCallExpression(node) || import_typescript13.default.isNewExpression(node)) {
26981
28076
  for (const recognizer of CALL_SINKS) {
26982
28077
  let match;
26983
28078
  const begin = performance.now();
@@ -26992,7 +28087,7 @@ function runExtract(rootDir, options) {
26992
28087
  break;
26993
28088
  }
26994
28089
  }
26995
- } else if (import_typescript10.default.isClassDeclaration(node) || import_typescript10.default.isClassExpression(node)) {
28090
+ } else if (import_typescript13.default.isClassDeclaration(node) || import_typescript13.default.isClassExpression(node)) {
26996
28091
  for (const recognizer of classRecognizers) {
26997
28092
  try {
26998
28093
  for (const match of recognizer.match(node, ctx2))
@@ -27002,9 +28097,9 @@ function runExtract(rootDir, options) {
27002
28097
  }
27003
28098
  }
27004
28099
  }
27005
- import_typescript10.default.forEachChild(node, visit);
28100
+ import_typescript13.default.forEachChild(node, visit2);
27006
28101
  };
27007
- visit(source);
28102
+ visit2(source);
27008
28103
  }
27009
28104
  } catch (error) {
27010
28105
  warnings.push(`sinks ${entry.configPath ?? "(fallback)"}: ${error.message}`);
@@ -27054,7 +28149,7 @@ function runExtract(rootDir, options) {
27054
28149
  const sources = [];
27055
28150
  for (const { source: role, flow } of flowing) {
27056
28151
  const argument = call.arguments[named.fn.parameters.indexOf(flow.param)];
27057
- if (!argument || import_typescript10.default.isSpreadElement(argument))
28152
+ if (!argument || import_typescript13.default.isSpreadElement(argument))
27058
28153
  continue;
27059
28154
  const arg = descendArg(argument, [flow.key, flow.viaProperty ? undefined : role.arg.key].filter((part) => Boolean(part)));
27060
28155
  sources.push({ ...role, bindings: extendBindings(role.bindings, callerBindings), arg });
@@ -27183,11 +28278,21 @@ function runExtract(rootDir, options) {
27183
28278
  timings.models = Date.now() - begin;
27184
28279
  result.durationMs = Date.now() - started;
27185
28280
  }
28281
+ if (options.tools ?? true) {
28282
+ const begin = Date.now();
28283
+ try {
28284
+ result.toolDefinitions = toolDefinitionRefs(emitToolsCached(result, ctx));
28285
+ } catch (error) {
28286
+ warnings.push(`tools: ${error.message}`);
28287
+ }
28288
+ timings.tools = Date.now() - begin;
28289
+ result.durationMs = Date.now() - started;
28290
+ }
27186
28291
  return { result, ctx };
27187
28292
  }
27188
28293
  function nodeSpanning(source, start, end) {
27189
28294
  let best;
27190
- const visit = (node) => {
28295
+ const visit2 = (node) => {
27191
28296
  const nodeStart = node.getStart(source);
27192
28297
  if (nodeStart > start || node.getEnd() < end)
27193
28298
  return;
@@ -27196,9 +28301,9 @@ function nodeSpanning(source, start, end) {
27196
28301
  return;
27197
28302
  }
27198
28303
  best = node;
27199
- import_typescript10.default.forEachChild(node, visit);
28304
+ import_typescript13.default.forEachChild(node, visit2);
27200
28305
  };
27201
- visit(source);
28306
+ visit2(source);
27202
28307
  return best;
27203
28308
  }
27204
28309
  function serializeExtractResult(result) {
@@ -27242,4 +28347,853 @@ function assignAgentIds(result, agentForScope) {
27242
28347
  }
27243
28348
  }
27244
28349
 
27245
- export { startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, valueChildren, selectKey, allValues, renderings, CALL_SINKS, registerCallSink, registerClassSink, isModelId, collectModels, modelArtifacts, modelUnknowns, collectModelLiterals, EXTRACT_SCHEMA_VERSION, ENUMERATORS, toolNamesOf, clearExtractCache, extractHarness, extractHarnessWithContext, 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 };
28350
+ // src/harness-extract/enumerators/agents.ts
28351
+ function agentForScope(scope, enumeration) {
28352
+ return enumeration.agentForScope(scope);
28353
+ }
28354
+ function createAgentScopeResolver(result, ctx) {
28355
+ return enumerateAgents(result, ctx).agentForScope;
28356
+ }
28357
+ var enumerations = new WeakMap;
28358
+ var AGENT_BASES4 = new Set(["Think", "Agent", "AIChatAgent", "McpAgent"]);
28359
+ var HTTP_METHODS2 = new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]);
28360
+ function routeOf(fn, file) {
28361
+ const name = functionName(fn);
28362
+ if (name && HTTP_METHODS2.has(name) && /(?:^|\/)(?:route|\+server)\.[cm]?[jt]sx?$/.test(file.path))
28363
+ return `${name} ${file.path}`;
28364
+ const parent = fn.parent;
28365
+ 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)) {
28366
+ const path = parent.arguments.find(import_typescript14.default.isStringLiteralLike);
28367
+ if (path)
28368
+ return `${parent.expression.name.text.toUpperCase()} ${path.text} (${file.path})`;
28369
+ }
28370
+ return;
28371
+ }
28372
+ function enumerateAgents(result, ctx) {
28373
+ const cached = enumerations.get(ctx);
28374
+ if (cached)
28375
+ return cached;
28376
+ const repo = enumerationRepository(ctx);
28377
+ const scopes = new Map;
28378
+ const byNode = new Map;
28379
+ const classes = [];
28380
+ const bound = new Set(detectBoundRuntimeClasses(ctx.rootDir).filter((x) => x.kind === "durable_object").map((x) => x.className));
28381
+ const memo = createFrameworkMemo();
28382
+ const keyOf = (node) => `${node.getSourceFile().fileName}:${node.getStart()}`;
28383
+ for (const file of repo.files) {
28384
+ if (!/\.[cm]?[jt]sx?$/.test(file.path) || TEST_PATH4.test(file.path) || EVAL_PATH2.test(file.path) || /^scripts\//.test(file.path) && !repo.deployedFiles.has(file.path))
28385
+ continue;
28386
+ const checker = ctx.checkerFor(file.path);
28387
+ visit(file.source, (node) => {
28388
+ if ((import_typescript14.default.isClassDeclaration(node) || import_typescript14.default.isClassExpression(node)) && node.name) {
28389
+ const name2 = node.name.text;
28390
+ const info = checker ? frameworkBaseOf(node, checker, memo) : undefined;
28391
+ const directBase = node.heritageClauses?.flatMap((h) => h.types).map((x) => x.expression.getText()) ?? [];
28392
+ const protocolEvents = new Set;
28393
+ visit(node, (member2) => {
28394
+ if (import_typescript14.default.isStringLiteralLike(member2))
28395
+ protocolEvents.add(member2.text);
28396
+ });
28397
+ const realtime = protocolEvents.has("session.update") && protocolEvents.has("response.create") && [...protocolEvents].some((event) => event.includes("function_call"));
28398
+ const exported = import_typescript14.default.getCombinedModifierFlags(node) & import_typescript14.default.ModifierFlags.Export;
28399
+ const abstract = import_typescript14.default.getCombinedModifierFlags(node) & import_typescript14.default.ModifierFlags.Abstract;
28400
+ if (!abstract && (exported || bound.has(name2)) && (info?.base && AGENT_BASES4.has(info.base) || directBase.some((x) => AGENT_BASES4.has(x)) || exported && realtime)) {
28401
+ classes.push({ file, node, name: name2, chain: info?.chain ?? [name2, ...directBase] });
28402
+ }
28403
+ }
28404
+ if (!isFunctionLike(node) || !node.body)
28405
+ return;
28406
+ const name = functionName(node);
28407
+ const cls = enclosingClass(node)?.name?.text;
28408
+ const route = routeOf(node, file);
28409
+ const label = cls && name ? `${cls}.${name}` : name ?? route ?? `${file.path}:${lineOf5(node)}`;
28410
+ const scope = {
28411
+ key: keyOf(node),
28412
+ label,
28413
+ aliases: [label, ...name ? [name] : [], ...route ? [route] : [], `${file.path}::${label}`, `${file.path}#${label}`],
28414
+ file,
28415
+ node,
28416
+ className: cls,
28417
+ route,
28418
+ calls: new Set,
28419
+ virtualCalls: new Map,
28420
+ deployedCalls: new Set,
28421
+ callsByWorker: new Map(repo.workers.map((worker) => [worker.id, new Set])),
28422
+ callers: new Set,
28423
+ hasModel: false,
28424
+ modelWorkers: new Set,
28425
+ hasTools: false,
28426
+ toolFeedback: false,
28427
+ configuredSteps: false,
28428
+ hasLoop: false,
28429
+ forcedOutput: false
28430
+ };
28431
+ const qualified = (fn, fnName) => {
28432
+ const owner = enclosingClass(fn);
28433
+ return owner?.name && (fn.parent === owner || fn.parent?.parent === owner) ? `${owner.name.text}.${fnName}` : fnName;
28434
+ };
28435
+ if (name) {
28436
+ const parts = [qualified(node, name)];
28437
+ 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;
28438
+ const object = member2 && import_typescript14.default.isObjectLiteralExpression(member2.parent) ? member2.parent : undefined;
28439
+ if (object)
28440
+ parts.unshift(import_typescript14.default.isVariableDeclaration(object.parent) && import_typescript14.default.isIdentifier(object.parent.name) ? object.parent.name.text : `L${lineOf5(object)}`);
28441
+ for (let outer = (object ?? node).parent;outer; outer = outer.parent) {
28442
+ if (isFunctionLike(outer)) {
28443
+ const outerName = functionName(outer);
28444
+ if (outerName)
28445
+ parts.unshift(qualified(outer, outerName));
28446
+ }
28447
+ }
28448
+ scope.aliases.push(`${file.path}#${parts.join(".")}`);
28449
+ }
28450
+ scope.aliases.push(scope.key);
28451
+ scopes.set(scope.key, scope);
28452
+ byNode.set(node, scope);
28453
+ });
28454
+ }
28455
+ const classChain = (node, seen = new Set) => {
28456
+ if (seen.has(keyOf(node)))
28457
+ return [];
28458
+ seen.add(keyOf(node));
28459
+ const checker = ctx.checkerFor(node.getSourceFile().fileName.slice(ctx.rootDir.length + 1));
28460
+ const bases = node.heritageClauses?.flatMap((clause) => clause.types).flatMap((base) => {
28461
+ const declaration = checker && valueDeclaration(resolvedSymbol(base.expression, checker));
28462
+ return declaration && import_typescript14.default.isClassLike(declaration) ? classChain(declaration, seen) : [];
28463
+ }) ?? [];
28464
+ return [node, ...bases];
28465
+ };
28466
+ for (const cls of classes)
28467
+ cls.nodes = classChain(cls.node);
28468
+ const virtualEdges = new Map;
28469
+ const nearest = (node) => {
28470
+ for (let current = node;current; current = current.parent) {
28471
+ const scope = byNode.get(current);
28472
+ if (scope)
28473
+ return scope;
28474
+ }
28475
+ return;
28476
+ };
28477
+ const bindingTruth = (condition, worker) => {
28478
+ if (condition.kind === import_typescript14.default.SyntaxKind.TrueKeyword)
28479
+ return true;
28480
+ if (condition.kind === import_typescript14.default.SyntaxKind.FalseKeyword)
28481
+ return false;
28482
+ if (import_typescript14.default.isPrefixUnaryExpression(condition) && condition.operator === import_typescript14.default.SyntaxKind.ExclamationToken) {
28483
+ const value = bindingTruth(condition.operand, worker);
28484
+ return value === undefined ? undefined : !value;
28485
+ }
28486
+ 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))
28487
+ return true;
28488
+ return;
28489
+ };
28490
+ 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])));
28491
+ const deployed = (node, worker) => {
28492
+ for (let current = node;current.parent; current = current.parent) {
28493
+ const parent = current.parent;
28494
+ if (import_typescript14.default.isIfStatement(parent)) {
28495
+ const truth = bindingTruth(parent.expression, worker);
28496
+ if (truth !== undefined && (current === parent.thenStatement ? !truth : current === parent.elseStatement ? truth : false))
28497
+ return false;
28498
+ }
28499
+ if (import_typescript14.default.isBlock(parent))
28500
+ for (const prior of parent.statements) {
28501
+ if (prior.getStart() >= current.getStart())
28502
+ break;
28503
+ if (import_typescript14.default.isIfStatement(prior)) {
28504
+ const truth = bindingTruth(prior.expression, worker);
28505
+ if (truth !== undefined && returns(truth ? prior.thenStatement : prior.elseStatement))
28506
+ return false;
28507
+ }
28508
+ }
28509
+ }
28510
+ return true;
28511
+ };
28512
+ const markModel = (scope, node) => {
28513
+ scope.hasModel = true;
28514
+ for (const worker of repo.workers)
28515
+ if (deployed(node, worker.id))
28516
+ scope.modelWorkers.add(worker.id);
28517
+ };
28518
+ for (const site of result.callSites) {
28519
+ if (site.isTest || site.isEval)
28520
+ continue;
28521
+ const file = repo.files.find((x) => x.path === site.path);
28522
+ if (!file)
28523
+ continue;
28524
+ const offset = file.source.getPositionOfLineAndCharacter(Math.max(0, site.line - 1), Math.max(0, site.col - 1));
28525
+ let anchor = file.source;
28526
+ const descend = (node) => {
28527
+ if (node.getStart() <= offset && node.getEnd() >= offset) {
28528
+ anchor = node;
28529
+ import_typescript14.default.forEachChild(node, descend);
28530
+ }
28531
+ };
28532
+ descend(file.source);
28533
+ const scope = nearest(anchor);
28534
+ if (!scope)
28535
+ continue;
28536
+ markModel(scope, anchor);
28537
+ const tools = site.toolsArg ? ctx.nodeAt(site.toolsArg) : undefined;
28538
+ scope.hasTools ||= Boolean(tools && !(import_typescript14.default.isObjectLiteralExpression(tools) && tools.properties.length === 0) && !(import_typescript14.default.isArrayLiteralExpression(tools) && tools.elements.length === 0));
28539
+ scope.aliases.push(site.scope);
28540
+ }
28541
+ const targetsOf = (node, file) => {
28542
+ const checker = ctx.checkerFor(file.path);
28543
+ if (!checker)
28544
+ return [];
28545
+ const at = import_typescript14.default.isPropertyAccessExpression(node) ? node.name : node;
28546
+ const declaration = valueDeclaration(resolvedSymbol(at, checker));
28547
+ if (!declaration)
28548
+ return [];
28549
+ const direct = byNode.get(declaration) ?? scopes.get(keyOf(declaration));
28550
+ if (direct)
28551
+ return [direct];
28552
+ if (import_typescript14.default.isVariableDeclaration(declaration) && declaration.initializer) {
28553
+ const fn = byNode.get(declaration.initializer) ?? scopes.get(keyOf(declaration.initializer));
28554
+ if (fn)
28555
+ return [fn];
28556
+ }
28557
+ return [];
28558
+ };
28559
+ for (const scope of scopes.values()) {
28560
+ const inspect = (node) => {
28561
+ if (node !== scope.node && isFunctionLike(node)) {
28562
+ return;
28563
+ }
28564
+ if (import_typescript14.default.isWhileStatement(node) || import_typescript14.default.isDoStatement(node) || import_typescript14.default.isForStatement(node) || import_typescript14.default.isForOfStatement(node))
28565
+ scope.hasLoop = true;
28566
+ if ((import_typescript14.default.isIdentifier(node) || import_typescript14.default.isStringLiteralLike(node)) && /^(?:tool_calls|toolCalls|tool_use|tool_result|tool_results|toolResults)$/.test(node.text)) {
28567
+ scope.hasTools = true;
28568
+ scope.toolFeedback = true;
28569
+ }
28570
+ if (import_typescript14.default.isObjectLiteralExpression(node)) {
28571
+ const fields = new Map(node.properties.filter(import_typescript14.default.isPropertyAssignment).map((p2) => [nameOf(p2.name), p2.initializer]));
28572
+ const type = fields.get("type");
28573
+ if (type && import_typescript14.default.isStringLiteralLike(type) && type.text === "tool" && fields.has("name"))
28574
+ scope.forcedOutput = true;
28575
+ }
28576
+ if (import_typescript14.default.isCallExpression(node) || import_typescript14.default.isNewExpression(node)) {
28577
+ const callee = node.expression.getText();
28578
+ if (/(?:chat\.)?completions\.create$|messages\.(?:create|stream)$|responses\.(?:create|stream)$/.test(callee))
28579
+ markModel(scope, node);
28580
+ if (/\.runTurn$/.test(callee) && scope.node.parameters.some((param) => /tools/i.test(param.name.getText())))
28581
+ markModel(scope, node);
28582
+ const connect = (at) => {
28583
+ for (const target of byNode.has(at) ? [byNode.get(at)] : targetsOf(at, scope.file)) {
28584
+ if (import_typescript14.default.isPropertyAccessExpression(at) && at.expression.kind === import_typescript14.default.SyntaxKind.ThisKeyword) {
28585
+ virtualEdges.set(`${scope.key}|${target.key}`, at.name.text);
28586
+ scope.virtualCalls.set(target.key, at.name.text);
28587
+ }
28588
+ scope.calls.add(target.key);
28589
+ if (deployed(at))
28590
+ scope.deployedCalls.add(target.key);
28591
+ for (const [worker, calls] of scope.callsByWorker)
28592
+ if (deployed(at, worker))
28593
+ calls.add(target.key);
28594
+ target.callers.add(scope.key);
28595
+ }
28596
+ };
28597
+ connect(node.expression);
28598
+ const connectArgument = (at) => {
28599
+ if (isFunctionLike(at)) {
28600
+ connect(at);
28601
+ return;
28602
+ }
28603
+ if (import_typescript14.default.isIdentifier(at) || import_typescript14.default.isPropertyAccessExpression(at))
28604
+ connect(at);
28605
+ import_typescript14.default.forEachChild(at, connectArgument);
28606
+ };
28607
+ for (const argument of node.arguments ?? [])
28608
+ connectArgument(argument);
28609
+ for (const argument of node.arguments ?? [])
28610
+ if (import_typescript14.default.isObjectLiteralExpression(argument)) {
28611
+ const fields = new Set(argument.properties.map((p2) => nameOf(p2.name)));
28612
+ if (fields.has("model") && fields.has("messages") && fields.has("tools")) {
28613
+ markModel(scope, node);
28614
+ scope.hasTools = true;
28615
+ }
28616
+ }
28617
+ if (/(?:^|\.)(?:stepCountIs|isStepCount)$/.test(node.expression.getText()) && node.arguments?.[0] && import_typescript14.default.isNumericLiteral(node.arguments?.[0]) && Number(node.arguments?.[0].text) > 1) {
28618
+ scope.hasLoop = true;
28619
+ scope.configuredSteps = true;
28620
+ }
28621
+ }
28622
+ if (import_typescript14.default.isPropertyAssignment(node) && nameOf(node.name) === "maxSteps" && import_typescript14.default.isNumericLiteral(node.initializer) && Number(node.initializer.text) > 1) {
28623
+ scope.hasLoop = true;
28624
+ scope.configuredSteps = true;
28625
+ }
28626
+ import_typescript14.default.forEachChild(node, inspect);
28627
+ };
28628
+ inspect(scope.node);
28629
+ }
28630
+ const modelQueue = [...scopes.values()].filter((scope) => scope.hasModel);
28631
+ for (let index = 0;index < modelQueue.length; index++) {
28632
+ const scope = modelQueue[index];
28633
+ if (scope.reachesModel)
28634
+ continue;
28635
+ scope.reachesModel = true;
28636
+ for (const caller of scope.callers) {
28637
+ const parent = scopes.get(caller);
28638
+ if (parent && !parent.reachesModel)
28639
+ modelQueue.push(parent);
28640
+ }
28641
+ }
28642
+ const agents = new Map;
28643
+ const owners = new Map;
28644
+ const assign = (key, id) => {
28645
+ let values = owners.get(key);
28646
+ if (!values)
28647
+ owners.set(key, values = new Set);
28648
+ values.add(id);
28649
+ };
28650
+ for (const cls of classes) {
28651
+ const emitted2 = agent(cls.name, cls.file, cls.node, "Concrete agent/framework class or realtime model/tool bridge", repo.status(cls.file.path));
28652
+ agents.set(emitted2.id, emitted2);
28653
+ }
28654
+ for (const scope of scopes.values()) {
28655
+ let nestedInFunction = false;
28656
+ for (let parent = scope.node.parent;parent && !import_typescript14.default.isClassLike(parent); parent = parent.parent)
28657
+ if (isFunctionLike(parent)) {
28658
+ nestedInFunction = true;
28659
+ break;
28660
+ }
28661
+ if (scope.className && !nestedInFunction) {
28662
+ let member2 = scope.node;
28663
+ while (member2.parent && !import_typescript14.default.isClassLike(member2.parent))
28664
+ member2 = member2.parent;
28665
+ const memberName = "name" in member2 ? nameOf(member2.name) : undefined;
28666
+ for (const cls of classes) {
28667
+ const ownerClass = enclosingClass(scope.node);
28668
+ const baseIndex = cls.nodes.findIndex((node) => ownerClass && keyOf(node) === keyOf(ownerClass));
28669
+ if (baseIndex < 0)
28670
+ continue;
28671
+ const overridden = memberName && cls.nodes.slice(0, baseIndex).some((node) => node.members.some((candidate) => nameOf(candidate.name) === memberName));
28672
+ if (!overridden)
28673
+ assign(scope.key, componentId("agent", cls.file.path, cls.name));
28674
+ }
28675
+ }
28676
+ if (!scope.className && !scope.forcedOutput && scope.hasLoop && scope.hasTools && (scope.toolFeedback || scope.configuredSteps) && scope.reachesModel) {
28677
+ let boundary = scope;
28678
+ for (let parent = scope.node.parent;parent; parent = parent.parent) {
28679
+ const outer = byNode.get(parent);
28680
+ if (outer?.route) {
28681
+ boundary = outer;
28682
+ break;
28683
+ }
28684
+ }
28685
+ const name = boundary.route ?? functionName(boundary.node);
28686
+ if (!name)
28687
+ continue;
28688
+ const emitted2 = agent(name, boundary.file, scope.node, "Function or route owns a multi-step model/tool feedback loop", repo.status(boundary.file.path));
28689
+ agents.set(emitted2.id, emitted2);
28690
+ assign(boundary.key, emitted2.id);
28691
+ }
28692
+ }
28693
+ let changed = true;
28694
+ while (changed) {
28695
+ changed = false;
28696
+ for (const scope of scopes.values())
28697
+ for (const callee of scope.calls)
28698
+ for (const id of owners.get(scope.key) ?? []) {
28699
+ let targetKey = callee;
28700
+ const virtual = virtualEdges.get(`${scope.key}|${callee}`), concrete = classes.find((cls) => componentId("agent", cls.file.path, cls.name) === id);
28701
+ if (virtual && concrete) {
28702
+ const implementation = concrete.nodes.flatMap((node) => node.members.filter((member2) => nameOf(member2.name) === virtual))[0];
28703
+ if (implementation && scopes.has(keyOf(implementation)))
28704
+ targetKey = keyOf(implementation);
28705
+ }
28706
+ const before = owners.get(targetKey)?.size ?? 0;
28707
+ assign(targetKey, id);
28708
+ changed ||= (owners.get(targetKey)?.size ?? 0) !== before;
28709
+ }
28710
+ }
28711
+ const scopeOwners = new Map;
28712
+ const mergeAlias = (label, ids) => {
28713
+ let values = scopeOwners.get(label);
28714
+ if (!values)
28715
+ scopeOwners.set(label, values = new Set);
28716
+ for (const id of ids)
28717
+ values.add(id);
28718
+ };
28719
+ const classAliases = new Map;
28720
+ for (const cls of classes)
28721
+ for (const base of cls.nodes) {
28722
+ if (!base.name)
28723
+ continue;
28724
+ const qualified = `${base.getSourceFile().fileName.slice(ctx.rootDir.length + 1)}#${base.name.text}`;
28725
+ mergeAlias(qualified, [componentId("agent", cls.file.path, cls.name)]);
28726
+ let variants = classAliases.get(base.name.text);
28727
+ if (!variants)
28728
+ classAliases.set(base.name.text, variants = new Set);
28729
+ variants.add(qualified);
28730
+ }
28731
+ for (const [name, variants] of classAliases)
28732
+ if (variants.size === 1)
28733
+ mergeAlias(name, scopeOwners.get([...variants][0]) ?? []);
28734
+ const aliases = new Map;
28735
+ for (const scope of scopes.values())
28736
+ for (const alias of scope.aliases) {
28737
+ const matches = aliases.get(alias) ?? [];
28738
+ matches.push(scope);
28739
+ aliases.set(alias, matches);
28740
+ }
28741
+ for (const [alias, matches] of aliases) {
28742
+ const candidates = matches.map((scope) => [...owners.get(scope.key) ?? []].sort());
28743
+ if (candidates.every((ids) => JSON.stringify(ids) === JSON.stringify(candidates[0])))
28744
+ mergeAlias(alias, candidates[0]);
28745
+ }
28746
+ const output = {
28747
+ runtimeAgents: [...agents.values()].sort((a, b) => a.id.localeCompare(b.id)),
28748
+ agentForScope: (scope) => scope ? [...scopeOwners.get(scope) ?? []].sort() : [],
28749
+ scopes: [...scopes.values()]
28750
+ };
28751
+ enumerations.set(ctx, output);
28752
+ assignAgentIds(result, output.agentForScope);
28753
+ return output;
28754
+ }
28755
+
28756
+ // src/harness-extract/enumerators/workflows.ts
28757
+ var import_typescript15 = __toESM(require_typescript(), 1);
28758
+ function enumerateWorkflows(result, ctx) {
28759
+ const output = emptyResult();
28760
+ const repo = enumerationRepository(ctx);
28761
+ const nodeKey = (node) => `${node.getSourceFile().fileName}:${node.getStart()}`;
28762
+ const bindings = new Set;
28763
+ for (const worker of repo.workers) {
28764
+ const file = repo.files.find((entry) => entry.path === worker.main), checker = file && ctx.checkerFor(file.path);
28765
+ const module = file && checker?.getSymbolAtLocation(file.source);
28766
+ if (!module || !checker)
28767
+ continue;
28768
+ for (const name of worker.workflowClasses) {
28769
+ let exported = checker.getExportsOfModule(module).find((symbol) => symbol.name === name);
28770
+ if (exported && exported.flags & import_typescript15.default.SymbolFlags.Alias)
28771
+ exported = checker.getAliasedSymbol(exported);
28772
+ const declaration = exported && valueDeclaration(exported);
28773
+ if (declaration && import_typescript15.default.isClassDeclaration(declaration))
28774
+ bindings.add(nodeKey(declaration));
28775
+ }
28776
+ }
28777
+ const memo = createFrameworkMemo();
28778
+ for (const file of repo.files) {
28779
+ if (!/\.[cm]?[jt]sx?$/.test(file.path) || TEST_PATH4.test(file.path) || EVAL_PATH2.test(file.path))
28780
+ continue;
28781
+ visit(file.source, (node) => {
28782
+ if (!import_typescript15.default.isClassDeclaration(node) || !node.name || import_typescript15.default.getCombinedModifierFlags(node) & import_typescript15.default.ModifierFlags.Abstract)
28783
+ return;
28784
+ const checker = ctx.checkerFor(file.path);
28785
+ const base = checker ? frameworkBaseOf(node, checker, memo)?.base : undefined;
28786
+ const directBase = node.heritageClauses?.flatMap((h) => h.types).map((x) => x.expression.getText()) ?? [];
28787
+ if (!bindings.has(nodeKey(node)) && base !== "WorkflowEntrypoint" && base !== "AgentWorkflow" && !directBase.some((x) => /^(?:WorkflowEntrypoint|AgentWorkflow)$/.test(x)))
28788
+ return;
28789
+ const entry = artifact("entrypoint", node.name.text, file, node, "Concrete Workflow class or Wrangler workflow binding", repo.status(file.path));
28790
+ entry.id = componentId("workflow", file.path, node.name.text);
28791
+ if (bindings.has(nodeKey(node))) {
28792
+ Object.assign(entry, { componentKind: "workflow", trigger: "workflow_binding" });
28793
+ }
28794
+ output.artifacts.push(entry);
28795
+ });
28796
+ }
28797
+ for (const worker of repo.workers.filter((entry) => entry.cron)) {
28798
+ const scopes = enumerateAgents(result, ctx).scopes;
28799
+ const byKey = new Map(scopes.map((scope) => [scope.key, scope]));
28800
+ const implementations = new Map, workerClasses = new Set;
28801
+ const deployedCalls = (scope) => {
28802
+ const calls = scope.callsByWorker.get(worker.id) ?? scope.deployedCalls;
28803
+ const cls = enclosingClass(scope.node);
28804
+ if (!cls || !workerClasses.has(nodeKey(cls)))
28805
+ return calls;
28806
+ const member2 = scope.node.parent === cls ? scope.node : scope.node.parent;
28807
+ if (import_typescript15.default.getCombinedModifierFlags(member2) & import_typescript15.default.ModifierFlags.Static)
28808
+ return calls;
28809
+ return new Set([...calls].map((key) => {
28810
+ const method = scope.virtualCalls.get(key);
28811
+ return method && implementations.has(method) ? implementations.get(method) : key;
28812
+ }));
28813
+ };
28814
+ const modelScopes = new Set(scopes.filter((scope) => scope.modelWorkers.has(worker.id)).map((scope) => scope.key));
28815
+ const mainFile = repo.files.find((file) => file.path === worker.main), checker = mainFile && ctx.checkerFor(mainFile.path);
28816
+ const exportedNodes = new Set, visited = new Set;
28817
+ const resolveWorker = (node) => {
28818
+ if (!node || visited.has(node))
28819
+ return;
28820
+ visited.add(node);
28821
+ if (import_typescript15.default.isParenthesizedExpression(node) || import_typescript15.default.isAsExpression(node) || import_typescript15.default.isSatisfiesExpression(node) || import_typescript15.default.isNonNullExpression(node)) {
28822
+ resolveWorker(node.expression);
28823
+ return;
28824
+ }
28825
+ if (import_typescript15.default.isCallExpression(node) && /(?:^|\.)withSentry$/.test(node.expression.getText())) {
28826
+ for (const argument of node.arguments)
28827
+ resolveWorker(argument);
28828
+ return;
28829
+ }
28830
+ if (import_typescript15.default.isExportAssignment(node)) {
28831
+ resolveWorker(node.expression);
28832
+ return;
28833
+ }
28834
+ if (import_typescript15.default.isVariableDeclaration(node)) {
28835
+ resolveWorker(node.initializer);
28836
+ return;
28837
+ }
28838
+ if (import_typescript15.default.isIdentifier(node) && checker) {
28839
+ resolveWorker(valueDeclaration(resolvedSymbol(node, checker)));
28840
+ return;
28841
+ }
28842
+ exportedNodes.add(node);
28843
+ };
28844
+ const module = mainFile && checker?.getSymbolAtLocation(mainFile.source);
28845
+ const exported = module && checker?.getExportsOfModule(module).find((symbol2) => symbol2.name === "default");
28846
+ const symbol = exported && checker && (exported.flags & import_typescript15.default.SymbolFlags.Alias ? checker.getAliasedSymbol(exported) : exported);
28847
+ resolveWorker(symbol && valueDeclaration(symbol));
28848
+ const collectImplementations = (node) => {
28849
+ if (!import_typescript15.default.isClassLike(node) || workerClasses.has(nodeKey(node)))
28850
+ return;
28851
+ workerClasses.add(nodeKey(node));
28852
+ for (const member2 of node.members) {
28853
+ if (import_typescript15.default.getCombinedModifierFlags(member2) & import_typescript15.default.ModifierFlags.Static)
28854
+ continue;
28855
+ const name = nameOf(member2.name);
28856
+ const implementation = byKey.get(nodeKey(member2)) ?? (import_typescript15.default.isPropertyDeclaration(member2) && member2.initializer ? byKey.get(nodeKey(member2.initializer)) : undefined);
28857
+ if (name && !implementations.has(name))
28858
+ implementations.set(name, implementation?.key ?? "(non-callable override)");
28859
+ }
28860
+ if (checker)
28861
+ for (const base of node.heritageClauses?.flatMap((clause) => clause.types) ?? []) {
28862
+ const declaration = valueDeclaration(resolvedSymbol(base.expression, checker));
28863
+ if (declaration)
28864
+ collectImplementations(declaration);
28865
+ }
28866
+ };
28867
+ for (const node of exportedNodes)
28868
+ collectImplementations(node);
28869
+ let changed = true;
28870
+ while (changed) {
28871
+ changed = false;
28872
+ for (const scope of scopes)
28873
+ if (!modelScopes.has(scope.key) && [...deployedCalls(scope)].some((key) => modelScopes.has(key))) {
28874
+ modelScopes.add(scope.key);
28875
+ changed = true;
28876
+ }
28877
+ }
28878
+ const scheduledNodes = new Set;
28879
+ const resolveScheduled = (node, seen2 = new Set) => {
28880
+ if (!node || seen2.has(node))
28881
+ return;
28882
+ seen2.add(node);
28883
+ if (import_typescript15.default.isIdentifier(node) && checker) {
28884
+ resolveScheduled(valueDeclaration(resolvedSymbol(node, checker)), seen2);
28885
+ return;
28886
+ }
28887
+ if (import_typescript15.default.isVariableDeclaration(node) || import_typescript15.default.isPropertyAssignment(node) || import_typescript15.default.isPropertyDeclaration(node)) {
28888
+ resolveScheduled(node.initializer, seen2);
28889
+ return;
28890
+ }
28891
+ if (import_typescript15.default.isShorthandPropertyAssignment(node)) {
28892
+ resolveScheduled(checker && valueDeclaration(checker.getShorthandAssignmentValueSymbol(node)), seen2);
28893
+ return;
28894
+ }
28895
+ if (import_typescript15.default.isParenthesizedExpression(node) || import_typescript15.default.isAsExpression(node) || import_typescript15.default.isSatisfiesExpression(node) || import_typescript15.default.isNonNullExpression(node)) {
28896
+ resolveScheduled(node.expression, seen2);
28897
+ return;
28898
+ }
28899
+ scheduledNodes.add(node);
28900
+ };
28901
+ const collectScheduled = (node, seen2 = new Set) => {
28902
+ if (seen2.has(node))
28903
+ return;
28904
+ seen2.add(node);
28905
+ const members = import_typescript15.default.isObjectLiteralExpression(node) ? node.properties : import_typescript15.default.isClassLike(node) ? node.members : [];
28906
+ const handlers = members.filter((member2) => nameOf(member2.name) === "scheduled" && !(import_typescript15.default.getCombinedModifierFlags(member2) & import_typescript15.default.ModifierFlags.Static));
28907
+ for (const member2 of handlers)
28908
+ resolveScheduled(member2);
28909
+ if (!handlers.length && import_typescript15.default.isClassLike(node) && checker)
28910
+ for (const base of node.heritageClauses?.flatMap((clause) => clause.types) ?? []) {
28911
+ const declaration = valueDeclaration(resolvedSymbol(base.expression, checker));
28912
+ if (declaration)
28913
+ collectScheduled(declaration, seen2);
28914
+ }
28915
+ };
28916
+ for (const node of exportedNodes)
28917
+ collectScheduled(node);
28918
+ const roots = scopes.filter((scope) => [...scheduledNodes].some((node) => node.getSourceFile().fileName === scope.node.getSourceFile().fileName && node.getStart() === scope.node.getStart()));
28919
+ const seen = new Set;
28920
+ const queue = roots.flatMap((scope) => scope.modelWorkers.has(worker.id) ? [scope.key] : [...deployedCalls(scope)]);
28921
+ for (let i = 0;i < queue.length; i++) {
28922
+ const key = queue[i];
28923
+ if (seen.has(key))
28924
+ continue;
28925
+ seen.add(key);
28926
+ const scope = byKey.get(key);
28927
+ if (!scope)
28928
+ continue;
28929
+ if (!modelScopes.has(scope.key)) {
28930
+ if (/(?:Cron|Pipeline)$/.test(scope.label)) {
28931
+ const entry = artifact("entrypoint", scope.label, scope.file, scope.node, "Scheduled entrypoint has no deployed model step on its own pipeline", repo.status(scope.file.path));
28932
+ const proof = [...scope.calls].map((callee) => byKey.get(callee)).filter((callee) => callee?.reachesModel).map((callee) => `${callee.file.path}#${callee.label}`);
28933
+ Object.assign(entry, { exclusionReason: scope.reachesModel ? "Model reachable only through a queue consumer or statically excluded fallback" : "No model reachable from scheduled pipeline", proofPath: [`${scope.file.path}#${scope.label}`, ...proof] });
28934
+ output.artifacts.push(entry);
28935
+ } else
28936
+ queue.push(...deployedCalls(scope));
28937
+ continue;
28938
+ }
28939
+ if (/(?:Cron|Pipeline)$/.test(scope.label) || scope.modelWorkers.has(worker.id)) {
28940
+ const entry = artifact("entrypoint", scope.label, scope.file, scope.node, "Cron dispatch reaches this model-backed pipeline", repo.status(scope.file.path));
28941
+ entry.id = componentId("workflow", scope.file.path, scope.label);
28942
+ entry.componentKind = "workflow";
28943
+ entry.trigger = "cron";
28944
+ output.artifacts.push(entry);
28945
+ if (roots.includes(scope))
28946
+ queue.push(...deployedCalls(scope));
28947
+ } else
28948
+ queue.push(...deployedCalls(scope));
28949
+ }
28950
+ }
28951
+ return stableResult(output);
28952
+ }
28953
+
28954
+ // src/harness-extract/enumerators/catalog.ts
28955
+ var import_typescript16 = __toESM(require_typescript(), 1);
28956
+ var THINK_WORKSPACE_TOOLS = ["read", "write", "edit", "list", "find", "grep", "delete"];
28957
+ function strings(expression, checker, seen = new Set) {
28958
+ if (!expression)
28959
+ return [];
28960
+ const node = unwrap(expression);
28961
+ if (seen.has(node))
28962
+ return [];
28963
+ seen.add(node);
28964
+ if (import_typescript16.default.isIdentifier(node)) {
28965
+ const declaration = checker && valueDeclaration(resolvedSymbol(node, checker));
28966
+ if (!declaration || !import_typescript16.default.isVariableDeclaration(declaration))
28967
+ return [];
28968
+ return strings(declaration.initializer, checker, seen);
28969
+ }
28970
+ if (import_typescript16.default.isArrayLiteralExpression(node))
28971
+ return node.elements.flatMap((entry) => import_typescript16.default.isSpreadElement(entry) ? strings(entry.expression, checker, seen) : strings(entry, checker, seen));
28972
+ if (import_typescript16.default.isStringLiteralLike(node))
28973
+ return [{ name: node.text, node }];
28974
+ if (import_typescript16.default.isNewExpression(node) && node.expression.getText() === "Set")
28975
+ return strings(node.arguments?.[0], checker, seen);
28976
+ return [];
28977
+ }
28978
+ function property(object, name) {
28979
+ const entry = object.properties.find((item) => item.name && nameOf(item.name) === name);
28980
+ return entry && import_typescript16.default.isPropertyAssignment(entry) ? entry.initializer : entry && import_typescript16.default.isShorthandPropertyAssignment(entry) ? entry.name : undefined;
28981
+ }
28982
+ function inheritedTrue(node, propertyName2, checker, seen = new Set) {
28983
+ if (seen.has(node))
28984
+ return false;
28985
+ seen.add(node);
28986
+ const own = node.members.find((member2) => nameOf(member2.name) === propertyName2);
28987
+ if (own && import_typescript16.default.isPropertyDeclaration(own) && own.initializer)
28988
+ return unwrap(own.initializer).kind === import_typescript16.default.SyntaxKind.TrueKeyword;
28989
+ if (checker)
28990
+ for (const base of node.heritageClauses?.flatMap((h) => h.types) ?? []) {
28991
+ const declaration = valueDeclaration(resolvedSymbol(base.expression, checker));
28992
+ if (declaration && (import_typescript16.default.isClassDeclaration(declaration) || import_typescript16.default.isClassExpression(declaration)))
28993
+ return inheritedTrue(declaration, propertyName2, checker, seen);
28994
+ }
28995
+ return false;
28996
+ }
28997
+ function enumerateToolCatalog(result, ctx) {
28998
+ const output = emptyResult(), repo = enumerationRepository(ctx), agents = enumerateAgents(result, ctx);
28999
+ const agentByName = new Map(agents.runtimeAgents.map((entry) => [entry.name, entry.id]));
29000
+ const symbolOwners = new Map;
29001
+ for (const scope of agents.scopes) {
29002
+ const owners = agents.agentForScope(scope.key);
29003
+ const checker = ctx.checkerFor(scope.file.path);
29004
+ if (!owners.length || !checker)
29005
+ continue;
29006
+ visit(scope.node, (node) => {
29007
+ if (!import_typescript16.default.isIdentifier(node) || !/ALLOW|MCP_NAME/.test(node.text))
29008
+ return;
29009
+ const declaration = valueDeclaration(resolvedSymbol(node, checker));
29010
+ if (!declaration || !import_typescript16.default.isVariableDeclaration(declaration) || !import_typescript16.default.isIdentifier(declaration.name))
29011
+ return;
29012
+ const key = `${declaration.getSourceFile().fileName}:${declaration.name.text}`;
29013
+ let existing = symbolOwners.get(key);
29014
+ if (!existing)
29015
+ symbolOwners.set(key, existing = new Set);
29016
+ for (const id of owners)
29017
+ existing.add(id);
29018
+ });
29019
+ }
29020
+ const ownersAt = (node, path) => {
29021
+ const scope = agents.scopes.filter((s) => s.file.path === path && s.node.getStart() <= node.getStart() && s.node.getEnd() >= node.getEnd()).sort((a, b) => a.node.getWidth() - b.node.getWidth())[0];
29022
+ return scope ? agents.agentForScope(scope.key) : [];
29023
+ };
29024
+ const memo = createFrameworkMemo();
29025
+ const thinkIds = new Set;
29026
+ for (const runtime of agents.runtimeAgents) {
29027
+ const file = repo.files.find((entry) => entry.path === runtime.evidence[0]?.path), checker = file && ctx.checkerFor(file.path);
29028
+ if (!file || !checker)
29029
+ continue;
29030
+ visit(file.source, (node) => {
29031
+ if ((import_typescript16.default.isClassDeclaration(node) || import_typescript16.default.isClassExpression(node)) && node.name?.text === runtime.name && frameworkBaseOf(node, checker, memo)?.base === "Think")
29032
+ thinkIds.add(runtime.id);
29033
+ });
29034
+ }
29035
+ const add = (name, file, node, source, reason, owners = []) => {
29036
+ const evidenceFile = repo.files.find((entry2) => entry2.source.fileName === node.getSourceFile().fileName) ?? file;
29037
+ const entry = artifact("tool", name, evidenceFile, node, reason, repo.status(file.path));
29038
+ entry.catalogSource = source;
29039
+ entry.usedByAgentIds = owners;
29040
+ output.artifacts.push(entry);
29041
+ return entry;
29042
+ };
29043
+ for (const file of repo.files) {
29044
+ if (!/\.[cm]?[jt]sx?$/.test(file.path) || TEST_PATH4.test(file.path) || EVAL_PATH2.test(file.path) || /^scripts\//.test(file.path) && !repo.deployedFiles.has(file.path))
29045
+ continue;
29046
+ const checker = ctx.checkerFor(file.path), declarations = new Map;
29047
+ visit(file.source, (node) => {
29048
+ if (import_typescript16.default.isVariableDeclaration(node) && import_typescript16.default.isIdentifier(node.name) && node.initializer)
29049
+ declarations.set(node.name.text, node.initializer);
29050
+ });
29051
+ visit(file.source, (node) => {
29052
+ if ((import_typescript16.default.isClassDeclaration(node) || import_typescript16.default.isClassExpression(node)) && node.name && agentByName.has(node.name.text)) {
29053
+ const info = checker ? frameworkBaseOf(node, checker, memo) : undefined;
29054
+ const directThink = node.heritageClauses?.some((h) => h.types.some((t) => t.expression.getText() === "Think"));
29055
+ if (info?.base === "Think" || directThink) {
29056
+ const owners2 = agents.agentForScope(`${file.path}#${node.name.text}`);
29057
+ const names = [...THINK_WORKSPACE_TOOLS];
29058
+ if (inheritedTrue(node, "workspaceBash", checker))
29059
+ names.push("bash");
29060
+ for (const name of names)
29061
+ add(name, file, node, "think", "Think workspace tool inherited by this concrete agent", owners2);
29062
+ }
29063
+ }
29064
+ if (import_typescript16.default.isPropertyAccessExpression(node) && node.name.text === "activate_skill" || import_typescript16.default.isPropertyAssignment(node) && nameOf(node.name) === "activate_skill") {
29065
+ const owner = ownersAt(node, file.path);
29066
+ add("activate_skill", file, node, "think", "Source explicitly exposes Think skill activation", owner);
29067
+ }
29068
+ if (import_typescript16.default.isCallExpression(node) && import_typescript16.default.isPropertyAccessExpression(node.expression) && /^(?:registerTool|tool)$/.test(node.expression.name.text) && checker) {
29069
+ const receiver = valueDeclaration(resolvedSymbol(node.expression.expression, checker));
29070
+ const init = receiver && import_typescript16.default.isVariableDeclaration(receiver) && receiver.initializer ? unwrap(receiver.initializer) : undefined;
29071
+ const origin = init && import_typescript16.default.isNewExpression(init) && import_typescript16.default.isIdentifier(init.expression) ? importOrigin(init.expression, checker) : undefined;
29072
+ const name = node.arguments[0];
29073
+ if (origin?.module.startsWith("@modelcontextprotocol/sdk/") && origin.imported === "McpServer" && name && import_typescript16.default.isStringLiteralLike(name)) {
29074
+ add(name.text, file, name, "mcp_server", "MCP SDK server explicitly registers this model-facing tool name", ownersAt(node, file.path));
29075
+ }
29076
+ }
29077
+ if (import_typescript16.default.isCallExpression(node) && import_typescript16.default.isPropertyAccessExpression(node.expression) && node.expression.expression.getText() === "Output" && node.expression.name.text === "object") {
29078
+ const owners2 = ownersAt(node, file.path).filter((id) => thinkIds.has(id));
29079
+ if (owners2.length && checker && import_typescript16.default.isIdentifier(node.expression.expression) && ["ai", "@cloudflare/think"].includes(importOrigin(node.expression.expression, checker)?.module ?? ""))
29080
+ add("think_final_answer", file, node, "think", "Think structured output is offered as the framework final-answer tool", owners2);
29081
+ }
29082
+ if (import_typescript16.default.isCallExpression(node) && import_typescript16.default.isIdentifier(node.expression) && node.expression.text === "createExecuteRuntime") {
29083
+ const owners2 = ownersAt(node, file.path).filter((id) => thinkIds.has(id));
29084
+ if (owners2.length && checker && importOrigin(node.expression, checker)?.module.startsWith("@cloudflare/think"))
29085
+ add("execute", file, node, "think", "Think Code Mode runtime explicitly enabled for this agent", owners2);
29086
+ }
29087
+ if (!import_typescript16.default.isObjectLiteralExpression(node))
29088
+ return;
29089
+ const serverNames = strings(property(node, "name"), checker), allow = property(node, "allow");
29090
+ if (serverNames.length !== 1 || !allow || !property(node, "url"))
29091
+ return;
29092
+ const server = serverNames[0].name;
29093
+ const owners = ownersAt(node, file.path);
29094
+ if (import_typescript16.default.isStringLiteralLike(unwrap(allow)) && unwrap(allow).text === "all") {
29095
+ const entry = add(`${server} dynamic MCP tools`, file, allow, "mcp_dynamic_group", "Server schemas are admitted dynamically as one bounded catalog group", owners);
29096
+ entry.serverName = server;
29097
+ entry.dynamicGroup = true;
29098
+ entry.namePattern = `tool_<${server}ServerId>_*`;
29099
+ return;
29100
+ }
29101
+ for (const tool of strings(allow, checker)) {
29102
+ const name = `tool_<${server}ServerIdNoDashes>_${tool.name}`;
29103
+ const entry = add(name, file, tool.node, "mcp_allowlist", "Literal MCP allowlist converted by the Agents SDK tool_<serverId>_<name> contract", owners);
29104
+ entry.id = componentId("tool", file.path, `${server}:${name}`);
29105
+ entry.serverName = server;
29106
+ entry.namePattern = name;
29107
+ }
29108
+ });
29109
+ for (const [name, initializer] of declarations) {
29110
+ const match = name.match(/^(.*)_ALLOWED_TOOLS$/);
29111
+ if (!match)
29112
+ continue;
29113
+ const serverName = strings(declarations.get(`${match[1]}_MCP_NAME`), checker)[0]?.name;
29114
+ if (!serverName)
29115
+ continue;
29116
+ for (const tool of strings(initializer, checker)) {
29117
+ const entry = add(`${serverName}_${tool.name}`, file, tool.node, "mcp_allowlist", "Explicit named MCP allowlist with server-prefixed model name");
29118
+ entry.serverName = serverName;
29119
+ entry.usedByAgentIds = [...symbolOwners.get(`${file.source.fileName}:${name}`) ?? []].sort();
29120
+ }
29121
+ }
29122
+ }
29123
+ const merged = new Map;
29124
+ for (const item of output.artifacts) {
29125
+ const previous = merged.get(item.name);
29126
+ if (previous) {
29127
+ previous.usedByAgentIds = [...new Set([...previous.usedByAgentIds, ...item.usedByAgentIds])].sort();
29128
+ const seen = new Set(previous.evidence.map((e) => `${e.path}:${e.line}`));
29129
+ previous.evidence.push(...item.evidence.filter((e) => !seen.has(`${e.path}:${e.line}`)));
29130
+ if (item.status === "in_prod" || item.status === "reachable" && previous.status === "defined_only")
29131
+ previous.status = item.status;
29132
+ } else {
29133
+ item.id = `tool:catalog:${item.name}`;
29134
+ merged.set(item.name, item);
29135
+ }
29136
+ }
29137
+ output.artifacts = [...merged.values()];
29138
+ return stableResult(output);
29139
+ }
29140
+
29141
+ // src/harness-extract/enumerators/index.ts
29142
+ var ENUMERATORS = [
29143
+ { id: "agents", enumerate: ({ result }, ctx) => ({ runtimeAgents: enumerateAgents(result, ctx).runtimeAgents }) },
29144
+ { id: "workflows", enumerate: ({ result }, ctx) => enumerateWorkflows(result, ctx) },
29145
+ { id: "framework-mcp-catalog", enumerate: ({ result }, ctx) => enumerateToolCatalog(result, ctx) },
29146
+ { id: "tool-registry", enumerate: ({ result }, ctx) => ({ artifacts: toolArtifacts(emitToolsCached(result, ctx), enumerateAgents(result, ctx).runtimeAgents) }) }
29147
+ ];
29148
+ function enumerateHarnessComponents(result, ctx) {
29149
+ const agents = enumerateAgents(result, ctx), workflows = enumerateWorkflows(result, ctx), catalog = enumerateToolCatalog(result, ctx);
29150
+ return stableResult({ runtimeAgents: agents.runtimeAgents, artifacts: [...workflows.artifacts, ...toolArtifacts(emitToolsCached(result, ctx), agents.runtimeAgents), ...catalog.artifacts], warnings: [...workflows.warnings, ...catalog.warnings] });
29151
+ }
29152
+ function mergeEnumeratedComponents(artifacts, components) {
29153
+ const merged = new Map;
29154
+ const definitions = new Map;
29155
+ const registry = components.artifacts.filter((item) => item.type === "tool" && item.id.startsWith("tool.extract."));
29156
+ for (const item of [...registry, ...artifacts, ...components.artifacts.filter((item2) => !registry.includes(item2))]) {
29157
+ const key = item.type === "tool" ? `tool:${item.name}` : item.id;
29158
+ if (item.type === "tool") {
29159
+ const own = item.definitionVariants ?? (item.body ? [{ sourcePath: item.sourcePath, body: item.body, evidence: item.evidence }] : []);
29160
+ let variants = definitions.get(key);
29161
+ for (const variant of own) {
29162
+ if (!variant.body)
29163
+ continue;
29164
+ if (!variants)
29165
+ definitions.set(key, variants = []);
29166
+ if (!variants.some((entry) => entry.id === item.id && entry.sourcePath === variant.sourcePath && entry.body === variant.body))
29167
+ variants.push({ id: item.id, sourcePath: variant.sourcePath, body: variant.body, evidence: [...variant.evidence ?? item.evidence], usedByAgentIds: [...item.usedByAgentIds] });
29168
+ }
29169
+ }
29170
+ const previous = merged.get(key);
29171
+ if (!previous) {
29172
+ merged.set(key, { ...item, evidence: [...item.evidence], usedByAgentIds: [...item.usedByAgentIds] });
29173
+ continue;
29174
+ }
29175
+ const rank = { defined_only: 0, reachable: 1, in_prod: 2 };
29176
+ if (item.status && (!previous.status || rank[item.status] > rank[previous.status]))
29177
+ previous.status = item.status;
29178
+ previous.usedByAgentIds = [...new Set([...previous.usedByAgentIds, ...item.usedByAgentIds])].sort();
29179
+ const evidence = new Set(previous.evidence.map((entry) => `${entry.path}:${entry.line}`));
29180
+ previous.evidence.push(...item.evidence.filter((entry) => !evidence.has(`${entry.path}:${entry.line}`)));
29181
+ if (!previous.body && item.body && !previous.definitionVariants)
29182
+ previous.body = item.body;
29183
+ }
29184
+ for (const [key, variants] of definitions) {
29185
+ const item = merged.get(key);
29186
+ if (variants.length > 1 || item.id !== variants[0].id)
29187
+ item.definitionVariants = variants;
29188
+ if (new Set(variants.map((entry) => entry.body)).size > 1)
29189
+ delete item.body;
29190
+ }
29191
+ const output = [...merged.values()].sort((a, b) => a.id.localeCompare(b.id));
29192
+ const runtimeAgents = components.runtimeAgents.map((entry) => ({
29193
+ ...entry,
29194
+ artifactIds: [...new Set([...entry.artifactIds, ...output.filter((item) => item.usedByAgentIds.includes(entry.id)).map((item) => item.id)])].sort()
29195
+ }));
29196
+ return { runtimeAgents, artifacts: output };
29197
+ }
29198
+
29199
+ 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 };