@agentyx/core 0.1.1 → 0.2.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
@@ -54,6 +54,17 @@ var AgentyxConfigValidationError = class extends AgentyxError {
54
54
  this.filePath = filePath;
55
55
  }
56
56
  };
57
+ var UnknownEnabledCapabilityError = class extends AgentyxError {
58
+ capabilityName;
59
+ knownCapabilities;
60
+ constructor(capabilityName, knownCapabilities) {
61
+ const known = knownCapabilities.length > 0 ? [...knownCapabilities].sort().join(", ") : "none";
62
+ super("unknown_enabled_capability", `Unknown enabled capability "${capabilityName}". Known optional capabilities: ${known}.`);
63
+ this.name = "UnknownEnabledCapabilityError";
64
+ this.capabilityName = capabilityName;
65
+ this.knownCapabilities = knownCapabilities;
66
+ }
67
+ };
57
68
  function toConfigIssues(error) {
58
69
  return error.issues.map((issue) => ({
59
70
  path: formatIssuePath(issue.path),
@@ -69,11 +80,7 @@ function formatIssuePath(path) {
69
80
  }
70
81
  //#endregion
71
82
  //#region src/mcp/schema.ts
72
- const MCP_CAPABILITY_LEVELS = [
73
- "essential",
74
- "recommended",
75
- "optional"
76
- ];
83
+ const MCP_CAPABILITY_LEVELS = ["default", "optional"];
77
84
  const mcpCapabilityLevelSchema = z.enum(MCP_CAPABILITY_LEVELS);
78
85
  const MCP_CONTEXT_COSTS = [
79
86
  "low",
@@ -91,14 +98,14 @@ const commonMcpServerDefinitionSchema = z.strictObject({
91
98
  });
92
99
  const explicitMcpServerReferenceSchema = z.strictObject({
93
100
  name: mcpServerNameSchema.describe("MCP server identifier."),
94
- level: mcpCapabilityLevelSchema.describe("How important this MCP capability is to the declaring stack.").default("recommended")
101
+ activation: mcpCapabilityLevelSchema.describe("Whether this MCP capability is active by default or explicit opt-in.").default("default")
95
102
  });
96
103
  const mcpServerReferenceSchema = z.union([mcpServerNameSchema, explicitMcpServerReferenceSchema]).transform((value) => typeof value === "string" ? {
97
104
  name: value,
98
- level: "recommended"
105
+ activation: "default"
99
106
  } : value).pipe(z.strictObject({
100
107
  name: mcpServerNameSchema.describe("MCP server identifier."),
101
- level: mcpCapabilityLevelSchema.describe("How important this MCP capability is to the declaring stack.")
108
+ activation: mcpCapabilityLevelSchema.describe("Whether this MCP capability is active by default or explicit opt-in.")
102
109
  }));
103
110
  const stdioMcpServerDefinitionSchema = commonMcpServerDefinitionSchema.extend({
104
111
  transport: z.literal("stdio"),
@@ -135,44 +142,65 @@ const skillMetadataSchema = z.strictObject({
135
142
  */
136
143
  const skillDefinitionSchema = skillMetadataSchema.extend({ content: z.string().trim().min(1, "Skill content must be non-empty.").describe("The Markdown instructions handed to an agent.") });
137
144
  //#endregion
138
- //#region src/stack/schema.ts
139
- /**
140
- * Stack names are plain identifiers. They are intentionally not constrained to
141
- * a closed list so that external registries can contribute stacks later.
142
- */
143
- const stackNameSchema = z.string().min(1, "Stack names must be non-empty strings.");
145
+ //#region src/tool/schema.ts
146
+ const TOOL_ACTIVATION_LEVELS = ["default", "optional"];
147
+ const toolActivationLevelSchema = z.enum(TOOL_ACTIVATION_LEVELS);
148
+ const toolNameSchema = z.string().min(1, "Tool names must be non-empty strings.").regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Tool names must be lowercase kebab-case, for example \"rtk\".");
149
+ const toolReferenceSchema = z.union([toolNameSchema, z.strictObject({
150
+ name: toolNameSchema.describe("Tool identifier."),
151
+ activation: toolActivationLevelSchema.default("default")
152
+ })]).transform((value) => typeof value === "string" ? {
153
+ name: value,
154
+ activation: "default"
155
+ } : value).pipe(z.strictObject({
156
+ name: toolNameSchema.describe("Tool identifier."),
157
+ activation: toolActivationLevelSchema
158
+ }));
159
+ const toolDefinitionSchema = z.strictObject({
160
+ name: toolNameSchema.describe("Unique tool identifier."),
161
+ description: z.string().trim().min(1, "Tool descriptions must be non-empty strings."),
162
+ kind: z.literal("executable"),
163
+ command: z.string().trim().min(1, "Tool executable command must be a non-empty string."),
164
+ optional: z.boolean().default(true),
165
+ installHint: z.string().trim().min(1, "Tool install hints must be non-empty strings.").optional()
166
+ });
167
+ //#endregion
168
+ //#region src/pack/schema.ts
169
+ const PACK_CATEGORIES = [
170
+ "engineering",
171
+ "language",
172
+ "framework",
173
+ "efficiency",
174
+ "workflow"
175
+ ];
176
+ const packCategorySchema = z.enum(PACK_CATEGORIES);
144
177
  /**
145
- * A stack describes a development environment that can build on other stacks
146
- * and contribute provider-agnostic capabilities to them.
178
+ * Pack names are plain identifiers. They are intentionally not constrained to
179
+ * a closed list so that external registries can contribute packs later.
147
180
  */
148
- const stackDefinitionSchema = z.strictObject({
149
- name: stackNameSchema.describe("Unique stack identifier."),
150
- description: z.string().min(1, "Stack descriptions must be non-empty when provided.").describe("Short human-readable summary of the stack.").optional(),
151
- extends: z.array(stackNameSchema).describe("Stacks this stack builds on, in dependency-first order.").default([]),
152
- skills: z.array(skillNameSchema).describe("Skills this stack contributes, in declaration order.").default([]),
153
- mcpServers: z.array(mcpServerReferenceSchema).describe("MCP servers this stack contributes, in declaration order.").default([])
181
+ const packNameSchema = z.string().min(1, "Pack names must be non-empty strings.");
182
+ /** A pack is a composable provider-neutral capability bundle. */
183
+ const packDefinitionSchema = z.strictObject({
184
+ name: packNameSchema.describe("Unique pack identifier."),
185
+ category: packCategorySchema.describe("Discoverability category; does not affect resolution.").default("engineering"),
186
+ description: z.string().min(1, "Pack descriptions must be non-empty when provided.").describe("Short human-readable summary of the pack.").optional(),
187
+ skills: z.array(skillNameSchema).describe("Skills this pack contributes, in declaration order.").default([]),
188
+ mcpServers: z.array(mcpServerReferenceSchema).describe("MCP servers this pack contributes, in declaration order.").default([]),
189
+ tools: z.array(toolReferenceSchema).describe("Local tools this pack contributes, in declaration order.").default([])
154
190
  });
155
191
  //#endregion
156
192
  //#region src/config/schema.ts
157
- /** How much autonomy the generated environment should grant an agent. */
158
- const AGENTYX_PROFILES = [
159
- "lean",
160
- "balanced",
161
- "autonomous"
162
- ];
163
- const agentyxProfileSchema = z.enum(AGENTYX_PROFILES, { error: `Profile must be one of: ${AGENTYX_PROFILES.join(", ")}.` });
164
- /** Applied when a configuration omits `profile`. */
165
- const DEFAULT_AGENTYX_PROFILE = "balanced";
166
193
  /**
167
194
  * Targets stay free-form strings on purpose: third-party adapters should be
168
195
  * able to register providers without a change to this schema.
169
196
  */
170
197
  const agentyxTargetSchema = z.string().min(1, "Targets must be non-empty strings.");
198
+ const enabledCapabilityNameSchema = z.string().min(1, "Enabled capability names must be non-empty strings.").regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "Enabled capability names must be lowercase kebab-case, for example \"rtk\".");
171
199
  /** The `.agentyx.json` project configuration. */
172
200
  const agentyxConfigSchema = z.strictObject({
173
201
  $schema: z.string().min(1, "$schema must be a non-empty string.").describe("Optional path or URL to the Agentyx JSON Schema.").optional(),
174
- extends: z.array(stackNameSchema).describe("Stacks this project builds on.").default([]),
175
- profile: agentyxProfileSchema.describe("How much autonomy the generated environment grants.").default(DEFAULT_AGENTYX_PROFILE),
202
+ packs: z.array(packNameSchema).describe("Capability packs this project selects.").default([]),
203
+ enable: z.array(enabledCapabilityNameSchema).describe("Optional capabilities to activate by explicit identifier.").default([]),
176
204
  targets: z.array(agentyxTargetSchema).describe("Coding-agent providers this project targets.").default([])
177
205
  });
178
206
  //#endregion
@@ -250,7 +278,7 @@ var UnknownMcpServerError = class extends AgentyxError {
250
278
  requiredBy;
251
279
  knownServers;
252
280
  constructor(serverName, requiredBy, knownServers) {
253
- const origin = requiredBy === void 0 ? "" : ` (required by stack "${requiredBy}")`;
281
+ const origin = requiredBy === void 0 ? "" : ` (required by "${requiredBy}")`;
254
282
  const known = knownServers.length > 0 ? [...knownServers].sort().join(", ") : "none";
255
283
  super("unknown_mcp_server", `Unknown MCP server "${serverName}"${origin}. Known MCP servers: ${known}.`);
256
284
  this.name = "UnknownMcpServerError";
@@ -323,208 +351,210 @@ function createMcpServerRegistry(sources) {
323
351
  get
324
352
  };
325
353
  }
326
- const builtInMcpServerRegistry = createMcpServerRegistry([{
327
- name: "context7",
328
- load: () => ({
329
- name: "context7",
330
- description: "Fetch up-to-date library documentation from Context7.",
331
- transport: "http",
332
- contextCost: "medium",
333
- url: "https://mcp.context7.com/mcp"
334
- })
335
- }, {
336
- name: "playwright",
337
- load: () => ({
338
- name: "playwright",
339
- description: "Automate and inspect browsers through Playwright MCP.",
340
- transport: "stdio",
341
- contextCost: "high",
342
- command: "npx",
343
- args: ["@playwright/mcp@latest"]
344
- })
345
- }]);
346
- const builtInMcpServerNames = builtInMcpServerRegistry.names;
347
- //#endregion
348
- //#region src/optimization/profile.ts
349
- const optimizationProfiles = [
354
+ const builtInMcpServerRegistry = createMcpServerRegistry([
350
355
  {
351
- name: "lean",
352
- goal: "Minimum context and tool overhead.",
353
- mcpLevels: ["essential"],
354
- notes: [
355
- "Installs all resolved Skills.",
356
- "Keeps MCP exposure to essential capabilities.",
357
- "Prefers local CLI or native tools when they cover the same workflow."
358
- ]
356
+ name: "context7",
357
+ load: () => ({
358
+ name: "context7",
359
+ description: "Fetch up-to-date library documentation from Context7.",
360
+ transport: "http",
361
+ contextCost: "medium",
362
+ url: "https://mcp.context7.com/mcp"
363
+ })
359
364
  },
360
365
  {
361
- name: "balanced",
362
- goal: "Good default developer experience with conservative autonomy.",
363
- mcpLevels: ["essential", "recommended"],
364
- notes: ["Installs all resolved Skills.", "Includes default and recommended MCP capabilities."]
366
+ name: "playwright",
367
+ load: () => ({
368
+ name: "playwright",
369
+ description: "Automate and inspect browsers through Playwright MCP.",
370
+ transport: "stdio",
371
+ contextCost: "high",
372
+ command: "npx",
373
+ args: ["@playwright/mcp@latest"]
374
+ })
365
375
  },
366
376
  {
367
- name: "autonomous",
368
- goal: "Maximum agent capability from declared stack capabilities.",
369
- mcpLevels: [
370
- "essential",
371
- "recommended",
372
- "optional"
373
- ],
374
- notes: ["Installs all resolved Skills.", "Includes optional MCP capabilities declared by the selected stacks."]
377
+ name: "codebase-memory",
378
+ load: () => ({
379
+ name: "codebase-memory",
380
+ description: "Structural code-intelligence MCP backed by a persistent code knowledge graph.",
381
+ transport: "stdio",
382
+ contextCost: "high",
383
+ command: "codebase-memory-mcp"
384
+ })
375
385
  }
376
- ];
377
- const optimizationProfileNames = optimizationProfiles.map((profile) => profile.name);
378
- function getOptimizationProfile(name) {
379
- const profile = optimizationProfiles.find((candidate) => candidate.name === name);
380
- if (profile === void 0) throw new Error(`Unknown optimization profile: ${name}`);
381
- return profile;
382
- }
383
- function isMcpLevelEnabled(profile, level) {
384
- return getOptimizationProfile(profile).mcpLevels.includes(level);
385
- }
386
+ ]);
387
+ const builtInMcpServerNames = builtInMcpServerRegistry.names;
386
388
  //#endregion
387
- //#region src/stack/errors.ts
388
- /**
389
- * Raised when a requested or inherited stack is not present in the registry.
390
- *
391
- * The offending name is exposed as `stackName`; `stack` stays the JS stack
392
- * trace inherited from `Error`.
393
- */
394
- var UnknownStackError = class extends AgentyxError {
395
- stackName;
389
+ //#region src/pack/errors.ts
390
+ /** Raised when a requested pack is not present in the registry. */
391
+ var UnknownPackError = class extends AgentyxError {
392
+ packName;
396
393
  requiredBy;
397
- knownStacks;
398
- constructor(stackName, requiredBy, knownStacks) {
394
+ knownPacks;
395
+ constructor(packName, requiredBy, knownPacks) {
399
396
  const origin = requiredBy === void 0 ? "" : ` (required by "${requiredBy}")`;
400
- const known = knownStacks.length > 0 ? [...knownStacks].sort().join(", ") : "none";
401
- super("unknown_stack", `Unknown stack "${stackName}"${origin}. Known stacks: ${known}.`);
402
- this.name = "UnknownStackError";
403
- this.stackName = stackName;
397
+ const known = knownPacks.length > 0 ? [...knownPacks].sort().join(", ") : "none";
398
+ super("unknown_pack", `Unknown pack "${packName}"${origin}. Known packs: ${known}.`);
399
+ this.name = "UnknownPackError";
400
+ this.packName = packName;
404
401
  this.requiredBy = requiredBy;
405
- this.knownStacks = knownStacks;
402
+ this.knownPacks = knownPacks;
406
403
  }
407
404
  };
408
- /** Raised when stack inheritance forms a cycle. */
409
- var CircularStackDependencyError = class extends AgentyxError {
410
- /** The cycle path, starting and ending with the same stack. */
405
+ /** @deprecated Packs no longer inherit from other packs. */
406
+ var CircularPackDependencyError = class extends AgentyxError {
407
+ /** The cycle path, starting and ending with the same pack. */
411
408
  cycle;
412
409
  constructor(cycle) {
413
- super("circular_stack_dependency", `Circular stack dependency: ${cycle.join(" -> ")}.`);
414
- this.name = "CircularStackDependencyError";
410
+ super("circular_pack_dependency", `Circular pack dependency: ${cycle.join(" -> ")}.`);
411
+ this.name = "CircularPackDependencyError";
415
412
  this.cycle = cycle;
416
413
  }
417
414
  };
418
- /** Raised when a registry is built from definitions that reuse a stack name. */
419
- var DuplicateStackError = class extends AgentyxError {
420
- stackName;
421
- constructor(stackName) {
422
- super("duplicate_stack", `Duplicate stack definition: "${stackName}".`);
423
- this.name = "DuplicateStackError";
424
- this.stackName = stackName;
415
+ /** Raised when a registry is built from definitions that reuse a pack name. */
416
+ var DuplicatePackError = class extends AgentyxError {
417
+ packName;
418
+ constructor(packName) {
419
+ super("duplicate_pack", `Duplicate pack definition: "${packName}".`);
420
+ this.name = "DuplicatePackError";
421
+ this.packName = packName;
425
422
  }
426
423
  };
427
424
  //#endregion
428
- //#region src/stack/registry.ts
425
+ //#region src/pack/registry.ts
429
426
  /** Validates definitions and indexes them by name. */
430
- function createStackRegistry(definitions) {
427
+ function createPackRegistry(definitions) {
431
428
  const registry = /* @__PURE__ */ new Map();
432
429
  for (const definition of definitions) {
433
- const stack = stackDefinitionSchema.parse(definition);
434
- if (registry.has(stack.name)) throw new DuplicateStackError(stack.name);
435
- registry.set(stack.name, stack);
430
+ const pack = packDefinitionSchema.parse(definition);
431
+ if (registry.has(pack.name)) throw new DuplicatePackError(pack.name);
432
+ registry.set(pack.name, pack);
436
433
  }
437
434
  return registry;
438
435
  }
439
436
  /**
440
- * The stacks Agentyx ships with, expressed as data. Relationships live here, not
437
+ * The packs Agentyx ships with, expressed as data. Relationships live here, not
441
438
  * in the resolver.
442
439
  */
443
- const builtInStacks = [
440
+ const builtInPacks = [
444
441
  {
445
- name: "core",
446
- description: "Baseline development environment shared by every Agentyx stack.",
442
+ name: "technical",
443
+ category: "engineering",
444
+ description: "General software-engineering quality independent of language or framework.",
447
445
  skills: [
448
- "planning",
449
- "systematic-debugging",
450
- "verification"
446
+ "engineering-principles",
447
+ "code-quality",
448
+ "api-design",
449
+ "code-review"
451
450
  ]
452
451
  },
453
452
  {
454
453
  name: "typescript",
455
- description: "TypeScript development environment.",
456
- extends: ["core"],
457
- skills: ["typescript-modern"]
454
+ category: "language",
455
+ description: "TypeScript language conventions for strict, modern code.",
456
+ skills: [
457
+ "typescript-strict",
458
+ "typescript-modeling",
459
+ "typescript-modern"
460
+ ]
458
461
  },
459
462
  {
460
463
  name: "angular",
464
+ category: "framework",
461
465
  description: "Modern Angular development environment.",
462
- extends: ["typescript"],
463
- skills: ["angular-modern"],
466
+ skills: [
467
+ "angular-modern",
468
+ "angular-signals",
469
+ "angular-architecture",
470
+ "angular-testing"
471
+ ],
472
+ mcpServers: ["context7"]
473
+ },
474
+ {
475
+ name: "efficiency",
476
+ category: "efficiency",
477
+ description: "Reduce context and tool overhead without weakening verification.",
478
+ skills: [
479
+ "context-efficient-development",
480
+ "concise-output",
481
+ "targeted-exploration",
482
+ "focused-verification"
483
+ ],
464
484
  mcpServers: [{
465
- name: "context7",
466
- level: "recommended"
485
+ name: "codebase-memory",
486
+ activation: "optional"
487
+ }],
488
+ tools: [{
489
+ name: "rtk",
490
+ activation: "optional"
467
491
  }]
492
+ },
493
+ {
494
+ name: "agentic",
495
+ category: "workflow",
496
+ description: "Provider-neutral development workflows for substantial coding-agent work.",
497
+ skills: [
498
+ "brainstorming",
499
+ "planning",
500
+ "systematic-debugging",
501
+ "verification",
502
+ "parallel-work",
503
+ "worktree-workflow",
504
+ "subagent-driven-development",
505
+ "requesting-code-review"
506
+ ]
468
507
  }
469
508
  ];
470
509
  /** The registry used by default when no explicit registry is supplied. */
471
- const builtInStackRegistry = createStackRegistry(builtInStacks);
510
+ const builtInPackRegistry = createPackRegistry(builtInPacks);
472
511
  //#endregion
473
- //#region src/stack/resolver.ts
512
+ //#region src/pack/resolver.ts
474
513
  /**
475
- * Expands the requested stacks into the full inheritance chain.
514
+ * Resolves selected packs without hidden inheritance.
476
515
  *
477
- * The result is dependency-first, de-duplicated and deterministic: stacks are
478
- * visited in the order they are requested, and each stack's parents are visited
479
- * in declaration order before the stack itself.
516
+ * The result preserves configured order, removes duplicates by first
517
+ * occurrence, and validates every requested pack.
480
518
  *
481
- * @throws {UnknownStackError} when a requested or inherited stack is missing.
482
- * @throws {CircularStackDependencyError} when inheritance forms a cycle.
519
+ * @throws {UnknownPackError} when a requested pack is missing.
483
520
  */
484
- function resolveStacks(requestedStacks, registry = builtInStackRegistry) {
521
+ function resolvePacks(requestedPacks, registry = builtInPackRegistry) {
485
522
  const resolved = [];
486
- const settled = /* @__PURE__ */ new Set();
487
- const path = [];
488
- const visit = (name, requiredBy) => {
489
- if (settled.has(name)) return;
490
- const cycleStart = path.indexOf(name);
491
- if (cycleStart !== -1) throw new CircularStackDependencyError([...path.slice(cycleStart), name]);
492
- const definition = registry.get(name);
493
- if (definition === void 0) throw new UnknownStackError(name, requiredBy, [...registry.keys()]);
494
- path.push(name);
495
- for (const parent of definition.extends) visit(parent, name);
496
- path.pop();
497
- settled.add(name);
523
+ const seen = /* @__PURE__ */ new Set();
524
+ for (const name of requestedPacks) {
525
+ if (seen.has(name)) continue;
526
+ if (!registry.has(name)) throw new UnknownPackError(name, void 0, [...registry.keys()]);
527
+ seen.add(name);
498
528
  resolved.push(name);
499
- };
500
- for (const name of requestedStacks) visit(name, void 0);
529
+ }
501
530
  return resolved;
502
531
  }
503
532
  //#endregion
504
533
  //#region src/mcp/resolver.ts
505
- function collectStackMcpServerReferences(resolvedStacks, stackRegistry, mcpRegistry) {
534
+ function collectPackMcpServerReferences(resolvedPacks, packRegistry, mcpRegistry) {
506
535
  const servers = [];
507
536
  const seen = /* @__PURE__ */ new Set();
508
- for (const stackName of resolvedStacks) for (const server of stackRegistry.get(stackName)?.mcpServers ?? []) {
537
+ for (const packName of resolvedPacks) for (const server of packRegistry.get(packName)?.mcpServers ?? []) {
509
538
  const serverName = server.name;
510
539
  if (seen.has(serverName)) continue;
511
- if (!mcpRegistry.has(serverName)) throw new UnknownMcpServerError(serverName, stackName, mcpRegistry.names);
540
+ if (!mcpRegistry.has(serverName)) throw new UnknownMcpServerError(serverName, packName, mcpRegistry.names);
512
541
  seen.add(serverName);
513
542
  servers.push(server);
514
543
  }
515
544
  return servers;
516
545
  }
517
- function filterEffectiveMcpServers(servers, profile) {
518
- return servers.filter((server) => isMcpLevelEnabled(profile, server.level)).map((server) => server.name);
546
+ function filterEffectiveMcpServers(servers, enabledCapabilities) {
547
+ const enabled = new Set(enabledCapabilities);
548
+ return servers.filter((server) => server.activation === "default" || enabled.has(server.name)).map((server) => server.name);
519
549
  }
520
- function collectStackMcpServers(resolvedStacks, stackRegistry, mcpRegistry, profile = DEFAULT_AGENTYX_PROFILE) {
521
- return filterEffectiveMcpServers(collectStackMcpServerReferences(resolvedStacks, stackRegistry, mcpRegistry), profile);
550
+ function collectPackMcpServers(resolvedPacks, packRegistry, mcpRegistry, enabledCapabilities = []) {
551
+ return filterEffectiveMcpServers(collectPackMcpServerReferences(resolvedPacks, packRegistry, mcpRegistry), enabledCapabilities);
522
552
  }
523
- function resolveStackMcpServerReferences(requestedStacks, stackRegistry = builtInStackRegistry, mcpRegistry = builtInMcpServerRegistry) {
524
- return collectStackMcpServerReferences(resolveStacks(requestedStacks, stackRegistry), stackRegistry, mcpRegistry);
553
+ function resolvePackMcpServerReferences(requestedPacks, packRegistry = builtInPackRegistry, mcpRegistry = builtInMcpServerRegistry) {
554
+ return collectPackMcpServerReferences(resolvePacks(requestedPacks, packRegistry), packRegistry, mcpRegistry);
525
555
  }
526
- function resolveStackMcpServers(requestedStacks, stackRegistry = builtInStackRegistry, mcpRegistry = builtInMcpServerRegistry, profile = DEFAULT_AGENTYX_PROFILE) {
527
- return collectStackMcpServers(resolveStacks(requestedStacks, stackRegistry), stackRegistry, mcpRegistry, profile);
556
+ function resolvePackMcpServers(requestedPacks, packRegistry = builtInPackRegistry, mcpRegistry = builtInMcpServerRegistry, enabledCapabilities = []) {
557
+ return collectPackMcpServers(resolvePacks(requestedPacks, packRegistry), packRegistry, mcpRegistry, enabledCapabilities);
528
558
  }
529
559
  //#endregion
530
560
  //#region src/assets.ts
@@ -545,18 +575,18 @@ const BUILT_IN_SKILLS_PATH = fileURLToPath(new URL("../skills", import.meta.url)
545
575
  //#endregion
546
576
  //#region src/skill/errors.ts
547
577
  /**
548
- * Raised when a stack references a skill the registry does not know.
578
+ * Raised when a pack references a skill the registry does not know.
549
579
  *
550
- * The offending name is exposed as `skillName`; `stack` stays the JS stack
580
+ * The offending name is exposed as `skillName`; `pack` stays the JS pack
551
581
  * trace inherited from `Error`.
552
582
  */
553
583
  var UnknownSkillError = class extends AgentyxError {
554
584
  skillName;
555
- /** The stack that declared the skill, when the failure came from resolution. */
585
+ /** The pack that declared the skill, when the failure came from resolution. */
556
586
  requiredBy;
557
587
  knownSkills;
558
588
  constructor(skillName, requiredBy, knownSkills) {
559
- const origin = requiredBy === void 0 ? "" : ` (required by stack "${requiredBy}")`;
589
+ const origin = requiredBy === void 0 ? "" : ` (required by pack "${requiredBy}")`;
560
590
  const known = knownSkills.length > 0 ? [...knownSkills].sort().join(", ") : "none";
561
591
  super("unknown_skill", `Unknown skill "${skillName}"${origin}. Known skills: ${known}.`);
562
592
  this.name = "UnknownSkillError";
@@ -724,14 +754,32 @@ function createSkillRegistry(sources) {
724
754
  /**
725
755
  * The skills Agentyx ships with. The names are the directory names under
726
756
  * `packages/core/skills`, and knowing them without touching the filesystem is
727
- * what lets stack resolution validate references without reading any body.
757
+ * what lets pack resolution validate references without reading any body.
728
758
  */
729
759
  const builtInSkillNames = [
760
+ "engineering-principles",
761
+ "code-quality",
762
+ "api-design",
763
+ "code-review",
730
764
  "planning",
731
765
  "systematic-debugging",
732
766
  "verification",
767
+ "brainstorming",
768
+ "parallel-work",
769
+ "worktree-workflow",
770
+ "subagent-driven-development",
771
+ "requesting-code-review",
772
+ "typescript-strict",
773
+ "typescript-modeling",
733
774
  "typescript-modern",
734
- "angular-modern"
775
+ "angular-modern",
776
+ "angular-signals",
777
+ "angular-architecture",
778
+ "angular-testing",
779
+ "context-efficient-development",
780
+ "concise-output",
781
+ "targeted-exploration",
782
+ "focused-verification"
735
783
  ];
736
784
  /** The absolute path of a built-in skill's `SKILL.md`. */
737
785
  function builtInSkillPath(name) {
@@ -763,59 +811,169 @@ function loadBuiltInSkill(name) {
763
811
  //#endregion
764
812
  //#region src/skill/resolver.ts
765
813
  /**
766
- * Collects the skills contributed by an already-resolved stack chain.
814
+ * Collects the skills contributed by an already-resolved pack chain.
767
815
  *
768
816
  * Only identifiers are produced — no skill body is read — so this stays cheap
769
817
  * enough to run on every `resolve`.
770
818
  *
771
- * @throws {UnknownSkillError} when a stack references a skill the registry lacks.
819
+ * @throws {UnknownSkillError} when a pack references a skill the registry lacks.
772
820
  */
773
- function collectStackSkills(resolvedStacks, stackRegistry, skillRegistry) {
821
+ function collectPackSkills(resolvedPacks, packRegistry, skillRegistry) {
774
822
  const skills = [];
775
823
  const seen = /* @__PURE__ */ new Set();
776
- for (const stackName of resolvedStacks) for (const skillName of stackRegistry.get(stackName)?.skills ?? []) {
824
+ for (const packName of resolvedPacks) for (const skillName of packRegistry.get(packName)?.skills ?? []) {
777
825
  if (seen.has(skillName)) continue;
778
- if (!skillRegistry.has(skillName)) throw new UnknownSkillError(skillName, stackName, skillRegistry.names);
826
+ if (!skillRegistry.has(skillName)) throw new UnknownSkillError(skillName, packName, skillRegistry.names);
779
827
  seen.add(skillName);
780
828
  skills.push(skillName);
781
829
  }
782
830
  return skills;
783
831
  }
784
832
  /**
785
- * Expands the requested stacks and returns the skills they contribute.
833
+ * Resolves the requested packs and returns the skills they contribute.
786
834
  *
787
- * The result follows the resolved stack order, then each stack's declaration
835
+ * The result follows the resolved pack order, then each pack's declaration
788
836
  * order, and is de-duplicated by first occurrence. Skills do not extend other
789
837
  * skills, so there is nothing further to expand.
790
838
  *
791
- * @throws {UnknownStackError} when a requested or inherited stack is missing.
792
- * @throws {CircularStackDependencyError} when stack inheritance forms a cycle.
793
- * @throws {UnknownSkillError} when a stack references a skill the registry lacks.
839
+ * @throws {UnknownPackError} when a requested pack is missing.
840
+ * @throws {UnknownSkillError} when a pack references a skill the registry lacks.
794
841
  */
795
- function resolveStackSkills(requestedStacks, stackRegistry = builtInStackRegistry, skillRegistry = builtInSkillRegistry) {
796
- return collectStackSkills(resolveStacks(requestedStacks, stackRegistry), stackRegistry, skillRegistry);
842
+ function resolvePackSkills(requestedPacks, packRegistry = builtInPackRegistry, skillRegistry = builtInSkillRegistry) {
843
+ return collectPackSkills(resolvePacks(requestedPacks, packRegistry), packRegistry, skillRegistry);
844
+ }
845
+ //#endregion
846
+ //#region src/tool/errors.ts
847
+ var UnknownToolError = class extends AgentyxError {
848
+ toolName;
849
+ requiredBy;
850
+ knownTools;
851
+ constructor(toolName, requiredBy, knownTools) {
852
+ const origin = requiredBy === void 0 ? "" : ` (required by "${requiredBy}")`;
853
+ const known = knownTools.length > 0 ? [...knownTools].sort().join(", ") : "none";
854
+ super("unknown_tool", `Unknown tool "${toolName}"${origin}. Known tools: ${known}.`);
855
+ this.name = "UnknownToolError";
856
+ this.toolName = toolName;
857
+ this.requiredBy = requiredBy;
858
+ this.knownTools = knownTools;
859
+ }
860
+ };
861
+ var DuplicateToolError = class extends AgentyxError {
862
+ toolName;
863
+ constructor(toolName) {
864
+ super("duplicate_tool", `Duplicate tool definition: "${toolName}".`);
865
+ this.name = "DuplicateToolError";
866
+ this.toolName = toolName;
867
+ }
868
+ };
869
+ var InvalidToolError = class extends AgentyxError {
870
+ constructor(origin, reason, options) {
871
+ const message = reason instanceof Error ? reason.message : String(reason);
872
+ super("invalid_tool", `Invalid ${origin}: ${message}.`, options);
873
+ this.name = "InvalidToolError";
874
+ }
875
+ };
876
+ //#endregion
877
+ //#region src/tool/registry.ts
878
+ function createToolRegistry(sources) {
879
+ const byName = /* @__PURE__ */ new Map();
880
+ for (const source of sources) {
881
+ const name = toolNameSchema.safeParse(source.name);
882
+ if (!name.success) throw new InvalidToolError(`tool source "${source.name}"`, name.error);
883
+ if (byName.has(name.data)) throw new DuplicateToolError(name.data);
884
+ byName.set(name.data, source);
885
+ }
886
+ const names = [...byName.keys()];
887
+ const loaded = /* @__PURE__ */ new Map();
888
+ const get = (name) => {
889
+ const cached = loaded.get(name);
890
+ if (cached !== void 0) return cached;
891
+ const source = byName.get(name);
892
+ if (source === void 0) throw new UnknownToolError(name, void 0, names);
893
+ const origin = `tool "${name}"`;
894
+ const tool = toolDefinitionSchema.safeParse(source.load());
895
+ if (!tool.success) throw new InvalidToolError(origin, tool.error);
896
+ if (tool.data.name !== name) throw new InvalidToolError(origin, `it declares the name "${tool.data.name}"`);
897
+ loaded.set(name, tool.data);
898
+ return tool.data;
899
+ };
900
+ return {
901
+ names,
902
+ has: (name) => byName.has(name),
903
+ listMetadata: () => names.map((name) => {
904
+ const tool = get(name);
905
+ return {
906
+ name: tool.name,
907
+ description: tool.description,
908
+ kind: tool.kind,
909
+ command: tool.command,
910
+ optional: tool.optional
911
+ };
912
+ }),
913
+ get
914
+ };
915
+ }
916
+ const builtInToolRegistry = createToolRegistry([{
917
+ name: "rtk",
918
+ load: () => ({
919
+ name: "rtk",
920
+ description: "Rust Token Killer command-output proxy for reducing coding-agent context noise.",
921
+ kind: "executable",
922
+ command: "rtk",
923
+ optional: true,
924
+ installHint: "Install from the rtk-ai/rtk project if your local workflow benefits from it."
925
+ })
926
+ }]);
927
+ const builtInToolNames = builtInToolRegistry.names;
928
+ //#endregion
929
+ //#region src/tool/resolver.ts
930
+ function collectPackToolReferences(resolvedPacks, packRegistry, toolRegistry) {
931
+ const tools = [];
932
+ const seen = /* @__PURE__ */ new Set();
933
+ for (const packName of resolvedPacks) for (const tool of packRegistry.get(packName)?.tools ?? []) {
934
+ if (seen.has(tool.name)) continue;
935
+ if (!toolRegistry.has(tool.name)) throw new UnknownToolError(tool.name, packName, toolRegistry.names);
936
+ seen.add(tool.name);
937
+ tools.push(tool);
938
+ }
939
+ return tools;
940
+ }
941
+ function filterEffectiveTools(tools, enabledCapabilities) {
942
+ const enabled = new Set(enabledCapabilities);
943
+ return tools.filter((tool) => tool.activation === "default" || enabled.has(tool.name)).map((tool) => tool.name);
944
+ }
945
+ function resolvePackToolReferences(requestedPacks, packRegistry = builtInPackRegistry, toolRegistry = builtInToolRegistry) {
946
+ return collectPackToolReferences(resolvePacks(requestedPacks, packRegistry), packRegistry, toolRegistry);
947
+ }
948
+ function resolvePackTools(requestedPacks, packRegistry = builtInPackRegistry, toolRegistry = builtInToolRegistry, enabledCapabilities = []) {
949
+ return filterEffectiveTools(resolvePackToolReferences(requestedPacks, packRegistry, toolRegistry), enabledCapabilities);
797
950
  }
798
951
  //#endregion
799
952
  //#region src/config/resolver.ts
800
953
  /**
801
- * Combines a validated project configuration with stack and skill resolution.
954
+ * Combines a validated project configuration with pack and skill resolution.
802
955
  * The input is never mutated.
803
956
  *
804
- * @throws {UnknownStackError} when a configured stack is missing.
805
- * @throws {CircularStackDependencyError} when inheritance forms a cycle.
806
- * @throws {UnknownSkillError} when a stack references an unknown skill.
957
+ * @throws {UnknownPackError} when a configured pack is missing.
958
+ * @throws {CircularPackDependencyError} when inheritance forms a cycle.
959
+ * @throws {UnknownSkillError} when a pack references an unknown skill.
807
960
  */
808
- function resolveAgentyxConfig(config, registry = builtInStackRegistry, skillRegistry = builtInSkillRegistry, mcpRegistry = builtInMcpServerRegistry) {
809
- const requestedStacks = [...config.extends];
810
- const resolvedStacks = resolveStacks(requestedStacks, registry);
811
- const declaredMcpServers = collectStackMcpServerReferences(resolvedStacks, registry, mcpRegistry);
961
+ function resolveAgentyxConfig(config, registry = builtInPackRegistry, skillRegistry = builtInSkillRegistry, mcpRegistry = builtInMcpServerRegistry, toolRegistry = builtInToolRegistry) {
962
+ const requestedPacks = [...config.packs];
963
+ const resolvedPacks = resolvePacks(requestedPacks, registry);
964
+ const declaredMcpServers = collectPackMcpServerReferences(resolvedPacks, registry, mcpRegistry);
965
+ const declaredTools = collectPackToolReferences(resolvedPacks, registry, toolRegistry);
966
+ const knownOptionalCapabilities = [...declaredMcpServers.filter((server) => server.activation === "optional").map((server) => server.name), ...declaredTools.filter((tool) => tool.activation === "optional").map((tool) => tool.name)];
967
+ for (const capability of config.enable) if (!knownOptionalCapabilities.includes(capability)) throw new UnknownEnabledCapabilityError(capability, knownOptionalCapabilities);
812
968
  return {
813
- requestedStacks,
814
- resolvedStacks,
815
- skills: collectStackSkills(resolvedStacks, registry, skillRegistry),
969
+ requestedPacks,
970
+ resolvedPacks,
971
+ skills: collectPackSkills(resolvedPacks, registry, skillRegistry),
816
972
  declaredMcpServers,
817
- mcpServers: filterEffectiveMcpServers(declaredMcpServers, config.profile),
818
- profile: config.profile,
973
+ mcpServers: filterEffectiveMcpServers(declaredMcpServers, config.enable),
974
+ declaredTools,
975
+ tools: filterEffectiveTools(declaredTools, config.enable),
976
+ enabled: [...config.enable],
819
977
  targets: [...config.targets]
820
978
  };
821
979
  }
@@ -844,7 +1002,7 @@ async function detectProject(projectDir) {
844
1002
  const packageJsonPath = join(projectDir, "package.json");
845
1003
  const packageJson = await readPackageJson(packageJsonPath);
846
1004
  const packageManager = await detectPackageManager(projectDir, packageJson.data);
847
- const detectedStacks = await detectStacks(projectDir, packageJson.data);
1005
+ const detectedPacks = await detectPacks(projectDir, packageJson.data);
848
1006
  return {
849
1007
  projectDir,
850
1008
  packageJson: {
@@ -856,31 +1014,36 @@ async function detectProject(projectDir) {
856
1014
  error: packageJson.error
857
1015
  },
858
1016
  packageManager,
859
- detectedStacks,
860
- recommendedStack: recommendStack(detectedStacks)
1017
+ detectedPacks,
1018
+ recommendedPacks: recommendPacks(detectedPacks)
861
1019
  };
862
1020
  }
863
1021
  function buildAgentyxConfig(input) {
864
1022
  return {
865
- extends: [input.stack],
866
- profile: input.profile,
1023
+ packs: [...input.packs],
1024
+ enable: [...input.enable ?? []],
867
1025
  targets: [...input.targets]
868
1026
  };
869
1027
  }
870
1028
  function formatAgentyxConfig(config) {
871
1029
  return `${JSON.stringify(config, null, 2)}\n`;
872
1030
  }
873
- function recommendStack(detectedStacks) {
874
- if (detectedStacks.includes("angular")) return "angular";
875
- if (detectedStacks.includes("typescript")) return "typescript";
1031
+ function recommendPacks(detectedPacks) {
1032
+ if (detectedPacks.includes("angular")) return [
1033
+ "technical",
1034
+ "typescript",
1035
+ "angular"
1036
+ ];
1037
+ if (detectedPacks.includes("typescript")) return ["technical", "typescript"];
1038
+ return ["technical"];
876
1039
  }
877
- async function detectStacks(projectDir, packageJson) {
878
- const stacks = [];
1040
+ async function detectPacks(projectDir, packageJson) {
1041
+ const packs = [];
879
1042
  const dependencies = collectDependencies(packageJson);
880
1043
  const hasAngular = dependencies.has("@angular/core");
881
- if (dependencies.has("typescript") || await exists(join(projectDir, "tsconfig.json")) || hasAngular) stacks.push("typescript");
882
- if (hasAngular) stacks.push("angular");
883
- return stacks;
1044
+ if (dependencies.has("typescript") || await exists(join(projectDir, "tsconfig.json")) || hasAngular) packs.push("typescript");
1045
+ if (hasAngular) packs.push("angular");
1046
+ return packs;
884
1047
  }
885
1048
  async function detectPackageManager(projectDir, packageJson) {
886
1049
  const lockfiles = [];
@@ -976,6 +1139,6 @@ function isNotFound(cause) {
976
1139
  return cause instanceof Error && cause.code === "ENOENT";
977
1140
  }
978
1141
  //#endregion
979
- export { AGENTYX_CONFIG_FILENAME, AGENTYX_CONFIG_SCHEMA_ID, AGENTYX_PROFILES, AgentyxConfigNotFoundError, AgentyxConfigParseError, AgentyxConfigValidationError, AgentyxError, CircularStackDependencyError, DEFAULT_AGENTYX_PROFILE, DuplicateMcpServerError, DuplicateSkillError, DuplicateStackError, InvalidMcpServerError, InvalidSkillError, MCP_CAPABILITY_LEVELS, MCP_CONTEXT_COSTS, PACKAGE_MANAGERS, UnknownMcpServerError, UnknownSkillError, UnknownStackError, agentyxConfigPath, agentyxConfigSchema, agentyxCoreName, agentyxProfileSchema, buildAgentyxConfig, buildAgentyxConfigJsonSchema, builtInMcpServerNames, builtInMcpServerRegistry, builtInSkillNames, builtInSkillRegistry, builtInStackRegistry, builtInStacks, collectStackMcpServerReferences, collectStackMcpServers, createMcpServerRegistry, createSkillRegistry, createStackRegistry, detectProject, filterEffectiveMcpServers, formatAgentyxConfig, formatSkillMarkdown, getCoreStatus, getOptimizationProfile, isMcpLevelEnabled, loadAgentyxConfig, mcpCapabilityLevelSchema, mcpContextCostSchema, mcpEnvReferenceSchema, mcpServerDefinitionSchema, mcpServerReferenceSchema, optimizationProfileNames, optimizationProfiles, parseAgentyxConfig, parseSkillMarkdown, resolveAgentyxConfig, resolveStackMcpServerReferences, resolveStackMcpServers, resolveStackSkills, resolveStacks, skillDefinitionSchema, stackDefinitionSchema };
1142
+ export { AGENTYX_CONFIG_FILENAME, AGENTYX_CONFIG_SCHEMA_ID, AgentyxConfigNotFoundError, AgentyxConfigParseError, AgentyxConfigValidationError, AgentyxError, CircularPackDependencyError, DuplicateMcpServerError, DuplicatePackError, DuplicateSkillError, DuplicateToolError, InvalidMcpServerError, InvalidSkillError, InvalidToolError, MCP_CAPABILITY_LEVELS, MCP_CONTEXT_COSTS, PACKAGE_MANAGERS, PACK_CATEGORIES, TOOL_ACTIVATION_LEVELS, UnknownEnabledCapabilityError, UnknownMcpServerError, UnknownPackError, UnknownSkillError, UnknownToolError, agentyxConfigPath, agentyxConfigSchema, agentyxCoreName, agentyxTargetSchema, buildAgentyxConfig, buildAgentyxConfigJsonSchema, builtInMcpServerNames, builtInMcpServerRegistry, builtInPackRegistry, builtInPacks, builtInSkillNames, builtInSkillRegistry, builtInToolNames, builtInToolRegistry, collectPackMcpServerReferences, collectPackMcpServers, collectPackToolReferences, createMcpServerRegistry, createPackRegistry, createSkillRegistry, createToolRegistry, detectProject, enabledCapabilityNameSchema, filterEffectiveMcpServers, filterEffectiveTools, formatAgentyxConfig, formatSkillMarkdown, getCoreStatus, loadAgentyxConfig, mcpCapabilityLevelSchema, mcpContextCostSchema, mcpEnvReferenceSchema, mcpServerDefinitionSchema, mcpServerReferenceSchema, packCategorySchema, packDefinitionSchema, packNameSchema, parseAgentyxConfig, parseSkillMarkdown, resolveAgentyxConfig, resolvePackMcpServerReferences, resolvePackMcpServers, resolvePackSkills, resolvePackToolReferences, resolvePackTools, resolvePacks, skillDefinitionSchema, toolActivationLevelSchema, toolDefinitionSchema, toolNameSchema, toolReferenceSchema };
980
1143
 
981
1144
  //# sourceMappingURL=index.mjs.map