@agentyx/core 0.5.0 → 0.7.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
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";
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
@@ -97,6 +97,30 @@ var LocalSkillDirectoryError = class extends AgentyxError {
97
97
  }
98
98
  };
99
99
  //#endregion
100
+ //#region src/hook/schema.ts
101
+ const HOOK_ACTIVATION_LEVELS = ["default", "optional"];
102
+ const hookActivationLevelSchema = z.enum(HOOK_ACTIVATION_LEVELS);
103
+ const HOOK_EVENTS = ["SessionStart"];
104
+ const hookEventSchema = z.enum(HOOK_EVENTS);
105
+ const hookNameSchema = z.string().min(1, "Hook names must be non-empty strings.").regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Hook names must be lowercase kebab-case, for example \"session-doctor-bootstrap\".");
106
+ const hookDefinitionSchema = z.strictObject({
107
+ name: hookNameSchema.describe("Unique hook identifier."),
108
+ description: z.string().trim().min(1, "Hook descriptions must be non-empty strings."),
109
+ event: hookEventSchema.describe("The provider lifecycle event this hook runs on."),
110
+ command: z.string().trim().min(1, "Hook command must be a non-empty string."),
111
+ args: z.array(z.string()).default([])
112
+ });
113
+ const hookReferenceSchema = z.union([hookNameSchema, z.strictObject({
114
+ name: hookNameSchema.describe("Hook identifier."),
115
+ activation: hookActivationLevelSchema.default("default")
116
+ })]).transform((value) => typeof value === "string" ? {
117
+ name: value,
118
+ activation: "default"
119
+ } : value).pipe(z.strictObject({
120
+ name: hookNameSchema.describe("Hook identifier."),
121
+ activation: hookActivationLevelSchema.describe("Whether this hook is active by default or explicit opt-in.")
122
+ }));
123
+ //#endregion
100
124
  //#region src/mcp/schema.ts
101
125
  const MCP_CAPABILITY_LEVELS = ["default", "optional"];
102
126
  const mcpCapabilityLevelSchema = z.enum(MCP_CAPABILITY_LEVELS);
@@ -106,13 +130,15 @@ const MCP_CONTEXT_COSTS = [
106
130
  "high"
107
131
  ];
108
132
  const mcpContextCostSchema = z.enum(MCP_CONTEXT_COSTS);
133
+ const mcpRuntimeSchema = z.enum(["local", "may-download"]);
109
134
  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\".");
110
135
  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.") });
111
136
  const commonMcpServerDefinitionSchema = z.strictObject({
112
137
  name: mcpServerNameSchema.describe("Unique MCP server identifier."),
113
138
  description: z.string().trim().min(1, "MCP server descriptions must be non-empty strings."),
114
139
  transport: z.enum(["stdio", "http"]),
115
- contextCost: mcpContextCostSchema.describe("Qualitative context/tool-schema overhead classification; not token accounting.").optional()
140
+ contextCost: mcpContextCostSchema.describe("Qualitative context/tool-schema overhead classification; not token accounting.").optional(),
141
+ runtime: mcpRuntimeSchema.describe("Whether launching this server can fetch a package on first use; see MCP_RUNTIMES.").optional()
116
142
  });
