@agentyx/core 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { z } from "zod";
2
- import { access, readFile, readdir, realpath } from "node:fs/promises";
3
- import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
4
- import { readFileSync } from "node:fs";
2
+ import { access, readFile, readdir, realpath, stat } from "node:fs/promises";
3
+ import { delimiter, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
4
+ import { constants, readFileSync } from "node:fs";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { createHash } from "node:crypto";
7
7
  //#region src/errors.ts
@@ -96,6 +96,15 @@ var LocalSkillDirectoryError = class extends AgentyxError {
96
96
  this.directory = directory;
97
97
  }
98
98
  };
99
+ /** Raised when a configured project-context path is missing or escapes the project. */
100
+ var ProjectContextPathError = class extends AgentyxError {
101
+ path;
102
+ constructor(path, reason, options) {
103
+ super("project_context_path_error", `Invalid project context path "${path}": ${reason}.`, options);
104
+ this.name = "ProjectContextPathError";
105
+ this.path = path;
106
+ }
107
+ };
99
108
  //#endregion
100
109
  //#region src/hook/schema.ts
101
110
  const HOOK_ACTIVATION_LEVELS = ["default", "optional"];
@@ -130,13 +139,15 @@ const MCP_CONTEXT_COSTS = [
130
139
  "high"
131
140
  ];
132
141
  const mcpContextCostSchema = z.enum(MCP_CONTEXT_COSTS);
142
+ const mcpRuntimeSchema = z.enum(["local", "may-download"]);
133
143
  const mcpServerNameSchema = z.string().min(1, "MCP server names must be non-empty strings.").regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "MCP server names must be lowercase kebab-case, for example \"context7\".");
134
144
  const mcpEnvReferenceSchema = z.strictObject({ fromEnv: z.string().trim().min(1, "Environment variable references must be non-empty strings.").regex(/^[A-Za-z_][A-Za-z0-9_]*$/, "Environment variable names must be valid shell names.") });
135
145
  const commonMcpServerDefinitionSchema = z.strictObject({
136
146
  name: mcpServerNameSchema.describe("Unique MCP server identifier."),
137
147
  description: z.string().trim().min(1, "MCP server descriptions must be non-empty strings."),
138
148
  transport: z.enum(["stdio", "http"]),
139
- contextCost: mcpContextCostSchema.describe("Qualitative context/tool-schema overhead classification; not token accounting.").optional()
149
+ contextCost: mcpContextCostSchema.describe("Qualitative context/tool-schema overhead classification; not token accounting.").optional(),
150
+ runtime: mcpRuntimeSchema.describe("Whether launching this server can fetch a package on first use; see MCP_RUNTIMES.").optional()
140
151
  });
