@agentyx/core 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["formatIssues"],"sources":["../src/errors.ts","../src/config/errors.ts","../src/mcp/schema.ts","../src/skill/schema.ts","../src/stack/schema.ts","../src/config/schema.ts","../src/config/json-schema.ts","../src/config/loader.ts","../src/mcp/errors.ts","../src/mcp/registry.ts","../src/mcp/built-in.ts","../src/optimization/profile.ts","../src/stack/errors.ts","../src/stack/registry.ts","../src/stack/resolver.ts","../src/mcp/resolver.ts","../src/assets.ts","../src/skill/errors.ts","../src/skill/markdown.ts","../src/skill/registry.ts","../src/skill/built-in.ts","../src/skill/resolver.ts","../src/config/resolver.ts","../src/meta.ts","../src/project/detector.ts"],"sourcesContent":["/**\n * Base class for every failure Agentyx raises deliberately.\n *\n * Consumers can catch `AgentyxError` to separate expected domain failures from\n * unexpected runtime errors, and branch on the stable `code` when they need to\n * handle a specific failure.\n */\nexport class AgentyxError extends Error {\n readonly code: string;\n\n constructor(code: string, message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = \"AgentyxError\";\n this.code = code;\n }\n}\n","import type { ZodError } from \"zod\";\nimport { AgentyxError } from \"../errors.js\";\n\n/** A single configuration problem, addressed by its location in the document. */\nexport interface AgentyxConfigIssue {\n /** Dotted path to the offending value, or `(root)` for the document itself. */\n readonly path: string;\n readonly message: string;\n}\n\n/** Raised when the supplied directory has no `.agentyx.json`. */\nexport class AgentyxConfigNotFoundError extends AgentyxError {\n readonly filePath: string;\n\n constructor(filePath: string, options?: ErrorOptions) {\n super(\"agentyx_config_not_found\", `Agentyx configuration file not found: ${filePath}`, options);\n this.name = \"AgentyxConfigNotFoundError\";\n this.filePath = filePath;\n }\n}\n\n/** Raised when `.agentyx.json` is not valid JSON. */\nexport class AgentyxConfigParseError extends AgentyxError {\n readonly filePath: string;\n\n constructor(filePath: string, reason: string, options?: ErrorOptions) {\n super(\"agentyx_config_parse_error\", `${filePath} is not valid JSON: ${reason}`, options);\n this.name = \"AgentyxConfigParseError\";\n this.filePath = filePath;\n }\n}\n\n/** Raised when the document parses as JSON but violates the Agentyx schema. */\nexport class AgentyxConfigValidationError extends AgentyxError {\n readonly issues: readonly AgentyxConfigIssue[];\n /** The file the configuration came from, when it was read from disk. */\n readonly filePath: string | undefined;\n\n constructor(error: ZodError, filePath?: string) {\n const issues = toConfigIssues(error);\n const location = filePath === undefined ? \"\" : ` in ${filePath}`;\n const details = issues.map((issue) => ` - ${issue.path}: ${issue.message}`).join(\"\\n\");\n\n super(\"agentyx_config_invalid\", `Invalid Agentyx configuration${location}:\\n${details}`);\n this.name = \"AgentyxConfigValidationError\";\n this.issues = issues;\n this.filePath = filePath;\n }\n}\n\nfunction toConfigIssues(error: ZodError): readonly AgentyxConfigIssue[] {\n return error.issues.map((issue) => ({\n path: formatIssuePath(issue.path),\n message: issue.message,\n }));\n}\n\nfunction formatIssuePath(path: readonly PropertyKey[]): string {\n if (path.length === 0) {\n return \"(root)\";\n }\n\n return path.reduce<string>((formatted, segment) => {\n if (typeof segment === \"number\") {\n return `${formatted}[${segment}]`;\n }\n\n return formatted === \"\" ? String(segment) : `${formatted}.${String(segment)}`;\n }, \"\");\n}\n","import { z } from \"zod\";\n\nexport const MCP_CAPABILITY_LEVELS = [\"essential\", \"recommended\", \"optional\"] as const;\n\nexport const mcpCapabilityLevelSchema = z.enum(MCP_CAPABILITY_LEVELS);\n\nexport const MCP_CONTEXT_COSTS = [\"low\", \"medium\", \"high\"] as const;\n\nexport const mcpContextCostSchema = z.enum(MCP_CONTEXT_COSTS);\n\nexport const mcpServerNameSchema = z\n .string()\n .min(1, \"MCP server names must be non-empty strings.\")\n .regex(\n /^[a-z0-9]+(?:-[a-z0-9]+)*$/,\n 'MCP server names must be lowercase kebab-case, for example \"context7\".',\n );\n\nexport const mcpEnvReferenceSchema = z.strictObject({\n fromEnv: z\n .string()\n .trim()\n .min(1, \"Environment variable references must be non-empty strings.\")\n .regex(/^[A-Za-z_][A-Za-z0-9_]*$/, \"Environment variable names must be valid shell names.\"),\n});\n\nconst commonMcpServerDefinitionSchema = z.strictObject({\n name: mcpServerNameSchema.describe(\"Unique MCP server identifier.\"),\n description: z.string().trim().min(1, \"MCP server descriptions must be non-empty strings.\"),\n transport: z.enum([\"stdio\", \"http\"]),\n contextCost: mcpContextCostSchema\n .describe(\"Qualitative context/tool-schema overhead classification; not token accounting.\")\n .optional(),\n});\n\nconst explicitMcpServerReferenceSchema = z.strictObject({\n name: mcpServerNameSchema.describe(\"MCP server identifier.\"),\n level: mcpCapabilityLevelSchema\n .describe(\"How important this MCP capability is to the declaring stack.\")\n .default(\"recommended\"),\n});\n\nexport const mcpServerReferenceSchema = z\n .union([mcpServerNameSchema, explicitMcpServerReferenceSchema])\n .transform((value) =>\n typeof value === \"string\"\n ? {\n name: value,\n level: \"recommended\" as const,\n }\n : value,\n )\n .pipe(\n z.strictObject({\n name: mcpServerNameSchema.describe(\"MCP server identifier.\"),\n level: mcpCapabilityLevelSchema.describe(\n \"How important this MCP capability is to the declaring stack.\",\n ),\n }),\n );\n\nexport const stdioMcpServerDefinitionSchema = commonMcpServerDefinitionSchema.extend({\n transport: z.literal(\"stdio\"),\n command: z.string().trim().min(1, \"MCP stdio command must be a non-empty string.\"),\n args: z.array(z.string()).default([]),\n env: z.record(z.string().min(1), mcpEnvReferenceSchema).default({}),\n});\n\nexport const httpMcpServerDefinitionSchema = commonMcpServerDefinitionSchema.extend({\n transport: z.literal(\"http\"),\n url: z.url(\"MCP HTTP URL must be a valid URL.\"),\n headers: z.record(z.string().min(1), mcpEnvReferenceSchema).default({}),\n});\n\nexport const mcpServerDefinitionSchema = z.discriminatedUnion(\"transport\", [\n stdioMcpServerDefinitionSchema,\n httpMcpServerDefinitionSchema,\n]);\n\nexport type McpEnvReference = z.infer<typeof mcpEnvReferenceSchema>;\nexport type McpCapabilityLevel = z.infer<typeof mcpCapabilityLevelSchema>;\nexport type McpContextCost = z.infer<typeof mcpContextCostSchema>;\nexport type McpServerDefinition = z.infer<typeof mcpServerDefinitionSchema>;\nexport type McpServerDefinitionInput = z.input<typeof mcpServerDefinitionSchema>;\nexport type McpServerReference = z.infer<typeof mcpServerReferenceSchema>;\nexport type McpServerReferenceInput = z.input<typeof mcpServerReferenceSchema>;\n","import { z } from \"zod\";\n\n/**\n * Skill names double as directory names for `SKILL.md` files, so they are\n * constrained to a lowercase slug. That keeps them stable across filesystems\n * and makes them safe to join onto a path.\n */\nexport const skillNameSchema = z\n .string()\n .min(1, \"Skill names must be non-empty strings.\")\n .regex(\n /^[a-z0-9]+(?:-[a-z0-9]+)*$/,\n 'Skill names must be lowercase kebab-case, for example \"typescript-modern\".',\n );\n\n/**\n * The metadata a Skill carries, and exactly what a `SKILL.md` frontmatter block\n * may declare. Kept separate from the full definition so the parser can reject\n * a frontmatter key that tries to supply the body.\n */\nexport const skillMetadataSchema = z.strictObject({\n name: skillNameSchema.describe(\"Unique skill identifier.\"),\n description: z\n .string()\n .trim()\n .min(1, \"Skill descriptions must be non-empty strings.\")\n .describe(\"One-line summary of what the skill tells an agent to do.\"),\n});\n\n/**\n * A Skill is reusable instruction text for a coding agent. It is deliberately\n * provider-independent: nothing here says how or where a provider installs it.\n */\nexport const skillDefinitionSchema = skillMetadataSchema.extend({\n content: z\n .string()\n .trim()\n .min(1, \"Skill content must be non-empty.\")\n .describe(\"The Markdown instructions handed to an agent.\"),\n});\n\n/** A validated skill definition. */\nexport type SkillDefinition = z.infer<typeof skillDefinitionSchema>;\n\n/** The shape accepted when authoring a skill definition. */\nexport type SkillDefinitionInput = z.input<typeof skillDefinitionSchema>;\n","import { z } from \"zod\";\nimport { mcpServerReferenceSchema } from \"../mcp/schema.js\";\nimport { skillNameSchema } from \"../skill/schema.js\";\n\n/**\n * Stack names are plain identifiers. They are intentionally not constrained to\n * a closed list so that external registries can contribute stacks later.\n */\nexport const stackNameSchema = z.string().min(1, \"Stack names must be non-empty strings.\");\n\n/**\n * A stack describes a development environment that can build on other stacks\n * and contribute provider-agnostic capabilities to them.\n */\nexport const stackDefinitionSchema = z.strictObject({\n name: stackNameSchema.describe(\"Unique stack identifier.\"),\n description: z\n .string()\n .min(1, \"Stack descriptions must be non-empty when provided.\")\n .describe(\"Short human-readable summary of the stack.\")\n .optional(),\n extends: z\n .array(stackNameSchema)\n .describe(\"Stacks this stack builds on, in dependency-first order.\")\n .default([]),\n skills: z\n .array(skillNameSchema)\n .describe(\"Skills this stack contributes, in declaration order.\")\n .default([]),\n mcpServers: z\n .array(mcpServerReferenceSchema)\n .describe(\"MCP servers this stack contributes, in declaration order.\")\n .default([]),\n});\n\n/** A validated stack definition, with defaults always present. */\nexport type StackDefinition = z.infer<typeof stackDefinitionSchema>;\n\n/** The shape accepted when authoring a stack definition. */\nexport type StackDefinitionInput = z.input<typeof stackDefinitionSchema>;\n","import { z } from \"zod\";\nimport { stackNameSchema } from \"../stack/schema.js\";\n\n/** How much autonomy the generated environment should grant an agent. */\nexport const AGENTYX_PROFILES = [\"lean\", \"balanced\", \"autonomous\"] as const;\n\nexport const agentyxProfileSchema = z.enum(AGENTYX_PROFILES, {\n error: `Profile must be one of: ${AGENTYX_PROFILES.join(\", \")}.`,\n});\n\nexport type AgentyxProfile = z.infer<typeof agentyxProfileSchema>;\n\n/** Applied when a configuration omits `profile`. */\nexport const DEFAULT_AGENTYX_PROFILE: AgentyxProfile = \"balanced\";\n\n/**\n * Targets stay free-form strings on purpose: third-party adapters should be\n * able to register providers without a change to this schema.\n */\nexport const agentyxTargetSchema = z.string().min(1, \"Targets must be non-empty strings.\");\n\n/** The `.agentyx.json` project configuration. */\nexport const agentyxConfigSchema = z.strictObject({\n $schema: z\n .string()\n .min(1, \"$schema must be a non-empty string.\")\n .describe(\"Optional path or URL to the Agentyx JSON Schema.\")\n .optional(),\n extends: z.array(stackNameSchema).describe(\"Stacks this project builds on.\").default([]),\n profile: agentyxProfileSchema\n .describe(\"How much autonomy the generated environment grants.\")\n .default(DEFAULT_AGENTYX_PROFILE),\n targets: z\n .array(agentyxTargetSchema)\n .describe(\"Coding-agent providers this project targets.\")\n .default([]),\n});\n\n/** A validated configuration, with defaults applied. */\nexport type AgentyxConfig = z.infer<typeof agentyxConfigSchema>;\n\n/** The shape accepted in a `.agentyx.json` file. */\nexport type AgentyxConfigInput = z.input<typeof agentyxConfigSchema>;\n","import { z } from \"zod\";\nimport { agentyxConfigSchema } from \"./schema.js\";\n\n/** Canonical identifier of the published `.agentyx.json` schema. */\nexport const AGENTYX_CONFIG_SCHEMA_ID = \"https://agentyx.dev/schema/agentyx.schema.json\";\n\n/**\n * Derives the JSON Schema for `.agentyx.json` from the Zod model, which stays the\n * single source of truth. The committed `schema/agentyx.schema.json` is generated\n * from this function and verified by tests.\n *\n * The `input` view is used so that fields with defaults stay optional, which is\n * what an author writing the file cares about.\n */\nexport function buildAgentyxConfigJsonSchema(): Record<string, unknown> {\n return {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n $id: AGENTYX_CONFIG_SCHEMA_ID,\n title: \"Agentyx project configuration\",\n description: \"Configuration for an Agentyx project (.agentyx.json).\",\n ...z.toJSONSchema(agentyxConfigSchema, { io: \"input\" }),\n };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport {\n AgentyxConfigNotFoundError,\n AgentyxConfigParseError,\n AgentyxConfigValidationError,\n} from \"./errors.js\";\nimport { type AgentyxConfig, agentyxConfigSchema } from \"./schema.js\";\n\nexport const AGENTYX_CONFIG_FILENAME = \".agentyx.json\";\n\n/** The absolute path `.agentyx.json` is read from for a given project. */\nexport function agentyxConfigPath(projectPath: string = process.cwd()): string {\n return resolve(projectPath, AGENTYX_CONFIG_FILENAME);\n}\n\n/**\n * Validates an already-parsed configuration document.\n *\n * @throws {AgentyxConfigValidationError} when the document violates the schema.\n */\nexport function parseAgentyxConfig(value: unknown, filePath?: string): AgentyxConfig {\n const result = agentyxConfigSchema.safeParse(value);\n\n if (!result.success) {\n throw new AgentyxConfigValidationError(result.error, filePath);\n }\n\n return result.data;\n}\n\n/**\n * Reads and validates `.agentyx.json` from `projectPath`.\n *\n * Parent directories are not searched, and invalid configurations are never\n * silently repaired.\n *\n * @throws {AgentyxConfigNotFoundError} when the file does not exist.\n * @throws {AgentyxConfigParseError} when the file is not valid JSON.\n * @throws {AgentyxConfigValidationError} when the document violates the schema.\n */\nexport async function loadAgentyxConfig(\n projectPath: string = process.cwd(),\n): Promise<AgentyxConfig> {\n const filePath = agentyxConfigPath(projectPath);\n let contents: string;\n\n try {\n contents = await readFile(filePath, \"utf8\");\n } catch (cause) {\n if (isFileNotFound(cause)) {\n throw new AgentyxConfigNotFoundError(filePath, { cause });\n }\n\n throw cause;\n }\n\n let document: unknown;\n\n try {\n document = JSON.parse(contents);\n } catch (cause) {\n const reason = cause instanceof Error ? cause.message : String(cause);\n throw new AgentyxConfigParseError(filePath, reason, { cause });\n }\n\n return parseAgentyxConfig(document, filePath);\n}\n\nfunction isFileNotFound(cause: unknown): boolean {\n return cause instanceof Error && (cause as NodeJS.ErrnoException).code === \"ENOENT\";\n}\n","import type { ZodError } from \"zod\";\nimport { AgentyxError } from \"../errors.js\";\n\nexport class UnknownMcpServerError extends AgentyxError {\n readonly serverName: string;\n readonly requiredBy: string | undefined;\n readonly knownServers: readonly string[];\n\n constructor(serverName: string, requiredBy: string | undefined, knownServers: readonly string[]) {\n const origin = requiredBy === undefined ? \"\" : ` (required by stack \"${requiredBy}\")`;\n const known = knownServers.length > 0 ? [...knownServers].sort().join(\", \") : \"none\";\n\n super(\n \"unknown_mcp_server\",\n `Unknown MCP server \"${serverName}\"${origin}. Known MCP servers: ${known}.`,\n );\n this.name = \"UnknownMcpServerError\";\n this.serverName = serverName;\n this.requiredBy = requiredBy;\n this.knownServers = knownServers;\n }\n}\n\nexport class DuplicateMcpServerError extends AgentyxError {\n readonly serverName: string;\n\n constructor(serverName: string) {\n super(\"duplicate_mcp_server\", `Duplicate MCP server definition: \"${serverName}\".`);\n this.name = \"DuplicateMcpServerError\";\n this.serverName = serverName;\n }\n}\n\nexport class InvalidMcpServerError extends AgentyxError {\n readonly origin: string;\n readonly reason: string;\n\n constructor(origin: string, reason: string | ZodError, options?: ErrorOptions) {\n const detail = typeof reason === \"string\" ? reason : formatIssues(reason);\n\n super(\"invalid_mcp_server\", `Invalid MCP server in ${origin}: ${detail}`, options);\n this.name = \"InvalidMcpServerError\";\n this.origin = origin;\n this.reason = detail;\n }\n}\n\nfunction formatIssues(error: ZodError): string {\n return error.issues\n .map((issue) => {\n const path = issue.path.map(String).join(\".\");\n\n return path === \"\" ? issue.message : `${path}: ${issue.message}`;\n })\n .join(\"; \");\n}\n","import { DuplicateMcpServerError, InvalidMcpServerError, UnknownMcpServerError } from \"./errors.js\";\nimport {\n type McpServerDefinition,\n type McpServerDefinitionInput,\n mcpServerDefinitionSchema,\n mcpServerNameSchema,\n} from \"./schema.js\";\n\nexport interface McpServerSource {\n readonly name: string;\n load(): McpServerDefinitionInput;\n}\n\nexport interface McpServerMetadata {\n readonly name: string;\n readonly description: string;\n readonly transport: McpServerDefinition[\"transport\"];\n readonly contextCost?: McpServerDefinition[\"contextCost\"];\n}\n\nexport interface McpServerRegistry {\n readonly names: readonly string[];\n has(name: string): boolean;\n listMetadata(): readonly McpServerMetadata[];\n get(name: string): McpServerDefinition;\n}\n\nexport function createMcpServerRegistry(sources: Iterable<McpServerSource>): McpServerRegistry {\n const byName = new Map<string, McpServerSource>();\n\n for (const source of sources) {\n const name = mcpServerNameSchema.safeParse(source.name);\n\n if (!name.success) {\n throw new InvalidMcpServerError(`MCP server source \"${source.name}\"`, name.error);\n }\n\n if (byName.has(name.data)) {\n throw new DuplicateMcpServerError(name.data);\n }\n\n byName.set(name.data, source);\n }\n\n const names = [...byName.keys()];\n const loaded = new Map<string, McpServerDefinition>();\n const get = (name: string): McpServerDefinition => {\n const cached = loaded.get(name);\n\n if (cached !== undefined) {\n return cached;\n }\n\n const source = byName.get(name);\n\n if (source === undefined) {\n throw new UnknownMcpServerError(name, undefined, names);\n }\n\n const origin = `MCP server \"${name}\"`;\n const server = mcpServerDefinitionSchema.safeParse(source.load());\n\n if (!server.success) {\n throw new InvalidMcpServerError(origin, server.error);\n }\n\n if (server.data.name !== name) {\n throw new InvalidMcpServerError(origin, `it declares the name \"${server.data.name}\"`);\n }\n\n loaded.set(name, server.data);\n\n return server.data;\n };\n\n return {\n names,\n has: (name) => byName.has(name),\n listMetadata: () =>\n names.map((name) => {\n const server = get(name);\n\n return {\n name: server.name,\n description: server.description,\n transport: server.transport,\n contextCost: server.contextCost,\n };\n }),\n get,\n };\n}\n","import { createMcpServerRegistry, type McpServerSource } from \"./registry.js\";\n\nexport const builtInMcpServerSources: readonly McpServerSource[] = [\n {\n name: \"context7\",\n load: () => ({\n name: \"context7\",\n description: \"Fetch up-to-date library documentation from Context7.\",\n transport: \"http\",\n contextCost: \"medium\",\n url: \"https://mcp.context7.com/mcp\",\n }),\n },\n {\n name: \"playwright\",\n load: () => ({\n name: \"playwright\",\n description: \"Automate and inspect browsers through Playwright MCP.\",\n transport: \"stdio\",\n contextCost: \"high\",\n command: \"npx\",\n args: [\"@playwright/mcp@latest\"],\n }),\n },\n];\n\nexport const builtInMcpServerRegistry = createMcpServerRegistry(builtInMcpServerSources);\n\nexport const builtInMcpServerNames: readonly string[] = builtInMcpServerRegistry.names;\n","import type { AgentyxProfile } from \"../config/schema.js\";\nimport type { McpCapabilityLevel } from \"../mcp/schema.js\";\n\nexport interface OptimizationProfileDefinition {\n readonly name: AgentyxProfile;\n readonly goal: string;\n readonly mcpLevels: readonly McpCapabilityLevel[];\n readonly notes: readonly string[];\n}\n\nexport const optimizationProfiles: readonly OptimizationProfileDefinition[] = [\n {\n name: \"lean\",\n goal: \"Minimum context and tool overhead.\",\n mcpLevels: [\"essential\"],\n notes: [\n \"Installs all resolved Skills.\",\n \"Keeps MCP exposure to essential capabilities.\",\n \"Prefers local CLI or native tools when they cover the same workflow.\",\n ],\n },\n {\n name: \"balanced\",\n goal: \"Good default developer experience with conservative autonomy.\",\n mcpLevels: [\"essential\", \"recommended\"],\n notes: [\"Installs all resolved Skills.\", \"Includes default and recommended MCP capabilities.\"],\n },\n {\n name: \"autonomous\",\n goal: \"Maximum agent capability from declared stack capabilities.\",\n mcpLevels: [\"essential\", \"recommended\", \"optional\"],\n notes: [\n \"Installs all resolved Skills.\",\n \"Includes optional MCP capabilities declared by the selected stacks.\",\n ],\n },\n];\n\nexport const optimizationProfileNames: readonly AgentyxProfile[] = optimizationProfiles.map(\n (profile) => profile.name,\n);\n\nexport function getOptimizationProfile(name: AgentyxProfile): OptimizationProfileDefinition {\n const profile = optimizationProfiles.find((candidate) => candidate.name === name);\n\n if (profile === undefined) {\n throw new Error(`Unknown optimization profile: ${name}`);\n }\n\n return profile;\n}\n\nexport function isMcpLevelEnabled(profile: AgentyxProfile, level: McpCapabilityLevel): boolean {\n return getOptimizationProfile(profile).mcpLevels.includes(level);\n}\n","import { AgentyxError } from \"../errors.js\";\n\n/**\n * Raised when a requested or inherited stack is not present in the registry.\n *\n * The offending name is exposed as `stackName`; `stack` stays the JS stack\n * trace inherited from `Error`.\n */\nexport class UnknownStackError extends AgentyxError {\n readonly stackName: string;\n readonly requiredBy: string | undefined;\n readonly knownStacks: readonly string[];\n\n constructor(stackName: string, requiredBy: string | undefined, knownStacks: readonly string[]) {\n const origin = requiredBy === undefined ? \"\" : ` (required by \"${requiredBy}\")`;\n const known = knownStacks.length > 0 ? [...knownStacks].sort().join(\", \") : \"none\";\n\n super(\"unknown_stack\", `Unknown stack \"${stackName}\"${origin}. Known stacks: ${known}.`);\n this.name = \"UnknownStackError\";\n this.stackName = stackName;\n this.requiredBy = requiredBy;\n this.knownStacks = knownStacks;\n }\n}\n\n/** Raised when stack inheritance forms a cycle. */\nexport class CircularStackDependencyError extends AgentyxError {\n /** The cycle path, starting and ending with the same stack. */\n readonly cycle: readonly string[];\n\n constructor(cycle: readonly string[]) {\n super(\"circular_stack_dependency\", `Circular stack dependency: ${cycle.join(\" -> \")}.`);\n this.name = \"CircularStackDependencyError\";\n this.cycle = cycle;\n }\n}\n\n/** Raised when a registry is built from definitions that reuse a stack name. */\nexport class DuplicateStackError extends AgentyxError {\n readonly stackName: string;\n\n constructor(stackName: string) {\n super(\"duplicate_stack\", `Duplicate stack definition: \"${stackName}\".`);\n this.name = \"DuplicateStackError\";\n this.stackName = stackName;\n }\n}\n","import { DuplicateStackError } from \"./errors.js\";\nimport {\n type StackDefinition,\n type StackDefinitionInput,\n stackDefinitionSchema,\n} from \"./schema.js\";\n\n/**\n * A registry is a name lookup over stack definitions. Keeping it a plain map\n * means the resolver stays independent of where definitions come from, so\n * external registries can be added later without touching resolution.\n */\nexport type StackRegistry = ReadonlyMap<string, StackDefinition>;\n\n/** Validates definitions and indexes them by name. */\nexport function createStackRegistry(definitions: Iterable<StackDefinitionInput>): StackRegistry {\n const registry = new Map<string, StackDefinition>();\n\n for (const definition of definitions) {\n const stack = stackDefinitionSchema.parse(definition);\n\n if (registry.has(stack.name)) {\n throw new DuplicateStackError(stack.name);\n }\n\n registry.set(stack.name, stack);\n }\n\n return registry;\n}\n\n/**\n * The stacks Agentyx ships with, expressed as data. Relationships live here, not\n * in the resolver.\n */\nexport const builtInStacks: readonly StackDefinitionInput[] = [\n {\n name: \"core\",\n description: \"Baseline development environment shared by every Agentyx stack.\",\n skills: [\"planning\", \"systematic-debugging\", \"verification\"],\n },\n {\n name: \"typescript\",\n description: \"TypeScript development environment.\",\n extends: [\"core\"],\n skills: [\"typescript-modern\"],\n },\n {\n name: \"angular\",\n description: \"Modern Angular development environment.\",\n extends: [\"typescript\"],\n skills: [\"angular-modern\"],\n mcpServers: [{ name: \"context7\", level: \"recommended\" }],\n },\n];\n\n/** The registry used by default when no explicit registry is supplied. */\nexport const builtInStackRegistry: StackRegistry = createStackRegistry(builtInStacks);\n","import { CircularStackDependencyError, UnknownStackError } from \"./errors.js\";\nimport { builtInStackRegistry, type StackRegistry } from \"./registry.js\";\n\n/**\n * Expands the requested stacks into the full inheritance chain.\n *\n * The result is dependency-first, de-duplicated and deterministic: stacks are\n * visited in the order they are requested, and each stack's parents are visited\n * in declaration order before the stack itself.\n *\n * @throws {UnknownStackError} when a requested or inherited stack is missing.\n * @throws {CircularStackDependencyError} when inheritance forms a cycle.\n */\nexport function resolveStacks(\n requestedStacks: readonly string[],\n registry: StackRegistry = builtInStackRegistry,\n): string[] {\n const resolved: string[] = [];\n const settled = new Set<string>();\n const path: string[] = [];\n\n const visit = (name: string, requiredBy: string | undefined): void => {\n if (settled.has(name)) {\n return;\n }\n\n const cycleStart = path.indexOf(name);\n\n if (cycleStart !== -1) {\n throw new CircularStackDependencyError([...path.slice(cycleStart), name]);\n }\n\n const definition = registry.get(name);\n\n if (definition === undefined) {\n throw new UnknownStackError(name, requiredBy, [...registry.keys()]);\n }\n\n path.push(name);\n\n for (const parent of definition.extends) {\n visit(parent, name);\n }\n\n path.pop();\n settled.add(name);\n resolved.push(name);\n };\n\n for (const name of requestedStacks) {\n visit(name, undefined);\n }\n\n return resolved;\n}\n","import type { AgentyxProfile } from \"../config/schema.js\";\nimport { DEFAULT_AGENTYX_PROFILE } from \"../config/schema.js\";\nimport { isMcpLevelEnabled } from \"../optimization/profile.js\";\nimport { builtInStackRegistry, type StackRegistry } from \"../stack/registry.js\";\nimport { resolveStacks } from \"../stack/resolver.js\";\nimport { builtInMcpServerRegistry } from \"./built-in.js\";\nimport { UnknownMcpServerError } from \"./errors.js\";\nimport type { McpServerRegistry } from \"./registry.js\";\nimport type { McpServerReference } from \"./schema.js\";\n\nexport function collectStackMcpServerReferences(\n resolvedStacks: readonly string[],\n stackRegistry: StackRegistry,\n mcpRegistry: McpServerRegistry,\n): McpServerReference[] {\n const servers: McpServerReference[] = [];\n const seen = new Set<string>();\n\n for (const stackName of resolvedStacks) {\n for (const server of stackRegistry.get(stackName)?.mcpServers ?? []) {\n const serverName = server.name;\n\n if (seen.has(serverName)) {\n continue;\n }\n\n if (!mcpRegistry.has(serverName)) {\n throw new UnknownMcpServerError(serverName, stackName, mcpRegistry.names);\n }\n\n seen.add(serverName);\n servers.push(server);\n }\n }\n\n return servers;\n}\n\nexport function filterEffectiveMcpServers(\n servers: readonly McpServerReference[],\n profile: AgentyxProfile,\n): string[] {\n return servers\n .filter((server) => isMcpLevelEnabled(profile, server.level))\n .map((server) => server.name);\n}\n\nexport function collectStackMcpServers(\n resolvedStacks: readonly string[],\n stackRegistry: StackRegistry,\n mcpRegistry: McpServerRegistry,\n profile: AgentyxProfile = DEFAULT_AGENTYX_PROFILE,\n): string[] {\n return filterEffectiveMcpServers(\n collectStackMcpServerReferences(resolvedStacks, stackRegistry, mcpRegistry),\n profile,\n );\n}\n\nexport function resolveStackMcpServerReferences(\n requestedStacks: readonly string[],\n stackRegistry: StackRegistry = builtInStackRegistry,\n mcpRegistry: McpServerRegistry = builtInMcpServerRegistry,\n): McpServerReference[] {\n return collectStackMcpServerReferences(\n resolveStacks(requestedStacks, stackRegistry),\n stackRegistry,\n mcpRegistry,\n );\n}\n\nexport function resolveStackMcpServers(\n requestedStacks: readonly string[],\n stackRegistry: StackRegistry = builtInStackRegistry,\n mcpRegistry: McpServerRegistry = builtInMcpServerRegistry,\n profile: AgentyxProfile = DEFAULT_AGENTYX_PROFILE,\n): string[] {\n return collectStackMcpServers(\n resolveStacks(requestedStacks, stackRegistry),\n stackRegistry,\n mcpRegistry,\n profile,\n );\n}\n","import { fileURLToPath } from \"node:url\";\n\n/**\n * Location of the non-code assets that ship with `@agentyx/core`.\n *\n * **This module must stay directly under `src/`.** The path is derived from\n * `import.meta.url` rather than the working directory, and `src/assets.ts` and\n * the bundled `dist/index.mjs` sit at the same depth below the package root, so\n * one relative path is correct both in development and in the published\n * package. Moving this file into a subdirectory breaks built-in skill loading;\n * `packages/core/test/built-in-skills.test.ts` guards against that.\n *\n * `skills/` is listed in the package's `files`, so it is published alongside\n * `dist/`.\n */\nexport const BUILT_IN_SKILLS_PATH = fileURLToPath(new URL(\"../skills\", import.meta.url));\n","import type { ZodError } from \"zod\";\nimport { AgentyxError } from \"../errors.js\";\n\n/**\n * Raised when a stack references a skill the registry does not know.\n *\n * The offending name is exposed as `skillName`; `stack` stays the JS stack\n * trace inherited from `Error`.\n */\nexport class UnknownSkillError extends AgentyxError {\n readonly skillName: string;\n /** The stack that declared the skill, when the failure came from resolution. */\n readonly requiredBy: string | undefined;\n readonly knownSkills: readonly string[];\n\n constructor(skillName: string, requiredBy: string | undefined, knownSkills: readonly string[]) {\n const origin = requiredBy === undefined ? \"\" : ` (required by stack \"${requiredBy}\")`;\n const known = knownSkills.length > 0 ? [...knownSkills].sort().join(\", \") : \"none\";\n\n super(\"unknown_skill\", `Unknown skill \"${skillName}\"${origin}. Known skills: ${known}.`);\n this.name = \"UnknownSkillError\";\n this.skillName = skillName;\n this.requiredBy = requiredBy;\n this.knownSkills = knownSkills;\n }\n}\n\n/** Raised when a registry is built from sources that reuse a skill name. */\nexport class DuplicateSkillError extends AgentyxError {\n readonly skillName: string;\n\n constructor(skillName: string) {\n super(\"duplicate_skill\", `Duplicate skill definition: \"${skillName}\".`);\n this.name = \"DuplicateSkillError\";\n this.skillName = skillName;\n }\n}\n\n/**\n * Raised when a skill exists but cannot be turned into a valid definition —\n * malformed `SKILL.md` frontmatter, a missing field, an unreadable file.\n *\n * Built-in skills ship with Agentyx, so this is a programmer error rather than\n * something a user can fix in their project.\n */\nexport class InvalidSkillError extends AgentyxError {\n /** Where the skill came from: a file path, or a label for an in-memory source. */\n readonly origin: string;\n readonly reason: string;\n\n constructor(origin: string, reason: string | ZodError, options?: ErrorOptions) {\n const detail = typeof reason === \"string\" ? reason : formatIssues(reason);\n\n super(\"invalid_skill\", `Invalid skill in ${origin}: ${detail}`, options);\n this.name = \"InvalidSkillError\";\n this.origin = origin;\n this.reason = detail;\n }\n}\n\nfunction formatIssues(error: ZodError): string {\n return error.issues\n .map((issue) => {\n const path = issue.path.map(String).join(\".\");\n\n return path === \"\" ? issue.message : `${path}: ${issue.message}`;\n })\n .join(\"; \");\n}\n","import { InvalidSkillError } from \"./errors.js\";\nimport {\n type SkillDefinition,\n type SkillDefinitionInput,\n skillDefinitionSchema,\n skillMetadataSchema,\n} from \"./schema.js\";\n\nconst DELIMITER = \"---\";\nconst BYTE_ORDER_MARK = /^\\uFEFF/;\nconst LINE_BREAK = /[\\r\\n]/;\n\n/**\n * A `SKILL.md` file is a frontmatter block followed by the Markdown body:\n *\n * ```md\n * ---\n * name: planning\n * description: Plan non-trivial work before editing.\n * ---\n *\n * Instructions...\n * ```\n *\n * The frontmatter is a deliberately small YAML subset — a flat block of\n * `key: value` pairs, values optionally quoted — so that core keeps depending\n * on Zod alone. Anything richer is rejected rather than guessed at.\n *\n * The body is preserved as written apart from trimming the blank lines around\n * it, and `origin` is only used to make errors readable.\n *\n * @throws {InvalidSkillError} when the frontmatter or the resulting skill is invalid.\n */\nexport function parseSkillMarkdown(markdown: string, origin: string): SkillDefinition {\n const lines = markdown.replace(BYTE_ORDER_MARK, \"\").split(/\\r?\\n/);\n\n if (lines[0]?.trim() !== DELIMITER) {\n throw new InvalidSkillError(\n origin,\n `the file must start with a \"${DELIMITER}\" frontmatter line`,\n );\n }\n\n const closing = lines.findIndex((line, index) => index > 0 && line.trim() === DELIMITER);\n\n if (closing === -1) {\n throw new InvalidSkillError(\n origin,\n `the frontmatter block is never closed with \"${DELIMITER}\"`,\n );\n }\n\n const metadata = skillMetadataSchema.safeParse(parseFrontmatter(lines.slice(1, closing), origin));\n\n if (!metadata.success) {\n throw new InvalidSkillError(origin, metadata.error);\n }\n\n const skill = skillDefinitionSchema.safeParse({\n ...metadata.data,\n content: lines.slice(closing + 1).join(\"\\n\"),\n });\n\n if (!skill.success) {\n throw new InvalidSkillError(origin, skill.error);\n }\n\n return skill.data;\n}\n\n/**\n * Renders a skill as canonical `SKILL.md` text — the inverse of\n * `parseSkillMarkdown`, and the single representation every consumer installs.\n *\n * Keeping this in core is what stops a provider from owning a copy of a skill\n * body: an adapter decides *where* a skill goes, never what it says.\n *\n * The output is deterministic. Frontmatter is always `name` then `description`,\n * the body is the trimmed content, and the file ends with exactly one newline,\n * so re-rendering an unchanged skill produces a byte-identical file and an\n * installer can compare content instead of guessing.\n *\n * @throws {InvalidSkillError} when the definition is invalid, or when the\n * description cannot be represented in the flat frontmatter subset the parser\n * accepts.\n */\nexport function formatSkillMarkdown(skill: SkillDefinitionInput): string {\n const origin = typeof skill.name === \"string\" ? `skill \"${skill.name}\"` : \"skill definition\";\n const parsed = skillDefinitionSchema.safeParse(skill);\n\n if (!parsed.success) {\n throw new InvalidSkillError(origin, parsed.error);\n }\n\n const { name, description, content } = parsed.data;\n\n if (LINE_BREAK.test(description)) {\n throw new InvalidSkillError(origin, \"the description must not contain a line break\");\n }\n\n return `${DELIMITER}\\nname: ${name}\\ndescription: ${description}\\n${DELIMITER}\\n\\n${content}\\n`;\n}\n\nfunction parseFrontmatter(lines: readonly string[], origin: string): Record<string, string> {\n const entries = new Map<string, string>();\n\n for (const [index, line] of lines.entries()) {\n if (line.trim() === \"\") {\n continue;\n }\n\n const separator = line.indexOf(\":\");\n // +2: the opening delimiter line, plus the shift from a zero-based index.\n const lineNumber = index + 2;\n\n if (separator === -1) {\n throw new InvalidSkillError(\n origin,\n `frontmatter line ${lineNumber} is not \"key: value\": ${line}`,\n );\n }\n\n const key = line.slice(0, separator).trim();\n\n if (key === \"\") {\n throw new InvalidSkillError(origin, `frontmatter line ${lineNumber} has an empty key`);\n }\n\n if (entries.has(key)) {\n throw new InvalidSkillError(\n origin,\n `duplicate frontmatter key \"${key}\" on line ${lineNumber}`,\n );\n }\n\n entries.set(key, unquote(line.slice(separator + 1).trim()));\n }\n\n return Object.fromEntries(entries);\n}\n\nfunction unquote(value: string): string {\n const quoted = /^\"(.*)\"$|^'(.*)'$/.exec(value);\n\n return quoted?.[1] ?? quoted?.[2] ?? value;\n}\n","import { DuplicateSkillError, InvalidSkillError, UnknownSkillError } from \"./errors.js\";\nimport {\n type SkillDefinition,\n type SkillDefinitionInput,\n skillDefinitionSchema,\n skillNameSchema,\n} from \"./schema.js\";\n\n/**\n * Where a single skill comes from. The name is known up front so that listing\n * and existence checks stay cheap, and `load` is only called when something\n * actually needs the instructions — a design that keeps `resolve` working on\n * identifiers alone.\n *\n * This is also the seam an external or remote registry would plug into later.\n */\nexport interface SkillSource {\n readonly name: string;\n /** Produces the definition. Called at most once per registry. */\n load(): SkillDefinitionInput;\n}\n\n/** A name lookup over skills, independent of where the definitions live. */\nexport interface SkillRegistry {\n /** Registered names in registration order. Never reads a skill body. */\n readonly names: readonly string[];\n has(name: string): boolean;\n /**\n * Loads, validates and caches a skill.\n *\n * @throws {UnknownSkillError} when the name is not registered.\n * @throws {InvalidSkillError} when the source yields an invalid definition.\n */\n get(name: string): SkillDefinition;\n}\n\n/**\n * Indexes skill sources by name.\n *\n * Names and duplicates are validated here; the definitions themselves are\n * validated the first time each skill is loaded.\n *\n * @throws {DuplicateSkillError} when two sources share a name.\n * @throws {InvalidSkillError} when a source name is not a valid skill name.\n */\nexport function createSkillRegistry(sources: Iterable<SkillSource>): SkillRegistry {\n const byName = new Map<string, SkillSource>();\n\n for (const source of sources) {\n const name = skillNameSchema.safeParse(source.name);\n\n if (!name.success) {\n throw new InvalidSkillError(`skill source \"${source.name}\"`, name.error);\n }\n\n if (byName.has(name.data)) {\n throw new DuplicateSkillError(name.data);\n }\n\n byName.set(name.data, source);\n }\n\n const names = [...byName.keys()];\n const loaded = new Map<string, SkillDefinition>();\n\n return {\n names,\n has: (name) => byName.has(name),\n get: (name) => {\n const cached = loaded.get(name);\n\n if (cached !== undefined) {\n return cached;\n }\n\n const source = byName.get(name);\n\n if (source === undefined) {\n throw new UnknownSkillError(name, undefined, names);\n }\n\n const origin = `skill \"${name}\"`;\n const skill = skillDefinitionSchema.safeParse(source.load());\n\n if (!skill.success) {\n throw new InvalidSkillError(origin, skill.error);\n }\n\n if (skill.data.name !== name) {\n throw new InvalidSkillError(origin, `it declares the name \"${skill.data.name}\"`);\n }\n\n loaded.set(name, skill.data);\n\n return skill.data;\n },\n };\n}\n","import { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { BUILT_IN_SKILLS_PATH } from \"../assets.js\";\nimport { InvalidSkillError } from \"./errors.js\";\nimport { parseSkillMarkdown } from \"./markdown.js\";\nimport { createSkillRegistry, type SkillRegistry } from \"./registry.js\";\nimport type { SkillDefinition } from \"./schema.js\";\n\n/**\n * The skills Agentyx ships with. The names are the directory names under\n * `packages/core/skills`, and knowing them without touching the filesystem is\n * what lets stack resolution validate references without reading any body.\n */\nexport const builtInSkillNames = [\n \"planning\",\n \"systematic-debugging\",\n \"verification\",\n \"typescript-modern\",\n \"angular-modern\",\n] as const;\n\n/** The absolute path of a built-in skill's `SKILL.md`. */\nexport function builtInSkillPath(name: string): string {\n return join(BUILT_IN_SKILLS_PATH, name, \"SKILL.md\");\n}\n\n/** The registry used by default when no explicit registry is supplied. */\nexport const builtInSkillRegistry: SkillRegistry = createSkillRegistry(\n builtInSkillNames.map((name) => ({ name, load: () => loadBuiltInSkill(name) })),\n);\n\n/**\n * Reads one built-in `SKILL.md`.\n *\n * Reading is synchronous on purpose: the files are small package assets, they\n * are only touched when a command asks for instructions, and a synchronous read\n * keeps `SkillRegistry.get` a plain lookup instead of infecting every caller\n * with a promise.\n */\nfunction loadBuiltInSkill(name: string): SkillDefinition {\n const filePath = builtInSkillPath(name);\n let markdown: string;\n\n try {\n markdown = readFileSync(filePath, \"utf8\");\n } catch (cause) {\n const reason = cause instanceof Error ? cause.message : String(cause);\n\n throw new InvalidSkillError(filePath, `the file could not be read: ${reason}`, { cause });\n }\n\n return parseSkillMarkdown(markdown, filePath);\n}\n","import { builtInStackRegistry, type StackRegistry } from \"../stack/registry.js\";\nimport { resolveStacks } from \"../stack/resolver.js\";\nimport { builtInSkillRegistry } from \"./built-in.js\";\nimport { UnknownSkillError } from \"./errors.js\";\nimport type { SkillRegistry } from \"./registry.js\";\n\n/**\n * Collects the skills contributed by an already-resolved stack chain.\n *\n * Only identifiers are produced — no skill body is read — so this stays cheap\n * enough to run on every `resolve`.\n *\n * @throws {UnknownSkillError} when a stack references a skill the registry lacks.\n */\nexport function collectStackSkills(\n resolvedStacks: readonly string[],\n stackRegistry: StackRegistry,\n skillRegistry: SkillRegistry,\n): string[] {\n const skills: string[] = [];\n const seen = new Set<string>();\n\n for (const stackName of resolvedStacks) {\n for (const skillName of stackRegistry.get(stackName)?.skills ?? []) {\n if (seen.has(skillName)) {\n continue;\n }\n\n if (!skillRegistry.has(skillName)) {\n throw new UnknownSkillError(skillName, stackName, skillRegistry.names);\n }\n\n seen.add(skillName);\n skills.push(skillName);\n }\n }\n\n return skills;\n}\n\n/**\n * Expands the requested stacks and returns the skills they contribute.\n *\n * The result follows the resolved stack order, then each stack's declaration\n * order, and is de-duplicated by first occurrence. Skills do not extend other\n * skills, so there is nothing further to expand.\n *\n * @throws {UnknownStackError} when a requested or inherited stack is missing.\n * @throws {CircularStackDependencyError} when stack inheritance forms a cycle.\n * @throws {UnknownSkillError} when a stack references a skill the registry lacks.\n */\nexport function resolveStackSkills(\n requestedStacks: readonly string[],\n stackRegistry: StackRegistry = builtInStackRegistry,\n skillRegistry: SkillRegistry = builtInSkillRegistry,\n): string[] {\n return collectStackSkills(\n resolveStacks(requestedStacks, stackRegistry),\n stackRegistry,\n skillRegistry,\n );\n}\n","import { builtInMcpServerRegistry } from \"../mcp/built-in.js\";\nimport type { McpServerRegistry } from \"../mcp/registry.js\";\nimport { collectStackMcpServerReferences, filterEffectiveMcpServers } from \"../mcp/resolver.js\";\nimport type { McpServerReference } from \"../mcp/schema.js\";\nimport { builtInSkillRegistry } from \"../skill/built-in.js\";\nimport type { SkillRegistry } from \"../skill/registry.js\";\nimport { collectStackSkills } from \"../skill/resolver.js\";\nimport { builtInStackRegistry, type StackRegistry } from \"../stack/registry.js\";\nimport { resolveStacks } from \"../stack/resolver.js\";\nimport type { AgentyxConfig, AgentyxProfile } from \"./schema.js\";\n\n/** A project configuration with its stack inheritance expanded. */\nexport interface ResolvedAgentyxConfig {\n /** The stacks the project asked for, in configuration order. */\n readonly requestedStacks: readonly string[];\n /** The full inheritance chain, dependency-first and de-duplicated. */\n readonly resolvedStacks: readonly string[];\n /**\n * Skill identifiers contributed by the resolved stacks, in resolution order.\n * Identifiers only — reading the instructions is a separate, explicit step.\n */\n readonly skills: readonly string[];\n readonly declaredMcpServers: readonly McpServerReference[];\n readonly mcpServers: readonly string[];\n readonly profile: AgentyxProfile;\n readonly targets: readonly string[];\n}\n\n/**\n * Combines a validated project configuration with stack and skill resolution.\n * The input is never mutated.\n *\n * @throws {UnknownStackError} when a configured stack is missing.\n * @throws {CircularStackDependencyError} when inheritance forms a cycle.\n * @throws {UnknownSkillError} when a stack references an unknown skill.\n */\nexport function resolveAgentyxConfig(\n config: AgentyxConfig,\n registry: StackRegistry = builtInStackRegistry,\n skillRegistry: SkillRegistry = builtInSkillRegistry,\n mcpRegistry: McpServerRegistry = builtInMcpServerRegistry,\n): ResolvedAgentyxConfig {\n const requestedStacks = [...config.extends];\n const resolvedStacks = resolveStacks(requestedStacks, registry);\n const declaredMcpServers = collectStackMcpServerReferences(resolvedStacks, registry, mcpRegistry);\n\n return {\n requestedStacks,\n resolvedStacks,\n skills: collectStackSkills(resolvedStacks, registry, skillRegistry),\n declaredMcpServers,\n mcpServers: filterEffectiveMcpServers(declaredMcpServers, config.profile),\n profile: config.profile,\n targets: [...config.targets],\n };\n}\n","export const agentyxCoreName = \"agentyx-core\";\n\nexport function getCoreStatus(): string {\n return \"ready\";\n}\n","import { access, readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { AgentyxConfigInput, AgentyxProfile } from \"../config/schema.js\";\n\nexport const PACKAGE_MANAGERS = [\"pnpm\", \"npm\", \"yarn\", \"bun\"] as const;\n\nexport type PackageManagerName = (typeof PACKAGE_MANAGERS)[number];\n\nexport interface PackageManagerDetection {\n readonly name: PackageManagerName | undefined;\n readonly source: \"lockfile\" | \"package-json\" | undefined;\n readonly lockfiles: readonly string[];\n readonly ambiguous: boolean;\n}\n\nexport interface ProjectPackageJsonDetection {\n readonly present: boolean;\n readonly valid: boolean;\n readonly path: string;\n readonly name: string | undefined;\n readonly packageManager: string | undefined;\n readonly error: string | undefined;\n}\n\nexport interface ProjectDetection {\n readonly projectDir: string;\n readonly packageJson: ProjectPackageJsonDetection;\n readonly packageManager: PackageManagerDetection;\n readonly detectedStacks: readonly string[];\n readonly recommendedStack: string | undefined;\n}\n\ninterface PackageJson {\n readonly name?: unknown;\n readonly packageManager?: unknown;\n readonly dependencies?: unknown;\n readonly devDependencies?: unknown;\n readonly peerDependencies?: unknown;\n readonly optionalDependencies?: unknown;\n}\n\nconst lockfileManagers: ReadonlyMap<string, PackageManagerName> = new Map([\n [\"pnpm-lock.yaml\", \"pnpm\"],\n [\"package-lock.json\", \"npm\"],\n [\"yarn.lock\", \"yarn\"],\n [\"bun.lock\", \"bun\"],\n [\"bun.lockb\", \"bun\"],\n]);\n\nexport async function detectProject(projectDir: string): Promise<ProjectDetection> {\n const packageJsonPath = join(projectDir, \"package.json\");\n const packageJson = await readPackageJson(packageJsonPath);\n const packageManager = await detectPackageManager(projectDir, packageJson.data);\n const detectedStacks = await detectStacks(projectDir, packageJson.data);\n\n return {\n projectDir,\n packageJson: {\n present: packageJson.present,\n valid: packageJson.valid,\n path: packageJsonPath,\n name: getString(packageJson.data?.name),\n packageManager: getString(packageJson.data?.packageManager),\n error: packageJson.error,\n },\n packageManager,\n detectedStacks,\n recommendedStack: recommendStack(detectedStacks),\n };\n}\n\nexport function buildAgentyxConfig(input: {\n readonly stack: string;\n readonly profile: AgentyxProfile;\n readonly targets: readonly string[];\n}): AgentyxConfigInput {\n return {\n extends: [input.stack],\n profile: input.profile,\n targets: [...input.targets],\n };\n}\n\nexport function formatAgentyxConfig(config: AgentyxConfigInput): string {\n return `${JSON.stringify(config, null, 2)}\\n`;\n}\n\nfunction recommendStack(detectedStacks: readonly string[]): string | undefined {\n if (detectedStacks.includes(\"angular\")) {\n return \"angular\";\n }\n\n if (detectedStacks.includes(\"typescript\")) {\n return \"typescript\";\n }\n\n return undefined;\n}\n\nasync function detectStacks(\n projectDir: string,\n packageJson: PackageJson | undefined,\n): Promise<readonly string[]> {\n const stacks: string[] = [];\n const dependencies = collectDependencies(packageJson);\n const hasAngular = dependencies.has(\"@angular/core\");\n const hasTypeScript =\n dependencies.has(\"typescript\") || (await exists(join(projectDir, \"tsconfig.json\")));\n\n if (hasTypeScript || hasAngular) {\n stacks.push(\"typescript\");\n }\n\n if (hasAngular) {\n stacks.push(\"angular\");\n }\n\n return stacks;\n}\n\nasync function detectPackageManager(\n projectDir: string,\n packageJson: PackageJson | undefined,\n): Promise<PackageManagerDetection> {\n const lockfiles: string[] = [];\n const managers = new Set<PackageManagerName>();\n\n for (const [file, manager] of lockfileManagers) {\n if (await exists(join(projectDir, file))) {\n lockfiles.push(file);\n managers.add(manager);\n }\n }\n\n if (managers.size === 1) {\n return {\n name: [...managers][0],\n source: \"lockfile\",\n lockfiles,\n ambiguous: false,\n };\n }\n\n if (managers.size > 1) {\n return {\n name: undefined,\n source: \"lockfile\",\n lockfiles,\n ambiguous: true,\n };\n }\n\n const declared = parsePackageManagerName(getString(packageJson?.packageManager));\n\n return {\n name: declared,\n source: declared === undefined ? undefined : \"package-json\",\n lockfiles,\n ambiguous: false,\n };\n}\n\nasync function readPackageJson(path: string): Promise<{\n readonly present: boolean;\n readonly valid: boolean;\n readonly data: PackageJson | undefined;\n readonly error: string | undefined;\n}> {\n let contents: string;\n\n try {\n contents = await readFile(path, \"utf8\");\n } catch (cause) {\n if (isNotFound(cause)) {\n return { present: false, valid: false, data: undefined, error: undefined };\n }\n\n const reason = cause instanceof Error ? cause.message : String(cause);\n return { present: true, valid: false, data: undefined, error: reason };\n }\n\n try {\n return { present: true, valid: true, data: JSON.parse(contents), error: undefined };\n } catch (cause) {\n const reason = cause instanceof Error ? cause.message : String(cause);\n return { present: true, valid: false, data: undefined, error: reason };\n }\n}\n\nfunction collectDependencies(packageJson: PackageJson | undefined): ReadonlySet<string> {\n const dependencies = new Set<string>();\n\n for (const field of [\n packageJson?.dependencies,\n packageJson?.devDependencies,\n packageJson?.peerDependencies,\n packageJson?.optionalDependencies,\n ]) {\n if (isRecord(field)) {\n for (const name of Object.keys(field)) {\n dependencies.add(name);\n }\n }\n }\n\n return dependencies;\n}\n\nfunction parsePackageManagerName(value: string | undefined): PackageManagerName | undefined {\n const name = value?.split(\"@\")[0];\n\n return PACKAGE_MANAGERS.includes(name as PackageManagerName)\n ? (name as PackageManagerName)\n : undefined;\n}\n\nfunction getString(value: unknown): string | undefined {\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nasync function exists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch (cause) {\n if (isNotFound(cause)) {\n return false;\n }\n\n throw cause;\n }\n}\n\nfunction isNotFound(cause: unknown): boolean {\n return cause instanceof Error && (cause as NodeJS.ErrnoException).code === \"ENOENT\";\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@agentyx/core",
3
+ "version": "0.1.0",
4
+ "description": "Shared domain foundations for Agentyx: configuration model, stack resolution and skills.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Andersseen",
8
+ "homepage": "https://github.com/Andersseen/agentyx/tree/main/packages/core#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/Andersseen/agentyx.git",
12
+ "directory": "packages/core"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/Andersseen/agentyx/issues"
16
+ },
17
+ "keywords": [
18
+ "agentyx",
19
+ "coding-agents",
20
+ "configuration",
21
+ "developer-tools",
22
+ "skills",
23
+ "stacks"
24
+ ],
25
+ "sideEffects": false,
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.mts",
29
+ "default": "./dist/index.mjs"
30
+ },
31
+ "./schema/agentyx.schema.json": "./schema/agentyx.schema.json"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "schema",
36
+ "skills"
37
+ ],
38
+ "engines": {
39
+ "node": ">=22"
40
+ },
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "dependencies": {
45
+ "zod": "^4.0.17"
46
+ },
47
+ "scripts": {
48
+ "build": "tsdown src/index.ts --dts --clean",
49
+ "clean": "rm -rf dist",
50
+ "schema": "node scripts/generate-schema.mjs",
51
+ "typecheck": "tsc --noEmit -p tsconfig.json"
52
+ }
53
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://agentyx.dev/schema/agentyx.schema.json",
4
+ "title": "Agentyx project configuration",
5
+ "description": "Configuration for an Agentyx project (.agentyx.json).",
6
+ "type": "object",
7
+ "properties": {
8
+ "$schema": {
9
+ "type": "string",
10
+ "minLength": 1,
11
+ "description": "Optional path or URL to the Agentyx JSON Schema."
12
+ },
13
+ "extends": {
14
+ "default": [],
15
+ "type": "array",
16
+ "items": {
17
+ "type": "string",
18
+ "minLength": 1
19
+ },
20
+ "description": "Stacks this project builds on."
21
+ },
22
+ "profile": {
23
+ "default": "balanced",
24
+ "type": "string",
25
+ "enum": ["lean", "balanced", "autonomous"],
26
+ "description": "How much autonomy the generated environment grants."
27
+ },
28
+ "targets": {
29
+ "default": [],
30
+ "type": "array",
31
+ "items": {
32
+ "type": "string",
33
+ "minLength": 1
34
+ },
35
+ "description": "Coding-agent providers this project targets."
36
+ }
37
+ },
38
+ "additionalProperties": false
39
+ }
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: angular-modern
3
+ description: Modern Angular conventions - standalone, signals, inject(), OnPush, zoneless.
4
+ ---
5
+
6
+ # Modern Angular
7
+
8
+ Write new code with the current APIs. Reach for a legacy pattern only when there is no modern
9
+ equivalent.
10
+
11
+ ## Components
12
+
13
+ Components, directives, and pipes are standalone: declare what a template needs in `imports` and do
14
+ not add an `NgModule` for new code. Set `changeDetection: ChangeDetectionStrategy.OnPush` on every
15
+ component.
16
+
17
+ Keep components small — template, local state, and the wiring between them. Logic worth testing on
18
+ its own belongs in a service or a plain function, not behind a component fixture.
19
+
20
+ ## State
21
+
22
+ Use signals for component state. Derive with `computed()` rather than recomputing in the template
23
+ or syncing fields by hand, and keep `effect()` for genuine side effects — never for writing state
24
+ that a `computed()` could express.
25
+
26
+ Declare inputs with `input()` and `input.required()`, outputs with `output()`, and two-way bindings
27
+ with `model()`. Query the view with the signal APIs, `viewChild()` and `contentChild()`.
28
+
29
+ RxJS still fits streams of events over time; bridge with `toSignal()` and `toObservable()` at the
30
+ edges instead of mixing both styles in one component.
31
+
32
+ ## Injection
33
+
34
+ Call `inject()` in field initialisers instead of taking constructor parameters. It composes inside
35
+ plain functions and reads better with `readonly` fields.
36
+
37
+ ## Templates
38
+
39
+ Use built-in control flow — `@if`, `@for`, `@switch`, `@defer` — not `*ngIf` and `*ngFor`, and give
40
+ every `@for` a `track` expression. Read signals directly in the template; the binding tracks them
41
+ for you.
42
+
43
+ ## Zoneless
44
+
45
+ Do not rely on `zone.js` patching. Drive updates through signals, avoid reaching for
46
+ `ChangeDetectorRef.detectChanges()` or `NgZone.run()`, and never trigger change detection as a side
47
+ effect.
@@ -0,0 +1,39 @@
1
+ ---
2
+ name: planning
3
+ description: Plan non-trivial work before editing, and keep small changes small.
4
+ ---
5
+
6
+ # Planning
7
+
8
+ Match the plan to the size of the change. A one-line fix does not need one. Work that touches
9
+ several files, changes a public contract, or has no obvious shape does.
10
+
11
+ ## Before editing
12
+
13
+ - Read the code you are about to change, and the code that calls it. Do not edit a file you have
14
+ not opened.
15
+ - Name the files the change will touch and what each one does differently afterwards.
16
+ - State the assumptions the change rests on, and check the ones that are cheap to check. An
17
+ assumption you cannot verify is an open question, not a fact.
18
+
19
+ ## Decomposing
20
+
21
+ Split work where a step can be verified on its own. Every step should leave the project working:
22
+ tests passing, build succeeding, nothing half-migrated.
23
+
24
+ Order the steps so the load-bearing part comes first. Finding a design problem after the tests and
25
+ the documentation are written wastes both.
26
+
27
+ ## Scope
28
+
29
+ Solve the problem in front of you. Do not add structure for requirements that have not arrived — an
30
+ interface with one implementation, an option nobody sets, or a layer that only forwards calls is a
31
+ cost with no payer.
32
+
33
+ Prefer the change that fits how the code already works over the one that is cleaner in isolation.
34
+ Consistency is cheaper to maintain than local elegance.
35
+
36
+ ## When the plan is wrong
37
+
38
+ A plan is a hypothesis. When the code contradicts it, revise it and say so rather than forcing the
39
+ original steps through. Report what changed and why.
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: systematic-debugging
3
+ description: Find the root cause from evidence instead of guessing at fixes.
4
+ ---
5
+
6
+ # Systematic debugging
7
+
8
+ A bug is the gap between what the code does and what you believe it does. Close it with evidence,
9
+ not with edits.
10
+
11
+ ## Reproduce first
12
+
13
+ Get a reliable reproduction before changing anything: a failing test, a command, an input. Without
14
+ one you cannot know that you fixed it. An intermittent failure still counts — record how often it
15
+ happens and under what conditions.
16
+
17
+ ## Gather evidence
18
+
19
+ Read the real error, the whole stack trace, and the code at the top frame. Then narrow it down:
20
+ which input, which branch, which layer. Adding a log line, bisecting the input, or reverting a
21
+ recent change all beat reasoning about code you have not read.
22
+
23
+ Keep what you observed separate from what you inferred.
24
+
25
+ ## Find the root cause
26
+
27
+ Keep asking why until the answer is a mechanism rather than a symptom. "The value is undefined" is
28
+ a symptom; "the loader returns before the cache is populated" is a mechanism. Stop when your
29
+ explanation accounts for every detail you saw, including the ones that looked irrelevant. A detail
30
+ that does not fit means the explanation is wrong.
31
+
32
+ ## Fix
33
+
34
+ Change the smallest thing that addresses the cause you identified. Do not fold refactors,
35
+ renames, or unrelated cleanups into a bug fix — they hide the fix in the diff.
36
+
37
+ Never apply a change you cannot justify. Editing until the symptom disappears leaves the bug in
38
+ place and usually adds another.
39
+
40
+ ## Verify
41
+
42
+ Confirm the reproduction passes now, and that it failed before for the reason you claimed. Run the
43
+ surrounding tests to catch regressions, and add a test that fails without the fix.
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: typescript-modern
3
+ description: Modern TypeScript conventions - strict types, inference, small explicit APIs.
4
+ ---
5
+
6
+ # Modern TypeScript
7
+
8
+ Write types that describe the domain, and let the compiler do the rest.
9
+
10
+ ## Typing
11
+
12
+ Keep `strict` on and treat `any` as a defect. When a value really is unknown, type it `unknown` and
13
+ narrow it — with `typeof`, `instanceof`, a discriminant check, or a validator that returns a typed
14
+ result.
15
+
16
+ Annotate what forms a contract: exported functions, public fields, and the boundaries where outside
17
+ data enters. Let inference handle everything else; restating an obvious type is noise that drifts
18
+ out of date.
19
+
20
+ Avoid assertions. `as` and `!` silence the compiler without changing the value, so each one is an
21
+ unchecked claim. Prove it with a real check instead.
22
+
23
+ ## Modelling
24
+
25
+ Use discriminated unions for values that come in variants: a `kind` field plus the data that
26
+ variant carries beats one wide object of optional properties, and it lets the compiler prove a
27
+ `switch` is exhaustive.
28
+
29
+ Make illegal states unrepresentable where it is cheap — required fields instead of optional ones, a
30
+ union instead of two booleans, `readonly` on data that is not meant to change.
31
+
32
+ Derive types instead of duplicating them. When a schema or a constant already describes a shape,
33
+ infer from it; two declarations of the same thing will disagree eventually.
34
+
35
+ ## Modules and APIs
36
+
37
+ Use ESM. Export the smallest surface callers need and keep helpers module-private — every export is
38
+ a contract you have to keep.
39
+
40
+ Prefer plain functions and plain objects. Classes earn their place when there is real state or
41
+ identity; factories, containers, and single-implementation interfaces usually do not.
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: verification
3
+ description: Back completion claims with evidence, and report failures plainly.
4
+ ---
5
+
6
+ # Verification
7
+
8
+ "Done" is a claim about observed behaviour. Make it only once you have observed the behaviour.
9
+
10
+ ## Run something
11
+
12
+ Before reporting work as complete, run what the project already provides: its tests, its type check,
13
+ its linter, its build. Use the narrow check while iterating and the full gate before handing work
14
+ back.
15
+
16
+ Some changes are not covered by an automated check — command-line output, a migration, a
17
+ configuration change. Exercise those by hand, and say how you did it.
18
+
19
+ ## Separate fact from assumption
20
+
21
+ Report what you ran and what it printed. Mark anything you did not verify as unverified. "Tests
22
+ pass" means you ran them and read the result; it does not mean the change looks right.
23
+
24
+ Compiling is not passing. Passing is not correct. A test that never ran proves nothing.
25
+
26
+ ## Report failures
27
+
28
+ State failures plainly, with the command and its real output. Do not present a partial result as a
29
+ success, and do not bury a broken step under the steps that worked.
30
+
31
+ If something fails for a reason unrelated to your change, say so explicitly instead of ignoring it.
32
+ If you could not run a check, say which one and why.
33
+
34
+ ## Keep it proportional
35
+
36
+ Verification should match the risk. A typo in a comment does not need the full suite; a change to
37
+ resolution logic, a schema, or a public API does. Skipping a check is a decision to state, not a
38
+ detail to leave out.