117
143
  const explicitMcpServerReferenceSchema = z.strictObject({
118
144
  name: mcpServerNameSchema.describe("MCP server identifier."),
@@ -204,7 +230,8 @@ const packDefinitionSchema = z.strictObject({
204
230
  description: z.string().min(1, "Pack descriptions must be non-empty when provided.").describe("Short human-readable summary of the pack.").optional(),
205
231
  skills: z.array(skillNameSchema).describe("Skills this pack contributes, in declaration order.").default([]),
206
232
  mcpServers: z.array(mcpServerReferenceSchema).describe("MCP servers this pack contributes, in declaration order.").default([]),
207
- tools: z.array(toolReferenceSchema).describe("Local tools this pack contributes, in declaration order.").default([])
233
+ tools: z.array(toolReferenceSchema).describe("Local tools this pack contributes, in declaration order.").default([]),
234
+ hooks: z.array(hookReferenceSchema).describe("Provider lifecycle hooks this pack contributes, in declaration order.").default([])
208
235
  });
209
236
  //#endregion
210
237
  //#region src/source/schema.ts
@@ -434,6 +461,10 @@ const builtInPacks = [
434
461
  tools: [{
435
462
  name: "rtk",
436
463
  activation: "optional"
464
+ }],
465
+ hooks: [{
466
+ name: "session-doctor-bootstrap",
467
+ activation: "default"
437
468
  }]
438
469
  },
439
470
  {
@@ -641,14 +672,14 @@ var InvalidSkillError = class extends AgentyxError {
641
672
  origin;
642
673
  reason;
643
674
  constructor(origin, reason, options) {
644
- const detail = typeof reason === "string" ? reason : formatIssues$1(reason);
675
+ const detail = typeof reason === "string" ? reason : formatIssues$2(reason);
645
676
  super("invalid_skill", `Invalid skill in ${origin}: ${detail}`, options);
646
677
  this.name = "InvalidSkillError";
647
678
  this.origin = origin;
648
679
  this.reason = detail;
649
680
  }
650
681
  };
651
- function formatIssues$1(error) {
682
+ function formatIssues$2(error) {
652
683
  return error.issues.map((issue) => {
653
684
  const path = issue.path.map(String).join(".");
654
685
  return path === "" ? issue.message : `${path}: ${issue.message}`;
@@ -969,13 +1000,20 @@ async function loadLocalSkillSources(projectDir, directories) {
969
1000
  for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
970
1001
  if (!entry.isDirectory()) continue;
971
1002
  const filePath = join(rootRealPath, entry.name, "SKILL.md");
972
- let markdown;
1003
+ let realFilePath;
973
1004
  try {
974
- markdown = await readFile(filePath, "utf8");
1005
+ realFilePath = await realpath(filePath);
975
1006
  } catch (cause) {
976
1007
  if (cause instanceof Error && cause.code === "ENOENT") continue;
977
1008
  throw localDirectoryError(directory, `cannot read ${entry.name}/SKILL.md`, cause);
978
1009
  }
1010
+ if (!isInside$1(realFilePath, rootRealPath)) throw new LocalSkillDirectoryError(directory, `${entry.name}/SKILL.md resolves outside the skill directory`);
1011
+ let markdown;
1012
+ try {
1013
+ markdown = await readFile(realFilePath, "utf8");
1014
+ } catch (cause) {
1015
+ throw localDirectoryError(directory, `cannot read ${entry.name}/SKILL.md`, cause);
1016
+ }
979
1017
  const skill = parseSkillMarkdown(markdown, filePath);
980
1018
  if (skill.name !== entry.name) throw new LocalSkillDirectoryError(directory, `${entry.name}/SKILL.md declares the name "${skill.name}"`);
981
1019
  sources.push({
@@ -994,6 +1032,149 @@ function localDirectoryError(directory, reason, cause) {
994
1032
  return new LocalSkillDirectoryError(directory, reason, cause instanceof Error ? { cause } : void 0);
995
1033
  }
996
1034
  //#endregion
1035
+ //#region src/hook/errors.ts
1036
+ var UnknownHookError = class extends AgentyxError {
1037
+ hookName;
1038
+ requiredBy;
1039
+ knownHooks;
1040
+ constructor(hookName, requiredBy, knownHooks) {
1041
+ const origin = requiredBy === void 0 ? "" : ` (required by "${requiredBy}")`;
1042
+ const known = knownHooks.length > 0 ? [...knownHooks].sort().join(", ") : "none";
1043
+ super("unknown_hook", `Unknown hook "${hookName}"${origin}. Known hooks: ${known}.`);
1044
+ this.name = "UnknownHookError";
1045
+ this.hookName = hookName;
1046
+ this.requiredBy = requiredBy;
1047
+ this.knownHooks = knownHooks;
1048
+ }
1049
+ };
1050
+ var DuplicateHookError = class extends AgentyxError {
1051
+ hookName;
1052
+ constructor(hookName) {
1053
+ super("duplicate_hook", `Duplicate hook definition: "${hookName}".`);
1054
+ this.name = "DuplicateHookError";
1055
+ this.hookName = hookName;
1056
+ }
1057
+ };
1058
+ var InvalidHookError = class extends AgentyxError {
1059
+ origin;
1060
+ reason;
1061
+ constructor(origin, reason, options) {
1062
+ const detail = typeof reason === "string" ? reason : formatIssues$1(reason);
1063
+ super("invalid_hook", `Invalid hook in ${origin}: ${detail}`, options);
1064
+ this.name = "InvalidHookError";
1065
+ this.origin = origin;
1066
+ this.reason = detail;
1067
+ }
1068
+ };
1069
+ function formatIssues$1(error) {
1070
+ return error.issues.map((issue) => {
1071
+ const path = issue.path.map(String).join(".");
1072
+ return path === "" ? issue.message : `${path}: ${issue.message}`;
1073
+ }).join("; ");
1074
+ }
1075
+ //#endregion
1076
+ //#region src/hook/registry.ts
1077
+ function createHookRegistry(sources) {
1078
+ const byName = /* @__PURE__ */ new Map();
1079
+ for (const source of sources) {
1080
+ const name = hookNameSchema.safeParse(source.name);
1081
+ if (!name.success) throw new InvalidHookError(`Hook source "${source.name}"`, name.error);
1082
+ if (byName.has(name.data)) throw new DuplicateHookError(name.data);
1083
+ byName.set(name.data, source);
1084
+ }
1085
+ const names = [...byName.keys()];
1086
+ const loaded = /* @__PURE__ */ new Map();
1087
+ const get = (name) => {
1088
+ const cached = loaded.get(name);
1089
+ if (cached !== void 0) return cached;
1090
+ const source = byName.get(name);
1091
+ if (source === void 0) throw new UnknownHookError(name, void 0, names);
1092
+ const origin = `Hook "${name}"`;
1093
+ const hook = hookDefinitionSchema.safeParse(source.load());
1094
+ if (!hook.success) throw new InvalidHookError(origin, hook.error);
1095
+ if (hook.data.name !== name) throw new InvalidHookError(origin, `it declares the name "${hook.data.name}"`);
1096
+ loaded.set(name, hook.data);
1097
+ return hook.data;
1098
+ };
1099
+ return {
1100
+ names,
1101
+ has: (name) => byName.has(name),
1102
+ listMetadata: () => names.map((name) => {
1103
+ const hook = get(name);
1104
+ return {
1105
+ name: hook.name,
1106
+ description: hook.description,
1107
+ event: hook.event
1108
+ };
1109
+ }),
1110
+ get
1111
+ };
1112
+ }
1113
+ const builtInHookRegistry = createHookRegistry([{
1114
+ name: "session-doctor-bootstrap",
1115
+ load: () => ({
1116
+ name: "session-doctor-bootstrap",
1117
+ description: "Reports Agentyx project health at session start; silent when healthy.",
1118
+ event: "SessionStart",
1119
+ command: "npx",
1120
+ args: [
1121
+ "--no-install",
1122
+ "agentyx",
1123
+ "doctor",
1124
+ "--hook"
1125
+ ]
1126
+ })
1127
+ }]);
1128
+ const builtInHookNames = builtInHookRegistry.names;
1129
+ //#endregion
1130
+ //#region src/pack/resolver.ts
1131
+ /**
1132
+ * Resolves selected packs without hidden inheritance.
1133
+ *
1134
+ * The result preserves configured order, removes duplicates by first
1135
+ * occurrence, and validates every requested pack.
1136
+ *
1137
+ * @throws {UnknownPackError} when a requested pack is missing.
1138
+ */
1139
+ function resolvePacks(requestedPacks, registry = builtInPackRegistry) {
1140
+ const resolved = [];
1141
+ const seen = /* @__PURE__ */ new Set();
1142
+ for (const name of requestedPacks) {
1143
+ if (seen.has(name)) continue;
1144
+ if (!registry.has(name)) throw new UnknownPackError(name, void 0, [...registry.keys()]);
1145
+ seen.add(name);
1146
+ resolved.push(name);
1147
+ }
1148
+ return resolved;
1149
+ }
1150
+ //#endregion
1151
+ //#region src/hook/resolver.ts
1152
+ function collectPackHookReferences(resolvedPacks, packRegistry, hookRegistry) {
1153
+ const hooks = [];
1154
+ const seen = /* @__PURE__ */ new Set();
1155
+ for (const packName of resolvedPacks) for (const hook of packRegistry.get(packName)?.hooks ?? []) {
1156
+ const hookName = hook.name;
1157
+ if (seen.has(hookName)) continue;
1158
+ if (!hookRegistry.has(hookName)) throw new UnknownHookError(hookName, packName, hookRegistry.names);
1159
+ seen.add(hookName);
1160
+ hooks.push(hook);
1161
+ }
1162
+ return hooks;
1163
+ }
1164
+ function filterEffectiveHooks(hooks, enabledCapabilities) {
1165
+ const enabled = new Set(enabledCapabilities);
1166
+ return hooks.filter((hook) => hook.activation === "default" || enabled.has(hook.name)).map((hook) => hook.name);
1167
+ }
1168
+ function collectPackHooks(resolvedPacks, packRegistry, hookRegistry, enabledCapabilities = []) {
1169
+ return filterEffectiveHooks(collectPackHookReferences(resolvedPacks, packRegistry, hookRegistry), enabledCapabilities);
1170
+ }
1171
+ function resolvePackHookReferences(requestedPacks, packRegistry = builtInPackRegistry, hookRegistry = builtInHookRegistry) {
1172
+ return collectPackHookReferences(resolvePacks(requestedPacks, packRegistry), packRegistry, hookRegistry);
1173
+ }
1174
+ function resolvePackHooks(requestedPacks, packRegistry = builtInPackRegistry, hookRegistry = builtInHookRegistry, enabledCapabilities = []) {
1175
+ return collectPackHooks(resolvePacks(requestedPacks, packRegistry), packRegistry, hookRegistry, enabledCapabilities);
1176
+ }
1177
+ //#endregion
997
1178
  //#region src/mcp/errors.ts
998
1179
  var UnknownMcpServerError = class extends AgentyxError {
999
1180
  serverName;
@@ -1067,7 +1248,8 @@ function createMcpServerRegistry(sources) {
1067
1248
  name: server.name,
1068
1249
  description: server.description,
1069
1250
  transport: server.transport,
1070
- contextCost: server.contextCost
1251
+ contextCost: server.contextCost,
1252
+ runtime: server.runtime
1071
1253
  };
1072
1254
  }),
1073
1255
  get
@@ -1081,6 +1263,7 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1081
1263
  description: "Fetch up-to-date library documentation from Context7.",
1082
1264
  transport: "http",
1083
1265
  contextCost: "medium",
1266
+ runtime: "local",
1084
1267
  url: "https://mcp.context7.com/mcp"
1085
1268
  })
1086
1269
  },
@@ -1091,8 +1274,9 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1091
1274
  description: "Automate and inspect browsers through Playwright MCP.",
1092
1275
  transport: "stdio",
1093
1276
  contextCost: "high",
1277
+ runtime: "may-download",
1094
1278
  command: "npx",
1095
- args: ["@playwright/mcp@latest"]
1279
+ args: ["@playwright/mcp@0.0.81"]
1096
1280
  })
1097
1281
  },
1098
1282
  {
@@ -1102,6 +1286,7 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1102
1286
  description: "Structural code-intelligence MCP backed by a persistent code knowledge graph.",
1103
1287
  transport: "stdio",
1104
1288
  contextCost: "high",
1289
+ runtime: "local",
1105
1290
  command: "codebase-memory-mcp"
1106
1291
  })
1107
1292
  },
@@ -1112,6 +1297,7 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1112
1297
  description: "Read repositories, issues, pull requests and workflow runs on GitHub.",
1113
1298
  transport: "http",
1114
1299
  contextCost: "high",
1300
+ runtime: "local",
1115
1301
  url: "https://api.githubcopilot.com/mcp/"
1116
1302
  })
