@moda-ai/cli 1.55.78 → 1.55.80

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.
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  buildDoctorReport
3
- } from "./cli-rp1079xm.js";
3
+ } from "./cli-73zjnpb6.js";
4
4
  import"./cli-rrggdmf8.js";
5
- import"./cli-8y7tzqkf.js";
5
+ import"./cli-v5yk8rj2.js";
6
6
  import"./cli-mm48br00.js";
7
7
  import {
8
8
  readHarnessSyncState
@@ -95,7 +95,7 @@ async function buildAgentContext(context) {
95
95
  const graph = readHarnessGraphIfPresent(context.cwd);
96
96
  const reportState = readHarnessReportState(context.cwd);
97
97
  const syncState = readHarnessSyncState(context.cwd);
98
- const harness = graph ? await import("./harness-nryjq52p.js") : undefined;
98
+ const harness = graph ? await import("./harness-kr9jtz2a.js") : undefined;
99
99
  const topFindings = doctor.checks.filter((check) => check.status === "fail" || check.status === "warning").slice(0, 12).map(checkToFinding);
100
100
  const evidenceRefs = [
101
101
  ...doctor.checks.map(checkToEvidenceRef),
@@ -4,7 +4,7 @@ import {
4
4
  } from "./cli-rrggdmf8.js";
5
5
  import {
6
6
  inspectPromptManifest
7
- } from "./cli-8y7tzqkf.js";
7
+ } from "./cli-v5yk8rj2.js";
8
8
  import {
9
9
  readHarnessSyncState,
10
10
  renderDoctorHuman,
@@ -395,7 +395,7 @@ async function harnessCurrentCheck(cwd, manifestPath, manifestExists, tenantId)
395
395
  };
396
396
  }
397
397
  try {
398
- const { scanHarness } = await import("./harness-nryjq52p.js");
398
+ const { scanHarness } = await import("./harness-kr9jtz2a.js");
399
399
  const current = scanHarness({
400
400
  rootDir: cwd,
401
401
  scannerVersion: "doctor",
@@ -15932,9 +15932,50 @@ function detectDependencies(input) {
15932
15932
  import { createHash as createHash4 } from "node:crypto";
15933
15933
  import { readFileSync as readFileSync6 } from "node:fs";
15934
15934
  import { join as join7 } from "node:path";
15935
+
15936
+ // ../../packages/harness-bundle/src/detect/links.ts
15937
+ function resolveBundleLink(link, links, opts = {}) {
15938
+ const via = [];
15939
+ let hops = 0;
15940
+ const walk = (base, target2, top) => {
15941
+ if (target2.startsWith("/"))
15942
+ return;
15943
+ const out = [...base];
15944
+ const segments = target2.split("/").filter((segment) => segment !== "" && segment !== ".");
15945
+ for (let i = 0;i < segments.length; i++) {
15946
+ const segment = segments[i];
15947
+ if (segment === "..") {
15948
+ if (out.length === 0)
15949
+ return;
15950
+ out.pop();
15951
+ continue;
15952
+ }
15953
+ out.push(segment);
15954
+ const path = out.join("/");
15955
+ const next = links.get(path);
15956
+ if (next === undefined || top && opts.followLast === false && i === segments.length - 1)
15957
+ continue;
15958
+ if (++hops > 40)
15959
+ return;
15960
+ via.push(path);
15961
+ const resolved2 = walk(out.slice(0, -1), next, false);
15962
+ if (!resolved2)
15963
+ return;
15964
+ out.splice(0, out.length, ...resolved2);
15965
+ }
15966
+ return out;
15967
+ };
15968
+ const target = links.get(link);
15969
+ if (target === undefined)
15970
+ return;
15971
+ const resolved = walk(link.split("/").slice(0, -1), target, true);
15972
+ return resolved ? { path: resolved.length > 0 ? resolved.join("/") : ".", via } : undefined;
15973
+ }
15974
+
15975
+ // ../../packages/harness-bundle/src/register/harness-digest.ts
15935
15976
  var WORKSPACE_INPUT = /^(?:package\.json|bun\.lockb?|package-lock\.json|npm-shrinkwrap\.json|pnpm-lock\.yaml|pnpm-workspace\.yaml|yarn\.lock|\.yarnrc\.yml|turbo\.json|nx\.json|lerna\.json|tsconfig[\w.-]*\.json|pyproject\.toml|uv\.lock|poetry\.lock|Pipfile(?:\.lock)?|requirements[\w.-]*\.txt|go\.(?:mod|sum|work)|Cargo\.(?:toml|lock)|Gemfile(?:\.lock)?|\.nvmrc|\.node-version|\.python-version|\.tool-versions|(?:tsup|vite|rollup|esbuild|webpack|babel|swc)\.config\.[\w.]+)$/;
15936
15977
  var RUNTIME_CATEGORIES = new Set(["prompt", "schema", "migration", "seed_data", "api_spec"]);
15937
- var INERT = new Set(["doc", "test", "ci"]);
15978
+ var INERT = new Set(["test", "ci"]);
15938
15979
  var INERT_DIR = /(^|\/)(\.github|\.gitlab|\.circleci|\.buildkite|\.devcontainer|\.vscode|\.idea|\.cursor|\.claude|\.codex|\.windsurf|\.agents|\.husky|\.changeset|evals?|evaluations?|benchmarks?|\.?screenshots?|[\w.-]+-out)(\/|$)/;
15939
15980
  function harnessFiles(manifest, map, read) {
15940
15981
  const paths = new Set(manifest.files.map((f) => f.path));
@@ -15991,6 +16032,7 @@ function harnessDigest(manifest, map, filesDir) {
15991
16032
  }
15992
16033
  };
15993
16034
  const byPath = new Map(manifest.files.map((f) => [f.path, f]));
16035
+ const links = new Map(manifest.files.flatMap((f) => f.symlinkTarget !== undefined ? [[f.path, f.symlinkTarget]] : []));
15994
16036
  const hash = createHash4("sha256");
15995
16037
  hash.update(JSON.stringify({
15996
16038
  v: 1,
@@ -16002,12 +16044,37 @@ function harnessDigest(manifest, map, filesDir) {
16002
16044
  }));
16003
16045
  for (const path of harnessFiles(manifest, map, read)) {
16004
16046
  const f = byPath.get(path);
16005
- if (f)
16006
- hash.update(`
16047
+ if (!f)
16048
+ continue;
16049
+ hash.update(`
16007
16050
  ${f.path}\x00${f.sha256}\x00${f.executable ? 1 : 0}\x00${f.symlinkTarget ?? ""}`);
16051
+ for (const t of f.symlinkTarget !== undefined ? linkTargets(f, byPath, links) : [])
16052
+ hash.update(`\x00->${t.path}\x00${t.sha256}\x00${t.executable ? 1 : 0}`);
16008
16053
  }
16009
16054
  return `sha256:${hash.digest("hex")}`;
16010
16055
  }
16056
+ function linkTargets(link, byPath, links) {
16057
+ const out = new Map;
16058
+ const seen = new Set;
16059
+ const visit = (from) => {
16060
+ if (seen.has(from))
16061
+ return;
16062
+ seen.add(from);
16063
+ const target = resolveBundleLink(from, links)?.path;
16064
+ if (target === undefined)
16065
+ return;
16066
+ const exact = byPath.get(target);
16067
+ const hits = exact ? [exact] : [...byPath.values()].filter((f) => target === "." || f.path.startsWith(`${target}/`));
16068
+ for (const f of hits) {
16069
+ if (f.symlinkTarget !== undefined)
16070
+ visit(f.path);
16071
+ else
16072
+ out.set(f.path, f);
16073
+ }
16074
+ };
16075
+ visit(link.path);
16076
+ return [...out.values()].sort((a, b) => a.path < b.path ? -1 : 1);
16077
+ }
16011
16078
  function wranglerAssetDirs(configPath, text) {
16012
16079
  const dir = dirname5(configPath);
16013
16080
  const raw = [];
@@ -16120,7 +16187,8 @@ function registrationBody(collected, options) {
16120
16187
  manifestBytes: collected.manifestFile.bytes,
16121
16188
  ...collected.dependencyMapFile ? { dependencyMapSha256: collected.dependencyMapFile.sha256, dependencyMapBytes: collected.dependencyMapFile.bytes } : {},
16122
16189
  ...gitFields(collected.manifest),
16123
- ...options.imageRef ? { imageRef: options.imageRef } : {}
16190
+ ...options.imageRef ? { imageRef: options.imageRef } : {},
16191
+ ...collected.manifest.harnessDigest ? { harnessDigest: collected.manifest.harnessDigest } : {}
16124
16192
  };
16125
16193
  }
16126
16194
  async function uploadRegistration(collected, options, client) {
@@ -16236,10 +16304,13 @@ async function registerCollected(context, options, collected) {
16236
16304
  }, profileOptions)),
16237
16305
  complete: async (id) => await callControlAPI(`/harness-registrations/${encodeURIComponent(id)}/complete`, { method: "POST" }, profileOptions, { timeoutMs: 300000 })
16238
16306
  };
16239
- const { registration: completed } = await uploadRegistration(collected, options, client);
16307
+ const uploaded = await uploadRegistration(collected, options, client);
16308
+ const { deduplicated } = uploaded;
16309
+ const completed = deduplicated ? await callControlAPI(`/harness-registrations/${encodeURIComponent(uploaded.registration.id)}`, {}, profileOptions).catch(() => ({ ...uploaded.registration, checklistIncomplete: true })) : uploaded.registration;
16240
16310
  await withFullChecklist(completed, profileOptions);
16241
16311
  const dashboardUrl = `${resolveModaBaseUrl(profileOptions)}${completed.dashboardPath}`;
16242
- emit(context, { ...report, dryRun: false, registration: { ...completed, dashboardUrl } }, renderRegisterReport(report, { ...completed, dashboardUrl }), completed.status === "failed" ? "error" : undefined);
16312
+ const shown = { ...completed, dashboardUrl, ...deduplicated ? { unchanged: true } : {} };
16313
+ emit(context, { ...report, dryRun: false, registration: shown }, renderRegisterReport(report, shown), completed.status === "failed" ? "error" : undefined);
16243
16314
  return { exitCode: completed.status === "failed" ? 1 : 0 };
16244
16315
  }
16245
16316
  async function runHarnessRegistration(context) {
@@ -16540,6 +16611,8 @@ function renderRegistrationStatus(registration) {
16540
16611
  ` Harness ${registration.harnessName} (${registration.mode} mode)`,
16541
16612
  ` Status ${registration.status}`
16542
16613
  ];
16614
+ if (registration.unchanged)
16615
+ lines.push(" Unchanged nothing the harness depends on changed since this registration, so no new one was created");
16543
16616
  if (registration.failureReason)
16544
16617
  lines.push(` Reason ${registration.failureReason}`);
16545
16618
  if (registration.git?.commit)
@@ -19149,7 +19222,7 @@ async function runHarnessCommand(context) {
19149
19222
  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.");
19150
19223
  }
19151
19224
  if (context.flags["github-actions"] === "true") {
19152
- const { runGithubActionsAnalyze } = await import("./harness-github-actions-pdm6ee74.js");
19225
+ const { runGithubActionsAnalyze } = await import("./harness-github-actions-96tgqbwb.js");
19153
19226
  const result = await runGithubActionsAnalyze(rootDir, {
19154
19227
  writeReport: (report2) => {
19155
19228
  const normalized = normalizeHarnessReport(report2);
@@ -19295,8 +19368,8 @@ async function runHarnessCommand(context) {
19295
19368
  }
19296
19369
  const { artifacts, unknowns } = deterministicGraphItems(rootDir, promote === "all" ? undefined : promote);
19297
19370
  tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
19298
- const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-xqa9km2a.js");
19299
- const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-ms5t7pph.js");
19371
+ const { extractHarnessWithContext: extractHarnessWithContext2 } = await import("./index-tze518d6.js");
19372
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-psa47r72.js");
19300
19373
  let components = { runtimeAgents: [], artifacts: [], warnings: [] };
19301
19374
  if (promote === "all" || promote === "topology" || promote === "tools") {
19302
19375
  const { result, ctx } = extractHarnessWithContext2(rootDir);
@@ -19330,8 +19403,8 @@ async function runHarnessCommand(context) {
19330
19403
  }
19331
19404
  case "extract": {
19332
19405
  writeHumanProgress(context, "Harness extract: tracing model call sites (no LLM, no network)...");
19333
- const { extractHarnessWithContext: extractHarnessWithContext2, serializeExtractResult } = await import("./index-xqa9km2a.js");
19334
- const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-ms5t7pph.js");
19406
+ const { extractHarnessWithContext: extractHarnessWithContext2, serializeExtractResult } = await import("./index-tze518d6.js");
19407
+ const { enumerateHarnessComponents, mergeEnumeratedComponents } = await import("./index-psa47r72.js");
19335
19408
  const { result, ctx } = extractHarnessWithContext2(rootDir, { fresh: true });
19336
19409
  const artifacts = deterministicArtifacts(rootDir);
19337
19410
  tagComponentStatus({ runtimeAgents: [], artifacts }, rootDir);
@@ -25873,6 +25946,8 @@ function promoteAll(report, rootDir) {
25873
25946
  let artifact;
25874
25947
  switch (candidate.kind) {
25875
25948
  case "tool_definition":
25949
+ if (FIXTURE_DIR2.test(candidate.path) || isTestInput(candidate.path))
25950
+ break;
25876
25951
  artifact = promoteToolCandidate(candidate, rootDir, confidence2, fileCache);
25877
25952
  break;
25878
25953
  case "prompt_file":
@@ -27534,7 +27609,7 @@ function toolNamesOf(tree) {
27534
27609
  visit2(child, false, spread);
27535
27610
  spread.forEach(set);
27536
27611
  } else if (child.key) {
27537
- set({ name: child.key, path: child.path, line: child.line, via: "key" });
27612
+ set({ name: child.key, path: child.path, line: child.line, start: child.start, via: "key" });
27538
27613
  }
27539
27614
  }
27540
27615
  names.push(...record.values());
@@ -27592,6 +27667,7 @@ function emitTools(result, ctx, options = {}) {
27592
27667
  const packageOf = workspacePackages(ctx.rootDir);
27593
27668
  const found = new Map;
27594
27669
  const ownersByTool = new Map;
27670
+ const recordSpans = new Map;
27595
27671
  let definitionBytes = 0;
27596
27672
  const limit = () => {
27597
27673
  const warning = "tools: bounded tool catalog budget reached; some evidence or bodies omitted";
@@ -27617,9 +27693,14 @@ function emitTools(result, ctx, options = {}) {
27617
27693
  found.set(key, tool);
27618
27694
  ownersByTool.set(key, { direct: [], rpc: [], open: [] });
27619
27695
  }
27696
+ if (evidence.start !== undefined && evidence.end !== undefined && /^(?:tools record key|tool stored under this key)$/.test(evidence.reason)) {
27697
+ const spans = recordSpans.get(tool) ?? [];
27698
+ spans.push({ path: evidence.path, start: evidence.start, end: evidence.end });
27699
+ recordSpans.set(tool, spans);
27700
+ }
27620
27701
  if (enumerationRepository(ctx).status(evidence.path) !== "defined_only")
27621
27702
  tool.status = "reachable";
27622
- if (tool.evidence.length < MAX_EVIDENCE_PER_TOOL && !tool.evidence.some((other) => other.path === evidence.path && other.line === evidence.line)) {
27703
+ if (tool.evidence.length < MAX_EVIDENCE_PER_TOOL && !tool.evidence.some((other) => other.path === evidence.path && other.line === evidence.line && other.start === evidence.start && other.end === evidence.end)) {
27623
27704
  tool.evidence.push(evidence);
27624
27705
  tool.calledFrom.push({ path: evidence.path, line: evidence.line, ...enclosing ? { enclosing } : {} });
27625
27706
  }
@@ -27658,7 +27739,7 @@ function emitTools(result, ctx, options = {}) {
27658
27739
  const checker = program.getTypeChecker();
27659
27740
  const tracer = tracerFor(program);
27660
27741
  const names = (expression) => literalStrings(expression, tracer).slice(0, MAX_NAMES_PER_SITE);
27661
- const at = (node, reason) => ({ path: rel2, line: lineOf(node), reason });
27742
+ const at = (node, reason) => ({ path: rel2, line: lineOf(node), reason, start: node.getStart(), end: node.getEnd() });
27662
27743
  const visitObject = (object) => {
27663
27744
  const keys = object.properties.map((property) => propertyNameText(property.name) ?? "");
27664
27745
  const nameExpr = propertyValue(object, "name");
@@ -27688,9 +27769,10 @@ function emitTools(result, ctx, options = {}) {
27688
27769
  continue;
27689
27770
  const agents = owners.ownersOf(property, program);
27690
27771
  const options2 = toolOptions(property.initializer);
27691
- const definition = definitionNode(property.initializer, checker);
27772
+ const definitions = definitionNodes(property.initializer, checker);
27692
27773
  for (const name of list)
27693
- add(name, "record", at(property, "tools record key"), agents, definition, options2 ? displayNameOf(options2, tracer) : undefined, enclosingName(property));
27774
+ for (const definition of definitions)
27775
+ add(name, "record", at(property, "tools record key"), agents, definition, options2 ? displayNameOf(options2, tracer) : undefined, enclosingName(property));
27694
27776
  }
27695
27777
  };
27696
27778
  const visit2 = (node) => {
@@ -27702,9 +27784,10 @@ function emitTools(result, ctx, options = {}) {
27702
27784
  if (list.length > 0) {
27703
27785
  const agents = owners.ownersOf(node, program);
27704
27786
  const options2 = toolOptions(node.right);
27705
- const definition = definitionNode(node.right, checker);
27787
+ const definitions = definitionNodes(node.right, checker);
27706
27788
  for (const name of list)
27707
- add(name, "record", at(node, "tool stored under this key"), agents, definition, options2 ? displayNameOf(options2, tracer) : undefined, enclosingName(node));
27789
+ for (const definition of definitions)
27790
+ add(name, "record", at(node, "tool stored under this key"), agents, definition, options2 ? displayNameOf(options2, tracer) : undefined, enclosingName(node));
27708
27791
  }
27709
27792
  }
27710
27793
  } catch {}
@@ -27723,6 +27806,15 @@ function emitTools(result, ctx, options = {}) {
27723
27806
  const local = candidates.filter((tool) => (tool.package ?? "") === packageOf(path));
27724
27807
  return local.length === 1 ? local[0] : candidates.length === 1 ? candidates[0] : undefined;
27725
27808
  };
27809
+ const targetsForHit = (name, path, start) => {
27810
+ const offered = [...found.values()].filter((tool) => tool.name === name && tool.surface).flatMap((tool) => (recordSpans.get(tool) ?? []).filter((entry) => entry.path === path && start !== undefined && entry.start !== undefined && entry.end !== undefined && entry.start <= start && start < entry.end).map((entry) => ({ tool, width: entry.end - entry.start })));
27811
+ if (offered.length > 0) {
27812
+ const nearest = Math.min(...offered.map((entry) => entry.width));
27813
+ return [...new Set(offered.filter((entry) => entry.width === nearest).map((entry) => entry.tool))];
27814
+ }
27815
+ const target = targetFor(name, path);
27816
+ return target ? [target] : [];
27817
+ };
27726
27818
  for (const role of result.roles) {
27727
27819
  if (role.role !== "tools" || role.sink.isTest || skipPath(role.sink.path))
27728
27820
  continue;
@@ -27731,9 +27823,11 @@ function emitTools(result, ctx, options = {}) {
27731
27823
  for (const hit of toolNamesOf(role.tree).names) {
27732
27824
  if (skipPath(hit.path))
27733
27825
  continue;
27734
- const target = targetFor(hit.name, hit.path);
27735
- const ambiguous = !target && [...found.values()].some((tool) => tool.name === hit.name && tool.surface);
27736
- 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}` }, ambiguous ? { direct: [], rpc: [], open: [] } : siteOwners, undefined, undefined, role.sink.enclosing, target?.surface);
27826
+ const targets = targetsForHit(hit.name, hit.path, hit.start);
27827
+ const ambiguous = targets.length === 0 && [...found.values()].some((tool) => tool.name === hit.name && tool.surface);
27828
+ for (const target of targets.length > 0 ? targets : [undefined]) {
27829
+ 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}` }, ambiguous ? { direct: [], rpc: [], open: [] } : siteOwners, undefined, undefined, role.sink.enclosing, target?.surface);
27830
+ }
27737
27831
  }
27738
27832
  }
27739
27833
  joinSurfaces(found, ownersByTool);
@@ -27750,7 +27844,10 @@ function emitTools(result, ctx, options = {}) {
27750
27844
  let owners2 = callOwners.get(hit.name);
27751
27845
  if (!owners2)
27752
27846
  callOwners.set(hit.name, owners2 = []);
27753
- owners2.push({ pkg: packageOf(hit.path), surface: surfaceOf(hit.path, packageOf(hit.path)), ids });
27847
+ const targets = targetsForHit(hit.name, hit.path, hit.start);
27848
+ for (const surface of targets.length > 0 ? targets.map((tool) => tool.surface) : [surfaceOf(hit.path, packageOf(hit.path))]) {
27849
+ owners2.push({ pkg: packageOf(hit.path), surface, ids });
27850
+ }
27754
27851
  }
27755
27852
  }
27756
27853
  for (const [key, tool] of found) {
@@ -27924,8 +28021,48 @@ function isSchemaProperty(object) {
27924
28021
  const holder = parent.parent;
27925
28022
  return import_typescript12.default.isObjectLiteralExpression(holder) && import_typescript12.default.isPropertyAssignment(holder.parent) && propertyNameText(holder.parent.name) === "properties";
27926
28023
  }
28024
+ function executeToolFactories(expression, checker) {
28025
+ const value = unwrap(expression);
28026
+ if (!import_typescript12.default.isPropertyAccessExpression(value) || value.name.text !== "tool")
28027
+ return [];
28028
+ const find = (node, seen, depth) => {
28029
+ const current = unwrap(node);
28030
+ if (depth > 6 || seen.has(current))
28031
+ return [];
28032
+ seen.add(current);
28033
+ if (import_typescript12.default.isIdentifier(current)) {
28034
+ const declaration = valueDeclaration(resolvedSymbol(current, checker));
28035
+ if (declaration && import_typescript12.default.isVariableDeclaration(declaration) && declaration.initializer && declaration.parent.flags & import_typescript12.default.NodeFlags.Const) {
28036
+ return find(declaration.initializer, seen, depth + 1);
28037
+ }
28038
+ }
28039
+ if (import_typescript12.default.isConditionalExpression(current))
28040
+ return [...find(current.whenTrue, new Set(seen), depth + 1), ...find(current.whenFalse, new Set(seen), depth + 1)];
28041
+ if (import_typescript12.default.isCallExpression(current) && import_typescript12.default.isIdentifier(current.expression)) {
28042
+ const origin = importOrigin(current.expression, checker);
28043
+ if (origin?.imported === "createExecuteRuntime" && origin.module === "@cloudflare/think/tools/execute")
28044
+ return [current];
28045
+ }
28046
+ return [];
28047
+ };
28048
+ return [...new Set(find(value.expression, new Set, 0))];
28049
+ }
28050
+ function definitionNodes(expression, checker, depth = 0) {
28051
+ const value = unwrap(expression);
28052
+ const factories = executeToolFactories(value, checker);
28053
+ if (factories.length > 0)
28054
+ return factories;
28055
+ if (import_typescript12.default.isIdentifier(value) && depth < 2) {
28056
+ const declaration = valueDeclaration(resolvedSymbol(value, checker));
28057
+ if (declaration && import_typescript12.default.isVariableDeclaration(declaration) && declaration.initializer)
28058
+ return definitionNodes(declaration.initializer, checker, depth + 1);
28059
+ }
28060
+ return [definitionNode(value, checker)];
28061
+ }
27927
28062
  function isToolValue(expression, checker, depth = 0) {
27928
28063
  const value = unwrap(expression);
28064
+ if (executeToolFactories(value, checker).length > 0)
28065
+ return true;
27929
28066
  if (import_typescript12.default.isCallExpression(value)) {
27930
28067
  const callee = unwrap(value.expression);
27931
28068
  const name = import_typescript12.default.isIdentifier(callee) ? callee : import_typescript12.default.isPropertyAccessExpression(callee) ? callee.name : undefined;
@@ -29212,6 +29349,50 @@ function inheritedTrue(node, propertyName2, checker, seen = new Set) {
29212
29349
  }
29213
29350
  return false;
29214
29351
  }
29352
+ function hasSkillSources(node, checker, seen = new Set) {
29353
+ if (seen.has(node))
29354
+ return false;
29355
+ seen.add(node);
29356
+ const member2 = node.members.find((member3) => nameOf(member3.name) === "getSkills" && !(import_typescript16.default.getCombinedModifierFlags(member3) & import_typescript16.default.ModifierFlags.Static));
29357
+ if (member2) {
29358
+ const hook = import_typescript16.default.isMethodDeclaration(member2) ? member2 : import_typescript16.default.isPropertyDeclaration(member2) && member2.initializer && (import_typescript16.default.isArrowFunction(unwrap(member2.initializer)) || import_typescript16.default.isFunctionExpression(unwrap(member2.initializer))) ? unwrap(member2.initializer) : undefined;
29359
+ if (!hook?.body)
29360
+ return false;
29361
+ const enabled = (expression, visited = new Set, depth = 0) => {
29362
+ const value = unwrap(expression);
29363
+ if (visited.has(value) || depth > 8)
29364
+ return false;
29365
+ visited.add(value);
29366
+ if (import_typescript16.default.isConditionalExpression(value))
29367
+ return enabled(value.whenTrue, new Set(visited), depth + 1) || enabled(value.whenFalse, new Set(visited), depth + 1);
29368
+ if (checker && (import_typescript16.default.isIdentifier(value) || import_typescript16.default.isPropertyAccessExpression(value))) {
29369
+ const declaration = valueDeclaration(resolvedSymbol(import_typescript16.default.isPropertyAccessExpression(value) ? value.name : value, checker));
29370
+ if (declaration && import_typescript16.default.isVariableDeclaration(declaration) && declaration.initializer && declaration.parent.flags & import_typescript16.default.NodeFlags.Const) {
29371
+ let populated = false;
29372
+ const symbol = resolvedSymbol(declaration.name, checker);
29373
+ const scan = (node2) => {
29374
+ if (import_typescript16.default.isCallExpression(node2) && import_typescript16.default.isPropertyAccessExpression(node2.expression) && ["push", "unshift", "splice"].includes(node2.expression.name.text) && resolvedSymbol(node2.expression.expression, checker) === symbol && node2.arguments.length > (node2.expression.name.text === "splice" ? 2 : 0))
29375
+ populated = true;
29376
+ if (import_typescript16.default.isBinaryExpression(node2) && node2.operatorToken.kind === import_typescript16.default.SyntaxKind.EqualsToken && import_typescript16.default.isElementAccessExpression(node2.left) && resolvedSymbol(node2.left.expression, checker) === symbol)
29377
+ populated = true;
29378
+ import_typescript16.default.forEachChild(node2, scan);
29379
+ };
29380
+ scan(declaration.getSourceFile());
29381
+ return populated || enabled(declaration.initializer, visited, depth + 1);
29382
+ }
29383
+ }
29384
+ return value.kind !== import_typescript16.default.SyntaxKind.NullKeyword && value.getText() !== "undefined" && (!import_typescript16.default.isArrayLiteralExpression(value) || value.elements.length > 0);
29385
+ };
29386
+ return returnExpressions(hook).some((expression) => enabled(expression));
29387
+ }
29388
+ if (checker)
29389
+ for (const base of node.heritageClauses?.flatMap((h) => h.types) ?? []) {
29390
+ const declaration = valueDeclaration(resolvedSymbol(base.expression, checker));
29391
+ if (declaration && (import_typescript16.default.isClassDeclaration(declaration) || import_typescript16.default.isClassExpression(declaration)) && hasSkillSources(declaration, checker, seen))
29392
+ return true;
29393
+ }
29394
+ return false;
29395
+ }
29215
29396
  function enumerateToolCatalog(result, ctx) {
29216
29397
  const output = emptyResult(), repo = enumerationRepository(ctx), agents = enumerateAgents(result, ctx);
29217
29398
  const agentByName = new Map(agents.runtimeAgents.map((entry) => [entry.name, entry.id]));
@@ -29275,6 +29456,8 @@ function enumerateToolCatalog(result, ctx) {
29275
29456
  const names = [...THINK_WORKSPACE_TOOLS];
29276
29457
  if (inheritedTrue(node, "workspaceBash", checker))
29277
29458
  names.push("bash");
29459
+ if (hasSkillSources(node, checker))
29460
+ names.push("read_skill_resource");
29278
29461
  for (const name of names)
29279
29462
  add(name, file, node, "think", "Think workspace tool inherited by this concrete agent", owners2);
29280
29463
  }
@@ -5768,7 +5768,7 @@ async function runPromptSyncExclusive(flags, profileOptions, options) {
5768
5768
  const analyzedDefinitions = new Map;
5769
5769
  if (flags["no-analyze"] !== "true") {
5770
5770
  options.onProgress?.("Analyzing prompt sources before sync.");
5771
- const { analyzeHarnessPrompts } = await import("./harness-nryjq52p.js");
5771
+ const { analyzeHarnessPrompts } = await import("./harness-kr9jtz2a.js");
5772
5772
  const result = await analyzeHarnessPrompts({
5773
5773
  rootDir: process.cwd(),
5774
5774
  existing: established.flatMap((prompt) => prompt.sourceDefinition ? [prompt.sourceDefinition.source] : []),
@@ -5796,7 +5796,7 @@ async function runPromptSyncExclusive(flags, profileOptions, options) {
5796
5796
  const mergedSources = mergePromptSources(manifest.sources, extraSources);
5797
5797
  const manifestUpdate = stableJson(mergedSources) === stableJson(mergePromptSources(manifest.sources, [])) ? undefined : $stringify({ version: 2, prompt_paths: manifest.promptPaths, sources: mergedSources });
5798
5798
  const prompts = await discoverPrompts(extraSources);
5799
- const { checkPromptAttribution } = await import("./prompt-attribution-2srq4cp7.js");
5799
+ const { checkPromptAttribution } = await import("./prompt-attribution-v8wjbtab.js");
5800
5800
  const attribution = checkPromptAttribution(process.cwd(), prompts.map((prompt) => prompt.key));
5801
5801
  const brokenAttribution = attribution.references.filter((reference) => reference.status === "missing");
5802
5802
  if (brokenAttribution.length) {
@@ -6102,7 +6102,7 @@ async function migratePromptManifest(options = {}) {
6102
6102
  let addedSources = [];
6103
6103
  let pendingSources = [];
6104
6104
  if (options.discover) {
6105
- const { analyzeHarnessPrompts } = await import("./harness-nryjq52p.js");
6105
+ const { analyzeHarnessPrompts } = await import("./harness-kr9jtz2a.js");
6106
6106
  const result = await analyzeHarnessPrompts({
6107
6107
  rootDir: root,
6108
6108
  existing: manifest.sources,
package/dist/cli.js CHANGED
@@ -2975,25 +2975,25 @@ function leafManifestFields(leaf, commands) {
2975
2975
  import { fileURLToPath } from "url";
2976
2976
  import { realpathSync } from "fs";
2977
2977
  async function runPromptsCommand(...args) {
2978
- return (await import("./prompts-tr91zg4n.js")).runPromptsCommand(...args);
2978
+ return (await import("./prompts-gr6vakz1.js")).runPromptsCommand(...args);
2979
2979
  }
2980
2980
  async function runSkillsCommand(...args) {
2981
2981
  return (await import("./skills-knpeqryb.js")).runSkillsCommand(...args);
2982
2982
  }
2983
2983
  async function runHarnessCommand(...args) {
2984
- return (await import("./harness-nryjq52p.js")).runHarnessCommand(...args);
2984
+ return (await import("./harness-kr9jtz2a.js")).runHarnessCommand(...args);
2985
2985
  }
2986
2986
  async function runSyncCommand(...args) {
2987
- return (await import("./sync-nfdd69cw.js")).runSyncCommand(...args);
2987
+ return (await import("./sync-cjeykd9k.js")).runSyncCommand(...args);
2988
2988
  }
2989
2989
  async function runRegistryCommand(...args) {
2990
2990
  return (await import("./registry-c64qr7ta.js")).runRegistryCommand(...args);
2991
2991
  }
2992
2992
  async function runDoctorCommand(...args) {
2993
- return (await import("./doctor-swctmdap.js")).runDoctorCommand(...args);
2993
+ return (await import("./doctor-kcvjttm0.js")).runDoctorCommand(...args);
2994
2994
  }
2995
2995
  async function runStatusCommand(...args) {
2996
- return (await import("./doctor-swctmdap.js")).runStatusCommand(...args);
2996
+ return (await import("./doctor-kcvjttm0.js")).runStatusCommand(...args);
2997
2997
  }
2998
2998
  async function runAuthCommand(...args) {
2999
2999
  return (await import("./profile-commands-1fdvrs5y.js")).runAuthCommand(...args);
@@ -3005,7 +3005,7 @@ async function runProfilesCommand(...args) {
3005
3005
  return (await import("./profile-commands-1fdvrs5y.js")).runProfilesCommand(...args);
3006
3006
  }
3007
3007
  async function runAgentCommand(...args) {
3008
- return (await import("./agent-9bb3wryr.js")).runAgentCommand(...args);
3008
+ return (await import("./agent-krfcc60c.js")).runAgentCommand(...args);
3009
3009
  }
3010
3010
  async function runProductionCommand(...args) {
3011
3011
  return (await import("./production-intelligence-f9sd68te.js")).runProductionCommand(...args);
@@ -6769,7 +6769,7 @@ var commandRegistry = createCommandRegistry([
6769
6769
  resetApiRequestCountBeforeRun: true,
6770
6770
  telemetry: "result-and-error",
6771
6771
  handler: async (context) => {
6772
- const { runInit } = await import("./index-y5ay9p49.js");
6772
+ const { runInit } = await import("./index-knkk2x7v.js");
6773
6773
  if (context.outputMode === "agent-stream") {
6774
6774
  context.output.writeEvent({
6775
6775
  event: "started",
@@ -3,9 +3,9 @@ import {
3
3
  promptsDiscoveredCheck,
4
4
  runDoctorCommand,
5
5
  runStatusCommand
6
- } from "./cli-rp1079xm.js";
6
+ } from "./cli-73zjnpb6.js";
7
7
  import"./cli-rrggdmf8.js";
8
- import"./cli-8y7tzqkf.js";
8
+ import"./cli-v5yk8rj2.js";
9
9
  import"./cli-mm48br00.js";
10
10
  import"./cli-k0vxtzxb.js";
11
11
  import"./cli-22yvg5kh.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildSourceSnapshot
3
- } from "./cli-pqnd8are.js";
3
+ } from "./cli-kq1b4vy0.js";
4
4
  import"./cli-k0vxtzxb.js";
5
5
  import"./cli-97fnztpy.js";
6
6
  import"./cli-y333w08f.js";
@@ -47,7 +47,7 @@ import {
47
47
  writeHarnessAnalyzeResult,
48
48
  writeHarnessArtifacts,
49
49
  writeHumanProgress
50
- } from "./cli-pqnd8are.js";
50
+ } from "./cli-kq1b4vy0.js";
51
51
  import"./cli-k0vxtzxb.js";
52
52
  import"./cli-97fnztpy.js";
53
53
  import {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  buildDoctorReport
3
- } from "./cli-rp1079xm.js";
3
+ } from "./cli-73zjnpb6.js";
4
4
  import {
5
5
  selectTenantAndCreateKey
6
6
  } from "./cli-n1406hqg.js";
@@ -20,7 +20,7 @@ import {
20
20
  import {
21
21
  initPrompts,
22
22
  runPromptSync
23
- } from "./cli-8y7tzqkf.js";
23
+ } from "./cli-v5yk8rj2.js";
24
24
  import {
25
25
  agentsMdProblem,
26
26
  runSkillSync
@@ -46,7 +46,7 @@ import {
46
46
  runCodingAgent,
47
47
  runHarnessCommand,
48
48
  startRemoteAnalyze
49
- } from "./cli-pqnd8are.js";
49
+ } from "./cli-kq1b4vy0.js";
50
50
  import {
51
51
  canonicalText,
52
52
  renderInitBanner,
@@ -7,7 +7,7 @@ import {
7
7
  enumerateToolCatalog,
8
8
  enumerateWorkflows,
9
9
  mergeEnumeratedComponents
10
- } from "./cli-pqnd8are.js";
10
+ } from "./cli-kq1b4vy0.js";
11
11
  import"./cli-k0vxtzxb.js";
12
12
  import"./cli-97fnztpy.js";
13
13
  import"./cli-y333w08f.js";
@@ -21,7 +21,7 @@ import {
21
21
  serializeExtractResult,
22
22
  toolNamesOf,
23
23
  valueChildren
24
- } from "./cli-pqnd8are.js";
24
+ } from "./cli-kq1b4vy0.js";
25
25
  import"./cli-k0vxtzxb.js";
26
26
  import"./cli-97fnztpy.js";
27
27
  import"./cli-y333w08f.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  inventoryFiles,
3
3
  safePromptEvidencePath
4
- } from "./cli-pqnd8are.js";
4
+ } from "./cli-kq1b4vy0.js";
5
5
  import"./cli-k0vxtzxb.js";
6
6
  import"./cli-97fnztpy.js";
7
7
  import"./cli-y333w08f.js";
@@ -3,7 +3,7 @@ import {
3
3
  checkPromptMapping,
4
4
  discoverHarnessPromptSources,
5
5
  safePromptEvidencePath
6
- } from "./cli-pqnd8are.js";
6
+ } from "./cli-kq1b4vy0.js";
7
7
  import"./cli-k0vxtzxb.js";
8
8
  import"./cli-97fnztpy.js";
9
9
  import"./cli-y333w08f.js";
@@ -9,7 +9,7 @@ import {
9
9
  runPromptSync,
10
10
  runPromptsCommand,
11
11
  writePromptSyncProgress
12
- } from "./cli-8y7tzqkf.js";
12
+ } from "./cli-v5yk8rj2.js";
13
13
  import {
14
14
  promptSourceHashPayload
15
15
  } from "./cli-mm48br00.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runPromptsCommand
3
- } from "./cli-8y7tzqkf.js";
3
+ } from "./cli-v5yk8rj2.js";
4
4
  import {
5
5
  runSkillsCommand
6
6
  } from "./cli-1smcq5pf.js";
@@ -10,7 +10,7 @@ import"./cli-hcwdz9sd.js";
10
10
  import"./cli-mm48br00.js";
11
11
  import {
12
12
  runHarnessCommand
13
- } from "./cli-pqnd8are.js";
13
+ } from "./cli-kq1b4vy0.js";
14
14
  import"./cli-k0vxtzxb.js";
15
15
  import"./cli-97fnztpy.js";
16
16
  import"./cli-y333w08f.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moda-ai/cli",
3
- "version": "1.55.78",
3
+ "version": "1.55.80",
4
4
  "description": "CLI for Moda: production monitoring and evals for AI agents.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema_version": "moda.skill_index.v1",
3
- "bundled_at": "2026-10-21T09:55:25.979Z",
4
- "cli_version": "1.55.78",
3
+ "bundled_at": "2026-10-21T10:47:22.832Z",
4
+ "cli_version": "1.55.80",
5
5
  "skills": [
6
6
  {
7
7
  "id": "integration-cloudflare-think",