@moda-ai/cli 1.55.71 → 1.55.73

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,6 +108,9 @@ import {
105
108
  __toESM
106
109
  } from "./cli-0v6na3yp.js";
107
110
 
111
+ // src/harness-extract/enumerators/agents.ts
112
+ var import_typescript12 = __toESM(require_typescript(), 1);
113
+
108
114
  // src/harness-extract/index.ts
109
115
  var import_typescript10 = __toESM(require_typescript(), 1);
110
116
  import { resolve as resolve13 } from "node:path";
@@ -3136,12 +3142,60 @@ function effectiveField(object, key) {
3136
3142
  });
3137
3143
  return fields;
3138
3144
  }
3145
+ var WRITTEN_SYMBOLS = new WeakMap;
3146
+ function writtenSymbols(file, checker) {
3147
+ let written = WRITTEN_SYMBOLS.get(file);
3148
+ if (written)
3149
+ return written;
3150
+ const found = new Set;
3151
+ const add = (node) => {
3152
+ const root = rootIdentifier(node);
3153
+ const symbol = root ? resolvedSymbol(root, checker) : undefined;
3154
+ if (symbol)
3155
+ found.add(symbol);
3156
+ };
3157
+ const visit = (node) => {
3158
+ if (import_typescript5.default.isBinaryExpression(node) && node.operatorToken.kind >= import_typescript5.default.SyntaxKind.FirstAssignment && node.operatorToken.kind <= import_typescript5.default.SyntaxKind.LastAssignment)
3159
+ add(node.left);
3160
+ else if (import_typescript5.default.isDeleteExpression(node))
3161
+ add(node.expression);
3162
+ else if ((import_typescript5.default.isPrefixUnaryExpression(node) || import_typescript5.default.isPostfixUnaryExpression(node)) && (node.operator === import_typescript5.default.SyntaxKind.PlusPlusToken || node.operator === import_typescript5.default.SyntaxKind.MinusMinusToken))
3163
+ add(node.operand);
3164
+ else if (import_typescript5.default.isCallExpression(node) && node.arguments.length > 0) {
3165
+ const callee = unwrap(node.expression);
3166
+ if (import_typescript5.default.isPropertyAccessExpression(callee) && callee.name.text === "assign")
3167
+ add(node.arguments[0]);
3168
+ }
3169
+ import_typescript5.default.forEachChild(node, visit);
3170
+ };
3171
+ visit(file);
3172
+ written = found;
3173
+ WRITTEN_SYMBOLS.set(file, written);
3174
+ return written;
3175
+ }
3176
+ function gatewayRequestLiteral(argument, checker) {
3177
+ const value = unwrap(argument);
3178
+ if (import_typescript5.default.isObjectLiteralExpression(value))
3179
+ return value;
3180
+ if (!import_typescript5.default.isIdentifier(value))
3181
+ return;
3182
+ const symbol = resolvedSymbol(value, checker);
3183
+ const declaration = valueDeclaration(symbol);
3184
+ if (!symbol || !declaration || !import_typescript5.default.isVariableDeclaration(declaration) || !declaration.initializer)
3185
+ return;
3186
+ if (!(import_typescript5.default.getCombinedNodeFlags(declaration) & import_typescript5.default.NodeFlags.Const))
3187
+ return;
3188
+ const literal = unwrap(declaration.initializer);
3189
+ if (!import_typescript5.default.isObjectLiteralExpression(literal))
3190
+ return;
3191
+ return writtenSymbols(declaration.getSourceFile(), checker).has(symbol) ? undefined : literal;
3192
+ }
3139
3193
  var GATEWAY_METHODS = new Set(["call", "stream"]);
3140
3194
  var GATEWAY_BODY_KEYS = { system: "system", messages: "messages", prompt: "prompt", model: "model", tools: "tools" };