1117
1303
  },
@@ -1122,6 +1308,7 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1122
1308
  description: "Inspect production issues, events and stack traces recorded by Sentry.",
1123
1309
  transport: "http",
1124
1310
  contextCost: "medium",
1311
+ runtime: "local",
1125
1312
  url: "https://mcp.sentry.dev/mcp"
1126
1313
  })
1127
1314
  },
@@ -1132,8 +1319,9 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1132
1319
  description: "Record performance traces and inspect pages through Chrome DevTools.",
1133
1320
  transport: "stdio",
1134
1321
  contextCost: "high",
1322
+ runtime: "may-download",
1135
1323
  command: "npx",
1136
- args: ["-y", "chrome-devtools-mcp@latest"]
1324
+ args: ["-y", "chrome-devtools-mcp@1.9.0"]
1137
1325
  })
1138
1326
  },
1139
1327
  {
@@ -1143,35 +1331,15 @@ const builtInMcpServerRegistry = createMcpServerRegistry([
1143
1331
  description: "Inspect and query Supabase project schemas, tables and logs.",
1144
1332
  transport: "stdio",
1145
1333
  contextCost: "high",
1334
+ runtime: "may-download",
1146
1335
  command: "npx",
1147
- args: ["-y", "@supabase/mcp-server-supabase@latest"],
1336
+ args: ["-y", "@supabase/mcp-server-supabase@0.13.0"],
1148
1337
  env: { SUPABASE_ACCESS_TOKEN: { fromEnv: "SUPABASE_ACCESS_TOKEN" } }
1149
1338
  })
1150
1339
  }
1151
1340
  ]);
1152
1341
  const builtInMcpServerNames = builtInMcpServerRegistry.names;
1153
1342
  //#endregion
1154
- //#region src/pack/resolver.ts
1155
- /**
1156
- * Resolves selected packs without hidden inheritance.
1157
- *
1158
- * The result preserves configured order, removes duplicates by first
1159
- * occurrence, and validates every requested pack.
1160
- *
1161
- * @throws {UnknownPackError} when a requested pack is missing.
1162
- */
1163
- function resolvePacks(requestedPacks, registry = builtInPackRegistry) {
1164
- const resolved = [];
1165
- const seen = /* @__PURE__ */ new Set();
1166
- for (const name of requestedPacks) {
1167
- if (seen.has(name)) continue;
1168
- if (!registry.has(name)) throw new UnknownPackError(name, void 0, [...registry.keys()]);
1169
- seen.add(name);
1170
- resolved.push(name);
1171
- }
1172
- return resolved;
1173
- }
1174
- //#endregion
1175
1343
  //#region src/mcp/resolver.ts