141
152
  const explicitMcpServerReferenceSchema = z.strictObject({
142
153
  name: mcpServerNameSchema.describe("MCP server identifier."),
@@ -278,6 +289,53 @@ const enabledCapabilityNameSchema = z.string().min(1, "Enabled capability names
278
289
  * every supported platform.
279
290
  */
280
291
  const skillDirectorySchema = z.string().min(1, "Skill directories must be non-empty strings.").regex(/^(?!\/)(?![A-Za-z]:)(?!.*(?:^|\/)\.\.(?:\/|$))[^\\\0]+$/, "Skill directories must be portable project-relative paths without parent traversal.");
292
+ const projectIdSchema = z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Project ids must be lowercase kebab-case identifiers.");
293
+ const projectTextSchema = z.string().min(1, "Must not be blank.").refine((value) => value.trim().length > 0, "Must not be blank.").refine((value) => Array.from(value).every((character) => {
294
+ const codePoint = character.codePointAt(0) ?? 0;
295
+ return codePoint > 31 && (codePoint < 127 || codePoint > 159);
296
+ }), "Must be single-line text without control characters.");
297
+ const projectUrlSchema = z.string().url("Must be a valid URL.");
298
+ const projectResourceNames = z.array(projectTextSchema).refine((items) => new Set(items).size === items.length, "Entries must be unique.");
299
+ const projectDocsSchema = z.array(projectUrlSchema).refine((items) => new Set(items).size === items.length, "Documentation URLs must be unique.");
300
+ const projectOwnsSchema = z.array(projectIdSchema).refine((items) => new Set(items).size === items.length, "Ownership entries must be unique.");
301
+ const projectMetadataSchema = z.strictObject({
302
+ id: projectIdSchema.describe("Stable, human-authored project identifier in kebab-case."),
303
+ name: projectTextSchema.describe("Human-readable project name."),
304
+ description: projectTextSchema.optional().describe("Short description of this project."),
305
+ repository: projectUrlSchema.optional().describe("Repository URL; descriptive and never fetched."),
306
+ docs: projectDocsSchema.default([]).describe("Documentation URLs; descriptive only."),
307
+ mcp: projectResourceNames.default([]).describe("MCP server identifiers available to consult."),
308
+ owns: projectOwnsSchema.default([]).describe("Architectural capabilities owned by this project.")
309
+ });
310
+ const projectRelationTypeSchema = z.enum([
311
+ "uses",
312
+ "integrates",
313
+ "consumes",
314
+ "extends"
315
+ ]);
316
+ const projectRelationSchema = z.strictObject({
317
+ id: projectIdSchema.describe("Stable identifier for the related project."),
318
+ name: projectTextSchema.describe("Human-readable related project name."),
319
+ type: projectRelationTypeSchema.describe("How the current project relates to this project."),
320
+ role: projectIdSchema.describe("Architectural role of the related project."),
321
+ repository: projectUrlSchema.optional().describe("Repository URL; descriptive and never fetched."),
322
+ docs: projectDocsSchema.default([]).describe("Documentation URLs; descriptive only."),
323
+ mcp: projectResourceNames.default([]).describe("MCP server identifiers available to consult."),
324
+ owns: projectOwnsSchema.default([]).describe("Architectural capabilities owned by this project."),
325
+ guidance: z.array(projectTextSchema).default([]).describe("Human-authored guidance for agents.")
326
+ });
327
+ const projectCommandSchema = z.strictObject({
328
+ command: projectTextSchema.describe("Suggested command; Agentyx never executes it."),
329
+ cwd: z.string().min(1).default(".").describe("Project-relative working directory.")
330
+ });
331
+ const projectContextSchema = z.strictObject({
332
+ commands: z.record(z.string().min(1).refine((name) => name.trim().length > 0, "Command names must not be blank."), projectCommandSchema).default({}),
333
+ areas: z.array(z.strictObject({
334
+ path: z.string().min(1),
335
+ purpose: projectTextSchema
336
+ })).default([]),
337
+ constraints: z.array(projectTextSchema).default([])
338
+ }).describe("Explicit repository-local facts for the generated project context Skill.");
281
339
  /** The `.agentyx.json` project configuration. */
282
340
  const agentyxConfigSchema = z.strictObject({
283
341
  $schema: z.string().min(1, "$schema must be a non-empty string.").describe("Optional path or URL to the Agentyx JSON Schema.").optional(),
@@ -286,7 +344,45 @@ const agentyxConfigSchema = z.strictObject({
286
344
  targets: z.array(agentyxTargetSchema).describe("Coding-agent providers this project targets.").default([]),
287
345
  skillDirectories: z.array(skillDirectorySchema).describe("Project-relative roots containing local Agent Skills.").optional(),
288
346
  localPacks: z.array(packDefinitionSchema).describe("Project-owned packs that can reference built-in or local Skills.").optional(),
289
- trustedSources: z.array(trustedSourceReferenceSchema).describe("Pinned local checkouts of known external skill/plugin sources.").optional()
347
+ trustedSources: z.array(trustedSourceReferenceSchema).describe("Pinned local checkouts of known external skill/plugin sources.").optional(),
348
+ project: projectMetadataSchema.optional().describe("Identity and ownership for this project."),
349
+ relations: z.array(projectRelationSchema).optional().describe("Direct architectural relationships."),
350
+ context: projectContextSchema.optional()
351
+ }).superRefine((config, context) => {
352
+ const relations = config.relations ?? [];
353
+ if (relations.length > 0 && config.project === void 0) context.addIssue({
354
+ code: "custom",
355
+ path: ["project"],
356
+ message: "Project metadata is required when relations are configured."
357
+ });
358
+ const ids = /* @__PURE__ */ new Set();
359
+ for (const [index, relation] of relations.entries()) {
360
+ if (config.project?.id === relation.id) context.addIssue({
361
+ code: "custom",
362
+ path: [
363
+ "relations",
364
+ index,
365
+ "id"
366
+ ],
367
+ message: "A project cannot relate to itself."
368
+ });
369
+ if (ids.has(relation.id)) context.addIssue({
370
+ code: "custom",
371
+ path: [
372
+ "relations",
373
+ index,
374
+ "id"
375
+ ],
376
+ message: "Related project ids must be unique."
377
+ });
378
+ ids.add(relation.id);
379
+ }
380
+ const areaPaths = config.context?.areas.map((area) => area.path) ?? [];
381
+ if (new Set(areaPaths).size !== areaPaths.length) context.addIssue({
382
+ code: "custom",
383
+ path: ["context", "areas"],
384
+ message: "Area paths must be unique."
385
+ });
290
386
  });
291
387
  //#endregion
292
388
  //#region src/config/json-schema.ts
@@ -357,6 +453,23 @@ function isFileNotFound(cause) {
357
453
  return cause instanceof Error && cause.code === "ENOENT";
358
454
  }
359
455
  //#endregion
456
+ //#region src/assets.ts
457
+ /**
458
+ * Location of the non-code assets that ship with `@agentyx/core`.
459
+ *
460
+ * **This module must stay directly under `src/`.** The path is derived from
461
+ * `import.meta.url` rather than the working directory, and `src/assets.ts` and
462
+ * the bundled `dist/index.mjs` sit at the same depth below the package root, so
463
+ * one relative path is correct both in development and in the published
464
+ * package. Moving this file into a subdirectory breaks built-in skill loading;
465
+ * `packages/core/test/built-in-skills.test.ts` guards against that.
466
+ *
467
+ * `skills/` is listed in the package's `files`, so it is published alongside
468
+ * `dist/`.
469
+ */
470
+ const BUILT_IN_SKILLS_PATH = fileURLToPath(new URL("../skills", import.meta.url));
471
+ const PROJECT_CONTEXT_TEMPLATE_PATH = fileURLToPath(new URL("../templates/project-context.md", import.meta.url));
472
+ //#endregion
360
473
  //#region src/pack/errors.ts
361
474
  /** Raised when a requested pack is not present in the registry. */
362
475
  var UnknownPackError = class extends AgentyxError {
@@ -611,22 +724,6 @@ const builtInPacks = [
611
724
  /** The registry used by default when no explicit registry is supplied. */
612
725
  const builtInPackRegistry = createPackRegistry(builtInPacks);
613
726
  //#endregion
614
- //#region src/assets.ts
615
- /**
616
- * Location of the non-code assets that ship with `@agentyx/core`.
617
- *
618
- * **This module must stay directly under `src/`.** The path is derived from
619
- * `import.meta.url` rather than the working directory, and `src/assets.ts` and
620
- * the bundled `dist/index.mjs` sit at the same depth below the package root, so
621
- * one relative path is correct both in development and in the published
622
- * package. Moving this file into a subdirectory breaks built-in skill loading;
623
- * `packages/core/test/built-in-skills.test.ts` guards against that.
624
- *
625
- * `skills/` is listed in the package's `files`, so it is published alongside
626
- * `dist/`.
627
- */
628
- const BUILT_IN_SKILLS_PATH = fileURLToPath(new URL("../skills", import.meta.url));
629
- //#endregion
630
727
  //#region src/skill/errors.ts
631
728
  /**
632
729
  * Raised when a pack references a skill the registry does not know.
@@ -965,18 +1062,70 @@ function getTrustedSourceDefinition(source, registry = knownTrustedSourceRegistr
965
1062
  async function loadAgentyxProject(projectPath = process.cwd()) {
966
1063
  const projectDir = resolve(projectPath);
967
1064
  const config = await loadAgentyxConfig(projectDir);
1065
+ await validateContextPaths(projectDir, config.context);
968
1066
  for (const source of config.trustedSources ?? []) getTrustedSourceDefinition(source);
969
1067
  const localSources = await loadLocalSkillSources(projectDir, config.skillDirectories ?? []);
970
- const skillRegistry = createSkillRegistry([...builtInSkillRegistry.names.map((name) => ({
971
- name,
972
- load: () => builtInSkillRegistry.get(name)
973
- })), ...localSources]);
1068
+ if (localSources.some((source) => source.name === "agentyx-project-context")) throw new DuplicateSkillError("agentyx-project-context");
1069
+ const generatedSources = config.project !== void 0 || config.context !== void 0 && hasContext(config.context) ? [createProjectContextSkill(config.project, config.relations ?? [], config.context)] : [];
1070
+ const skillRegistry = createSkillRegistry([
1071
+ ...builtInSkillRegistry.names.map((name) => ({
1072
+ name,
1073
+ load: () => builtInSkillRegistry.get(name)
1074
+ })),
1075
+ ...localSources,
1076
+ ...generatedSources
1077
+ ]);
974
1078
  return {
975
1079
  config,
976
1080
  packRegistry: config.localPacks === void 0 ? builtInPackRegistry : createPackRegistry([...builtInPacks, ...config.localPacks]),
977
- skillRegistry
1081
+ skillRegistry,
1082
+ graph: config.project === void 0 ? void 0 : {
1083
+ project: config.project,
1084
+ relations: config.relations ?? []
1085
+ }
978
1086
  };
979
1087
  }
1088
+ function createProjectContextSkill(project, relations, context) {
1089
+ return {
1090
+ name: "agentyx-project-context",
1091
+ load: () => {
1092
+ const template = readFileSync(PROJECT_CONTEXT_TEMPLATE_PATH, "utf8").trim();
1093
+ const data = JSON.stringify({
1094
+ project,
1095
+ relations,
1096
+ context
1097
+ }, null, 2);
1098
+ const longestFence = Math.max(0, ...Array.from(data.matchAll(/`+/g), (match) => match[0].length));
1099
+ const fence = "`".repeat(Math.max(3, longestFence + 1));
1100
+ return {
1101
+ name: "agentyx-project-context",
1102
+ description: "Repository facts and direct architectural relationships.",
1103
+ content: template.replace("{{PROJECT_FACTS}}", `${fence}json\n${data}\n${fence}`)
1104
+ };
1105
+ }
1106
+ };
1107
+ }
1108
+ function hasContext(context) {
1109
+ return Object.keys(context.commands).length > 0 || context.areas.length > 0 || context.constraints.length > 0;
1110
+ }
1111
+ async function validateContextPaths(projectDir, context) {
1112
+ if (context === void 0) return;
1113
+ const paths = [...Object.values(context.commands).map(({ cwd }) => cwd), ...context.areas.map(({ path }) => path)];
1114
+ const projectRealPath = await realpath(projectDir);
1115
+ for (const path of paths) {
1116
+ if (/^(?:\/|[A-Za-z]:)|\\|(?:^|\/)\.\.(?:\/|$)/.test(path)) throw new ProjectContextPathError(path, "it must be project-relative and cannot traverse parents");
1117
+ const resolvedPath = resolve(projectDir, path);
1118
+ let resolvedRealPath;
1119
+ try {
1120
+ resolvedRealPath = await realpath(resolvedPath);
1121
+ if (!(await stat(resolvedRealPath)).isDirectory()) throw new ProjectContextPathError(path, "it must name a directory");
1122
+ } catch (cause) {
1123
+ if (cause instanceof ProjectContextPathError) throw cause;
1124
+ throw new ProjectContextPathError(path, "it does not exist or cannot be read", cause instanceof Error ? { cause } : void 0);
1125
+ }
1126
+ if (!isInside$1(resolvedRealPath, projectRealPath)) throw new ProjectContextPathError(path, "it resolves outside the project");
1127
+ }
1128
+ }
980
1129
  async function loadLocalSkillSources(projectDir, directories) {
981
1130
  const projectRealPath = await realpath(projectDir);
982
1131
  const sources = [];
@@ -1116,6 +1265,7 @@ const builtInHookRegistry = createHookRegistry([{
1116
1265
  event: "SessionStart",
1117
1266
  command: "npx",
1118
1267
  args: [
1268
+ "--no-install",
1119
1269
  "agentyx",
1120
1270
  "doctor",
1121
1271
  "--hook"
@@ -1245,7 +1395,8 @@ function createMcpServerRegistry(sources) {
1245
1395
  name: server.name,
1246
1396
  description: server.description,
1247
1397
  transport: server.transport,
1248
- contextCost: server.contextCost
1398
+ contextCost: server.contextCost,
1399
+ runtime: server.runtime
1249
1400
  };
1250
1401
  }),
1251
1402
  get
@@ -1259,6 +1410,7 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1259
1410
  description: "Fetch up-to-date library documentation from Context7.",
1260
1411
  transport: "http",
1261
1412
  contextCost: "medium",
1413
+ runtime: "local",
1262
1414
  url: "https://mcp.context7.com/mcp"
1263
1415
  })
1264
1416
  },
@@ -1269,8 +1421,9 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1269
1421
  description: "Automate and inspect browsers through Playwright MCP.",
1270
1422
  transport: "stdio",
1271
1423
  contextCost: "high",
1424
+ runtime: "may-download",
1272
1425
  command: "npx",
1273
- args: ["@playwright/mcp@latest"]
1426
+ args: ["@playwright/mcp@0.0.81"]
1274
1427
  })
1275
1428
  },
1276
1429
  {
@@ -1280,6 +1433,7 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1280
1433
  description: "Structural code-intelligence MCP backed by a persistent code knowledge graph.",
1281
1434
  transport: "stdio",
1282
1435
  contextCost: "high",
1436
+ runtime: "local",
1283
1437
  command: "codebase-memory-mcp"
1284
1438
  })
1285
1439
  },
@@ -1290,6 +1444,7 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1290
1444
  description: "Read repositories, issues, pull requests and workflow runs on GitHub.",
1291
1445
  transport: "http",
1292
1446
  contextCost: "high",
1447
+ runtime: "local",
1293
1448
  url: "https://api.githubcopilot.com/mcp/"
1294
1449
  })
1295
1450
  },
@@ -1300,6 +1455,7 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1300
1455
  description: "Inspect production issues, events and stack traces recorded by Sentry.",
1301
1456
  transport: "http",
1302
1457
  contextCost: "medium",
1458
+ runtime: "local",
1303
1459
  url: "https://mcp.sentry.dev/mcp"
1304
1460
  })
1305
1461
  },
@@ -1310,8 +1466,9 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1310
1466
  description: "Record performance traces and inspect pages through Chrome DevTools.",
1311
1467
  transport: "stdio",
1312
1468
  contextCost: "high",
1469
+ runtime: "may-download",
1313
1470
  command: "npx",
1314
- args: ["-y", "chrome-devtools-mcp@latest"]
1471
+ args: ["-y", "chrome-devtools-mcp@1.9.0"]
1315
1472
  })
1316
1473
  },
1317
1474
  {
@@ -1321,8 +1478,9 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1321
1478
  description: "Inspect and query Supabase project schemas, tables and logs.",
1322
1479
  transport: "stdio",
1323
1480
  contextCost: "high",
1481
+ runtime: "may-download",
1324
1482
  command: "npx",
1325
- args: ["-y", "@supabase/mcp-server-supabase@latest"],
1483
+ args: ["-y", "@supabase/mcp-server-supabase@0.13.0"],
1326
1484
  env: { SUPABASE_ACCESS_TOKEN: { fromEnv: "SUPABASE_ACCESS_TOKEN" } }
1327
1485
  })
1328
1486
  }
@@ -1519,7 +1677,7 @@ function resolveAgentyxConfig(config, registry = builtInPackRegistry, skillRegis
1519
1677
  return {
1520
1678
  requestedPacks,
1521
1679
  resolvedPacks,
1522
- skills: collectPackSkills(resolvedPacks, registry, skillRegistry),
1680
+ skills: unique([...collectPackSkills(resolvedPacks, registry, skillRegistry), ...config.project !== void 0 || (config.relations?.length ?? 0) > 0 || hasProjectContext(config.context) ? ["agentyx-project-context"] : []]),
1523
1681
  declaredMcpServers,
1524
1682
  mcpServers: filterEffectiveMcpServers(declaredMcpServers, config.enable),
1525
1683
  declaredTools,
@@ -1530,6 +1688,12 @@ function resolveAgentyxConfig(config, registry = builtInPackRegistry, skillRegis
1530
1688
  targets: [...config.targets]
1531
1689
  };
1532
1690
  }
1691
+ function hasProjectContext(context) {
1692
+ return context !== void 0 && (Object.keys(context.commands).length > 0 || context.areas.length > 0 || context.constraints.length > 0);
1693
+ }
1694
+ function unique(values) {
1695
+ return [...new Set(values)];
1696
+ }
1533
1697
  //#endregion
1534
1698
  //#region src/manifest/errors.ts
1535
1699
  /** Raised when `.agentyx.lock.json` is not valid JSON. */
@@ -1740,13 +1904,92 @@ function getCoreStatus() {
1740
1904
  return "ready";
1741
1905
  }
1742
1906
  //#endregion
1743
- //#region src/project/detector.ts
1907
+ //#region src/project/executable.ts
1908
+ /** Whether `command` resolves to an executable file, via `PATH` unless it already contains a `/`. */
1909
+ async function isExecutableOnPath(command) {
1910
+ if (command.includes("/")) return isFileExecutable(command);
1911
+ for (const directory of (process.env.PATH ?? "").split(delimiter)) {
1912
+ if (directory.length === 0) continue;
1913
+ if (await isFileExecutable(`${directory}/${command}`)) return true;
1914
+ }
1915
+ return false;
1916
+ }
1917
+ async function isFileExecutable(path) {
1918
+ try {
1919
+ await access(path, constants.X_OK);
1920
+ return true;
1921
+ } catch {
1922
+ return false;
1923
+ }
1924
+ }
1925
+ //#endregion
1926
+ //#region src/project/signals.ts
1744
1927
  const PACKAGE_MANAGERS = [
1745
1928
  "pnpm",
1746
1929
  "npm",
1747
1930
  "yarn",
1748
1931
  "bun"
1749
1932
  ];
1933
+ /** Package name patterns matched exactly, or as a `@scope/*` prefix. */
1934
+ const TEST_FRAMEWORK_PATTERNS = [
1935
+ "vitest",
1936
+ "jest",
1937
+ "@jest/*",
1938
+ "@playwright/test",
1939
+ "cypress",
1940
+ "karma"
1941
+ ];
1942
+ const BROWSER_TESTING_PATTERNS = ["@playwright/test", "cypress"];
1943
+ const OBSERVABILITY_PATTERNS = ["@sentry/*", "@opentelemetry/*"];
1944
+ const DATA_TOOLING_PATTERNS = [
1945
+ "@supabase/*",
1946
+ "drizzle-orm",
1947
+ "prisma",
1948
+ "@prisma/client",
1949
+ "typeorm",
1950
+ "sequelize"
1951
+ ];
1952
+ const ACCESSIBILITY_PATTERNS = [
1953
+ "axe-core",
1954
+ "@axe-core/*",
1955
+ "pa11y"
1956
+ ];
1957
+ const DEPENDENCY_FIELDS = [
1958
+ "dependencies",
1959
+ "devDependencies",
1960
+ "peerDependencies",
1961
+ "optionalDependencies"
1962
+ ];
1963
+ const CONTAINER_IGNORED = /* @__PURE__ */ new Set([
1964
+ "node_modules",
1965
+ ".git",
1966
+ "dist",
1967
+ "build",
1968
+ "coverage"
1969
+ ]);
1970
+ /** Extensions counted as source files by the bounded repository-size scan. */
1971
+ const SOURCE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
1972
+ ".ts",
1973
+ ".tsx",
1974
+ ".js",
1975
+ ".jsx",
1976
+ ".mjs",
1977
+ ".cjs",
1978
+ ".vue",
1979
+ ".svelte",
1980
+ ".py",
1981
+ ".go",
1982
+ ".rs",
1983
+ ".java",
1984
+ ".kt",
1985
+ ".rb",
1986
+ ".php",
1987
+ ".css",
1988
+ ".scss",
1989
+ ".html"
1990
+ ]);
1991
+ /** Maximum directory entries visited by `scanRepositorySize`, regardless of match. */
1992
+ const REPOSITORY_SCAN_ENTRY_LIMIT = 5e3;
1750
1993
  const lockfileManagers = /* @__PURE__ */ new Map([
1751
1994
  ["pnpm-lock.yaml", "pnpm"],
1752
1995
  ["package-lock.json", "npm"],
@@ -1754,52 +1997,142 @@ const lockfileManagers = /* @__PURE__ */ new Map([
1754
1997
  ["bun.lock", "bun"],
1755
1998
  ["bun.lockb", "bun"]
1756
1999
  ]);
1757
- async function detectProject(projectDir) {
2000
+ /** Gathers every project signal with a bounded, cheap set of reads. */
2001
+ async function collectProjectSignals(projectDir) {
1758
2002
  const packageJsonPath = join(projectDir, "package.json");
1759
- const packageJson = await readPackageJson(packageJsonPath);
1760
- const packageManager = await detectPackageManager(projectDir, packageJson.data);
1761
- const detectedPacks = await detectPacks(projectDir, packageJson.data);
2003
+ const packageJsonResult = await readPackageJson(packageJsonPath);
2004
+ const packageJson = packageJsonResult.data;
2005
+ const [packageManager, containers, ci, monorepo, repositorySize, tsconfig, rtkAvailable] = await Promise.all([
2006
+ detectPackageManager(projectDir, packageJson),
2007
+ detectContainerFiles(projectDir),
2008
+ detectCiFiles(projectDir),
2009
+ detectMonorepo(projectDir, packageJson),
2010
+ scanRepositorySize(projectDir),
2011
+ exists(join(projectDir, "tsconfig.json")),
2012
+ isExecutableOnPath(builtInToolRegistry.get("rtk").command)
2013
+ ]);
1762
2014
  return {
1763
2015
  projectDir,
1764
2016
  packageJson: {
1765
- present: packageJson.present,
1766
- valid: packageJson.valid,
2017
+ present: packageJsonResult.present,
2018
+ valid: packageJsonResult.valid,
1767
2019
  path: packageJsonPath,
1768
- name: getString(packageJson.data?.name),
1769
- packageManager: getString(packageJson.data?.packageManager),
1770
- error: packageJson.error
2020
+ name: getString(packageJson?.name),
2021
+ packageManager: getString(packageJson?.packageManager),
2022
+ scripts: getStringRecord(packageJson?.scripts),
2023
+ error: packageJsonResult.error
1771
2024
  },
1772
2025
  packageManager,
1773
- detectedPacks,
1774
- recommendedPacks: recommendPacks(detectedPacks)
2026
+ typescript: {
2027
+ dependency: findDependency(packageJson, "typescript"),
2028
+ tsconfig
2029
+ },
2030
+ angular: findDependency(packageJson, "@angular/core"),
2031
+ testFrameworks: findAnyDependency(packageJson, TEST_FRAMEWORK_PATTERNS),
2032
+ browserTesting: findAnyDependency(packageJson, BROWSER_TESTING_PATTERNS),
2033
+ observability: findAnyDependency(packageJson, OBSERVABILITY_PATTERNS),
2034
+ dataTooling: findAnyDependency(packageJson, DATA_TOOLING_PATTERNS),
2035
+ accessibilityTooling: findAnyDependency(packageJson, ACCESSIBILITY_PATTERNS),
2036
+ containers,
2037
+ ci,
2038
+ monorepo,
2039
+ repositorySize,
2040
+ localTools: { rtkAvailable }
1775
2041
  };
1776
2042
  }
1777
- function buildAgentyxConfig(input) {
2043
+ /**
2044
+ * Counts source-like files under a bounded traversal, ignoring dependency, VCS and build output
2045
+ * directories. Stops after visiting `entryLimit` directory entries — cheap even on a monorepo — and
2046
+ * reports `capped` so callers never mistake a partial scan for a complete one.
2047
+ */
2048
+ async function scanRepositorySize(projectDir, options = {}) {
2049
+ const entryLimit = options.entryLimit ?? 5e3;
2050
+ const directories = [projectDir];
2051
+ let filesScanned = 0;
2052
+ let entriesVisited = 0;
2053
+ let capped = false;
2054
+ while (directories.length > 0 && !capped) {
2055
+ const directory = directories.shift();
2056
+ if (directory === void 0) break;
2057
+ let entries;
2058
+ try {
2059
+ entries = await readdir(directory, { withFileTypes: true });
2060
+ } catch {
2061
+ continue;
2062
+ }
2063
+ for (const entry of entries) {
2064
+ if (entriesVisited >= entryLimit) {
2065
+ capped = true;
2066
+ break;
2067
+ }
2068
+ entriesVisited += 1;
2069
+ if (entry.isDirectory()) {
2070
+ if (entry.name.startsWith(".") || CONTAINER_IGNORED.has(entry.name)) continue;
2071
+ directories.push(join(directory, entry.name));
2072
+ } else if (entry.isFile() && SOURCE_FILE_EXTENSIONS.has(extname(entry.name))) filesScanned += 1;
2073
+ }
2074
+ }
1778
2075
  return {
1779
- packs: [...input.packs],
1780
- enable: [...input.enable ?? []],
1781
- targets: [...input.targets]
2076
+ filesScanned,
2077
+ capped
1782
2078
  };
1783
2079
  }
1784
- function formatAgentyxConfig(config) {
1785
- return `${JSON.stringify(config, null, 2)}\n`;
2080
+ function findDependency(packageJson, pattern) {
2081
+ for (const field of DEPENDENCY_FIELDS) {
2082
+ const value = packageJson?.[field];
2083
+ if (!isRecord(value)) continue;
2084
+ if (pattern.endsWith("/*")) {
2085
+ const prefix = pattern.slice(0, -1);
2086
+ const name = Object.keys(value).find((key) => key.startsWith(prefix));
2087
+ if (name !== void 0) return {
2088
+ dependency: name,
2089
+ field
2090
+ };
2091
+ continue;
2092
+ }
2093
+ if (pattern in value) return {
2094
+ dependency: pattern,
2095
+ field
2096
+ };
2097
+ }
1786
2098
  }
1787
- function recommendPacks(detectedPacks) {
1788
- if (detectedPacks.includes("angular")) return [
1789
- "technical",
1790
- "typescript",
1791
- "angular"
1792
- ];
1793
- if (detectedPacks.includes("typescript")) return ["technical", "typescript"];
1794
- return ["technical"];
2099
+ function findAnyDependency(packageJson, patterns) {
2100
+ const matches = [];
2101
+ const seen = /* @__PURE__ */ new Set();
2102
+ for (const pattern of patterns) {
2103
+ const match = findDependency(packageJson, pattern);
2104
+ if (match !== void 0 && !seen.has(match.dependency)) {
2105
+ seen.add(match.dependency);
2106
+ matches.push(match);
2107
+ }
2108
+ }
2109
+ return matches;
2110
+ }
2111
+ async function detectContainerFiles(projectDir) {
2112
+ const [dockerfile, dockerCompose, compose] = await Promise.all([
2113
+ exists(join(projectDir, "Dockerfile")),
2114
+ exists(join(projectDir, "docker-compose.yml")),
2115
+ exists(join(projectDir, "compose.yml"))
2116
+ ]);
2117
+ return {
2118
+ dockerfile,
2119
+ compose: dockerCompose || compose
2120
+ };
1795
2121
  }
1796
- async function detectPacks(projectDir, packageJson) {
1797
- const packs = [];
1798
- const dependencies = collectDependencies(packageJson);
1799
- const hasAngular = dependencies.has("@angular/core");
1800
- if (dependencies.has("typescript") || await exists(join(projectDir, "tsconfig.json")) || hasAngular) packs.push("typescript");
1801
- if (hasAngular) packs.push("angular");
1802
- return packs;
2122
+ async function detectCiFiles(projectDir) {
2123
+ return { githubActions: await exists(join(projectDir, ".github", "workflows")) };
2124
+ }
2125
+ async function detectMonorepo(projectDir, packageJson) {
2126
+ const markers = [];
2127
+ if (await exists(join(projectDir, "pnpm-workspace.yaml"))) markers.push("pnpm-workspace.yaml");
2128
+ if (await exists(join(projectDir, "turbo.json"))) markers.push("turbo.json");
2129
+ if (await exists(join(projectDir, "nx.json"))) markers.push("nx.json");
2130
+ const workspaces = packageJson?.workspaces;
2131
+ if (Array.isArray(workspaces) || isRecord(workspaces)) markers.push("package.json workspaces");
2132
+ return {
2133
+ detected: markers.length > 0,
2134
+ markers
2135
+ };
1803
2136
  }
1804
2137
  async function detectPackageManager(projectDir, packageJson) {
1805
2138
  const lockfiles = [];
@@ -1862,16 +2195,6 @@ async function readPackageJson(path) {
1862
2195
  };
1863
2196
  }
1864
2197
  }
1865
- function collectDependencies(packageJson) {
1866
- const dependencies = /* @__PURE__ */ new Set();
1867
- for (const field of [
1868
- packageJson?.dependencies,
1869
- packageJson?.devDependencies,
1870
- packageJson?.peerDependencies,
1871
- packageJson?.optionalDependencies
1872
- ]) if (isRecord(field)) for (const name of Object.keys(field)) dependencies.add(name);
1873
- return dependencies;
1874
- }
1875
2198
  function parsePackageManagerName(value) {
1876
2199
  const name = value?.split("@")[0];
1877
2200
  return PACKAGE_MANAGERS.includes(name) ? name : void 0;
@@ -1879,6 +2202,10 @@ function parsePackageManagerName(value) {
1879
2202
  function getString(value) {
1880
2203
  return typeof value === "string" ? value : void 0;
1881
2204
  }
2205
+ function getStringRecord(value) {
2206
+ if (!isRecord(value)) return {};
2207
+ return Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === "string"));
2208
+ }
1882
2209
  function isRecord(value) {
1883
2210
  return typeof value === "object" && value !== null && !Array.isArray(value);
1884
2211
  }
@@ -1895,6 +2222,205 @@ function isNotFound(cause) {
1895
2222
  return cause instanceof Error && cause.code === "ENOENT";
1896
2223
  }
1897
2224
  //#endregion
2225
+ //#region src/project/detector.ts
2226
+ /**
2227
+ * Factual project detection only. It gathers `ProjectSignals` and never decides which packs or
2228
+ * capabilities fit — that policy lives in `recommendCapabilities`, kept separate so each half stays
2229
+ * independently testable.
2230
+ */
2231
+ async function detectProject(projectDir) {
2232
+ const signals = await collectProjectSignals(projectDir);
2233
+ return {
2234
+ projectDir,
2235
+ packageJson: signals.packageJson,
2236
+ packageManager: signals.packageManager,
2237
+ signals
2238
+ };
2239
+ }
2240
+ function buildAgentyxConfig(input) {
2241
+ return {
2242
+ packs: [...input.packs],
2243
+ enable: [...input.enable ?? []],
2244
+ targets: [...input.targets]
2245
+ };
2246
+ }
2247
+ function formatAgentyxConfig(config) {
2248
+ return `${JSON.stringify(config, null, 2)}\n`;
2249
+ }
2250
+ //#endregion
2251
+ //#region src/project/recommend.ts
2252
+ const RECOMMENDATION_CONFIDENCES = ["high", "medium"];
2253
+ /**
2254
+ * Heuristic thresholds for the `codebase-memory` capability suggestion, in scanned source files.
2255
+ * These are approximate signals, not exact token accounting, and a monorepo is treated as already
2256
+ * complex enough to lower the bar.
2257
+ */
2258
+ const CODEBASE_MEMORY_FILE_THRESHOLD = 2e3;
2259
+ const CODEBASE_MEMORY_MONOREPO_FILE_THRESHOLD = 800;
2260
+ /**
2261
+ * Applies conservative, deterministic policy on top of `ProjectSignals`. This is the only place
2262
+ * that turns an observed fact into a product suggestion — `ProjectSignals` stays fact-only so it
2263
+ * can be tested independently of pack names or capability policy.
2264
+ *
2265
+ * Never enables anything and never touches the filesystem: the caller decides what, if anything,
2266
+ * to do with the result.
2267
+ */
2268
+ function recommendCapabilities(signals, options = {}) {
2269
+ const packs = recommendPacks(signals);
2270
+ const configuredPacks = options.configuredPacks ?? [];
2271
+ return {
2272
+ packs,
2273
+ capabilities: recommendOptionalCapabilities(signals, /* @__PURE__ */ new Set([...packs.map((pack) => pack.name), ...configuredPacks]), configuredPacks)
2274
+ };
2275
+ }
2276
+ function recommendPacks(signals) {
2277
+ const packs = [];
2278
+ if (signals.packageJson.present) packs.push(packRecommendation("technical", "high", ["package.json detected — baseline engineering practices apply to any software project."]));
2279
+ const typescriptReasons = [...signals.typescript.dependency !== void 0 ? [dependencyReason("TypeScript", signals.typescript.dependency)] : [], ...signals.typescript.tsconfig ? ["tsconfig.json detected."] : []];
2280
+ if (typescriptReasons.length > 0) packs.push(packRecommendation("typescript", "high", typescriptReasons));
2281
+ if (signals.angular !== void 0) packs.push(packRecommendation("angular", "high", [dependencyReason("@angular/core", signals.angular)]));
2282
+ const testingMatches = dedupeMatches([...signals.testFrameworks, ...signals.browserTesting]);
2283
+ if (testingMatches.length > 0) packs.push(packRecommendation("testing", "high", testingMatches.map((match) => dependencyReason(match.dependency, match))));
2284
+ const devopsReasons = [
2285
+ ...signals.containers.dockerfile ? ["Dockerfile detected."] : [],
2286
+ ...signals.containers.compose ? ["Container compose file detected."] : [],
2287
+ ...signals.ci.githubActions ? ["GitHub Actions workflow detected (.github/workflows)."] : []
2288
+ ];
2289
+ if (devopsReasons.length > 0) packs.push(packRecommendation("devops", "high", devopsReasons));
2290
+ if (signals.observability.length > 0) packs.push(packRecommendation("observability", "high", signals.observability.map((match) => dependencyReason(match.dependency, match))));
2291
+ if (signals.dataTooling.length > 0) packs.push(packRecommendation("data", "high", signals.dataTooling.map((match) => dependencyReason(match.dependency, match))));
2292
+ if (signals.accessibilityTooling.length > 0) packs.push(packRecommendation("accessibility", "high", signals.accessibilityTooling.map((match) => dependencyReason(match.dependency, match))));
2293
+ return packs;
2294
+ }
2295
+ function recommendOptionalCapabilities(signals, activePacks, configuredPacks) {
2296
+ const capabilities = [];
2297
+ const playwrightMatch = signals.browserTesting.find((match) => match.dependency === "@playwright/test");
2298
+ if (activePacks.has("testing") && playwrightMatch !== void 0) capabilities.push(capabilityRecommendation("playwright", "high", ["Playwright is already part of this project; browser MCP may be useful for interactive browser work."]));
2299
+ if (signals.observability.find((match) => match.dependency.startsWith("@sentry/")) !== void 0) capabilities.push(capabilityRecommendation("sentry", "high", ["Sentry is already configured as a dependency."]));
2300
+ if (signals.dataTooling.find((match) => match.dependency.startsWith("@supabase/")) !== void 0) capabilities.push(capabilityRecommendation("supabase", "high", ["Supabase is already configured as a dependency."]));
2301
+ if (configuredPacks.includes("efficiency") && signals.localTools.rtkAvailable) capabilities.push(capabilityRecommendation("rtk", "high", ["RTK is already installed locally."]));
2302
+ const sizeThreshold = signals.monorepo.detected ? 800 : CODEBASE_MEMORY_FILE_THRESHOLD;
2303
+ if (signals.repositorySize.filesScanned >= sizeThreshold || signals.repositorySize.capped) capabilities.push(capabilityRecommendation("codebase-memory", "medium", [repositorySizeReason(signals)]));
2304
+ return capabilities;
2305
+ }
2306
+ function repositorySizeReason(signals) {
2307
+ const { filesScanned, capped } = signals.repositorySize;
2308
+ const scope = signals.monorepo.detected ? " across this monorepo" : "";
2309
+ return `Heuristic: found ${capped ? `at least ${filesScanned} source files (the scan was capped before finishing)` : `${filesScanned} source files`}${scope}. A persistent codebase-memory MCP may reduce repeated full-tree reads on a repository this size — this is an approximate signal, not an exact token measurement.`;
2310
+ }
2311
+ function packRecommendation(name, confidence, reasons) {
2312
+ return {
2313
+ kind: "pack",
2314
+ name,
2315
+ confidence,
2316
+ reasons
2317
+ };
2318
+ }
2319
+ /** Provenance comes from the pack registry itself — never a second, hand-maintained capability map. */
2320
+ function capabilityRecommendation(name, confidence, reasons) {
2321
+ return {
2322
+ kind: "capability",
2323
+ name,
2324
+ confidence,
2325
+ reasons,
2326
+ contributedBy: packsDeclaringOptionalCapability(name)
2327
+ };
2328
+ }
2329
+ function packsDeclaringOptionalCapability(name) {
2330
+ const packs = [];
2331
+ for (const pack of builtInPackRegistry.values()) if (pack.mcpServers.some((server) => server.name === name && server.activation === "optional") || pack.tools.some((tool) => tool.name === name && tool.activation === "optional") || pack.hooks.some((hook) => hook.name === name && hook.activation === "optional")) packs.push(pack.name);
2332
+ return packs;
2333
+ }
2334
+ function dependencyReason(label, match) {
2335
+ return label === match.dependency ? `Detected ${match.dependency} in ${match.field}.` : `Detected ${label} (${match.dependency}) in ${match.field}.`;
2336
+ }
2337
+ function dedupeMatches(matches) {
2338
+ const seen = /* @__PURE__ */ new Set();
2339
+ const result = [];
2340
+ for (const match of matches) if (!seen.has(match.dependency)) {
2341
+ seen.add(match.dependency);
2342
+ result.push(match);
2343
+ }
2344
+ return result;
2345
+ }
2346
+ //#endregion
2347
+ //#region src/project-graph.ts
2348
+ var ProjectGraphNotConfiguredError = class extends AgentyxError {
2349
+ constructor() {
2350
+ super("project_graph_not_configured", "Project Graph requires a project object in .agentyx.json.");
2351
+ this.name = "ProjectGraphNotConfiguredError";
2352
+ }
2353
+ };
2354
+ function createProjectGraph(project, relations) {
2355
+ return {
2356
+ project,
2357
+ relations: [...relations]
2358
+ };
2359
+ }
2360
+ function renderProjectGraphText(graph) {
2361
+ const rows = graph.relations.map((relation, index) => {
2362
+ return `${index === graph.relations.length - 1 ? "└──" : "├──"} ${relation.type} [${relation.role}] → ${relation.name}`;
2363
+ });
2364
+ return [graph.project.name, ...rows].join("\n");
2365
+ }
2366
+ function renderProjectGraphJson(graph) {
2367
+ return `${JSON.stringify(graph, null, 2)}\n`;
2368
+ }
2369
+ function renderProjectGraphMermaid(graph) {
2370
+ const current = mermaidId(graph.project.id);
2371
+ return ["graph LR", ...graph.relations.map((relation) => ` ${current}["${mermaidText(graph.project.name)}"] -->|${mermaidText(`${relation.type}: ${relation.role}`)}| ${mermaidId(relation.id)}["${mermaidText(relation.name)}"]`)].join("\n");
2372
+ }
2373
+ function renderProjectGraphSvg(graph) {
2374
+ const width = 720;
2375
+ const rowHeight = 92;
2376
+ const height = Math.max(180, 100 + graph.relations.length * rowHeight);
2377
+ const centerX = 360;
2378
+ const centerY = height / 2;
2379
+ const svg = [
2380
+ `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" role="img" aria-labelledby="title desc">`,
2381
+ `<title id="title">${xml(graph.project.name)} project graph</title>`,
2382
+ `<desc id="desc">Direct architectural relationships from ${xml(graph.project.name)}.</desc>`,
2383
+ "<defs><marker id=\"arrow\" markerWidth=\"10\" markerHeight=\"8\" refX=\"9\" refY=\"4\" orient=\"auto\"><path d=\"M0,0 L10,4 L0,8 z\" fill=\"#526579\"/></marker></defs>"
2384
+ ];
2385
+ graph.relations.forEach((relation, index) => {
2386
+ const y = 54 + index * rowHeight;
2387
+ const right = index % 2 === 0;
2388
+ const x = right ? 500 : 0;
2389
+ const edgeStart = right ? 488 : 232;
2390
+ const edgeEnd = right ? x : x + 220;
2391
+ svg.push(`<line x1="${edgeStart}" y1="${centerY}" x2="${edgeEnd}" y2="${y + 24}" stroke="#526579" stroke-width="2" marker-end="url(#arrow)"/>`);
2392
+ svg.push(`<text x="${right ? 494 : 226}" y="${Math.round((centerY + y + 24) / 2) - 7}" class="edge">${xml(truncate(`${relation.type} · ${relation.role}`, 34))}</text>`);
2393
+ svg.push(`<rect x="${x}" y="${y}" width="220" height="48" rx="10" class="node"/>`);
2394
+ svg.push(`<text x="${x + 110}" y="${y + 30}" class="label">${xml(truncate(relation.name, 22))}</text>`);
2395
+ });
2396
+ svg.push(`<rect x="232" y="${centerY - 34}" width="256" height="68" rx="14" class="current"/>`);
2397
+ svg.push(`<text x="${centerX}" y="${centerY + 6}" class="label">${xml(truncate(graph.project.name, 30))}</text>`);
2398
+ svg.push("<style>text{font-family:system-ui,sans-serif}.node{fill:#fff;stroke:#8da0b3;stroke-width:2}.current{fill:#e8f2ff;stroke:#2563a5;stroke-width:3}.label{text-anchor:middle;font-size:16px;font-weight:600;fill:#172536}.edge{text-anchor:middle;font-size:12px;fill:#34495e;paint-order:stroke;stroke:#fff;stroke-width:5px;stroke-linejoin:round}</style>");
2399
+ svg.push("</svg>");
2400
+ return `${svg.join("\n")}\n`;
2401
+ }
2402
+ function findProjectCapabilityOwners(graph, capability) {
2403
+ const owners = graph.relations.filter((relation) => relation.owns.includes(capability));
2404
+ return {
2405
+ capability,
2406
+ currentProject: graph.project.owns.includes(capability) ? graph.project : void 0,
2407
+ relatedProjects: owners
2408
+ };
2409
+ }
2410
+ function xml(value) {
2411
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&apos;");
2412
+ }
2413
+ function mermaidText(value) {
2414
+ return value.replaceAll("&", "&amp;").replaceAll("|", "&#124;").replaceAll("[", "&#91;").replaceAll("]", "&#93;").replaceAll("\"", "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
2415
+ }
2416
+ function mermaidId(value) {
2417
+ return `node_${Array.from(value).map((char) => char.codePointAt(0)?.toString(16) ?? "0").join("")}`;
2418
+ }
2419
+ function truncate(value, limit) {
2420
+ const characters = Array.from(value);
2421
+ return characters.length > limit ? `${characters.slice(0, limit - 1).join("")}…` : value;
2422
+ }
2423
+ //#endregion
1898
2424
  //#region src/source/inspection.ts
1899
2425
  async function inspectTrustedSource(projectPath, reference) {
1900
2426
  const definition = getTrustedSourceDefinition(reference);
@@ -1983,6 +2509,6 @@ function trustedSourceLoadError(sourceName, reason, cause) {
1983
2509
  return new TrustedSourceLoadError(sourceName, reason, cause instanceof Error ? { cause } : void 0);
1984
2510
  }
1985
2511
  //#endregion
1986
- export { AGENTYX_CONFIG_FILENAME, AGENTYX_CONFIG_SCHEMA_ID, AGENTYX_MANIFEST_FILENAME, AgentyxConfigNotFoundError, AgentyxConfigParseError, AgentyxConfigValidationError, AgentyxError, AgentyxManifestParseError, AgentyxManifestValidationError, CircularPackDependencyError, DuplicateHookError, DuplicateMcpServerError, DuplicatePackError, DuplicateSkillError, DuplicateToolError, DuplicateTrustedSourceError, HOOK_ACTIVATION_LEVELS, HOOK_EVENTS, INSTALL_MANIFEST_VERSION, InvalidHookError, InvalidMcpServerError, InvalidSkillError, InvalidToolError, LocalSkillDirectoryError, MCP_CAPABILITY_LEVELS, MCP_CONTEXT_COSTS, PACKAGE_MANAGERS, PACK_CATEGORIES, TOOL_ACTIVATION_LEVELS, TrustedSourceLoadError, UnknownEnabledCapabilityError, UnknownHookError, UnknownMcpServerError, UnknownPackError, UnknownSkillError, UnknownToolError, UnknownTrustedSourceError, agentyxConfigPath, agentyxConfigSchema, agentyxCoreName, agentyxManifestPath, agentyxTargetSchema, buildAgentyxConfig, buildAgentyxConfigJsonSchema, builtInHookNames, builtInHookRegistry, builtInMcpServerNames, builtInMcpServerRegistry, builtInPackRegistry, builtInPacks, builtInSkillNames, builtInSkillRegistry, builtInToolNames, builtInToolRegistry, codexPluginManifestSchema, collectPackHookReferences, collectPackHooks, collectPackMcpServerReferences, collectPackMcpServers, collectPackToolReferences, createHookRegistry, createMcpServerRegistry, createPackRegistry, createSkillRegistry, createToolRegistry, createTrustedSourceRegistry, detectProject, emptyInstallManifest, enabledCapabilityNameSchema, filterEffectiveHooks, filterEffectiveMcpServers, filterEffectiveTools, formatAgentyxConfig, formatInstallManifest, formatSkillMarkdown, getCoreStatus, getTrustedSourceDefinition, hashContent, hookActivationLevelSchema, hookDefinitionSchema, hookEventSchema, hookManifestEntrySchema, hookNameSchema, hookReferenceSchema, inspectTrustedSource, installManifestEntrySchema, installManifestSchema, knownTrustedSourceRegistry, knownTrustedSources, loadAgentyxConfig, loadAgentyxProject, loadInstallManifest, manifestEntriesByPath, mcpCapabilityLevelSchema, mcpContextCostSchema, mcpEnvReferenceSchema, mcpManifestEntrySchema, mcpServerDefinitionSchema, mcpServerReferenceSchema, packCategorySchema, packDefinitionSchema, packNameSchema, parseAgentyxConfig, parseInstallManifest, parseSkillMarkdown, resolveAgentyxConfig, resolvePackHookReferences, resolvePackHooks, resolvePackMcpServerReferences, resolvePackMcpServers, resolvePackSkills, resolvePackToolReferences, resolvePackTools, resolvePacks, skillDefinitionSchema, skillDirectorySchema, skillManifestEntrySchema, toolActivationLevelSchema, toolDefinitionSchema, toolNameSchema, toolReferenceSchema, trustedSourceDefinitionSchema, trustedSourceNameSchema, trustedSourcePathSchema, trustedSourceReferenceSchema, trustedSourceSkillSummarySchema };
2512
+ export { AGENTYX_CONFIG_FILENAME, AGENTYX_CONFIG_SCHEMA_ID, AGENTYX_MANIFEST_FILENAME, AgentyxConfigNotFoundError, AgentyxConfigParseError, AgentyxConfigValidationError, AgentyxError, AgentyxManifestParseError, AgentyxManifestValidationError, CODEBASE_MEMORY_FILE_THRESHOLD, CODEBASE_MEMORY_MONOREPO_FILE_THRESHOLD, CircularPackDependencyError, DuplicateHookError, DuplicateMcpServerError, DuplicatePackError, DuplicateSkillError, DuplicateToolError, DuplicateTrustedSourceError, HOOK_ACTIVATION_LEVELS, HOOK_EVENTS, INSTALL_MANIFEST_VERSION, InvalidHookError, InvalidMcpServerError, InvalidSkillError, InvalidToolError, LocalSkillDirectoryError, MCP_CAPABILITY_LEVELS, MCP_CONTEXT_COSTS, PACKAGE_MANAGERS, PACK_CATEGORIES, ProjectContextPathError, ProjectGraphNotConfiguredError, RECOMMENDATION_CONFIDENCES, REPOSITORY_SCAN_ENTRY_LIMIT, TOOL_ACTIVATION_LEVELS, TrustedSourceLoadError, UnknownEnabledCapabilityError, UnknownHookError, UnknownMcpServerError, UnknownPackError, UnknownSkillError, UnknownToolError, UnknownTrustedSourceError, agentyxConfigPath, agentyxConfigSchema, agentyxCoreName, agentyxManifestPath, agentyxTargetSchema, buildAgentyxConfig, buildAgentyxConfigJsonSchema, builtInHookNames, builtInHookRegistry, builtInMcpServerNames, builtInMcpServerRegistry, builtInPackRegistry, builtInPacks, builtInSkillNames, builtInSkillRegistry, builtInToolNames, builtInToolRegistry, codexPluginManifestSchema, collectPackHookReferences, collectPackHooks, collectPackMcpServerReferences, collectPackMcpServers, collectPackToolReferences, collectProjectSignals, createHookRegistry, createMcpServerRegistry, createPackRegistry, createProjectGraph, createSkillRegistry, createToolRegistry, createTrustedSourceRegistry, detectProject, emptyInstallManifest, enabledCapabilityNameSchema, filterEffectiveHooks, filterEffectiveMcpServers, filterEffectiveTools, findProjectCapabilityOwners, formatAgentyxConfig, formatInstallManifest, formatSkillMarkdown, getCoreStatus, getTrustedSourceDefinition, hashContent, hookActivationLevelSchema, hookDefinitionSchema, hookEventSchema, hookManifestEntrySchema, hookNameSchema, hookReferenceSchema, inspectTrustedSource, installManifestEntrySchema, installManifestSchema, isExecutableOnPath, knownTrustedSourceRegistry, knownTrustedSources, loadAgentyxConfig, loadAgentyxProject, loadInstallManifest, manifestEntriesByPath, mcpCapabilityLevelSchema, mcpContextCostSchema, mcpEnvReferenceSchema, mcpManifestEntrySchema, mcpServerDefinitionSchema, mcpServerReferenceSchema, packCategorySchema, packDefinitionSchema, packNameSchema, parseAgentyxConfig, parseInstallManifest, parseSkillMarkdown, projectContextSchema, projectMetadataSchema, projectRelationSchema, projectRelationTypeSchema, recommendCapabilities, renderProjectGraphJson, renderProjectGraphMermaid, renderProjectGraphSvg, renderProjectGraphText, resolveAgentyxConfig, resolvePackHookReferences, resolvePackHooks, resolvePackMcpServerReferences, resolvePackMcpServers, resolvePackSkills, resolvePackToolReferences, resolvePackTools, resolvePacks, scanRepositorySize, skillDefinitionSchema, skillDirectorySchema, skillManifestEntrySchema, toolActivationLevelSchema, toolDefinitionSchema, toolNameSchema, toolReferenceSchema, trustedSourceDefinitionSchema, trustedSourceNameSchema, trustedSourcePathSchema, trustedSourceReferenceSchema, trustedSourceSkillSummarySchema };
1987
2513
 
1988
2514
  //# sourceMappingURL=index.mjs.map