3141
3195
  var modelGatewaySink = {
3142
3196
  id: "model-gateway",
3143
3197
  sdk: "model-gateway",
3144
- match(call) {
3198
+ match(call, ctx) {
3145
3199
  if (!import_typescript5.default.isCallExpression(call) || call.arguments.length !== 1)
3146
3200
  return;
3147
3201
  const callee = unwrap(call.expression);
@@ -3150,8 +3204,8 @@ var modelGatewaySink = {
3150
3204
  const receiver = unwrap(callee.expression);
3151
3205
  if (!import_typescript5.default.isPropertyAccessExpression(receiver) || receiver.name.text !== "models")
3152
3206
  return;
3153
- const request = unwrap(call.arguments[0]);
3154
- if (!import_typescript5.default.isObjectLiteralExpression(request) || !propertyValue(request, "kind"))
3207
+ const request = gatewayRequestLiteral(call.arguments[0], ctx.checker);
3208
+ if (!request || !propertyValue(request, "kind"))
3155
3209
  return;
3156
3210
  const roles = [];
3157
3211
  for (const body of effectiveField(request, "body")) {
@@ -9092,7 +9146,7 @@ function isUnder2(path, root) {
9092
9146
  return true;
9093
9147
  return path === root || path.startsWith(`${root}/`);
9094
9148
  }
9095
- function stripJsonc(text) {
9149
+ function stripJsonc2(text) {
9096
9150
  let out = "";
9097
9151
  let i = 0;
9098
9152
  let inString = false;
@@ -9136,7 +9190,7 @@ function stripJsonc(text) {
9136
9190
  }
9137
9191
  function parseJsonLoose(text) {
9138
9192
  try {
9139
- return JSON.parse(stripJsonc(text));
9193
+ return JSON.parse(stripJsonc2(text));
9140
9194
  } catch {
9141
9195
  return;
9142
9196
  }
@@ -18983,7 +19037,7 @@ async function runHarnessCommand(context) {
18983
19037
  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.");
18984
19038
  }
18985
19039
  if (context.flags["github-actions"] === "true") {
18986
- const { runGithubActionsAnalyze } = await import("./harness-github-actions-6p1czt5h.js");
19040
+ const { runGithubActionsAnalyze } = await import("./harness-github-actions-p4011crc.js");
18987
19041
  const result = await runGithubActionsAnalyze(rootDir, {
18988
19042
  writeReport: (report2) => {
18989
19043
  const normalized = normalizeHarnessReport(report2);
@@ -19129,7 +19183,15 @@ async function runHarnessCommand(context) {
19129
19183
  }
19130
19184
  const { artifacts, unknowns } = deterministicGraphItems(rootDir, promote === "all" ? undefined : promote);
19131
19185
  tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
19132
- const promoted = { concern: promote, artifacts, unknowns };
19186
+ const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-4z7h9mam.js");
19187
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-femt9s00.js");
19188
+ let components = { runtimeAgents: [], artifacts: [], warnings: [] };
19189
+ if (promote === "all" || promote === "topology" || promote === "tools") {
19190
+ const { result, ctx } = extractHarnessWithContext2(rootDir);
19191
+ const found = enumerateHarnessComponents(result, ctx);
19192
+ components = promote === "tools" ? { ...found, artifacts: found.artifacts.filter((entry) => entry.type === "tool") } : promote === "topology" ? { ...found, artifacts: found.artifacts.filter((entry) => entry.type !== "tool") } : found;
19193
+ }
19194
+ const promoted = { concern: promote, unknowns, ...mergeEnumeratedComponents(artifacts, components) };
19133
19195
  const promoteWritten = [];
19134
19196
  if (promoteOut && !context.dryRun) {
19135
19197
  const target = resolve9(context.cwd, promoteOut);
@@ -19156,10 +19218,14 @@ async function runHarnessCommand(context) {
19156
19218
  }
19157
19219
  case "extract": {
19158
19220
  writeHumanProgress(context, "Harness extract: tracing model call sites (no LLM, no network)...");
19159
- const { extractHarness: extractHarness2, serializeExtractResult } = await import("./index-8pzrw7v9.js");
19160
- const result = extractHarness2(rootDir, { fresh: true });
19221
+ const { extractHarnessWithContext: extractHarnessWithContext2, serializeExtractResult } = await import("./index-4z7h9mam.js");
19222
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-femt9s00.js");
19223
+ const { result, ctx } = extractHarnessWithContext2(rootDir, { fresh: true });
19224
+ const artifacts = deterministicArtifacts(rootDir);
19225
+ tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
19226
+ const graph = mergeEnumeratedComponents(artifacts, enumerateHarnessComponents(result, ctx));
19161
19227
  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).`);
19162
- context.output.writeData(serializeExtractResult(result), {
19228
+ context.output.writeData({ ...serializeExtractResult(result), graph }, {
19163
19229
  status: result.warnings.length > 0 ? "degraded" : "success",
19164
19230
  ...result.warnings.length > 0 ? { warnings: result.warnings } : {}
19165
19231
  });
@@ -19939,18 +20005,19 @@ function deterministicGraphItems(rootDir, concern) {
19939
20005
  hydratePromptAndToolBodies(graph, rootDir);
19940
20006
  return { artifacts: graph.artifacts, unknowns: graph.unknowns };
19941
20007
  }
19942
- var extractedModelsCache = new Map;
20008
+ var extractedModelsCache = new WeakMap;
19943
20009
  function extractedModelItems(rootDir) {
19944
20010
  const empty = { artifacts: [], unknowns: [], rewritten: new Set, enabled: false };
19945
20011
  if (process.env.MODA_HARNESS_EXTRACT === "0")
19946
20012
  return empty;
19947
20013
  const key = resolve9(rootDir);
19948
- const cached = extractedModelsCache.get(key);
19949
- if (cached)
19950
- return cached;
19951
20014
  let items = { ...empty, enabled: true };
19952
20015
  try {
19953
- const result = extractHarness(key);
20016
+ const { result, ctx } = extractHarnessWithContext(key);
20017
+ createAgentScopeResolver(result, ctx);
20018
+ const cached = extractedModelsCache.get(result);
20019
+ if (cached)
20020
+ return cached;
19954
20021
  for (const warning of result.warnings)
19955
20022
  process.stderr.write(`warning: harness extraction incomplete; ${warning}
19956
20023
  `);
@@ -19960,11 +20027,11 @@ function extractedModelItems(rootDir) {
19960
20027
  rewritten: new Set((result.rewrittenModels ?? []).map((entry) => normalizedModelId(entry.id))),
19961
20028
  enabled: true
19962
20029
  };
20030
+ extractedModelsCache.set(result, items);
19963
20031
  } catch (error) {
19964
20032
  process.stderr.write(`warning: harness extraction failed; model artifacts come from the candidate pre-pass only (${error instanceof Error ? error.message : String(error)})
19965
20033
  `);
19966
20034
  }
19967
- extractedModelsCache.set(key, items);
19968
20035
  return items;
19969
20036
  }
19970
20037
  var normalizedModelId = (name) => String(name ?? "").trim().toLowerCase();
@@ -20132,7 +20199,7 @@ function withCallSitePrompts(rootDir, promoted) {
20132
20199
  const { result, ctx } = extractHarnessWithContext(rootDir);
20133
20200
  const sites = result.callSites.filter((site) => !site.isTest);
20134
20201
  const toolDefinitions = result.toolDefinitions ?? [];
20135
- return promptArtifactsFromCallSites(sites, ctx, promoted, { toolDefinitions }).artifacts;
20202
+ return promptArtifactsFromCallSites(sites, ctx, promoted, { toolDefinitions, agentForScope: createAgentScopeResolver(result, ctx) }).artifacts;
20136
20203
  } catch {
20137
20204
  return promoted;
20138
20205
  }
@@ -26342,25 +26409,29 @@ var REASON = {
26342
26409
  config: "model id in model configuration next to a model call"
26343
26410
  };
26344
26411
  function modelArtifacts(result) {
26345
- return (result.models ?? []).map((model) => ({
26346
- id: `model_config_${slug(model.id)}_${createHash9("sha256").update(model.id).digest("hex").slice(0, 8)}`,
26347
- type: "model_config",
26348
- name: model.id,
26349
- scope: "shared",
26350
- usedByAgentIds: [],
26351
- confidence: CONFIDENCE[model.resolution],
26352
- 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.",
26353
- evidence: [
26354
- { path: model.definition.path, line: model.definition.line, reason: REASON[model.resolution] },
26355
- ...model.calledFrom.slice(0, MAX_CALL_SITE_EVIDENCE).map((site) => ({
26356
- path: site.path,
26357
- line: site.line,
26358
- reason: `model call site${site.enclosing ? ` in ${site.enclosing}` : ""} (${site.callee})`
26359
- }))
26360
- ],
26361
- calledFrom: model.calledFrom.map((site) => ({ path: site.path, line: site.line, ...site.enclosing ? { enclosing: site.enclosing } : {} })),
26362
- resolution: model.resolution
26363
- }));
26412
+ const owners = new Map(result.callSites.map((site) => [site.id, site.agentIds ?? []]));
26413
+ return (result.models ?? []).map((model) => {
26414
+ const agentIds = [...new Set(model.calledFrom.flatMap((site) => owners.get(site.callSite) ?? []))].sort();
26415
+ return {
26416
+ id: `model_config_${slug(model.id)}_${createHash9("sha256").update(model.id).digest("hex").slice(0, 8)}`,
26417
+ type: "model_config",
26418
+ name: model.id,
26419
+ scope: agentIds.length === 1 ? "agent" : "shared",
26420
+ usedByAgentIds: agentIds,
26421
+ confidence: CONFIDENCE[model.resolution],
26422
+ 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.",
26423
+ evidence: [
26424
+ { path: model.definition.path, line: model.definition.line, reason: REASON[model.resolution] },
26425
+ ...model.calledFrom.slice(0, MAX_CALL_SITE_EVIDENCE).map((site) => ({
26426
+ path: site.path,
26427
+ line: site.line,
26428
+ reason: `model call site${site.enclosing ? ` in ${site.enclosing}` : ""} (${site.callee})`
26429
+ }))
26430
+ ],
26431
+ calledFrom: model.calledFrom.map((site) => ({ path: site.path, line: site.line, ...site.enclosing ? { enclosing: site.enclosing } : {} })),
26432
+ resolution: model.resolution
26433
+ };
26434
+ });
26364
26435
  }
26365
26436
  function describeSource(source) {
26366
26437
  const [kind, ...rest] = source.split(":");
@@ -26573,8 +26644,6 @@ function collectModelLiterals(rootDir) {
26573
26644
 
26574
26645
  // src/harness-extract/types.ts
26575
26646
  var EXTRACT_SCHEMA_VERSION = 1;
26576
- // src/harness-extract/enumerators/index.ts
26577
- var ENUMERATORS = [];
26578
26647
  // src/harness-extract/tools.ts
26579
26648
  var PASS_THROUGH2 = new Set(["ref", "call", "param", "oneOf", "lookup"]);
26580
26649
  var DEFINITION_KEYS = new Set(["description", "input_schema", "inputSchema", "parameters", "schema", "execute", "type", "strict"]);
@@ -27194,4 +27263,954 @@ function assignAgentIds(result, agentForScope) {
27194
27263
  }
27195
27264
  }
27196
27265
 
27197
- 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 };
27266
+ // src/harness-extract/enumerators/common.ts
27267
+ var import_typescript11 = __toESM(require_typescript(), 1);
27268
+ import { readdirSync as readdirSync8, readFileSync as readFileSync15 } from "node:fs";
27269
+ import { dirname as dirname10, join as join13, posix as posix2, relative as relative10 } from "node:path";
27270
+ var cache2 = new WeakMap;
27271
+ var SKIP = new Set(["node_modules", "dist", "build", "out", "vendor", "coverage", "__pycache__"]);
27272
+ var TEST_PATH4 = /(?:^|\/)(?:test|tests|__tests__|test-fixtures|fixtures?|__fixtures__|__mocks__|e2e)\/|\.(?:test|spec)\.[cm]?[jt]sx?$/i;
27273
+ var EVAL_PATH2 = /(?:^|\/)evals?\/|\.evals?\.[cm]?[jt]sx?$/i;
27274
+ function enumerationRepository(ctx) {
27275
+ const existing = cache2.get(ctx);
27276
+ if (existing)
27277
+ return existing;
27278
+ const files = [];
27279
+ const walk = (dir) => {
27280
+ for (const entry of readdirSync8(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
27281
+ const abs = join13(dir, entry.name);
27282
+ if (entry.isDirectory()) {
27283
+ if (!entry.name.startsWith(".") && !SKIP.has(entry.name))
27284
+ walk(abs);
27285
+ } else if (entry.isFile() && /\.(?:[cm]?[jt]sx?|py|jsonc?|toml)$/.test(entry.name) && !/\.d\.[cm]?ts$/.test(entry.name)) {
27286
+ const path = relative10(ctx.rootDir, abs).split("\\").join("/");
27287
+ try {
27288
+ const text = readFileSync15(abs, "utf8");
27289
+ if (text.length > 1024 * 1024)
27290
+ continue;
27291
+ const source = ctx.programFor(path)?.getSourceFile(abs) ?? import_typescript11.default.createSourceFile(abs, text, import_typescript11.default.ScriptTarget.Latest, true, path.endsWith("tsx") ? import_typescript11.default.ScriptKind.TSX : import_typescript11.default.ScriptKind.TS);
27292
+ files.push({ path, text, source });
27293
+ } catch {}
27294
+ }
27295
+ }
27296
+ };
27297
+ walk(ctx.rootDir);
27298
+ const workers = [];
27299
+ const paths = new Set(files.map((file) => file.path));
27300
+ const closure = (main) => {
27301
+ const found = new Set, pending = [main];
27302
+ for (let index = 0;index < pending.length; index++) {
27303
+ const path = pending[index];
27304
+ if (found.has(path))
27305
+ continue;
27306
+ found.add(path);
27307
+ const file = files.find((entry) => entry.path === path);
27308
+ if (!file)
27309
+ continue;
27310
+ for (const ref of import_typescript11.default.preProcessFile(file.text, true, true).importedFiles) {
27311
+ if (!ref.fileName.startsWith("."))
27312
+ continue;
27313
+ const base = posix2.normalize(posix2.join(posix2.dirname(path), ref.fileName)).replace(/\.[cm]?js$/, "");
27314
+ const target = [base, ...[".ts", ".tsx", ".js", ".mjs", "/index.ts", "/index.js"].map((suffix) => base + suffix)].find((candidate) => paths.has(candidate));
27315
+ if (target)
27316
+ pending.push(target);
27317
+ }
27318
+ }
27319
+ return found;
27320
+ };
27321
+ for (const file of files)
27322
+ if (/(?:^|\/)wrangler(?:\.[\w.-]+)?\.(?:jsonc?|toml)$/.test(file.path)) {
27323
+ try {
27324
+ const config2 = file.path.endsWith(".toml") ? parse(file.text) : JSON.parse(stripJsonc(file.text));
27325
+ const variants = [["default", config2], ...Object.entries(config2.env ?? {}).map(([name, section]) => [name, { ...config2, ...section, queues: section.queues, workflows: section.workflows }])];
27326
+ for (const [environment, section] of variants) {
27327
+ if (typeof section.main !== "string" || isTestWorkerConfig({ path: file.path, name: section.name, mains: [section.main] }))
27328
+ continue;
27329
+ const main = posix2.normalize(posix2.join(dirname10(file.path), section.main));
27330
+ workers.push({ id: `${file.path}#${environment}`, main, cron: Boolean(section.triggers?.crons?.length), queueBindings: new Set((section.queues?.producers ?? []).flatMap((producer) => typeof producer.binding === "string" ? [producer.binding] : [])), workflowClasses: (section.workflows ?? []).flatMap((binding) => typeof binding.class_name === "string" && !binding.script_name ? [binding.class_name] : []), files: closure(main) });
27331
+ }
27332
+ } catch {}
27333
+ }
27334
+ const queueBindingsFor = (path) => {
27335
+ const owners = workers.filter((worker) => worker.files.has(path));
27336
+ return new Set(owners[0] ? [...owners[0].queueBindings].filter((binding) => owners.every((worker) => worker.queueBindings.has(binding))) : []);
27337
+ };
27338
+ const reach = buildImportGraphReachability(ctx.rootDir);
27339
+ const repo = { files, workers, queueBindingsFor, cronEntrypoints: new Set(workers.filter((worker) => worker.cron).map((worker) => worker.main)), deployedFiles: reach.inProd, status: (path) => reach.inProd.has(path) || reach.reachable.has(path) ? "reachable" : "defined_only" };
27340
+ cache2.set(ctx, repo);
27341
+ return repo;
27342
+ }
27343
+ function lineOf5(node) {
27344
+ return node.getSourceFile().getLineAndCharacterOfPosition(node.getStart()).line + 1;
27345
+ }
27346
+ function nameOf(node) {
27347
+ if (!node)
27348
+ return;
27349
+ if (import_typescript11.default.isComputedPropertyName(node) && import_typescript11.default.isStringLiteralLike(node.expression))
27350
+ return node.expression.text;
27351
+ return import_typescript11.default.isIdentifier(node) || import_typescript11.default.isStringLiteralLike(node) || import_typescript11.default.isNumericLiteral(node) ? node.text : undefined;
27352
+ }
27353
+ function visit(node, fn) {
27354
+ fn(node);
27355
+ import_typescript11.default.forEachChild(node, (child) => visit(child, fn));
27356
+ }
27357
+ function componentId(kind, path, name) {
27358
+ return `${kind}:${path}:${name}`;
27359
+ }
27360
+ function artifact(type, name, file, node, reason, status) {
27361
+ return { id: componentId(type, file.path, name), type, name, scope: "shared", sourcePath: file.path, usedByAgentIds: [], confidence: 1, evidence: [{ path: file.path, line: lineOf5(node), reason }], status };
27362
+ }
27363
+ function agent(name, file, node, reason, status) {
27364
+ return { id: componentId("agent", file.path, name), name, kind: "runtime_agent", root: ".", entrypointIds: [], channelAdapterIds: [], artifactIds: [], identityNamespaceIds: [], deploymentIds: [], frameworkIds: [], modelProviderIds: [], confidence: 1, evidence: [{ path: file.path, line: lineOf5(node), reason }], status };
27365
+ }
27366
+ function emptyResult() {
27367
+ return { runtimeAgents: [], artifacts: [], warnings: [] };
27368
+ }
27369
+ function stableResult(result) {
27370
+ const unique2 = (values) => [...new Map(values.map((x) => [x.id, x])).values()].sort((a, b) => a.id.localeCompare(b.id));
27371
+ return { runtimeAgents: unique2(result.runtimeAgents), artifacts: unique2(result.artifacts), warnings: [...new Set(result.warnings)].sort() };
27372
+ }
27373
+
27374
+ // src/harness-extract/enumerators/agents.ts
27375
+ function agentForScope(scope, enumeration) {
27376
+ return enumeration.agentForScope(scope);
27377
+ }
27378
+ function createAgentScopeResolver(result, ctx) {
27379
+ return enumerateAgents(result, ctx).agentForScope;
27380
+ }
27381
+ var enumerations = new WeakMap;
27382
+ var AGENT_BASES3 = new Set(["Think", "Agent", "AIChatAgent", "McpAgent"]);
27383
+ var HTTP_METHODS2 = new Set(["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]);
27384
+ function routeOf(fn, file) {
27385
+ const name = functionName(fn);
27386
+ if (name && HTTP_METHODS2.has(name) && /(?:^|\/)(?:route|\+server)\.[cm]?[jt]sx?$/.test(file.path))
27387
+ return `${name} ${file.path}`;
27388
+ const parent = fn.parent;
27389
+ if (parent && import_typescript12.default.isCallExpression(parent) && import_typescript12.default.isPropertyAccessExpression(parent.expression) && /^(get|post|put|patch|delete|all|on)$/.test(parent.expression.name.text)) {
27390
+ const path = parent.arguments.find(import_typescript12.default.isStringLiteralLike);
27391
+ if (path)
27392
+ return `${parent.expression.name.text.toUpperCase()} ${path.text} (${file.path})`;
27393
+ }
27394
+ return;
27395
+ }
27396
+ function enumerateAgents(result, ctx) {
27397
+ const cached = enumerations.get(ctx);
27398
+ if (cached)
27399
+ return cached;
27400
+ const repo = enumerationRepository(ctx);
27401
+ const scopes = new Map;
27402
+ const byNode = new Map;
27403
+ const classes = [];
27404
+ const bound = new Set(detectBoundRuntimeClasses(ctx.rootDir).filter((x) => x.kind === "durable_object").map((x) => x.className));
27405
+ const memo = createFrameworkMemo();
27406
+ const keyOf = (node) => `${node.getSourceFile().fileName}:${node.getStart()}`;
27407
+ for (const file of repo.files) {
27408
+ 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))
27409
+ continue;
27410
+ const checker = ctx.checkerFor(file.path);
27411
+ visit(file.source, (node) => {
27412
+ if ((import_typescript12.default.isClassDeclaration(node) || import_typescript12.default.isClassExpression(node)) && node.name) {
27413
+ const name2 = node.name.text;
27414
+ const info = checker ? frameworkBaseOf(node, checker, memo) : undefined;
27415
+ const directBase = node.heritageClauses?.flatMap((h) => h.types).map((x) => x.expression.getText()) ?? [];
27416
+ const protocolEvents = new Set;
27417
+ visit(node, (member2) => {
27418
+ if (import_typescript12.default.isStringLiteralLike(member2))
27419
+ protocolEvents.add(member2.text);
27420
+ });
27421
+ const realtime = protocolEvents.has("session.update") && protocolEvents.has("response.create") && [...protocolEvents].some((event) => event.includes("function_call"));
27422
+ const exported = import_typescript12.default.getCombinedModifierFlags(node) & import_typescript12.default.ModifierFlags.Export;
27423
+ const abstract = import_typescript12.default.getCombinedModifierFlags(node) & import_typescript12.default.ModifierFlags.Abstract;
27424
+ if (!abstract && (exported || bound.has(name2)) && (info?.base && AGENT_BASES3.has(info.base) || directBase.some((x) => AGENT_BASES3.has(x)) || exported && realtime)) {
27425
+ classes.push({ file, node, name: name2, chain: info?.chain ?? [name2, ...directBase] });
27426
+ }
27427
+ }
27428
+ if (!isFunctionLike(node) || !node.body)
27429
+ return;
27430
+ const name = functionName(node);
27431
+ const cls = enclosingClass(node)?.name?.text;
27432
+ const route = routeOf(node, file);
27433
+ const label = cls && name ? `${cls}.${name}` : name ?? route ?? `${file.path}:${lineOf5(node)}`;
27434
+ const scope = {
27435
+ key: keyOf(node),
27436
+ label,
27437
+ aliases: [label, ...name ? [name] : [], ...route ? [route] : [], `${file.path}::${label}`, `${file.path}#${label}`],
27438
+ file,
27439
+ node,
27440
+ className: cls,
27441
+ route,
27442
+ calls: new Set,
27443
+ virtualCalls: new Map,
27444
+ deployedCalls: new Set,
27445
+ callsByWorker: new Map(repo.workers.map((worker) => [worker.id, new Set])),
27446
+ callers: new Set,
27447
+ hasModel: false,
27448
+ modelWorkers: new Set,
27449
+ hasTools: false,
27450
+ toolFeedback: false,
27451
+ configuredSteps: false,
27452
+ hasLoop: false,
27453
+ forcedOutput: false
27454
+ };
27455
+ const qualified = (fn, fnName) => {
27456
+ const owner = enclosingClass(fn);
27457
+ return owner?.name && (fn.parent === owner || fn.parent?.parent === owner) ? `${owner.name.text}.${fnName}` : fnName;
27458
+ };
27459
+ if (name) {
27460
+ const parts = [qualified(node, name)];
27461
+ const member2 = import_typescript12.default.isMethodDeclaration(node) || import_typescript12.default.isGetAccessorDeclaration(node) || import_typescript12.default.isSetAccessorDeclaration(node) ? node : import_typescript12.default.isPropertyAssignment(node.parent) ? node.parent : undefined;
27462
+ const object = member2 && import_typescript12.default.isObjectLiteralExpression(member2.parent) ? member2.parent : undefined;
27463
+ if (object)
27464
+ parts.unshift(import_typescript12.default.isVariableDeclaration(object.parent) && import_typescript12.default.isIdentifier(object.parent.name) ? object.parent.name.text : `L${lineOf5(object)}`);
27465
+ for (let outer = (object ?? node).parent;outer; outer = outer.parent) {
27466
+ if (isFunctionLike(outer)) {
27467
+ const outerName = functionName(outer);
27468
+ if (outerName)
27469
+ parts.unshift(qualified(outer, outerName));
27470
+ }
27471
+ }
27472
+ scope.aliases.push(`${file.path}#${parts.join(".")}`);
27473
+ }
27474
+ scope.aliases.push(scope.key);
27475
+ scopes.set(scope.key, scope);
27476
+ byNode.set(node, scope);
27477
+ });
27478
+ }
27479
+ const classChain = (node, seen = new Set) => {
27480
+ if (seen.has(keyOf(node)))
27481
+ return [];
27482
+ seen.add(keyOf(node));
27483
+ const checker = ctx.checkerFor(node.getSourceFile().fileName.slice(ctx.rootDir.length + 1));
27484
+ const bases = node.heritageClauses?.flatMap((clause) => clause.types).flatMap((base) => {
27485
+ const declaration = checker && valueDeclaration(resolvedSymbol(base.expression, checker));
27486
+ return declaration && import_typescript12.default.isClassLike(declaration) ? classChain(declaration, seen) : [];
27487
+ }) ?? [];
27488
+ return [node, ...bases];
27489
+ };
27490
+ for (const cls of classes)
27491
+ cls.nodes = classChain(cls.node);
27492
+ const virtualEdges = new Map;
27493
+ const nearest = (node) => {
27494
+ for (let current = node;current; current = current.parent) {
27495
+ const scope = byNode.get(current);
27496
+ if (scope)
27497
+ return scope;
27498
+ }
27499
+ return;
27500
+ };
27501
+ const bindingTruth = (condition, worker) => {
27502
+ if (condition.kind === import_typescript12.default.SyntaxKind.TrueKeyword)
27503
+ return true;
27504
+ if (condition.kind === import_typescript12.default.SyntaxKind.FalseKeyword)
27505
+ return false;
27506
+ if (import_typescript12.default.isPrefixUnaryExpression(condition) && condition.operator === import_typescript12.default.SyntaxKind.ExclamationToken) {
27507
+ const value = bindingTruth(condition.operand, worker);
27508
+ return value === undefined ? undefined : !value;
27509
+ }
27510
+ if (import_typescript12.default.isPropertyAccessExpression(condition) && /^(?:this\.)?env$/.test(condition.expression.getText()) && (worker ? repo.workers.find((entry) => entry.id === worker)?.queueBindings : repo.queueBindingsFor(condition.getSourceFile().fileName.slice(ctx.rootDir.length + 1)))?.has(condition.name.text))
27511
+ return true;
27512
+ return;
27513
+ };
27514
+ const returns = (node) => Boolean(node && (import_typescript12.default.isReturnStatement(node) || import_typescript12.default.isBlock(node) && node.statements.length && import_typescript12.default.isReturnStatement(node.statements[node.statements.length - 1])));
27515
+ const deployed = (node, worker) => {
27516
+ for (let current = node;current.parent; current = current.parent) {
27517
+ const parent = current.parent;
27518
+ if (import_typescript12.default.isIfStatement(parent)) {
27519
+ const truth = bindingTruth(parent.expression, worker);
27520
+ if (truth !== undefined && (current === parent.thenStatement ? !truth : current === parent.elseStatement ? truth : false))
27521
+ return false;
27522
+ }
27523
+ if (import_typescript12.default.isBlock(parent))
27524
+ for (const prior of parent.statements) {
27525
+ if (prior.getStart() >= current.getStart())
27526
+ break;
27527
+ if (import_typescript12.default.isIfStatement(prior)) {
27528
+ const truth = bindingTruth(prior.expression, worker);
27529
+ if (truth !== undefined && returns(truth ? prior.thenStatement : prior.elseStatement))
27530
+ return false;
27531
+ }
27532
+ }
27533
+ }
27534
+ return true;
27535
+ };
27536
+ const markModel = (scope, node) => {
27537
+ scope.hasModel = true;
27538
+ for (const worker of repo.workers)
27539
+ if (deployed(node, worker.id))
27540
+ scope.modelWorkers.add(worker.id);
27541
+ };
27542
+ for (const site of result.callSites) {
27543
+ if (site.isTest || site.isEval)
27544
+ continue;
27545
+ const file = repo.files.find((x) => x.path === site.path);
27546
+ if (!file)
27547
+ continue;
27548
+ const offset = file.source.getPositionOfLineAndCharacter(Math.max(0, site.line - 1), Math.max(0, site.col - 1));
27549
+ let anchor = file.source;
27550
+ const descend = (node) => {
27551
+ if (node.getStart() <= offset && node.getEnd() >= offset) {
27552
+ anchor = node;
27553
+ import_typescript12.default.forEachChild(node, descend);
27554
+ }
27555
+ };
27556
+ descend(file.source);
27557
+ const scope = nearest(anchor);
27558
+ if (!scope)
27559
+ continue;
27560
+ markModel(scope, anchor);
27561
+ const tools = site.toolsArg ? ctx.nodeAt(site.toolsArg) : undefined;
27562
+ scope.hasTools ||= Boolean(tools && !(import_typescript12.default.isObjectLiteralExpression(tools) && tools.properties.length === 0) && !(import_typescript12.default.isArrayLiteralExpression(tools) && tools.elements.length === 0));
27563
+ scope.aliases.push(site.scope);
27564
+ }
27565
+ const targetsOf = (node, file) => {
27566
+ const checker = ctx.checkerFor(file.path);
27567
+ if (!checker)
27568
+ return [];
27569
+ const at = import_typescript12.default.isPropertyAccessExpression(node) ? node.name : node;
27570
+ const declaration = valueDeclaration(resolvedSymbol(at, checker));
27571
+ if (!declaration)
27572
+ return [];
27573
+ const direct = byNode.get(declaration) ?? scopes.get(keyOf(declaration));
27574
+ if (direct)
27575
+ return [direct];
27576
+ if (import_typescript12.default.isVariableDeclaration(declaration) && declaration.initializer) {
27577
+ const fn = byNode.get(declaration.initializer) ?? scopes.get(keyOf(declaration.initializer));
27578
+ if (fn)
27579
+ return [fn];
27580
+ }
27581
+ return [];
27582
+ };
27583
+ for (const scope of scopes.values()) {
27584
+ const inspect = (node) => {
27585
+ if (node !== scope.node && isFunctionLike(node)) {
27586
+ return;
27587
+ }
27588
+ if (import_typescript12.default.isWhileStatement(node) || import_typescript12.default.isDoStatement(node) || import_typescript12.default.isForStatement(node) || import_typescript12.default.isForOfStatement(node))
27589
+ scope.hasLoop = true;
27590
+ if ((import_typescript12.default.isIdentifier(node) || import_typescript12.default.isStringLiteralLike(node)) && /^(?:tool_calls|toolCalls|tool_use|tool_result|tool_results|toolResults)$/.test(node.text)) {
27591
+ scope.hasTools = true;
27592
+ scope.toolFeedback = true;
27593
+ }
27594
+ if (import_typescript12.default.isObjectLiteralExpression(node)) {
27595
+ const fields = new Map(node.properties.filter(import_typescript12.default.isPropertyAssignment).map((p2) => [nameOf(p2.name), p2.initializer]));
27596
+ const type = fields.get("type");
27597
+ if (type && import_typescript12.default.isStringLiteralLike(type) && type.text === "tool" && fields.has("name"))
27598
+ scope.forcedOutput = true;
27599
+ }
27600
+ if (import_typescript12.default.isCallExpression(node) || import_typescript12.default.isNewExpression(node)) {
27601
+ const callee = node.expression.getText();
27602
+ if (/(?:chat\.)?completions\.create$|messages\.(?:create|stream)$|responses\.(?:create|stream)$/.test(callee))
27603
+ markModel(scope, node);
27604
+ if (/\.runTurn$/.test(callee) && scope.node.parameters.some((param) => /tools/i.test(param.name.getText())))
27605
+ markModel(scope, node);
27606
+ const connect = (at) => {
27607
+ for (const target of byNode.has(at) ? [byNode.get(at)] : targetsOf(at, scope.file)) {
27608
+ if (import_typescript12.default.isPropertyAccessExpression(at) && at.expression.kind === import_typescript12.default.SyntaxKind.ThisKeyword) {
27609
+ virtualEdges.set(`${scope.key}|${target.key}`, at.name.text);
27610
+ scope.virtualCalls.set(target.key, at.name.text);
27611
+ }
27612
+ scope.calls.add(target.key);
27613
+ if (deployed(at))
27614
+ scope.deployedCalls.add(target.key);
27615
+ for (const [worker, calls] of scope.callsByWorker)
27616
+ if (deployed(at, worker))
27617
+ calls.add(target.key);
27618
+ target.callers.add(scope.key);
27619
+ }
27620
+ };
27621
+ connect(node.expression);
27622
+ const connectArgument = (at) => {
27623
+ if (isFunctionLike(at)) {
27624
+ connect(at);
27625
+ return;
27626
+ }
27627
+ if (import_typescript12.default.isIdentifier(at) || import_typescript12.default.isPropertyAccessExpression(at))
27628
+ connect(at);
27629
+ import_typescript12.default.forEachChild(at, connectArgument);
27630
+ };
27631
+ for (const argument of node.arguments ?? [])
27632
+ connectArgument(argument);
27633
+ for (const argument of node.arguments ?? [])
27634
+ if (import_typescript12.default.isObjectLiteralExpression(argument)) {
27635
+ const fields = new Set(argument.properties.map((p2) => nameOf(p2.name)));
27636
+ if (fields.has("model") && fields.has("messages") && fields.has("tools")) {
27637
+ markModel(scope, node);
27638
+ scope.hasTools = true;
27639
+ }
27640
+ }
27641
+ if (/(?:^|\.)(?:stepCountIs|isStepCount)$/.test(node.expression.getText()) && node.arguments?.[0] && import_typescript12.default.isNumericLiteral(node.arguments?.[0]) && Number(node.arguments?.[0].text) > 1) {
27642
+ scope.hasLoop = true;
27643
+ scope.configuredSteps = true;
27644
+ }
27645
+ }
27646
+ if (import_typescript12.default.isPropertyAssignment(node) && nameOf(node.name) === "maxSteps" && import_typescript12.default.isNumericLiteral(node.initializer) && Number(node.initializer.text) > 1) {
27647
+ scope.hasLoop = true;
27648
+ scope.configuredSteps = true;
27649
+ }
27650
+ import_typescript12.default.forEachChild(node, inspect);
27651
+ };
27652
+ inspect(scope.node);
27653
+ }
27654
+ const modelQueue = [...scopes.values()].filter((scope) => scope.hasModel);
27655
+ for (let index = 0;index < modelQueue.length; index++) {
27656
+ const scope = modelQueue[index];
27657
+ if (scope.reachesModel)
27658
+ continue;
27659
+ scope.reachesModel = true;
27660
+ for (const caller of scope.callers) {
27661
+ const parent = scopes.get(caller);
27662
+ if (parent && !parent.reachesModel)
27663
+ modelQueue.push(parent);
27664
+ }
27665
+ }
27666
+ const agents = new Map;
27667
+ const owners = new Map;
27668
+ const assign = (key, id) => {
27669
+ let values = owners.get(key);
27670
+ if (!values)
27671
+ owners.set(key, values = new Set);
27672
+ values.add(id);
27673
+ };
27674
+ for (const cls of classes) {
27675
+ const emitted = agent(cls.name, cls.file, cls.node, "Concrete agent/framework class or realtime model/tool bridge", repo.status(cls.file.path));
27676
+ agents.set(emitted.id, emitted);
27677
+ }
27678
+ for (const scope of scopes.values()) {
27679
+ let nestedInFunction = false;
27680
+ for (let parent = scope.node.parent;parent && !import_typescript12.default.isClassLike(parent); parent = parent.parent)
27681
+ if (isFunctionLike(parent)) {
27682
+ nestedInFunction = true;
27683
+ break;
27684
+ }
27685
+ if (scope.className && !nestedInFunction) {
27686
+ let member2 = scope.node;
27687
+ while (member2.parent && !import_typescript12.default.isClassLike(member2.parent))
27688
+ member2 = member2.parent;
27689
+ const memberName = "name" in member2 ? nameOf(member2.name) : undefined;
27690
+ for (const cls of classes) {
27691
+ const ownerClass = enclosingClass(scope.node);
27692
+ const baseIndex = cls.nodes.findIndex((node) => ownerClass && keyOf(node) === keyOf(ownerClass));
27693
+ if (baseIndex < 0)
27694
+ continue;
27695
+ const overridden = memberName && cls.nodes.slice(0, baseIndex).some((node) => node.members.some((candidate) => nameOf(candidate.name) === memberName));
27696
+ if (!overridden)
27697
+ assign(scope.key, componentId("agent", cls.file.path, cls.name));
27698
+ }
27699
+ }
27700
+ if (!scope.className && !scope.forcedOutput && scope.hasLoop && scope.hasTools && (scope.toolFeedback || scope.configuredSteps) && scope.reachesModel) {
27701
+ let boundary = scope;
27702
+ for (let parent = scope.node.parent;parent; parent = parent.parent) {
27703
+ const outer = byNode.get(parent);
27704
+ if (outer?.route) {
27705
+ boundary = outer;
27706
+ break;
27707
+ }
27708
+ }
27709
+ const name = boundary.route ?? functionName(boundary.node);
27710
+ if (!name)
27711
+ continue;
27712
+ const emitted = agent(name, boundary.file, scope.node, "Function or route owns a multi-step model/tool feedback loop", repo.status(boundary.file.path));
27713
+ agents.set(emitted.id, emitted);
27714
+ assign(boundary.key, emitted.id);
27715
+ }
27716
+ }
27717
+ let changed = true;
27718
+ while (changed) {
27719
+ changed = false;
27720
+ for (const scope of scopes.values())
27721
+ for (const callee of scope.calls)
27722
+ for (const id of owners.get(scope.key) ?? []) {
27723
+ let targetKey = callee;
27724
+ const virtual = virtualEdges.get(`${scope.key}|${callee}`), concrete = classes.find((cls) => componentId("agent", cls.file.path, cls.name) === id);
27725
+ if (virtual && concrete) {
27726
+ const implementation = concrete.nodes.flatMap((node) => node.members.filter((member2) => nameOf(member2.name) === virtual))[0];
27727
+ if (implementation && scopes.has(keyOf(implementation)))
27728
+ targetKey = keyOf(implementation);
27729
+ }
27730
+ const before = owners.get(targetKey)?.size ?? 0;
27731
+ assign(targetKey, id);
27732
+ changed ||= (owners.get(targetKey)?.size ?? 0) !== before;
27733
+ }
27734
+ }
27735
+ const scopeOwners = new Map;
27736
+ const mergeAlias = (label, ids) => {
27737
+ let values = scopeOwners.get(label);
27738
+ if (!values)
27739
+ scopeOwners.set(label, values = new Set);
27740
+ for (const id of ids)
27741
+ values.add(id);
27742
+ };
27743
+ const classAliases = new Map;
27744
+ for (const cls of classes)
27745
+ for (const base of cls.nodes) {
27746
+ if (!base.name)
27747
+ continue;
27748
+ const qualified = `${base.getSourceFile().fileName.slice(ctx.rootDir.length + 1)}#${base.name.text}`;
27749
+ mergeAlias(qualified, [componentId("agent", cls.file.path, cls.name)]);
27750
+ let variants = classAliases.get(base.name.text);
27751
+ if (!variants)
27752
+ classAliases.set(base.name.text, variants = new Set);
27753
+ variants.add(qualified);
27754
+ }
27755
+ for (const [name, variants] of classAliases)
27756
+ if (variants.size === 1)
27757
+ mergeAlias(name, scopeOwners.get([...variants][0]) ?? []);
27758
+ const aliases = new Map;
27759
+ for (const scope of scopes.values())
27760
+ for (const alias of scope.aliases) {
27761
+ const matches = aliases.get(alias) ?? [];
27762
+ matches.push(scope);
27763
+ aliases.set(alias, matches);
27764
+ }
27765
+ for (const [alias, matches] of aliases) {
27766
+ const candidates = matches.map((scope) => [...owners.get(scope.key) ?? []].sort());
27767
+ if (candidates.every((ids) => JSON.stringify(ids) === JSON.stringify(candidates[0])))
27768
+ mergeAlias(alias, candidates[0]);
27769
+ }
27770
+ const output = {
27771
+ runtimeAgents: [...agents.values()].sort((a, b) => a.id.localeCompare(b.id)),
27772
+ agentForScope: (scope) => scope ? [...scopeOwners.get(scope) ?? []].sort() : [],
27773
+ scopes: [...scopes.values()]
27774
+ };
27775
+ enumerations.set(ctx, output);
27776
+ assignAgentIds(result, output.agentForScope);
27777
+ return output;
27778
+ }
27779
+
27780
+ // src/harness-extract/enumerators/workflows.ts
27781
+ var import_typescript13 = __toESM(require_typescript(), 1);
27782
+ function enumerateWorkflows(result, ctx) {
27783
+ const output = emptyResult();
27784
+ const repo = enumerationRepository(ctx);
27785
+ const nodeKey = (node) => `${node.getSourceFile().fileName}:${node.getStart()}`;
27786
+ const bindings = new Set;
27787
+ for (const worker of repo.workers) {
27788
+ const file = repo.files.find((entry) => entry.path === worker.main), checker = file && ctx.checkerFor(file.path);
27789
+ const module = file && checker?.getSymbolAtLocation(file.source);
27790
+ if (!module || !checker)
27791
+ continue;
27792
+ for (const name of worker.workflowClasses) {
27793
+ let exported = checker.getExportsOfModule(module).find((symbol) => symbol.name === name);
27794
+ if (exported && exported.flags & import_typescript13.default.SymbolFlags.Alias)
27795
+ exported = checker.getAliasedSymbol(exported);
27796
+ const declaration = exported && valueDeclaration(exported);
27797
+ if (declaration && import_typescript13.default.isClassDeclaration(declaration))
27798
+ bindings.add(nodeKey(declaration));
27799
+ }
27800
+ }
27801
+ const memo = createFrameworkMemo();
27802
+ for (const file of repo.files) {
27803
+ if (!/\.[cm]?[jt]sx?$/.test(file.path) || TEST_PATH4.test(file.path) || EVAL_PATH2.test(file.path))
27804
+ continue;
27805
+ visit(file.source, (node) => {
27806
+ if (!import_typescript13.default.isClassDeclaration(node) || !node.name || import_typescript13.default.getCombinedModifierFlags(node) & import_typescript13.default.ModifierFlags.Abstract)
27807
+ return;
27808
+ const checker = ctx.checkerFor(file.path);
27809
+ const base = checker ? frameworkBaseOf(node, checker, memo)?.base : undefined;
27810
+ const directBase = node.heritageClauses?.flatMap((h) => h.types).map((x) => x.expression.getText()) ?? [];
27811
+ if (!bindings.has(nodeKey(node)) && base !== "WorkflowEntrypoint" && base !== "AgentWorkflow" && !directBase.some((x) => /^(?:WorkflowEntrypoint|AgentWorkflow)$/.test(x)))
27812
+ return;
27813
+ const entry = artifact("entrypoint", node.name.text, file, node, "Concrete Workflow class or Wrangler workflow binding", repo.status(file.path));
27814
+ entry.id = componentId("workflow", file.path, node.name.text);
27815
+ if (bindings.has(nodeKey(node))) {
27816
+ Object.assign(entry, { componentKind: "workflow", trigger: "workflow_binding" });
27817
+ }
27818
+ output.artifacts.push(entry);
27819
+ });
27820
+ }
27821
+ for (const worker of repo.workers.filter((entry) => entry.cron)) {
27822
+ const scopes = enumerateAgents(result, ctx).scopes;
27823
+ const byKey = new Map(scopes.map((scope) => [scope.key, scope]));
27824
+ const implementations = new Map, workerClasses = new Set;
27825
+ const deployedCalls = (scope) => {
27826
+ const calls = scope.callsByWorker.get(worker.id) ?? scope.deployedCalls;
27827
+ const cls = enclosingClass(scope.node);
27828
+ if (!cls || !workerClasses.has(nodeKey(cls)))
27829
+ return calls;
27830
+ const member2 = scope.node.parent === cls ? scope.node : scope.node.parent;
27831
+ if (import_typescript13.default.getCombinedModifierFlags(member2) & import_typescript13.default.ModifierFlags.Static)
27832
+ return calls;
27833
+ return new Set([...calls].map((key) => {
27834
+ const method = scope.virtualCalls.get(key);
27835
+ return method && implementations.has(method) ? implementations.get(method) : key;
27836
+ }));
27837
+ };
27838
+ const modelScopes = new Set(scopes.filter((scope) => scope.modelWorkers.has(worker.id)).map((scope) => scope.key));
27839
+ const mainFile = repo.files.find((file) => file.path === worker.main), checker = mainFile && ctx.checkerFor(mainFile.path);
27840
+ const exportedNodes = new Set, visited = new Set;
27841
+ const resolveWorker = (node) => {
27842
+ if (!node || visited.has(node))
27843
+ return;
27844
+ visited.add(node);
27845
+ if (import_typescript13.default.isParenthesizedExpression(node) || import_typescript13.default.isAsExpression(node) || import_typescript13.default.isSatisfiesExpression(node) || import_typescript13.default.isNonNullExpression(node)) {
27846
+ resolveWorker(node.expression);
27847
+ return;
27848
+ }
27849
+ if (import_typescript13.default.isCallExpression(node) && /(?:^|\.)withSentry$/.test(node.expression.getText())) {
27850
+ for (const argument of node.arguments)
27851
+ resolveWorker(argument);
27852
+ return;
27853
+ }
27854
+ if (import_typescript13.default.isExportAssignment(node)) {
27855
+ resolveWorker(node.expression);
27856
+ return;
27857
+ }
27858
+ if (import_typescript13.default.isVariableDeclaration(node)) {
27859
+ resolveWorker(node.initializer);
27860
+ return;
27861
+ }
27862
+ if (import_typescript13.default.isIdentifier(node) && checker) {
27863
+ resolveWorker(valueDeclaration(resolvedSymbol(node, checker)));
27864
+ return;
27865
+ }
27866
+ exportedNodes.add(node);
27867
+ };
27868
+ const module = mainFile && checker?.getSymbolAtLocation(mainFile.source);
27869
+ const exported = module && checker?.getExportsOfModule(module).find((symbol2) => symbol2.name === "default");
27870
+ const symbol = exported && checker && (exported.flags & import_typescript13.default.SymbolFlags.Alias ? checker.getAliasedSymbol(exported) : exported);
27871
+ resolveWorker(symbol && valueDeclaration(symbol));
27872
+ const collectImplementations = (node) => {
27873
+ if (!import_typescript13.default.isClassLike(node) || workerClasses.has(nodeKey(node)))
27874
+ return;
27875
+ workerClasses.add(nodeKey(node));
27876
+ for (const member2 of node.members) {
27877
+ if (import_typescript13.default.getCombinedModifierFlags(member2) & import_typescript13.default.ModifierFlags.Static)
27878
+ continue;
27879
+ const name = nameOf(member2.name);
27880
+ const implementation = byKey.get(nodeKey(member2)) ?? (import_typescript13.default.isPropertyDeclaration(member2) && member2.initializer ? byKey.get(nodeKey(member2.initializer)) : undefined);
27881
+ if (name && !implementations.has(name))
27882
+ implementations.set(name, implementation?.key ?? "(non-callable override)");
27883
+ }
27884
+ if (checker)
27885
+ for (const base of node.heritageClauses?.flatMap((clause) => clause.types) ?? []) {
27886
+ const declaration = valueDeclaration(resolvedSymbol(base.expression, checker));
27887
+ if (declaration)
27888
+ collectImplementations(declaration);
27889
+ }
27890
+ };
27891
+ for (const node of exportedNodes)
27892
+ collectImplementations(node);
27893
+ let changed = true;
27894
+ while (changed) {
27895
+ changed = false;
27896
+ for (const scope of scopes)
27897
+ if (!modelScopes.has(scope.key) && [...deployedCalls(scope)].some((key) => modelScopes.has(key))) {
27898
+ modelScopes.add(scope.key);
27899
+ changed = true;
27900
+ }
27901
+ }
27902
+ const scheduledNodes = new Set;
27903
+ const resolveScheduled = (node, seen2 = new Set) => {
27904
+ if (!node || seen2.has(node))
27905
+ return;
27906
+ seen2.add(node);
27907
+ if (import_typescript13.default.isIdentifier(node) && checker) {
27908
+ resolveScheduled(valueDeclaration(resolvedSymbol(node, checker)), seen2);
27909
+ return;
27910
+ }
27911
+ if (import_typescript13.default.isVariableDeclaration(node) || import_typescript13.default.isPropertyAssignment(node) || import_typescript13.default.isPropertyDeclaration(node)) {
27912
+ resolveScheduled(node.initializer, seen2);
27913
+ return;
27914
+ }
27915
+ if (import_typescript13.default.isShorthandPropertyAssignment(node)) {
27916
+ resolveScheduled(checker && valueDeclaration(checker.getShorthandAssignmentValueSymbol(node)), seen2);
27917
+ return;
27918
+ }
27919
+ if (import_typescript13.default.isParenthesizedExpression(node) || import_typescript13.default.isAsExpression(node) || import_typescript13.default.isSatisfiesExpression(node) || import_typescript13.default.isNonNullExpression(node)) {
27920
+ resolveScheduled(node.expression, seen2);
27921
+ return;
27922
+ }
27923
+ scheduledNodes.add(node);
27924
+ };
27925
+ const collectScheduled = (node, seen2 = new Set) => {
27926
+ if (seen2.has(node))
27927
+ return;
27928
+ seen2.add(node);
27929
+ const members = import_typescript13.default.isObjectLiteralExpression(node) ? node.properties : import_typescript13.default.isClassLike(node) ? node.members : [];
27930
+ const handlers = members.filter((member2) => nameOf(member2.name) === "scheduled" && !(import_typescript13.default.getCombinedModifierFlags(member2) & import_typescript13.default.ModifierFlags.Static));
27931
+ for (const member2 of handlers)
27932
+ resolveScheduled(member2);
27933
+ if (!handlers.length && import_typescript13.default.isClassLike(node) && checker)
27934
+ for (const base of node.heritageClauses?.flatMap((clause) => clause.types) ?? []) {
27935
+ const declaration = valueDeclaration(resolvedSymbol(base.expression, checker));
27936
+ if (declaration)
27937
+ collectScheduled(declaration, seen2);
27938
+ }
27939
+ };
27940
+ for (const node of exportedNodes)
27941
+ collectScheduled(node);
27942
+ const roots = scopes.filter((scope) => [...scheduledNodes].some((node) => node.getSourceFile().fileName === scope.node.getSourceFile().fileName && node.getStart() === scope.node.getStart()));
27943
+ const seen = new Set;
27944
+ const queue = roots.flatMap((scope) => scope.modelWorkers.has(worker.id) ? [scope.key] : [...deployedCalls(scope)]);
27945
+ for (let i = 0;i < queue.length; i++) {
27946
+ const key = queue[i];
27947
+ if (seen.has(key))
27948
+ continue;
27949
+ seen.add(key);
27950
+ const scope = byKey.get(key);
27951
+ if (!scope)
27952
+ continue;
27953
+ if (!modelScopes.has(scope.key)) {
27954
+ if (/(?:Cron|Pipeline)$/.test(scope.label)) {
27955
+ 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));
27956
+ const proof = [...scope.calls].map((callee) => byKey.get(callee)).filter((callee) => callee?.reachesModel).map((callee) => `${callee.file.path}#${callee.label}`);
27957
+ 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] });
27958
+ output.artifacts.push(entry);
27959
+ } else
27960
+ queue.push(...deployedCalls(scope));
27961
+ continue;
27962
+ }
27963
+ if (/(?:Cron|Pipeline)$/.test(scope.label) || scope.modelWorkers.has(worker.id)) {
27964
+ const entry = artifact("entrypoint", scope.label, scope.file, scope.node, "Cron dispatch reaches this model-backed pipeline", repo.status(scope.file.path));
27965
+ entry.id = componentId("workflow", scope.file.path, scope.label);
27966
+ entry.componentKind = "workflow";
27967
+ entry.trigger = "cron";
27968
+ output.artifacts.push(entry);
27969
+ if (roots.includes(scope))
27970
+ queue.push(...deployedCalls(scope));
27971
+ } else
27972
+ queue.push(...deployedCalls(scope));
27973
+ }
27974
+ }
27975
+ return stableResult(output);
27976
+ }
27977
+
27978
+ // src/harness-extract/enumerators/catalog.ts
27979
+ var import_typescript14 = __toESM(require_typescript(), 1);
27980
+ var THINK_WORKSPACE_TOOLS = ["read", "write", "edit", "list", "find", "grep", "delete"];
27981
+ function strings(expression, checker, seen = new Set) {
27982
+ if (!expression)
27983
+ return [];
27984
+ const node = unwrap(expression);
27985
+ if (seen.has(node))
27986
+ return [];
27987
+ seen.add(node);
27988
+ if (import_typescript14.default.isIdentifier(node)) {
27989
+ const declaration = checker && valueDeclaration(resolvedSymbol(node, checker));
27990
+ if (!declaration || !import_typescript14.default.isVariableDeclaration(declaration))
27991
+ return [];
27992
+ return strings(declaration.initializer, checker, seen);
27993
+ }
27994
+ if (import_typescript14.default.isArrayLiteralExpression(node))
27995
+ return node.elements.flatMap((entry) => import_typescript14.default.isSpreadElement(entry) ? strings(entry.expression, checker, seen) : strings(entry, checker, seen));
27996
+ if (import_typescript14.default.isStringLiteralLike(node))
27997
+ return [{ name: node.text, node }];
27998
+ if (import_typescript14.default.isNewExpression(node) && node.expression.getText() === "Set")
27999
+ return strings(node.arguments?.[0], checker, seen);
28000
+ return [];
28001
+ }
28002
+ function property(object, name) {
28003
+ const entry = object.properties.find((item) => item.name && nameOf(item.name) === name);
28004
+ return entry && import_typescript14.default.isPropertyAssignment(entry) ? entry.initializer : entry && import_typescript14.default.isShorthandPropertyAssignment(entry) ? entry.name : undefined;
28005
+ }
28006
+ function inheritedTrue(node, propertyName2, checker, seen = new Set) {
28007
+ if (seen.has(node))
28008
+ return false;
28009
+ seen.add(node);
28010
+ const own = node.members.find((member2) => nameOf(member2.name) === propertyName2);
28011
+ if (own && import_typescript14.default.isPropertyDeclaration(own) && own.initializer)
28012
+ return unwrap(own.initializer).kind === import_typescript14.default.SyntaxKind.TrueKeyword;
28013
+ if (checker)
28014
+ for (const base of node.heritageClauses?.flatMap((h) => h.types) ?? []) {
28015
+ const declaration = valueDeclaration(resolvedSymbol(base.expression, checker));
28016
+ if (declaration && (import_typescript14.default.isClassDeclaration(declaration) || import_typescript14.default.isClassExpression(declaration)))
28017
+ return inheritedTrue(declaration, propertyName2, checker, seen);
28018
+ }
28019
+ return false;
28020
+ }
28021
+ function enumerateToolCatalog(result, ctx) {
28022
+ const output = emptyResult(), repo = enumerationRepository(ctx), agents = enumerateAgents(result, ctx);
28023
+ const agentByName = new Map(agents.runtimeAgents.map((entry) => [entry.name, entry.id]));
28024
+ const symbolOwners = new Map;
28025
+ for (const scope of agents.scopes) {
28026
+ const owners = agents.agentForScope(scope.key);
28027
+ const checker = ctx.checkerFor(scope.file.path);
28028
+ if (!owners.length || !checker)
28029
+ continue;
28030
+ visit(scope.node, (node) => {
28031
+ if (!import_typescript14.default.isIdentifier(node) || !/ALLOW|MCP_NAME/.test(node.text))
28032
+ return;
28033
+ const declaration = valueDeclaration(resolvedSymbol(node, checker));
28034
+ if (!declaration || !import_typescript14.default.isVariableDeclaration(declaration) || !import_typescript14.default.isIdentifier(declaration.name))
28035
+ return;
28036
+ const key = `${declaration.getSourceFile().fileName}:${declaration.name.text}`;
28037
+ let existing = symbolOwners.get(key);
28038
+ if (!existing)
28039
+ symbolOwners.set(key, existing = new Set);
28040
+ for (const id of owners)
28041
+ existing.add(id);
28042
+ });
28043
+ }
28044
+ const ownersAt = (node, path) => {
28045
+ 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];
28046
+ return scope ? agents.agentForScope(scope.key) : [];
28047
+ };
28048
+ const memo = createFrameworkMemo();
28049
+ const thinkIds = new Set;
28050
+ for (const runtime of agents.runtimeAgents) {
28051
+ const file = repo.files.find((entry) => entry.path === runtime.evidence[0]?.path), checker = file && ctx.checkerFor(file.path);
28052
+ if (!file || !checker)
28053
+ continue;
28054
+ visit(file.source, (node) => {
28055
+ if ((import_typescript14.default.isClassDeclaration(node) || import_typescript14.default.isClassExpression(node)) && node.name?.text === runtime.name && frameworkBaseOf(node, checker, memo)?.base === "Think")
28056
+ thinkIds.add(runtime.id);
28057
+ });
28058
+ }
28059
+ const add = (name, file, node, source, reason, owners = []) => {
28060
+ const evidenceFile = repo.files.find((entry2) => entry2.source.fileName === node.getSourceFile().fileName) ?? file;
28061
+ const entry = artifact("tool", name, evidenceFile, node, reason, repo.status(file.path));
28062
+ entry.catalogSource = source;
28063
+ entry.usedByAgentIds = owners;
28064
+ output.artifacts.push(entry);
28065
+ return entry;
28066
+ };
28067
+ for (const file of repo.files) {
28068
+ 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))
28069
+ continue;
28070
+ const checker = ctx.checkerFor(file.path), declarations = new Map;
28071
+ visit(file.source, (node) => {
28072
+ if (import_typescript14.default.isVariableDeclaration(node) && import_typescript14.default.isIdentifier(node.name) && node.initializer)
28073
+ declarations.set(node.name.text, node.initializer);
28074
+ });
28075
+ visit(file.source, (node) => {
28076
+ if ((import_typescript14.default.isClassDeclaration(node) || import_typescript14.default.isClassExpression(node)) && node.name && agentByName.has(node.name.text)) {
28077
+ const info = checker ? frameworkBaseOf(node, checker, memo) : undefined;
28078
+ const directThink = node.heritageClauses?.some((h) => h.types.some((t) => t.expression.getText() === "Think"));
28079
+ if (info?.base === "Think" || directThink) {
28080
+ const owners2 = agents.agentForScope(`${file.path}#${node.name.text}`);
28081
+ const names = [...THINK_WORKSPACE_TOOLS];
28082
+ if (inheritedTrue(node, "workspaceBash", checker))
28083
+ names.push("bash");
28084
+ for (const name of names)
28085
+ add(name, file, node, "think", "Think workspace tool inherited by this concrete agent", owners2);
28086
+ }
28087
+ }
28088
+ if (import_typescript14.default.isPropertyAccessExpression(node) && node.name.text === "activate_skill" || import_typescript14.default.isPropertyAssignment(node) && nameOf(node.name) === "activate_skill") {
28089
+ const owner = ownersAt(node, file.path);
28090
+ add("activate_skill", file, node, "think", "Source explicitly exposes Think skill activation", owner);
28091
+ }
28092
+ if (import_typescript14.default.isCallExpression(node) && import_typescript14.default.isPropertyAccessExpression(node.expression) && /^(?:registerTool|tool)$/.test(node.expression.name.text) && checker) {
28093
+ const receiver = valueDeclaration(resolvedSymbol(node.expression.expression, checker));
28094
+ const init = receiver && import_typescript14.default.isVariableDeclaration(receiver) && receiver.initializer ? unwrap(receiver.initializer) : undefined;
28095
+ const origin = init && import_typescript14.default.isNewExpression(init) && import_typescript14.default.isIdentifier(init.expression) ? importOrigin(init.expression, checker) : undefined;
28096
+ const name = node.arguments[0];
28097
+ if (origin?.module.startsWith("@modelcontextprotocol/sdk/") && origin.imported === "McpServer" && name && import_typescript14.default.isStringLiteralLike(name)) {
28098
+ add(name.text, file, name, "mcp_server", "MCP SDK server explicitly registers this model-facing tool name", ownersAt(node, file.path));
28099
+ }
28100
+ }
28101
+ if (import_typescript14.default.isCallExpression(node) && import_typescript14.default.isPropertyAccessExpression(node.expression) && node.expression.expression.getText() === "Output" && node.expression.name.text === "object") {
28102
+ const owners2 = ownersAt(node, file.path).filter((id) => thinkIds.has(id));
28103
+ if (owners2.length && checker && import_typescript14.default.isIdentifier(node.expression.expression) && ["ai", "@cloudflare/think"].includes(importOrigin(node.expression.expression, checker)?.module ?? ""))
28104
+ add("think_final_answer", file, node, "think", "Think structured output is offered as the framework final-answer tool", owners2);
28105
+ }
28106
+ if (import_typescript14.default.isCallExpression(node) && import_typescript14.default.isIdentifier(node.expression) && node.expression.text === "createExecuteRuntime") {
28107
+ const owners2 = ownersAt(node, file.path).filter((id) => thinkIds.has(id));
28108
+ if (owners2.length && checker && importOrigin(node.expression, checker)?.module.startsWith("@cloudflare/think"))
28109
+ add("execute", file, node, "think", "Think Code Mode runtime explicitly enabled for this agent", owners2);
28110
+ }
28111
+ if (!import_typescript14.default.isObjectLiteralExpression(node))
28112
+ return;
28113
+ const serverNames = strings(property(node, "name"), checker), allow = property(node, "allow");
28114
+ if (serverNames.length !== 1 || !allow || !property(node, "url"))
28115
+ return;
28116
+ const server = serverNames[0].name;
28117
+ const owners = ownersAt(node, file.path);
28118
+ if (import_typescript14.default.isStringLiteralLike(unwrap(allow)) && unwrap(allow).text === "all") {
28119
+ const entry = add(`${server} dynamic MCP tools`, file, allow, "mcp_dynamic_group", "Server schemas are admitted dynamically as one bounded catalog group", owners);
28120
+ entry.serverName = server;
28121
+ entry.dynamicGroup = true;
28122
+ entry.namePattern = `tool_<${server}ServerId>_*`;
28123
+ return;
28124
+ }
28125
+ for (const tool of strings(allow, checker)) {
28126
+ const name = `tool_<${server}ServerIdNoDashes>_${tool.name}`;
28127
+ const entry = add(name, file, tool.node, "mcp_allowlist", "Literal MCP allowlist converted by the Agents SDK tool_<serverId>_<name> contract", owners);
28128
+ entry.id = componentId("tool", file.path, `${server}:${name}`);
28129
+ entry.serverName = server;
28130
+ entry.namePattern = name;
28131
+ }
28132
+ });
28133
+ for (const [name, initializer] of declarations) {
28134
+ const match = name.match(/^(.*)_ALLOWED_TOOLS$/);
28135
+ if (!match)
28136
+ continue;
28137
+ const serverName = strings(declarations.get(`${match[1]}_MCP_NAME`), checker)[0]?.name;
28138
+ if (!serverName)
28139
+ continue;
28140
+ for (const tool of strings(initializer, checker)) {
28141
+ const entry = add(`${serverName}_${tool.name}`, file, tool.node, "mcp_allowlist", "Explicit named MCP allowlist with server-prefixed model name");
28142
+ entry.serverName = serverName;
28143
+ entry.usedByAgentIds = [...symbolOwners.get(`${file.source.fileName}:${name}`) ?? []].sort();
28144
+ }
28145
+ }
28146
+ }
28147
+ const merged = new Map;
28148
+ for (const item of output.artifacts) {
28149
+ const previous = merged.get(item.name);
28150
+ if (previous) {
28151
+ previous.usedByAgentIds = [...new Set([...previous.usedByAgentIds, ...item.usedByAgentIds])].sort();
28152
+ const seen = new Set(previous.evidence.map((e) => `${e.path}:${e.line}`));
28153
+ previous.evidence.push(...item.evidence.filter((e) => !seen.has(`${e.path}:${e.line}`)));
28154
+ if (item.status === "in_prod" || item.status === "reachable" && previous.status === "defined_only")
28155
+ previous.status = item.status;
28156
+ } else {
28157
+ item.id = `tool:catalog:${item.name}`;
28158
+ merged.set(item.name, item);
28159
+ }
28160
+ }
28161
+ output.artifacts = [...merged.values()];
28162
+ return stableResult(output);
28163
+ }
28164
+
28165
+ // src/harness-extract/enumerators/index.ts
28166
+ var ENUMERATORS = [
28167
+ { id: "agents", enumerate: ({ result }, ctx) => ({ runtimeAgents: enumerateAgents(result, ctx).runtimeAgents }) },
28168
+ { id: "workflows", enumerate: ({ result }, ctx) => enumerateWorkflows(result, ctx) },
28169
+ { id: "framework-mcp-catalog", enumerate: ({ result }, ctx) => enumerateToolCatalog(result, ctx) }
28170
+ ];
28171
+ function enumerateHarnessComponents(result, ctx) {
28172
+ const agents = enumerateAgents(result, ctx), workflows = enumerateWorkflows(result, ctx), catalog = enumerateToolCatalog(result, ctx);
28173
+ return stableResult({ runtimeAgents: agents.runtimeAgents, artifacts: [...workflows.artifacts, ...catalog.artifacts], warnings: [...workflows.warnings, ...catalog.warnings] });
28174
+ }
28175
+ function mergeEnumeratedComponents(artifacts, components) {
28176
+ const merged = new Map;
28177
+ const definitions = new Map;
28178
+ for (const item of [...artifacts, ...components.artifacts]) {
28179
+ const key = item.type === "tool" ? `tool:${item.name}` : item.id;
28180
+ if (item.type === "tool" && item.body) {
28181
+ let variants = definitions.get(key);
28182
+ if (!variants)
28183
+ definitions.set(key, variants = []);
28184
+ if (!variants.some((entry) => entry.id === item.id && entry.body === item.body))
28185
+ variants.push({ id: item.id, sourcePath: item.sourcePath, body: item.body, evidence: [...item.evidence], usedByAgentIds: [...item.usedByAgentIds] });
28186
+ }
28187
+ const previous = merged.get(key);
28188
+ if (!previous) {
28189
+ merged.set(key, { ...item, evidence: [...item.evidence], usedByAgentIds: [...item.usedByAgentIds] });
28190
+ continue;
28191
+ }
28192
+ const rank = { defined_only: 0, reachable: 1, in_prod: 2 };
28193
+ if (item.status && (!previous.status || rank[item.status] > rank[previous.status]))
28194
+ previous.status = item.status;
28195
+ previous.usedByAgentIds = [...new Set([...previous.usedByAgentIds, ...item.usedByAgentIds])].sort();
28196
+ const evidence = new Set(previous.evidence.map((entry) => `${entry.path}:${entry.line}`));
28197
+ previous.evidence.push(...item.evidence.filter((entry) => !evidence.has(`${entry.path}:${entry.line}`)));
28198
+ if (!previous.body && item.body && !previous.definitionVariants)
28199
+ previous.body = item.body;
28200
+ }
28201
+ for (const [key, variants] of definitions) {
28202
+ const item = merged.get(key);
28203
+ if (variants.length > 1 || item.id !== variants[0].id)
28204
+ item.definitionVariants = variants;
28205
+ if (new Set(variants.map((entry) => entry.body)).size > 1)
28206
+ delete item.body;
28207
+ }
28208
+ const output = [...merged.values()].sort((a, b) => a.id.localeCompare(b.id));
28209
+ const runtimeAgents = components.runtimeAgents.map((entry) => ({
28210
+ ...entry,
28211
+ artifactIds: [...new Set([...entry.artifactIds, ...output.filter((item) => item.usedByAgentIds.includes(entry.id)).map((item) => item.id)])].sort()
28212
+ }));
28213
+ return { runtimeAgents, artifacts: output };
28214
+ }
28215
+
28216
+ export { startRemoteAnalyze, pollRemoteAnalyzeUntilDone, isRecoverableRemoteRun, checkPromptMapping, safePromptEvidencePath, discoverHarnessPromptSources, valueChildren, selectKey, allValues, renderings, CALL_SINKS, registerCallSink, registerClassSink, isModelId, collectModels, modelArtifacts, modelUnknowns, collectModelLiterals, EXTRACT_SCHEMA_VERSION, agentForScope, createAgentScopeResolver, enumerateAgents, enumerateWorkflows, enumerateToolCatalog, ENUMERATORS, enumerateHarnessComponents, mergeEnumeratedComponents, 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 };