1176
1344
  function collectPackMcpServerReferences(resolvedPacks, packRegistry, mcpRegistry) {
1177
1345
  const servers = [];
@@ -1347,12 +1515,17 @@ function resolvePackTools(requestedPacks, packRegistry = builtInPackRegistry, to
1347
1515
  * @throws {UnknownPackError} when a configured pack is missing.
1348
1516
  * @throws {UnknownSkillError} when a pack references an unknown skill.
1349
1517
  */
1350
- function resolveAgentyxConfig(config, registry = builtInPackRegistry, skillRegistry = builtInSkillRegistry, mcpRegistry = builtInMcpServerRegistry, toolRegistry = builtInToolRegistry) {
1518
+ function resolveAgentyxConfig(config, registry = builtInPackRegistry, skillRegistry = builtInSkillRegistry, mcpRegistry = builtInMcpServerRegistry, toolRegistry = builtInToolRegistry, hookRegistry = builtInHookRegistry) {
1351
1519
  const requestedPacks = [...config.packs];
1352
1520
  const resolvedPacks = resolvePacks(requestedPacks, registry);
1353
1521
  const declaredMcpServers = collectPackMcpServerReferences(resolvedPacks, registry, mcpRegistry);
1354
1522
  const declaredTools = collectPackToolReferences(resolvedPacks, registry, toolRegistry);
1355
- const knownOptionalCapabilities = [...declaredMcpServers.filter((server) => server.activation === "optional").map((server) => server.name), ...declaredTools.filter((tool) => tool.activation === "optional").map((tool) => tool.name)];
1523
+ const declaredHooks = collectPackHookReferences(resolvedPacks, registry, hookRegistry);
1524
+ const knownOptionalCapabilities = [
1525
+ ...declaredMcpServers.filter((server) => server.activation === "optional").map((server) => server.name),
1526
+ ...declaredTools.filter((tool) => tool.activation === "optional").map((tool) => tool.name),
1527
+ ...declaredHooks.filter((hook) => hook.activation === "optional").map((hook) => hook.name)
1528
+ ];
1356
1529
  for (const capability of config.enable) if (!knownOptionalCapabilities.includes(capability)) throw new UnknownEnabledCapabilityError(capability, knownOptionalCapabilities);
1357
1530
  return {
1358
1531
  requestedPacks,
@@ -1362,6 +1535,8 @@ function resolveAgentyxConfig(config, registry = builtInPackRegistry, skillRegis
1362
1535
  mcpServers: filterEffectiveMcpServers(declaredMcpServers, config.enable),
1363
1536
  declaredTools,
1364
1537
  tools: filterEffectiveTools(declaredTools, config.enable),
1538
+ declaredHooks,
1539
+ hooks: filterEffectiveHooks(declaredHooks, config.enable),
1365
1540
  enabled: [...config.enable],
1366
1541
  targets: [...config.targets]
1367
1542
  };
@@ -1440,7 +1615,26 @@ const mcpManifestEntrySchema = z.strictObject({
1440
1615
  hash: contentHashSchema,
1441
1616
  created: z.boolean()
1442
1617
  });
1443
- const installManifestEntrySchema = z.discriminatedUnion("kind", [skillManifestEntrySchema, mcpManifestEntrySchema]);
1618
+ /**
1619
+ * A provider hook configuration file Agentyx contributed entries to.
1620
+ *
1621
+ * Shares the `mcp` entry's shape and rationale: the file is shared with the
1622
+ * user, so the entry records the hook names Agentyx added rather than
1623
+ * claiming the whole document.
1624
+ */
1625
+ const hookManifestEntrySchema = z.strictObject({
1626
+ kind: z.literal("hook"),
1627
+ path: managedPathSchema,
1628
+ hooks: z.array(z.string().min(1, "Hook names must be non-empty strings.")),
1629
+ targets: targetsSchema,
1630
+ hash: contentHashSchema,
1631
+ created: z.boolean()
1632
+ });
1633
+ const installManifestEntrySchema = z.discriminatedUnion("kind", [
1634
+ skillManifestEntrySchema,
1635
+ mcpManifestEntrySchema,
1636
+ hookManifestEntrySchema
1637
+ ]);
1444
1638
  /** The `.agentyx.lock.json` record of everything Agentyx installed into a project. */
1445
1639
  const installManifestSchema = z.strictObject({
1446
1640
  version: z.literal(1),
@@ -1517,13 +1711,21 @@ async function loadInstallManifest(projectPath = process.cwd()) {
1517
1711
  * touches the filesystem.
1518
1712
  */
1519
1713
  function formatInstallManifest(manifest) {
1520
- const entries = [...manifest.entries].map((entry) => entry.kind === "skill" ? {
1521
- ...entry,
1522
- targets: sorted(entry.targets)
1523
- } : {
1524
- ...entry,
1525
- targets: sorted(entry.targets),
1526
- servers: sorted(entry.servers)
1714
+ const entries = [...manifest.entries].map((entry) => {
1715
+ if (entry.kind === "skill") return {
1716
+ ...entry,
1717
+ targets: sorted(entry.targets)
1718
+ };
1719
+ if (entry.kind === "mcp") return {
1720
+ ...entry,
1721
+ targets: sorted(entry.targets),
1722
+ servers: sorted(entry.servers)
1723
+ };
1724
+ return {
1725
+ ...entry,
1726
+ targets: sorted(entry.targets),
1727
+ hooks: sorted(entry.hooks)
1728
+ };
1527
1729
  }).sort((left, right) => left.path.localeCompare(right.path));
1528
1730
  return `${JSON.stringify({
1529
1731
  version: manifest.version,
@@ -1549,13 +1751,92 @@ function getCoreStatus() {
1549
1751
  return "ready";
1550
1752
  }
1551
1753
  //#endregion
1552
- //#region src/project/detector.ts
1754
+ //#region src/project/executable.ts
1755
+ /** Whether `command` resolves to an executable file, via `PATH` unless it already contains a `/`. */
1756
+ async function isExecutableOnPath(command) {
1757
+ if (command.includes("/")) return isFileExecutable(command);
1758
+ for (const directory of (process.env.PATH ?? "").split(delimiter)) {
1759
+ if (directory.length === 0) continue;
1760
+ if (await isFileExecutable(`${directory}/${command}`)) return true;
1761
+ }
1762
+ return false;
1763
+ }
1764
+ async function isFileExecutable(path) {
1765
+ try {
1766
+ await access(path, constants.X_OK);
1767
+ return true;
1768
+ } catch {
1769
+ return false;
1770
+ }
1771
+ }
1772
+ //#endregion
1773
+ //#region src/project/signals.ts
1553
1774
  const PACKAGE_MANAGERS = [
1554
1775
  "pnpm",
1555
1776
  "npm",
1556
1777
  "yarn",
1557
1778
  "bun"
1558
1779
  ];
1780
+ /** Package name patterns matched exactly, or as a `@scope/*` prefix. */
1781
+ const TEST_FRAMEWORK_PATTERNS = [
1782
+ "vitest",
1783
+ "jest",
1784
+ "@jest/*",
1785
+ "@playwright/test",
1786
+ "cypress",
1787
+ "karma"
1788
+ ];
1789
+ const BROWSER_TESTING_PATTERNS = ["@playwright/test", "cypress"];
1790
+ const OBSERVABILITY_PATTERNS = ["@sentry/*", "@opentelemetry/*"];
1791
+ const DATA_TOOLING_PATTERNS = [
1792
+ "@supabase/*",
1793
+ "drizzle-orm",
1794
+ "prisma",
1795
+ "@prisma/client",
1796
+ "typeorm",
1797
+ "sequelize"
1798
+ ];
1799
+ const ACCESSIBILITY_PATTERNS = [
1800
+ "axe-core",
1801
+ "@axe-core/*",
1802
+ "pa11y"
1803
+ ];
1804
+ const DEPENDENCY_FIELDS = [
1805
+ "dependencies",
1806
+ "devDependencies",
1807
+ "peerDependencies",
1808
+ "optionalDependencies"
1809
+ ];
1810
+ const CONTAINER_IGNORED = /* @__PURE__ */ new Set([
1811
+ "node_modules",
1812
+ ".git",
1813
+ "dist",
1814
+ "build",
1815
+ "coverage"
1816
+ ]);
1817
+ /** Extensions counted as source files by the bounded repository-size scan. */
1818
+ const SOURCE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
1819
+ ".ts",
1820
+ ".tsx",
1821
+ ".js",
1822
+ ".jsx",
1823
+ ".mjs",
1824
+ ".cjs",
1825
+ ".vue",
1826
+ ".svelte",
1827
+ ".py",
1828
+ ".go",
1829
+ ".rs",
1830
+ ".java",
1831
+ ".kt",
1832
+ ".rb",
1833
+ ".php",
1834
+ ".css",
1835
+ ".scss",
1836
+ ".html"
1837
+ ]);
1838
+ /** Maximum directory entries visited by `scanRepositorySize`, regardless of match. */
1839
+ const REPOSITORY_SCAN_ENTRY_LIMIT = 5e3;
1559
1840
  const lockfileManagers = /* @__PURE__ */ new Map([
1560
1841
  ["pnpm-lock.yaml", "pnpm"],
1561
1842
  ["package-lock.json", "npm"],
@@ -1563,52 +1844,141 @@ const lockfileManagers = /* @__PURE__ */ new Map([
1563
1844
  ["bun.lock", "bun"],
1564
1845
  ["bun.lockb", "bun"]
1565
1846
  ]);
1566
- async function detectProject(projectDir) {
1847
+ /** Gathers every project signal with a bounded, cheap set of reads. */
1848
+ async function collectProjectSignals(projectDir) {
1567
1849
  const packageJsonPath = join(projectDir, "package.json");
1568
- const packageJson = await readPackageJson(packageJsonPath);
1569
- const packageManager = await detectPackageManager(projectDir, packageJson.data);
1570
- const detectedPacks = await detectPacks(projectDir, packageJson.data);
1850
+ const packageJsonResult = await readPackageJson(packageJsonPath);
1851
+ const packageJson = packageJsonResult.data;
1852
+ const [packageManager, containers, ci, monorepo, repositorySize, tsconfig, rtkAvailable] = await Promise.all([
1853
+ detectPackageManager(projectDir, packageJson),
1854
+ detectContainerFiles(projectDir),
1855
+ detectCiFiles(projectDir),
1856
+ detectMonorepo(projectDir, packageJson),
1857
+ scanRepositorySize(projectDir),
1858
+ exists(join(projectDir, "tsconfig.json")),
1859
+ isExecutableOnPath(builtInToolRegistry.get("rtk").command)
1860
+ ]);
1571
1861
  return {
1572
1862
  projectDir,
1573
1863
  packageJson: {
1574
- present: packageJson.present,
1575
- valid: packageJson.valid,
1864
+ present: packageJsonResult.present,
1865
+ valid: packageJsonResult.valid,
1576
1866
  path: packageJsonPath,
1577
- name: getString(packageJson.data?.name),
1578
- packageManager: getString(packageJson.data?.packageManager),
1579
- error: packageJson.error
1867
+ name: getString(packageJson?.name),
1868
+ packageManager: getString(packageJson?.packageManager),
1869
+ error: packageJsonResult.error
1580
1870
  },
1581
1871
  packageManager,
1582
- detectedPacks,
1583
- recommendedPacks: recommendPacks(detectedPacks)
1872
+ typescript: {
1873
+ dependency: findDependency(packageJson, "typescript"),
1874
+ tsconfig
1875
+ },
1876
+ angular: findDependency(packageJson, "@angular/core"),
1877
+ testFrameworks: findAnyDependency(packageJson, TEST_FRAMEWORK_PATTERNS),
1878
+ browserTesting: findAnyDependency(packageJson, BROWSER_TESTING_PATTERNS),
1879
+ observability: findAnyDependency(packageJson, OBSERVABILITY_PATTERNS),
1880
+ dataTooling: findAnyDependency(packageJson, DATA_TOOLING_PATTERNS),
1881
+ accessibilityTooling: findAnyDependency(packageJson, ACCESSIBILITY_PATTERNS),
1882
+ containers,
1883
+ ci,
1884
+ monorepo,
1885
+ repositorySize,
1886
+ localTools: { rtkAvailable }
1584
1887
  };
1585
1888
  }
1586
- function buildAgentyxConfig(input) {
1889
+ /**
1890
+ * Counts source-like files under a bounded traversal, ignoring dependency, VCS and build output
1891
+ * directories. Stops after visiting `entryLimit` directory entries — cheap even on a monorepo — and
1892
+ * reports `capped` so callers never mistake a partial scan for a complete one.
1893
+ */
1894
+ async function scanRepositorySize(projectDir, options = {}) {
1895
+ const entryLimit = options.entryLimit ?? 5e3;
1896
+ const directories = [projectDir];
1897
+ let filesScanned = 0;
1898
+ let entriesVisited = 0;
1899
+ let capped = false;
1900
+ while (directories.length > 0 && !capped) {
1901
+ const directory = directories.shift();
1902
+ if (directory === void 0) break;
1903
+ let entries;
1904
+ try {
1905
+ entries = await readdir(directory, { withFileTypes: true });
1906
+ } catch {
1907
+ continue;
1908
+ }
1909
+ for (const entry of entries) {
1910
+ if (entriesVisited >= entryLimit) {
1911
+ capped = true;
1912
+ break;
1913
+ }
1914
+ entriesVisited += 1;
1915
+ if (entry.isDirectory()) {
1916
+ if (entry.name.startsWith(".") || CONTAINER_IGNORED.has(entry.name)) continue;
1917
+ directories.push(join(directory, entry.name));
1918
+ } else if (entry.isFile() && SOURCE_FILE_EXTENSIONS.has(extname(entry.name))) filesScanned += 1;
1919
+ }
1920
+ }
1587
1921
  return {
1588
- packs: [...input.packs],
1589
- enable: [...input.enable ?? []],
1590
- targets: [...input.targets]
1922
+ filesScanned,
1923
+ capped
1591
1924
  };
1592
1925
  }
1593
- function formatAgentyxConfig(config) {
1594
- return `${JSON.stringify(config, null, 2)}\n`;
1926
+ function findDependency(packageJson, pattern) {
1927
+ for (const field of DEPENDENCY_FIELDS) {
1928
+ const value = packageJson?.[field];
1929
+ if (!isRecord(value)) continue;
1930
+ if (pattern.endsWith("/*")) {
1931
+ const prefix = pattern.slice(0, -1);
1932
+ const name = Object.keys(value).find((key) => key.startsWith(prefix));
1933
+ if (name !== void 0) return {
1934
+ dependency: name,
1935
+ field
1936
+ };
1937
+ continue;
1938
+ }
1939
+ if (pattern in value) return {
1940
+ dependency: pattern,
1941
+ field
1942
+ };
1943
+ }
1595
1944
  }
1596
- function recommendPacks(detectedPacks) {
1597
- if (detectedPacks.includes("angular")) return [
1598
- "technical",
1599
- "typescript",
1600
- "angular"
1601
- ];
1602
- if (detectedPacks.includes("typescript")) return ["technical", "typescript"];
1603
- return ["technical"];
1945
+ function findAnyDependency(packageJson, patterns) {
1946
+ const matches = [];
1947
+ const seen = /* @__PURE__ */ new Set();
1948
+ for (const pattern of patterns) {
1949
+ const match = findDependency(packageJson, pattern);
1950
+ if (match !== void 0 && !seen.has(match.dependency)) {
1951
+ seen.add(match.dependency);
1952
+ matches.push(match);
1953
+ }
1954
+ }
1955
+ return matches;
1956
+ }
1957
+ async function detectContainerFiles(projectDir) {
1958
+ const [dockerfile, dockerCompose, compose] = await Promise.all([
1959
+ exists(join(projectDir, "Dockerfile")),
1960
+ exists(join(projectDir, "docker-compose.yml")),
1961
+ exists(join(projectDir, "compose.yml"))
1962
+ ]);
1963
+ return {
1964
+ dockerfile,
1965
+ compose: dockerCompose || compose
1966
+ };
1604
1967
  }
1605
- async function detectPacks(projectDir, packageJson) {
1606
- const packs = [];
1607
- const dependencies = collectDependencies(packageJson);
1608
- const hasAngular = dependencies.has("@angular/core");
1609
- if (dependencies.has("typescript") || await exists(join(projectDir, "tsconfig.json")) || hasAngular) packs.push("typescript");
1610
- if (hasAngular) packs.push("angular");
1611
- return packs;
1968
+ async function detectCiFiles(projectDir) {
1969
+ return { githubActions: await exists(join(projectDir, ".github", "workflows")) };
1970
+ }
1971
+ async function detectMonorepo(projectDir, packageJson) {
1972
+ const markers = [];
1973
+ if (await exists(join(projectDir, "pnpm-workspace.yaml"))) markers.push("pnpm-workspace.yaml");
1974
+ if (await exists(join(projectDir, "turbo.json"))) markers.push("turbo.json");
1975
+ if (await exists(join(projectDir, "nx.json"))) markers.push("nx.json");
1976
+ const workspaces = packageJson?.workspaces;
1977
+ if (Array.isArray(workspaces) || isRecord(workspaces)) markers.push("package.json workspaces");
1978
+ return {
1979
+ detected: markers.length > 0,
1980
+ markers
1981
+ };
1612
1982
  }
1613
1983
  async function detectPackageManager(projectDir, packageJson) {
1614
1984
  const lockfiles = [];
@@ -1671,16 +2041,6 @@ async function readPackageJson(path) {
1671
2041
  };
1672
2042
  }
1673
2043
  }
1674
- function collectDependencies(packageJson) {
1675
- const dependencies = /* @__PURE__ */ new Set();
1676
- for (const field of [
1677
- packageJson?.dependencies,
1678
- packageJson?.devDependencies,
1679
- packageJson?.peerDependencies,
1680
- packageJson?.optionalDependencies
1681
- ]) if (isRecord(field)) for (const name of Object.keys(field)) dependencies.add(name);
1682
- return dependencies;
1683
- }
1684
2044
  function parsePackageManagerName(value) {
1685
2045
  const name = value?.split("@")[0];
1686
2046
  return PACKAGE_MANAGERS.includes(name) ? name : void 0;
@@ -1704,6 +2064,128 @@ function isNotFound(cause) {
1704
2064
  return cause instanceof Error && cause.code === "ENOENT";
1705
2065
  }
1706
2066
  //#endregion
2067
+ //#region src/project/detector.ts
2068
+ /**
2069
+ * Factual project detection only. It gathers `ProjectSignals` and never decides which packs or
2070
+ * capabilities fit — that policy lives in `recommendCapabilities`, kept separate so each half stays
2071
+ * independently testable.
2072
+ */
2073
+ async function detectProject(projectDir) {
2074
+ const signals = await collectProjectSignals(projectDir);
2075
+ return {
2076
+ projectDir,
2077
+ packageJson: signals.packageJson,
2078
+ packageManager: signals.packageManager,
2079
+ signals
2080
+ };
2081
+ }
2082
+ function buildAgentyxConfig(input) {
2083
+ return {
2084
+ packs: [...input.packs],
2085
+ enable: [...input.enable ?? []],
2086
+ targets: [...input.targets]
2087
+ };
2088
+ }
2089
+ function formatAgentyxConfig(config) {
2090
+ return `${JSON.stringify(config, null, 2)}\n`;
2091
+ }
2092
+ //#endregion
2093
+ //#region src/project/recommend.ts
2094
+ const RECOMMENDATION_CONFIDENCES = ["high", "medium"];
2095
+ /**
2096
+ * Heuristic thresholds for the `codebase-memory` capability suggestion, in scanned source files.
2097
+ * These are approximate signals, not exact token accounting, and a monorepo is treated as already
2098
+ * complex enough to lower the bar.
2099
+ */
2100
+ const CODEBASE_MEMORY_FILE_THRESHOLD = 2e3;
2101
+ const CODEBASE_MEMORY_MONOREPO_FILE_THRESHOLD = 800;
2102
+ /**
2103
+ * Applies conservative, deterministic policy on top of `ProjectSignals`. This is the only place
2104
+ * that turns an observed fact into a product suggestion — `ProjectSignals` stays fact-only so it
2105
+ * can be tested independently of pack names or capability policy.
2106
+ *
2107
+ * Never enables anything and never touches the filesystem: the caller decides what, if anything,
2108
+ * to do with the result.
2109
+ */
2110
+ function recommendCapabilities(signals, options = {}) {
2111
+ const packs = recommendPacks(signals);
2112
+ const configuredPacks = options.configuredPacks ?? [];
2113
+ return {
2114
+ packs,
2115
+ capabilities: recommendOptionalCapabilities(signals, /* @__PURE__ */ new Set([...packs.map((pack) => pack.name), ...configuredPacks]), configuredPacks)
2116
+ };
2117
+ }
2118
+ function recommendPacks(signals) {
2119
+ const packs = [];
2120
+ if (signals.packageJson.present) packs.push(packRecommendation("technical", "high", ["package.json detected — baseline engineering practices apply to any software project."]));
2121
+ const typescriptReasons = [...signals.typescript.dependency !== void 0 ? [dependencyReason("TypeScript", signals.typescript.dependency)] : [], ...signals.typescript.tsconfig ? ["tsconfig.json detected."] : []];
2122
+ if (typescriptReasons.length > 0) packs.push(packRecommendation("typescript", "high", typescriptReasons));
2123
+ if (signals.angular !== void 0) packs.push(packRecommendation("angular", "high", [dependencyReason("@angular/core", signals.angular)]));
2124
+ const testingMatches = dedupeMatches([...signals.testFrameworks, ...signals.browserTesting]);
2125
+ if (testingMatches.length > 0) packs.push(packRecommendation("testing", "high", testingMatches.map((match) => dependencyReason(match.dependency, match))));
2126
+ const devopsReasons = [
2127
+ ...signals.containers.dockerfile ? ["Dockerfile detected."] : [],
2128
+ ...signals.containers.compose ? ["Container compose file detected."] : [],
2129
+ ...signals.ci.githubActions ? ["GitHub Actions workflow detected (.github/workflows)."] : []
2130
+ ];
2131
+ if (devopsReasons.length > 0) packs.push(packRecommendation("devops", "high", devopsReasons));
2132
+ if (signals.observability.length > 0) packs.push(packRecommendation("observability", "high", signals.observability.map((match) => dependencyReason(match.dependency, match))));
2133
+ if (signals.dataTooling.length > 0) packs.push(packRecommendation("data", "high", signals.dataTooling.map((match) => dependencyReason(match.dependency, match))));
2134
+ if (signals.accessibilityTooling.length > 0) packs.push(packRecommendation("accessibility", "high", signals.accessibilityTooling.map((match) => dependencyReason(match.dependency, match))));
2135
+ return packs;
2136
+ }
2137
+ function recommendOptionalCapabilities(signals, activePacks, configuredPacks) {
2138
+ const capabilities = [];
2139
+ const playwrightMatch = signals.browserTesting.find((match) => match.dependency === "@playwright/test");
2140
+ 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."]));
2141
+ if (signals.observability.find((match) => match.dependency.startsWith("@sentry/")) !== void 0) capabilities.push(capabilityRecommendation("sentry", "high", ["Sentry is already configured as a dependency."]));
2142
+ if (signals.dataTooling.find((match) => match.dependency.startsWith("@supabase/")) !== void 0) capabilities.push(capabilityRecommendation("supabase", "high", ["Supabase is already configured as a dependency."]));
2143
+ if (configuredPacks.includes("efficiency") && signals.localTools.rtkAvailable) capabilities.push(capabilityRecommendation("rtk", "high", ["RTK is already installed locally."]));
2144
+ const sizeThreshold = signals.monorepo.detected ? 800 : CODEBASE_MEMORY_FILE_THRESHOLD;
2145
+ if (signals.repositorySize.filesScanned >= sizeThreshold || signals.repositorySize.capped) capabilities.push(capabilityRecommendation("codebase-memory", "medium", [repositorySizeReason(signals)]));
2146
+ return capabilities;
2147
+ }
2148
+ function repositorySizeReason(signals) {
2149
+ const { filesScanned, capped } = signals.repositorySize;
2150
+ const scope = signals.monorepo.detected ? " across this monorepo" : "";
2151
+ 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.`;
2152
+ }
2153
+ function packRecommendation(name, confidence, reasons) {
2154
+ return {
2155
+ kind: "pack",
2156
+ name,
2157
+ confidence,
2158
+ reasons
2159
+ };
2160
+ }
2161
+ /** Provenance comes from the pack registry itself — never a second, hand-maintained capability map. */
2162
+ function capabilityRecommendation(name, confidence, reasons) {
2163
+ return {
2164
+ kind: "capability",
2165
+ name,
2166
+ confidence,
2167
+ reasons,
2168
+ contributedBy: packsDeclaringOptionalCapability(name)
2169
+ };
2170
+ }
2171
+ function packsDeclaringOptionalCapability(name) {
2172
+ const packs = [];
2173
+ 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);
2174
+ return packs;
2175
+ }
2176
+ function dependencyReason(label, match) {
2177
+ return label === match.dependency ? `Detected ${match.dependency} in ${match.field}.` : `Detected ${label} (${match.dependency}) in ${match.field}.`;
2178
+ }
2179
+ function dedupeMatches(matches) {
2180
+ const seen = /* @__PURE__ */ new Set();
2181
+ const result = [];
2182
+ for (const match of matches) if (!seen.has(match.dependency)) {
2183
+ seen.add(match.dependency);
2184
+ result.push(match);
2185
+ }
2186
+ return result;
2187
+ }
2188
+ //#endregion
1707
2189
  //#region src/source/inspection.ts
1708
2190
  async function inspectTrustedSource(projectPath, reference) {
1709
2191
  const definition = getTrustedSourceDefinition(reference);
@@ -1792,6 +2274,6 @@ function trustedSourceLoadError(sourceName, reason, cause) {
1792
2274
  return new TrustedSourceLoadError(sourceName, reason, cause instanceof Error ? { cause } : void 0);
1793
2275
  }
1794
2276
  //#endregion
1795
- export { AGENTYX_CONFIG_FILENAME, AGENTYX_CONFIG_SCHEMA_ID, AGENTYX_MANIFEST_FILENAME, AgentyxConfigNotFoundError, AgentyxConfigParseError, AgentyxConfigValidationError, AgentyxError, AgentyxManifestParseError, AgentyxManifestValidationError, CircularPackDependencyError, DuplicateMcpServerError, DuplicatePackError, DuplicateSkillError, DuplicateToolError, DuplicateTrustedSourceError, INSTALL_MANIFEST_VERSION, InvalidMcpServerError, InvalidSkillError, InvalidToolError, LocalSkillDirectoryError, MCP_CAPABILITY_LEVELS, MCP_CONTEXT_COSTS, PACKAGE_MANAGERS, PACK_CATEGORIES, TOOL_ACTIVATION_LEVELS, TrustedSourceLoadError, UnknownEnabledCapabilityError, UnknownMcpServerError, UnknownPackError, UnknownSkillError, UnknownToolError, UnknownTrustedSourceError, agentyxConfigPath, agentyxConfigSchema, agentyxCoreName, agentyxManifestPath, agentyxTargetSchema, buildAgentyxConfig, buildAgentyxConfigJsonSchema, builtInMcpServerNames, builtInMcpServerRegistry, builtInPackRegistry, builtInPacks, builtInSkillNames, builtInSkillRegistry, builtInToolNames, builtInToolRegistry, codexPluginManifestSchema, collectPackMcpServerReferences, collectPackMcpServers, collectPackToolReferences, createMcpServerRegistry, createPackRegistry, createSkillRegistry, createToolRegistry, createTrustedSourceRegistry, detectProject, emptyInstallManifest, enabledCapabilityNameSchema, filterEffectiveMcpServers, filterEffectiveTools, formatAgentyxConfig, formatInstallManifest, formatSkillMarkdown, getCoreStatus, getTrustedSourceDefinition, hashContent, inspectTrustedSource, installManifestEntrySchema, installManifestSchema, knownTrustedSourceRegistry, knownTrustedSources, loadAgentyxConfig, loadAgentyxProject, loadInstallManifest, manifestEntriesByPath, mcpCapabilityLevelSchema, mcpContextCostSchema, mcpEnvReferenceSchema, mcpManifestEntrySchema, mcpServerDefinitionSchema, mcpServerReferenceSchema, packCategorySchema, packDefinitionSchema, packNameSchema, parseAgentyxConfig, parseInstallManifest, parseSkillMarkdown, resolveAgentyxConfig, resolvePackMcpServerReferences, resolvePackMcpServers, resolvePackSkills, resolvePackToolReferences, resolvePackTools, resolvePacks, skillDefinitionSchema, skillDirectorySchema, skillManifestEntrySchema, toolActivationLevelSchema, toolDefinitionSchema, toolNameSchema, toolReferenceSchema, trustedSourceDefinitionSchema, trustedSourceNameSchema, trustedSourcePathSchema, trustedSourceReferenceSchema, trustedSourceSkillSummarySchema };
2277
+ 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, 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, createSkillRegistry, createToolRegistry, createTrustedSourceRegistry, detectProject, emptyInstallManifest, enabledCapabilityNameSchema, filterEffectiveHooks, filterEffectiveMcpServers, filterEffectiveTools, 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, recommendCapabilities, resolveAgentyxConfig, resolvePackHookReferences, resolvePackHooks, resolvePackMcpServerReferences, resolvePackMcpServers, resolvePackSkills, resolvePackToolReferences, resolvePackTools, resolvePacks, scanRepositorySize, skillDefinitionSchema, skillDirectorySchema, skillManifestEntrySchema, toolActivationLevelSchema, toolDefinitionSchema, toolNameSchema, toolReferenceSchema, trustedSourceDefinitionSchema, trustedSourceNameSchema, trustedSourcePathSchema, trustedSourceReferenceSchema, trustedSourceSkillSummarySchema };
1796
2278
 
1797
2279
  //# sourceMappingURL=index.mjs.map