poe-code 3.0.191 → 3.0.192
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/cli/commands/configure-payload.d.ts +1 -1
- package/dist/cli/commands/configure-payload.js +16 -9
- package/dist/cli/commands/configure-payload.js.map +1 -1
- package/dist/cli/commands/configure.d.ts +7 -0
- package/dist/cli/commands/configure.js +25 -5
- package/dist/cli/commands/configure.js.map +1 -1
- package/dist/cli/commands/ensure-isolated-config.js +3 -2
- package/dist/cli/commands/ensure-isolated-config.js.map +1 -1
- package/dist/cli/commands/experiment.js +38 -39
- package/dist/cli/commands/experiment.js.map +1 -1
- package/dist/cli/commands/memory.js +20 -15
- package/dist/cli/commands/memory.js.map +1 -1
- package/dist/cli/commands/pipeline-loop-agent.d.ts +1 -0
- package/dist/cli/commands/pipeline-loop-agent.js +2 -0
- package/dist/cli/commands/pipeline-loop-agent.js.map +1 -0
- package/dist/cli/commands/pipeline.js +42 -71
- package/dist/cli/commands/pipeline.js.map +1 -1
- package/dist/cli/commands/ralph.js +37 -20
- package/dist/cli/commands/ralph.js.map +1 -1
- package/dist/cli/commands/shared.d.ts +1 -0
- package/dist/cli/commands/shared.js +30 -1
- package/dist/cli/commands/shared.js.map +1 -1
- package/dist/cli/commands/test.js +5 -2
- package/dist/cli/commands/test.js.map +1 -1
- package/dist/cli/poe-code-command-runner.js +2 -7
- package/dist/cli/poe-code-command-runner.js.map +1 -1
- package/dist/cli/program.js +55 -46
- package/dist/cli/program.js.map +1 -1
- package/dist/cli/service-registry.d.ts +7 -1
- package/dist/cli/service-registry.js.map +1 -1
- package/dist/index.js +9189 -2108
- package/dist/index.js.map +4 -4
- package/dist/providers/claude-code.js +18 -1
- package/dist/providers/claude-code.js.map +3 -3
- package/dist/providers/codex.js +18 -1
- package/dist/providers/codex.js.map +3 -3
- package/dist/providers/create-provider.d.ts +1 -0
- package/dist/providers/create-provider.js +3 -0
- package/dist/providers/create-provider.js.map +1 -1
- package/dist/providers/goose.js +19 -2
- package/dist/providers/goose.js.map +3 -3
- package/dist/providers/kimi.js +18 -1
- package/dist/providers/kimi.js.map +3 -3
- package/dist/providers/opencode.js +18 -1
- package/dist/providers/opencode.js.map +3 -3
- package/dist/providers/poe-agent.js +723 -300
- package/dist/providers/poe-agent.js.map +4 -4
- package/dist/providers/tiny-http-mcp-server.d.ts +22 -0
- package/dist/providers/tiny-http-mcp-server.js +1471 -0
- package/dist/providers/tiny-http-mcp-server.js.map +7 -0
- package/dist/templates/pipeline/SKILL_plan.md +64 -52
- package/package.json +10 -2
- package/packages/memory/dist/explain.cli.d.ts +1 -2
- package/packages/memory/dist/explain.cli.js +1 -2
- package/packages/memory/dist/explain.d.ts +1 -2
- package/packages/memory/dist/explain.js +19 -12
- package/packages/memory/dist/handle.d.ts +37 -0
- package/packages/memory/dist/handle.js +41 -0
- package/packages/memory/dist/index.d.ts +3 -1
- package/packages/memory/dist/index.js +1474 -452
- package/packages/memory/dist/index.js.map +4 -4
- package/packages/memory/dist/ingest.d.ts +12 -1
- package/packages/memory/dist/ingest.js +23 -12
- package/packages/memory/dist/mcp.d.ts +4 -2
- package/packages/memory/dist/mcp.js +6 -10
- package/packages/memory/dist/query.js +2 -8
- package/packages/memory/dist/types.d.ts +0 -21
- package/packages/tiny-oauth-test-server/dist/cli.js +191 -0
- package/packages/tiny-stdio-mcp-server/dist/server.js +9 -1
- package/packages/tiny-stdio-mcp-server/dist/types.d.ts +1 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/templates/py-poe-spawn/env.mustache", "../../src/templates/py-poe-spawn/main.py.mustache", "../../src/templates/py-poe-spawn/requirements.txt.mustache", "../../src/templates/codex/config.toml.mustache", "../../src/templates/tiny-http-mcp-server/server.mjs.mustache", "../../src/templates/tiny-http-mcp-server/verify-token.mjs.mustache", "../../packages/config-mutations/src/mutations/config-mutation.ts", "../../packages/config-mutations/src/mutations/file-mutation.ts", "../../packages/config-mutations/src/mutations/template-mutation.ts", "../../packages/config-mutations/src/execution/apply-mutation.ts", "../../packages/config-mutations/src/formats/json.ts", "../../packages/config-mutations/src/formats/toml.ts", "../../packages/config-mutations/src/formats/yaml.ts", "../../packages/config-mutations/src/formats/index.ts", "../../packages/config-mutations/src/execution/path-utils.ts", "../../packages/config-mutations/src/fs-utils.ts", "../../packages/config-mutations/src/execution/run-mutations.ts", "../../packages/config-mutations/src/template/render.ts", "../../src/services/service-install.ts", "../../src/providers/create-provider.ts", "../../src/providers/tiny-http-mcp-server.ts"],
|
|
4
|
+
"sourcesContent": ["POE_API_KEY={{apiKey}}\nPOE_BASE_URL=https://api.poe.com/v1\nMODEL={{model}}\n", "import os\nfrom openai import OpenAI\nfrom dotenv import load_dotenv\n\nload_dotenv()\n\nclient = OpenAI(\n api_key=os.getenv(\"POE_API_KEY\"),\n base_url=os.getenv(\"POE_BASE_URL\")\n)\n\nresponse = client.chat.completions.create(\n model=os.getenv(\"MODEL\", \"{{model}}\"),\n messages=[{\"role\": \"user\", \"content\": \"Tell me a joke\"}]\n)\n\nprint(response.choices[0].message.content)\n", "openai>=1.0.0\npython-dotenv>=1.0.0\n", "model_provider = \"poe\"\n\n[profiles.\"{{{profileName}}}\"]\nmodel = \"{{{model}}}\"\nmodel_provider = \"poe\"\nmodel_reasoning_effort = \"{{reasoningEffort}}\"\nmodel_verbosity = \"medium\"\n\n[model_providers.poe]\nname = \"poe\"\nbase_url = \"{{{baseUrl}}}\"\nwire_api = \"responses\"\nexperimental_bearer_token = \"{{apiKey}}\"\nrequires_openai_auth = false\nsupports_websockets = false\n", "import path from \"node:path\";\nimport { readFile } from \"node:fs/promises\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { createHttpServer } from \"tiny-http-mcp-server\";\n\nfunction isWindowsAbsolutePath(value) {\n if (value.length < 3) {\n return false;\n }\n\n const drive = value.charCodeAt(0);\n const separator = value[2];\n const isLetter =\n (drive >= 65 && drive <= 90) || (drive >= 97 && drive <= 122);\n\n return isLetter && value[1] === \":\" && (separator === \"\\\\\" || separator === \"/\");\n}\n\nfunction resolveModuleSpecifier(baseDir, value) {\n if (value.startsWith(\"file:\")) {\n return value;\n }\n\n if (value.startsWith(\".\") || value.startsWith(\"/\") || isWindowsAbsolutePath(value)) {\n const resolvedPath = path.isAbsolute(value)\n ? value\n : path.resolve(baseDir, value);\n return pathToFileURL(resolvedPath).href;\n }\n\n return value;\n}\n\nconst directory = path.dirname(fileURLToPath(import.meta.url));\nconst config = JSON.parse(\n await readFile(new URL(\"./config.json\", import.meta.url), \"utf8\")\n);\n\nconst verifierModule = await import(\n resolveModuleSpecifier(directory, config.oauth.verifierModule)\n);\nconst verifier = verifierModule[config.oauth.verifierExport ?? \"default\"];\n\nif (!verifier || typeof verifier.verify !== \"function\") {\n throw new Error(\"Verifier module must export an object with a verify() method.\");\n}\n\nconst server = createHttpServer({\n name: config.name,\n version: config.version,\n oauth: {\n resource: config.oauth.resource,\n authorizationServers: config.oauth.authorizationServers,\n requiredScopes: config.oauth.requiredScopes,\n scopesSupported: config.oauth.scopesSupported,\n bearerMethodsSupported: config.oauth.bearerMethodsSupported,\n verifier,\n },\n});\n\nconst handle = await server.listenHttp(config.listen);\n\nconsole.log(handle.url);\n\nconst shutdown = async () => {\n await handle.close();\n process.exit(0);\n};\n\nprocess.once(\"SIGINT\", () => {\n void shutdown();\n});\n\nprocess.once(\"SIGTERM\", () => {\n void shutdown();\n});\n", "import { TokenVerificationError } from \"tiny-http-mcp-server\";\n\nexport default {\n async verify(_input) {\n throw new TokenVerificationError({\n error: \"invalid_token\",\n errorDescription: \"Replace ~/.poe-code/tiny-http-mcp-server/verify-token.mjs with your token verifier.\",\n });\n },\n};\n", "import type {\n ConfigMergeMutation,\n ConfigPruneMutation,\n ConfigTransformMutation,\n ConfigObject,\n ValueResolver,\n MutationOptions\n} from \"../types.js\";\n\nexport interface MergeOptions {\n /** Target file path (must start with ~) */\n target: ValueResolver<string>;\n /** Value to merge into the config file */\n value: ValueResolver<ConfigObject>;\n /** Optional explicit format override */\n format?: \"json\" | \"toml\" | \"yaml\";\n /** Optional prune by prefix before merging (TOML) */\n pruneByPrefix?: Record<string, string>;\n /** Optional human-readable label for logging */\n label?: string;\n}\n\nexport interface PruneOptions {\n /** Target file path (must start with ~) */\n target: ValueResolver<string>;\n /** Shape to prune from the config file */\n shape: ValueResolver<ConfigObject>;\n /** Optional explicit format override */\n format?: \"json\" | \"toml\" | \"yaml\";\n /** Optional guard - only prune if predicate returns true */\n onlyIf?: (doc: ConfigObject, ctx: MutationOptions) => boolean;\n /** Optional human-readable label for logging */\n label?: string;\n}\n\nexport interface TransformOptions {\n /** Target file path (must start with ~) */\n target: ValueResolver<string>;\n /** Optional explicit format override */\n format?: \"json\" | \"toml\" | \"yaml\";\n /** Transform function - receives parsed content, returns transformed content */\n transform: (\n content: ConfigObject,\n ctx: MutationOptions\n ) => { content: ConfigObject | null; changed: boolean };\n /** Optional human-readable label for logging */\n label?: string;\n}\n\nfunction merge(options: MergeOptions): ConfigMergeMutation {\n return {\n kind: \"configMerge\",\n target: options.target,\n value: options.value,\n format: options.format,\n pruneByPrefix: options.pruneByPrefix,\n label: options.label\n };\n}\n\nfunction prune(options: PruneOptions): ConfigPruneMutation {\n return {\n kind: \"configPrune\",\n target: options.target,\n shape: options.shape,\n format: options.format,\n onlyIf: options.onlyIf,\n label: options.label\n };\n}\n\nfunction transform(options: TransformOptions): ConfigTransformMutation {\n return {\n kind: \"configTransform\",\n target: options.target,\n format: options.format,\n transform: options.transform,\n label: options.label\n };\n}\n\nexport const configMutation = {\n merge,\n prune,\n transform\n};\n", "import type {\n EnsureDirectoryMutation,\n RemoveDirectoryMutation,\n RemoveFileMutation,\n ChmodMutation,\n BackupMutation,\n ValueResolver\n} from \"../types.js\";\n\nexport interface EnsureDirectoryOptions {\n /** Directory path (must start with ~) */\n path: ValueResolver<string>;\n /** Optional human-readable label for logging */\n label?: string;\n}\n\nexport interface RemoveOptions {\n /** Target file path (must start with ~) */\n target: ValueResolver<string>;\n /** Only remove if file is empty/whitespace */\n whenEmpty?: boolean;\n /** Only remove if content matches regex */\n whenContentMatches?: RegExp;\n /** Optional human-readable label for logging */\n label?: string;\n}\n\nexport interface RemoveDirectoryOptions {\n /** Directory path (must start with ~) */\n path: ValueResolver<string>;\n /** Remove directory even when not empty */\n force?: boolean;\n /** Optional human-readable label for logging */\n label?: string;\n}\n\nexport interface ChmodOptions {\n /** Target file path (must start with ~) */\n target: ValueResolver<string>;\n /** File permission mode (e.g., 0o755) */\n mode: number;\n /** Optional human-readable label for logging */\n label?: string;\n}\n\nexport interface BackupOptions {\n /** Target file path to backup (must start with ~) */\n target: ValueResolver<string>;\n /** Optional human-readable label for logging */\n label?: string;\n}\n\nfunction ensureDirectory(options: EnsureDirectoryOptions): EnsureDirectoryMutation {\n return {\n kind: \"ensureDirectory\",\n path: options.path,\n label: options.label\n };\n}\n\nfunction remove(options: RemoveOptions): RemoveFileMutation {\n return {\n kind: \"removeFile\",\n target: options.target,\n whenEmpty: options.whenEmpty,\n whenContentMatches: options.whenContentMatches,\n label: options.label\n };\n}\n\nfunction removeDirectory(\n options: RemoveDirectoryOptions\n): RemoveDirectoryMutation {\n return {\n kind: \"removeDirectory\",\n path: options.path,\n force: options.force,\n label: options.label\n };\n}\n\nfunction chmod(options: ChmodOptions): ChmodMutation {\n return {\n kind: \"chmod\",\n target: options.target,\n mode: options.mode,\n label: options.label\n };\n}\n\nfunction backup(options: BackupOptions): BackupMutation {\n return {\n kind: \"backup\",\n target: options.target,\n label: options.label\n };\n}\n\nexport const fileMutation = {\n ensureDirectory,\n remove,\n removeDirectory,\n chmod,\n backup\n};\n", "import type {\n TemplateWriteMutation,\n TemplateMergeTomlMutation,\n TemplateMergeJsonMutation,\n ConfigObject,\n ValueResolver\n} from \"../types.js\";\n\nexport interface WriteOptions {\n /** Target file path (must start with ~) */\n target: ValueResolver<string>;\n /** Template ID to load via template loader */\n templateId: string;\n /** Context to pass to Mustache.render() */\n context?: ValueResolver<ConfigObject>;\n /** Optional human-readable label for logging */\n label?: string;\n}\n\nexport interface MergeTomlOptions {\n /** Target TOML file path (must start with ~) */\n target: ValueResolver<string>;\n /** Template ID to load via template loader */\n templateId: string;\n /** Context to pass to Mustache.render() */\n context?: ValueResolver<ConfigObject>;\n /** Optional human-readable label for logging */\n label?: string;\n}\n\nexport interface MergeJsonOptions {\n /** Target JSON file path (must start with ~) */\n target: ValueResolver<string>;\n /** Template ID to load via template loader */\n templateId: string;\n /** Context to pass to Mustache.render() */\n context?: ValueResolver<ConfigObject>;\n /** Optional human-readable label for logging */\n label?: string;\n}\n\nfunction write(options: WriteOptions): TemplateWriteMutation {\n return {\n kind: \"templateWrite\",\n target: options.target,\n templateId: options.templateId,\n context: options.context,\n label: options.label\n };\n}\n\nfunction mergeToml(options: MergeTomlOptions): TemplateMergeTomlMutation {\n return {\n kind: \"templateMergeToml\",\n target: options.target,\n templateId: options.templateId,\n context: options.context,\n label: options.label\n };\n}\n\nfunction mergeJson(options: MergeJsonOptions): TemplateMergeJsonMutation {\n return {\n kind: \"templateMergeJson\",\n target: options.target,\n templateId: options.templateId,\n context: options.context,\n label: options.label\n };\n}\n\nexport const templateMutation = {\n write,\n mergeToml,\n mergeJson\n};\n", "import Mustache from \"mustache\";\nimport type {\n Mutation,\n MutationContext,\n MutationOutcome,\n MutationDetails,\n ConfigObject,\n MutationOptions,\n ValueResolver,\n FileSystem\n} from \"../types.js\";\nimport { getConfigFormat, detectFormat } from \"../formats/index.js\";\nimport { resolvePath } from \"./path-utils.js\";\nimport {\n isNotFound,\n readFileIfExists,\n pathExists,\n createTimestamp\n} from \"../fs-utils.js\";\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\nfunction resolveValue<T>(\n resolver: ValueResolver<T>,\n options: MutationOptions\n): T {\n if (typeof resolver === \"function\") {\n return (resolver as (ctx: MutationOptions) => T)(options);\n }\n return resolver;\n}\n\nfunction createInvalidDocumentBackupPath(targetPath: string): string {\n const ext = targetPath.includes(\".\") ? targetPath.split(\".\").pop() : \"bak\";\n return `${targetPath}.invalid-${createTimestamp()}.${ext}`;\n}\n\nasync function backupInvalidDocument(\n fs: FileSystem,\n targetPath: string,\n content: string\n): Promise<void> {\n const backupPath = createInvalidDocumentBackupPath(targetPath);\n await fs.writeFile(backupPath, content, { encoding: \"utf8\" });\n}\n\nfunction describeMutation(kind: string, targetPath?: string): string {\n const displayPath = targetPath ?? \"target\";\n switch (kind) {\n case \"ensureDirectory\":\n return `Create ${displayPath}`;\n case \"removeDirectory\":\n return `Remove directory ${displayPath}`;\n case \"backup\":\n return `Backup ${displayPath}`;\n case \"templateWrite\":\n return `Write ${displayPath}`;\n case \"chmod\":\n return `Set permissions on ${displayPath}`;\n case \"removeFile\":\n return `Remove ${displayPath}`;\n case \"configMerge\":\n case \"configPrune\":\n case \"configTransform\":\n case \"templateMergeToml\":\n case \"templateMergeJson\":\n return `Update ${displayPath}`;\n default:\n return \"Operation\";\n }\n}\n\nfunction pruneKeysByPrefix(\n table: ConfigObject,\n prefix: string\n): ConfigObject {\n const result: ConfigObject = {};\n for (const [key, value] of Object.entries(table)) {\n if (!key.startsWith(prefix)) {\n result[key] = value;\n }\n }\n return result;\n}\n\nfunction isConfigObject(value: unknown): value is ConfigObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction mergeWithPruneByPrefix(\n base: ConfigObject,\n patch: ConfigObject,\n pruneByPrefix?: Record<string, string>\n): ConfigObject {\n const result: ConfigObject = { ...base };\n const prefixMap = pruneByPrefix ?? {};\n\n for (const [key, value] of Object.entries(patch)) {\n const current = result[key];\n const prefix = prefixMap[key];\n\n if (isConfigObject(current) && isConfigObject(value)) {\n if (prefix) {\n const pruned = pruneKeysByPrefix(current, prefix);\n result[key] = { ...pruned, ...value };\n } else {\n result[key] = mergeWithPruneByPrefix(\n current,\n value as ConfigObject,\n prefixMap\n );\n }\n continue;\n }\n result[key] = value;\n }\n return result;\n}\n\n// ============================================================================\n// Apply Mutation\n// ============================================================================\n\nexport async function applyMutation(\n mutation: Mutation,\n context: MutationContext,\n options: MutationOptions\n): Promise<{ outcome: MutationOutcome; details: MutationDetails }> {\n switch (mutation.kind) {\n case \"ensureDirectory\":\n return applyEnsureDirectory(mutation, context, options);\n case \"removeDirectory\":\n return applyRemoveDirectory(mutation, context, options);\n case \"removeFile\":\n return applyRemoveFile(mutation, context, options);\n case \"chmod\":\n return applyChmod(mutation, context, options);\n case \"backup\":\n return applyBackup(mutation, context, options);\n case \"configMerge\":\n return applyConfigMerge(mutation, context, options);\n case \"configPrune\":\n return applyConfigPrune(mutation, context, options);\n case \"configTransform\":\n return applyConfigTransform(mutation, context, options);\n case \"templateWrite\":\n return applyTemplateWrite(mutation, context, options);\n case \"templateMergeToml\":\n return applyTemplateMerge(mutation, context, options, \"toml\");\n case \"templateMergeJson\":\n return applyTemplateMerge(mutation, context, options, \"json\");\n default: {\n const never: never = mutation;\n throw new Error(`Unknown mutation kind: ${(never as Mutation).kind}`);\n }\n }\n}\n\n// ============================================================================\n// File Mutation Handlers\n// ============================================================================\n\nasync function applyEnsureDirectory(\n mutation: Extract<Mutation, { kind: \"ensureDirectory\" }>,\n context: MutationContext,\n options: MutationOptions\n): Promise<{ outcome: MutationOutcome; details: MutationDetails }> {\n const rawPath = resolveValue(mutation.path, options);\n const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);\n\n const details: MutationDetails = {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n\n const existed = await pathExists(context.fs, targetPath);\n\n if (!context.dryRun) {\n await context.fs.mkdir(targetPath, { recursive: true });\n }\n\n return {\n outcome: {\n changed: !existed,\n effect: \"mkdir\",\n detail: existed ? \"noop\" : \"create\"\n },\n details\n };\n}\n\nasync function applyRemoveDirectory(\n mutation: Extract<Mutation, { kind: \"removeDirectory\" }>,\n context: MutationContext,\n options: MutationOptions\n): Promise<{ outcome: MutationOutcome; details: MutationDetails }> {\n const rawPath = resolveValue(mutation.path, options);\n const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);\n\n const details: MutationDetails = {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n\n const existed = await pathExists(context.fs, targetPath);\n if (!existed) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n if (typeof context.fs.rm !== \"function\") {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n if (mutation.force) {\n if (!context.dryRun) {\n await context.fs.rm(targetPath, { recursive: true, force: true });\n }\n return {\n outcome: { changed: true, effect: \"delete\", detail: \"delete\" },\n details\n };\n }\n\n const entries = await context.fs.readdir(targetPath);\n if (entries.length > 0) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n if (!context.dryRun) {\n await context.fs.rm(targetPath, { recursive: true, force: true });\n }\n\n return {\n outcome: { changed: true, effect: \"delete\", detail: \"delete\" },\n details\n };\n}\n\nasync function applyRemoveFile(\n mutation: Extract<Mutation, { kind: \"removeFile\" }>,\n context: MutationContext,\n options: MutationOptions\n): Promise<{ outcome: MutationOutcome; details: MutationDetails }> {\n const rawPath = resolveValue(mutation.target, options);\n const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);\n\n const details: MutationDetails = {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n\n try {\n const content = await context.fs.readFile(targetPath, \"utf8\");\n const trimmed = content.trim();\n\n // Check whenContentMatches guard\n if (mutation.whenContentMatches && !mutation.whenContentMatches.test(trimmed)) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n // Check whenEmpty guard\n if (mutation.whenEmpty && trimmed.length > 0) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n if (!context.dryRun) {\n await context.fs.unlink(targetPath);\n }\n\n return {\n outcome: { changed: true, effect: \"delete\", detail: \"delete\" },\n details\n };\n } catch (error) {\n if (isNotFound(error)) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n throw error;\n }\n}\n\nasync function applyChmod(\n mutation: Extract<Mutation, { kind: \"chmod\" }>,\n context: MutationContext,\n options: MutationOptions\n): Promise<{ outcome: MutationOutcome; details: MutationDetails }> {\n const rawPath = resolveValue(mutation.target, options);\n const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);\n\n const details: MutationDetails = {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n\n if (typeof context.fs.chmod !== \"function\") {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n try {\n const stat = await context.fs.stat(targetPath);\n const currentMode = typeof stat.mode === \"number\" ? stat.mode & 0o777 : null;\n\n if (currentMode === mutation.mode) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n if (!context.dryRun) {\n await context.fs.chmod(targetPath, mutation.mode);\n }\n\n return {\n outcome: { changed: true, effect: \"chmod\", detail: \"update\" },\n details\n };\n } catch (error) {\n if (isNotFound(error)) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n throw error;\n }\n}\n\nasync function applyBackup(\n mutation: Extract<Mutation, { kind: \"backup\" }>,\n context: MutationContext,\n options: MutationOptions\n): Promise<{ outcome: MutationOutcome; details: MutationDetails }> {\n const rawPath = resolveValue(mutation.target, options);\n const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);\n\n const details: MutationDetails = {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n\n const content = await readFileIfExists(context.fs, targetPath);\n if (content === null) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n if (!context.dryRun) {\n const backupPath = `${targetPath}.backup-${createTimestamp()}`;\n await context.fs.writeFile(backupPath, content, { encoding: \"utf8\" });\n }\n\n return {\n outcome: { changed: true, effect: \"copy\", detail: \"backup\" },\n details\n };\n}\n\n// ============================================================================\n// Config Mutation Handlers\n// ============================================================================\n\nasync function applyConfigMerge(\n mutation: Extract<Mutation, { kind: \"configMerge\" }>,\n context: MutationContext,\n options: MutationOptions\n): Promise<{ outcome: MutationOutcome; details: MutationDetails }> {\n const rawPath = resolveValue(mutation.target, options);\n const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);\n\n const details: MutationDetails = {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n\n const formatName = mutation.format ?? detectFormat(rawPath);\n if (!formatName) {\n throw new Error(\n `Cannot detect config format for \"${rawPath}\". Provide explicit format option.`\n );\n }\n const format = getConfigFormat(formatName);\n\n const rawContent = await readFileIfExists(context.fs, targetPath);\n let current: ConfigObject;\n try {\n current = rawContent === null ? {} : format.parse(rawContent);\n } catch {\n // Invalid file - backup and start fresh\n if (rawContent !== null) {\n await backupInvalidDocument(context.fs, targetPath, rawContent);\n }\n current = {};\n }\n\n const value = resolveValue(mutation.value, options);\n\n // Use mergeWithPruneByPrefix for TOML files with pruneByPrefix option\n let merged: ConfigObject;\n if (mutation.pruneByPrefix) {\n merged = mergeWithPruneByPrefix(current, value, mutation.pruneByPrefix);\n } else {\n merged = format.merge(current, value);\n }\n\n const serialized = format.serialize(merged);\n const changed = serialized !== rawContent;\n\n if (changed && !context.dryRun) {\n await context.fs.writeFile(targetPath, serialized, { encoding: \"utf8\" });\n }\n\n return {\n outcome: {\n changed,\n effect: changed ? \"write\" : \"none\",\n detail: changed ? (rawContent === null ? \"create\" : \"update\") : \"noop\"\n },\n details\n };\n}\n\nasync function applyConfigPrune(\n mutation: Extract<Mutation, { kind: \"configPrune\" }>,\n context: MutationContext,\n options: MutationOptions\n): Promise<{ outcome: MutationOutcome; details: MutationDetails }> {\n const rawPath = resolveValue(mutation.target, options);\n const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);\n\n const details: MutationDetails = {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n\n const rawContent = await readFileIfExists(context.fs, targetPath);\n if (rawContent === null) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n const formatName = mutation.format ?? detectFormat(rawPath);\n if (!formatName) {\n throw new Error(\n `Cannot detect config format for \"${rawPath}\". Provide explicit format option.`\n );\n }\n const format = getConfigFormat(formatName);\n\n let current: ConfigObject;\n try {\n current = format.parse(rawContent);\n } catch {\n // Invalid file - can't prune, leave as-is\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n // Check onlyIf guard\n if (mutation.onlyIf && !mutation.onlyIf(current, options)) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n const shape = resolveValue(mutation.shape, options);\n const { changed, result } = format.prune(current, shape);\n\n if (!changed) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n // Delete file if empty\n if (Object.keys(result).length === 0) {\n if (!context.dryRun) {\n await context.fs.unlink(targetPath);\n }\n return {\n outcome: { changed: true, effect: \"delete\", detail: \"delete\" },\n details\n };\n }\n\n const serialized = format.serialize(result);\n if (!context.dryRun) {\n await context.fs.writeFile(targetPath, serialized, { encoding: \"utf8\" });\n }\n\n return {\n outcome: { changed: true, effect: \"write\", detail: \"update\" },\n details\n };\n}\n\nasync function applyConfigTransform(\n mutation: Extract<Mutation, { kind: \"configTransform\" }>,\n context: MutationContext,\n options: MutationOptions\n): Promise<{ outcome: MutationOutcome; details: MutationDetails }> {\n const rawPath = resolveValue(mutation.target, options);\n const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);\n\n const details: MutationDetails = {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n\n const formatName = mutation.format ?? detectFormat(rawPath);\n if (!formatName) {\n throw new Error(\n `Cannot detect config format for \"${rawPath}\". Provide explicit format option.`\n );\n }\n const format = getConfigFormat(formatName);\n\n const rawContent = await readFileIfExists(context.fs, targetPath);\n let current: ConfigObject;\n try {\n current = rawContent === null ? {} : format.parse(rawContent);\n } catch {\n if (rawContent !== null) {\n await backupInvalidDocument(context.fs, targetPath, rawContent);\n }\n current = {};\n }\n\n const { content: transformed, changed } = mutation.transform(current, options);\n\n if (!changed) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n\n // Delete file if null\n if (transformed === null) {\n if (rawContent === null) {\n return {\n outcome: { changed: false, effect: \"none\", detail: \"noop\" },\n details\n };\n }\n if (!context.dryRun) {\n await context.fs.unlink(targetPath);\n }\n return {\n outcome: { changed: true, effect: \"delete\", detail: \"delete\" },\n details\n };\n }\n\n const serialized = format.serialize(transformed);\n if (!context.dryRun) {\n await context.fs.writeFile(targetPath, serialized, { encoding: \"utf8\" });\n }\n\n return {\n outcome: {\n changed: true,\n effect: \"write\",\n detail: rawContent === null ? \"create\" : \"update\"\n },\n details\n };\n}\n\n// ============================================================================\n// Template Mutation Handlers\n// ============================================================================\n\nasync function applyTemplateWrite(\n mutation: Extract<Mutation, { kind: \"templateWrite\" }>,\n context: MutationContext,\n options: MutationOptions\n): Promise<{ outcome: MutationOutcome; details: MutationDetails }> {\n if (!context.templates) {\n throw new Error(\n \"Template mutations require a templates loader. \" +\n \"Provide templates function to runMutations context.\"\n );\n }\n\n const rawPath = resolveValue(mutation.target, options);\n const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);\n\n const details: MutationDetails = {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n\n const template = await context.templates(mutation.templateId);\n const templateContext = mutation.context\n ? resolveValue(mutation.context, options)\n : {};\n const rendered = Mustache.render(template, templateContext);\n\n const existed = await pathExists(context.fs, targetPath);\n\n if (!context.dryRun) {\n await context.fs.writeFile(targetPath, rendered, { encoding: \"utf8\" });\n }\n\n return {\n outcome: {\n changed: true,\n effect: \"write\",\n detail: existed ? \"update\" : \"create\"\n },\n details\n };\n}\n\nasync function applyTemplateMerge(\n mutation: Extract<Mutation, { kind: \"templateMergeToml\" | \"templateMergeJson\" }>,\n context: MutationContext,\n options: MutationOptions,\n formatName: \"toml\" | \"json\"\n): Promise<{ outcome: MutationOutcome; details: MutationDetails }> {\n if (!context.templates) {\n throw new Error(\n \"Template mutations require a templates loader. \" +\n \"Provide templates function to runMutations context.\"\n );\n }\n\n const rawPath = resolveValue(mutation.target, options);\n const targetPath = resolvePath(rawPath, context.homeDir, context.pathMapper);\n\n const details: MutationDetails = {\n kind: mutation.kind,\n label: mutation.label ?? describeMutation(mutation.kind, targetPath),\n targetPath\n };\n\n const format = getConfigFormat(formatName);\n\n // Load and render template\n const template = await context.templates(mutation.templateId);\n const templateContext = mutation.context\n ? resolveValue(mutation.context, options)\n : {};\n const rendered = Mustache.render(template, templateContext);\n\n // Parse rendered template\n let templateDoc: ConfigObject;\n try {\n templateDoc = format.parse(rendered);\n } catch (error) {\n throw new Error(\n `Failed to parse rendered template \"${mutation.templateId}\" as ${formatName.toUpperCase()}: ${error}`,\n { cause: error }\n );\n }\n\n // Read and parse existing file\n const rawContent = await readFileIfExists(context.fs, targetPath);\n let current: ConfigObject;\n try {\n current = rawContent === null ? {} : format.parse(rawContent);\n } catch {\n if (rawContent !== null) {\n await backupInvalidDocument(context.fs, targetPath, rawContent);\n }\n current = {};\n }\n\n // Merge\n const merged = format.merge(current, templateDoc);\n const serialized = format.serialize(merged);\n const changed = serialized !== rawContent;\n\n if (changed && !context.dryRun) {\n await context.fs.writeFile(targetPath, serialized, { encoding: \"utf8\" });\n }\n\n return {\n outcome: {\n changed,\n effect: changed ? \"write\" : \"none\",\n detail: changed ? (rawContent === null ? \"create\" : \"update\") : \"noop\"\n },\n details\n };\n}\n", "import * as jsonc from \"jsonc-parser\";\nimport type { ConfigFormat, ConfigObject, ConfigValue } from \"../types.js\";\n\nfunction isConfigObject(value: unknown): value is ConfigObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction detectIndent(content: string): string {\n const match = content.match(/^[\\t ]+/m);\n if (match) {\n return match[0];\n }\n return \" \";\n}\n\nfunction parse(content: string): ConfigObject {\n if (!content || content.trim() === \"\") {\n return {};\n }\n const errors: jsonc.ParseError[] = [];\n const parsed = jsonc.parse(content, errors, {\n allowTrailingComma: true,\n disallowComments: false\n });\n if (errors.length > 0) {\n throw new Error(`JSON parse error: ${jsonc.printParseErrorCode(errors[0].error)}`);\n }\n if (parsed === null || parsed === undefined) {\n return {};\n }\n if (!isConfigObject(parsed)) {\n throw new Error(\"Expected JSON object.\");\n }\n return parsed;\n}\n\nfunction serialize(obj: ConfigObject): string {\n return `${JSON.stringify(obj, null, 2)}\\n`;\n}\n\nfunction merge(base: ConfigObject, patch: ConfigObject): ConfigObject {\n const result: ConfigObject = { ...base };\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) {\n continue;\n }\n const existing = result[key];\n if (isConfigObject(existing) && isConfigObject(value)) {\n result[key] = merge(existing, value);\n continue;\n }\n result[key] = value as ConfigValue;\n }\n return result;\n}\n\nfunction prune(\n obj: ConfigObject,\n shape: ConfigObject\n): { changed: boolean; result: ConfigObject } {\n let changed = false;\n const result: ConfigObject = { ...obj };\n\n for (const [key, pattern] of Object.entries(shape)) {\n if (!(key in result)) {\n continue;\n }\n\n const current = result[key];\n\n // Empty object pattern means \"delete this key entirely\"\n if (isConfigObject(pattern) && Object.keys(pattern).length === 0) {\n delete result[key];\n changed = true;\n continue;\n }\n\n // Non-empty object pattern with object current: recurse\n if (isConfigObject(pattern) && isConfigObject(current)) {\n const { changed: childChanged, result: childResult } = prune(\n current,\n pattern\n );\n if (childChanged) {\n changed = true;\n }\n if (Object.keys(childResult).length === 0) {\n delete result[key];\n } else {\n result[key] = childResult;\n }\n continue;\n }\n\n delete result[key];\n changed = true;\n }\n\n return { changed, result };\n}\n\n/**\n * Modify JSON content at a specific path while preserving comments and formatting.\n * Uses jsonc-parser's modify() for targeted updates.\n *\n * @param content - The original JSON content (may include comments)\n * @param path - JSON path array, e.g. [\"mcpServers\", \"my-server\"]\n * @param value - The value to set (or undefined to remove)\n * @returns The modified JSON content with comments preserved\n */\nfunction modifyAtPath(\n content: string,\n path: (string | number)[],\n value: ConfigValue | undefined\n): string {\n const indent = detectIndent(content);\n const formattingOptions: jsonc.FormattingOptions = {\n tabSize: indent === \"\\t\" ? 1 : indent.length,\n insertSpaces: indent !== \"\\t\",\n eol: \"\\n\"\n };\n\n const edits = jsonc.modify(content, path, value, { formattingOptions });\n let result = jsonc.applyEdits(content, edits);\n\n if (!result.endsWith(\"\\n\")) {\n result += \"\\n\";\n }\n\n return result;\n}\n\n/**\n * Merge a patch into JSON content while preserving comments and formatting.\n * Uses jsonc.modify() for each top-level key to preserve existing comments.\n *\n * @param content - The original JSON content (may include comments)\n * @param patch - Object with values to merge\n * @returns The modified JSON content with comments preserved\n */\nfunction mergePreservingComments(\n content: string,\n patch: ConfigObject\n): string {\n let result = content || \"{}\";\n\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) {\n continue;\n }\n result = modifyAtPath(result, [key], value);\n }\n\n return result;\n}\n\n/**\n * Remove a key from JSON content while preserving comments and formatting.\n *\n * @param content - The original JSON content\n * @param path - JSON path array to the key to remove\n * @returns The modified JSON content with comments preserved\n */\nfunction removeAtPath(content: string, path: (string | number)[]): string {\n return modifyAtPath(content, path, undefined);\n}\n\nexport { detectIndent, modifyAtPath, mergePreservingComments, removeAtPath };\n\nexport const jsonFormat: ConfigFormat = {\n parse,\n serialize,\n merge,\n prune\n};\n", "import { parse as parseToml, stringify as stringifyToml } from \"smol-toml\";\nimport type { ConfigFormat, ConfigObject, ConfigValue } from \"../types.js\";\n\nfunction isConfigObject(value: unknown): value is ConfigObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parse(content: string): ConfigObject {\n if (!content || content.trim() === \"\") {\n return {};\n }\n const parsed = parseToml(content);\n if (!isConfigObject(parsed)) {\n throw new Error(\"Expected TOML document to be a table.\");\n }\n return parsed as ConfigObject;\n}\n\nfunction serialize(obj: ConfigObject): string {\n const serialized = stringifyToml(obj);\n return serialized.endsWith(\"\\n\") ? serialized : `${serialized}\\n`;\n}\n\nfunction merge(base: ConfigObject, patch: ConfigObject): ConfigObject {\n const result: ConfigObject = { ...base };\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) {\n continue;\n }\n const existing = result[key];\n if (isConfigObject(existing) && isConfigObject(value)) {\n result[key] = merge(existing, value);\n continue;\n }\n result[key] = value as ConfigValue;\n }\n return result;\n}\n\nfunction prune(\n obj: ConfigObject,\n shape: ConfigObject\n): { changed: boolean; result: ConfigObject } {\n let changed = false;\n const result: ConfigObject = { ...obj };\n\n for (const [key, pattern] of Object.entries(shape)) {\n if (!(key in result)) {\n continue;\n }\n\n const current = result[key];\n\n // Empty object pattern means \"delete this key entirely\"\n if (isConfigObject(pattern) && Object.keys(pattern).length === 0) {\n delete result[key];\n changed = true;\n continue;\n }\n\n // Non-empty object pattern with object current: recurse\n if (isConfigObject(pattern) && isConfigObject(current)) {\n const { changed: childChanged, result: childResult } = prune(\n current,\n pattern\n );\n if (childChanged) {\n changed = true;\n }\n if (Object.keys(childResult).length === 0) {\n delete result[key];\n } else {\n result[key] = childResult;\n }\n continue;\n }\n\n delete result[key];\n changed = true;\n }\n\n return { changed, result };\n}\n\nexport const tomlFormat: ConfigFormat = {\n parse,\n serialize,\n merge,\n prune\n};\n", "import { parse as parseYaml, stringify as stringifyYaml } from \"yaml\";\nimport type { ConfigFormat, ConfigObject, ConfigValue } from \"../types.js\";\n\nfunction isConfigObject(value: unknown): value is ConfigObject {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction parse(content: string): ConfigObject {\n if (!content || content.trim() === \"\") {\n return {};\n }\n const parsed = parseYaml(content);\n if (parsed === null || parsed === undefined) {\n return {};\n }\n if (!isConfigObject(parsed)) {\n throw new Error(\"Expected YAML object.\");\n }\n return parsed;\n}\n\nfunction serialize(obj: ConfigObject): string {\n const serialized = stringifyYaml(obj);\n return serialized.endsWith(\"\\n\") ? serialized : `${serialized}\\n`;\n}\n\nfunction merge(base: ConfigObject, patch: ConfigObject): ConfigObject {\n const result: ConfigObject = { ...base };\n for (const [key, value] of Object.entries(patch)) {\n if (value === undefined) {\n continue;\n }\n const existing = result[key];\n if (isConfigObject(existing) && isConfigObject(value)) {\n result[key] = merge(existing, value);\n continue;\n }\n result[key] = value as ConfigValue;\n }\n return result;\n}\n\nfunction prune(\n obj: ConfigObject,\n shape: ConfigObject\n): { changed: boolean; result: ConfigObject } {\n let changed = false;\n const result: ConfigObject = { ...obj };\n\n for (const [key, pattern] of Object.entries(shape)) {\n if (!(key in result)) {\n continue;\n }\n\n const current = result[key];\n\n if (isConfigObject(pattern) && Object.keys(pattern).length === 0) {\n delete result[key];\n changed = true;\n continue;\n }\n\n if (isConfigObject(pattern) && isConfigObject(current)) {\n const { changed: childChanged, result: childResult } = prune(current, pattern);\n if (childChanged) {\n changed = true;\n }\n if (Object.keys(childResult).length === 0) {\n delete result[key];\n } else {\n result[key] = childResult;\n }\n continue;\n }\n\n delete result[key];\n changed = true;\n }\n\n return { changed, result };\n}\n\nexport const yamlFormat: ConfigFormat = {\n parse,\n serialize,\n merge,\n prune\n};\n", "import type { ConfigFormat } from \"../types.js\";\nimport { jsonFormat } from \"./json.js\";\nimport { tomlFormat } from \"./toml.js\";\nimport { yamlFormat } from \"./yaml.js\";\n\nexport type FormatName = \"json\" | \"toml\" | \"yaml\";\n\nconst formatRegistry: Record<FormatName, ConfigFormat> = {\n json: jsonFormat,\n toml: tomlFormat,\n yaml: yamlFormat\n};\n\nconst extensionMap: Record<string, FormatName> = {\n \".json\": \"json\",\n \".toml\": \"toml\",\n \".yaml\": \"yaml\",\n \".yml\": \"yaml\"\n};\n\n/**\n * Get a format handler by path (auto-detect from extension) or explicit format name.\n */\nexport function getConfigFormat(pathOrFormat: string): ConfigFormat {\n // Check if it's an explicit format name\n if (pathOrFormat in formatRegistry) {\n return formatRegistry[pathOrFormat as FormatName];\n }\n\n // Try to detect from extension\n const ext = getExtension(pathOrFormat);\n const formatName = extensionMap[ext];\n\n if (!formatName) {\n throw new Error(\n `Unsupported config format. Cannot detect format from \"${pathOrFormat}\". ` +\n `Supported extensions: ${Object.keys(extensionMap).join(\", \")}. ` +\n `Supported format names: ${Object.keys(formatRegistry).join(\", \")}.`\n );\n }\n\n return formatRegistry[formatName];\n}\n\n/**\n * Detect format name from a file path.\n */\nexport function detectFormat(path: string): FormatName | undefined {\n const ext = getExtension(path);\n return extensionMap[ext];\n}\n\nfunction getExtension(path: string): string {\n const lastDot = path.lastIndexOf(\".\");\n if (lastDot === -1) {\n return \"\";\n }\n return path.slice(lastDot).toLowerCase();\n}\n\nexport { jsonFormat } from \"./json.js\";\nexport { tomlFormat } from \"./toml.js\";\nexport { yamlFormat } from \"./yaml.js\";\n", "import path from \"node:path\";\nimport type { PathMapper } from \"../types.js\";\n\n/**\n * Expand ~ shortcut to the provided home directory.\n */\nexport function expandHome(targetPath: string, homeDir: string): string {\n if (!targetPath?.startsWith(\"~\")) {\n return targetPath;\n }\n\n // Handle ~./ -> ~/.\n if (targetPath.startsWith(\"~./\")) {\n targetPath = `~/.${targetPath.slice(3)}`;\n }\n\n let remainder = targetPath.slice(1);\n\n // Remove leading slash or backslash\n if (remainder.startsWith(\"/\") || remainder.startsWith(\"\\\\\")) {\n remainder = remainder.slice(1);\n } else if (remainder.startsWith(\".\")) {\n // Handle ~/.\n remainder = remainder.slice(1);\n if (remainder.startsWith(\"/\") || remainder.startsWith(\"\\\\\")) {\n remainder = remainder.slice(1);\n }\n }\n\n return remainder.length === 0 ? homeDir : path.join(homeDir, remainder);\n}\n\n/**\n * Validate that a path is home-relative (starts with ~).\n * Throws if the path is not home-relative.\n */\nexport function validateHomePath(targetPath: string): void {\n if (typeof targetPath !== \"string\" || targetPath.length === 0) {\n throw new Error(\"Target path must be a non-empty string.\");\n }\n\n if (!targetPath.startsWith(\"~\")) {\n throw new Error(\n `All target paths must be home-relative (start with ~). Received: \"${targetPath}\"`\n );\n }\n}\n\n/**\n * Resolve a path with optional path mapping for isolated configurations.\n * 1. Validates the path starts with ~\n * 2. Expands ~ to home directory\n * 3. If pathMapper is provided, maps the directory portion and reconstructs the path\n */\nexport function resolvePath(\n rawPath: string,\n homeDir: string,\n pathMapper?: PathMapper\n): string {\n validateHomePath(rawPath);\n const expanded = expandHome(rawPath, homeDir);\n\n if (!pathMapper) {\n return expanded;\n }\n\n // Map the directory portion\n const rawDirectory = path.dirname(expanded);\n const mappedDirectory = pathMapper.mapTargetDirectory({\n targetDirectory: rawDirectory\n });\n const filename = path.basename(expanded);\n\n return filename.length === 0 ? mappedDirectory : path.join(mappedDirectory, filename);\n}\n", "import type { FileSystem } from \"./types.js\";\n\n/**\n * Check if an error is a \"file not found\" (ENOENT) error.\n */\nexport function isNotFound(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n (error as { code?: string }).code === \"ENOENT\"\n );\n}\n\n/**\n * Read a file if it exists, returning null if not found.\n */\nexport async function readFileIfExists(\n fs: FileSystem,\n target: string\n): Promise<string | null> {\n try {\n return await fs.readFile(target, \"utf8\");\n } catch (error) {\n if (isNotFound(error)) {\n return null;\n }\n throw error;\n }\n}\n\n/**\n * Check if a path exists (file or directory).\n */\nexport async function pathExists(\n fs: FileSystem,\n target: string\n): Promise<boolean> {\n try {\n await fs.stat(target);\n return true;\n } catch (error) {\n if (isNotFound(error)) {\n return false;\n }\n throw error;\n }\n}\n\n/**\n * Create an ISO timestamp safe for use in filenames.\n * Replaces colons and dots with dashes.\n */\nexport function createTimestamp(): string {\n return new Date().toISOString().replaceAll(\":\", \"-\").replaceAll(\".\", \"-\");\n}\n", "import type {\n Mutation,\n MutationContext,\n MutationResult,\n MutationOptions\n} from \"../types.js\";\nimport { applyMutation } from \"./apply-mutation.js\";\n\n/**\n * Execute an array of mutations in order.\n *\n * All dependencies must be injected - no defaults, no globals.\n */\nexport async function runMutations(\n mutations: Mutation[],\n context: MutationContext,\n options?: MutationOptions\n): Promise<MutationResult> {\n const effects: MutationResult[\"effects\"] = [];\n let anyChanged = false;\n const resolverOptions = options ?? {};\n\n for (const mutation of mutations) {\n const { outcome } = await executeMutation(\n mutation,\n context,\n resolverOptions\n );\n effects.push(outcome);\n if (outcome.changed) {\n anyChanged = true;\n }\n }\n\n return {\n changed: anyChanged,\n effects\n };\n}\n\nasync function executeMutation(\n mutation: Mutation,\n context: MutationContext,\n options: MutationOptions\n): Promise<{ outcome: MutationResult[\"effects\"][number]; details: { kind: string; label: string; targetPath?: string } }> {\n // Call onStart observer\n context.observers?.onStart?.({\n kind: mutation.kind,\n label: mutation.label ?? mutation.kind,\n targetPath: undefined // Will be resolved during apply\n });\n\n try {\n const { outcome, details } = await applyMutation(mutation, context, options);\n\n // Call onComplete observer\n context.observers?.onComplete?.(details, outcome);\n\n return { outcome, details };\n } catch (error) {\n // Call onError observer\n context.observers?.onError?.(\n {\n kind: mutation.kind,\n label: mutation.label ?? mutation.kind,\n targetPath: undefined\n },\n error\n );\n\n // Re-throw the error\n throw error;\n }\n}\n", "import Mustache from \"mustache\";\n\nexport type TemplateVariables = Record<string, string | number | boolean | string[]>;\n\n// Disable HTML escaping - we're rendering prompts, not HTML\nconst originalEscape = Mustache.escape;\n\n/**\n * Render a mustache template with the given variables.\n * Arrays are automatically joined with newlines.\n * HTML escaping is disabled.\n */\nexport function renderTemplate(\n template: string,\n variables: TemplateVariables\n): string {\n // Pre-process variables to handle arrays\n const processed: Record<string, string | number | boolean> = {};\n for (const [key, value] of Object.entries(variables)) {\n if (Array.isArray(value)) {\n processed[key] = value.join(\"\\n\");\n } else {\n processed[key] = value;\n }\n }\n\n // Temporarily disable HTML escaping\n Mustache.escape = (text: string) => text;\n try {\n return Mustache.render(template, processed);\n } finally {\n Mustache.escape = originalEscape;\n }\n}\n", "import type {\n CommandRunner,\n CommandCheckContext,\n CommandCheck\n} from \"../utils/command-checks.js\";\n\nexport interface InstallContext {\n isDryRun: boolean;\n runCommand: CommandRunner;\n logger: (message: string) => void;\n platform: NodeJS.Platform;\n}\n\nexport interface InstallCommand {\n id: string;\n command: string;\n args: string[];\n platforms?: NodeJS.Platform[];\n}\n\nexport interface ServiceInstallDefinition {\n id: string;\n summary: string;\n check: CommandCheck;\n steps: InstallCommand[];\n postChecks?: CommandCheck[];\n successMessage?: string;\n}\n\nexport async function runServiceInstall(\n definition: ServiceInstallDefinition,\n context: InstallContext\n): Promise<boolean> {\n const checkContext: CommandCheckContext = {\n isDryRun: context.isDryRun,\n runCommand: context.runCommand\n };\n\n let needsInstall = false;\n try {\n await definition.check.run(checkContext);\n context.logger(`${definition.summary} already installed.`);\n } catch (error) {\n const detail =\n error instanceof Error ? error.message : String(error);\n context.logger(`${definition.summary} not detected: ${detail}`);\n needsInstall = true;\n }\n\n if (!needsInstall) {\n return false;\n }\n\n if (context.isDryRun) {\n logInstallDryRun(definition, context);\n return true;\n }\n\n const platformSteps = filterStepsByPlatform(definition.steps, context.platform);\n for (const step of platformSteps) {\n await runInstallStep(step, context);\n }\n\n await definition.check.run(checkContext);\n\n if (definition.postChecks) {\n for (const postCheck of definition.postChecks) {\n await postCheck.run(checkContext);\n }\n }\n\n context.logger(\n definition.successMessage ?? `${definition.summary} installed.`\n );\n return true;\n}\n\nfunction describeInstallCommand(step: InstallCommand): string {\n return `[${step.id}] ${formatCommand(step.command, step.args)}`;\n}\n\nfunction formatCommand(command: string, args: string[]): string {\n return [command, ...args.map(quoteIfNeeded)].join(\" \");\n}\n\nfunction quoteIfNeeded(value: string): string {\n if (value.length === 0) {\n return '\"\"';\n }\n if (value.includes(\" \") || value.includes(\"\\t\") || value.includes(\"\\n\")) {\n return `\"${value.replaceAll('\"', '\\\\\"')}\"`;\n }\n return value;\n}\n\nfunction filterStepsByPlatform(\n steps: InstallCommand[],\n platform: NodeJS.Platform\n): InstallCommand[] {\n return steps.filter(\n (step) => !step.platforms || step.platforms.includes(platform)\n );\n}\n\nfunction logInstallDryRun(\n definition: ServiceInstallDefinition,\n context: InstallContext\n): void {\n context.logger(`Dry run: would install ${definition.summary}.`);\n const platformSteps = filterStepsByPlatform(definition.steps, context.platform);\n for (const step of platformSteps) {\n context.logger(`Dry run: ${describeInstallCommand(step)}`);\n }\n}\n\nasync function runInstallStep(\n step: InstallCommand,\n context: InstallContext\n): Promise<void> {\n context.logger(`Running ${describeInstallCommand(step)}`);\n const result = await context.runCommand(step.command, step.args);\n if (result.exitCode !== 0) {\n const stderr = result.stderr.trim();\n const suffix = stderr.length > 0 ? `: ${stderr}` : \"\";\n throw new Error(\n `${describeInstallCommand(step)} failed with exit code ${result.exitCode}${suffix}`\n );\n }\n}\n", "import type {\n ProviderService,\n ProviderContext,\n ProviderBranding,\n ProviderConfigurePrompts,\n ProviderIsolatedEnv\n} from \"../cli/service-registry.js\";\nimport {\n runMutations,\n type Mutation,\n type MutationObservers\n} from \"@poe-code/config-mutations\";\nimport {\n runServiceInstall,\n type ServiceInstallDefinition\n} from \"../services/service-install.js\";\n// Template imports are lazy to avoid breaking tsc output when imported\n// by generate-bin-wrappers.mjs (Node.js can't resolve .mustache as ESM modules)\nconst templateImports: Record<string, () => Promise<{ default: string }>> = {\n \"py-poe-spawn/env.mustache\": () => import(\"../templates/py-poe-spawn/env.mustache\"),\n \"py-poe-spawn/main.py.mustache\": () => import(\"../templates/py-poe-spawn/main.py.mustache\"),\n \"py-poe-spawn/requirements.txt.mustache\": () => import(\"../templates/py-poe-spawn/requirements.txt.mustache\"),\n \"codex/config.toml.mustache\": () => import(\"../templates/codex/config.toml.mustache\"),\n \"tiny-http-mcp-server/server.mjs.mustache\": () =>\n import(\"../templates/tiny-http-mcp-server/server.mjs.mustache\"),\n \"tiny-http-mcp-server/verify-token.mjs.mustache\": () =>\n import(\"../templates/tiny-http-mcp-server/verify-token.mjs.mustache\"),\n};\n\nasync function loadTemplate(templateId: string): Promise<string> {\n const loader = templateImports[templateId];\n if (!loader) {\n throw new Error(`Template not found: ${templateId}`);\n }\n const module = await loader();\n return module.default;\n}\n\ninterface ManifestVersionDefinition {\n configure: Mutation[];\n unconfigure?: Mutation[];\n}\n\nexport interface ServiceRunOptions {\n observers?: MutationObservers;\n}\n\ninterface CreateProviderOptions<\n ConfigureOptions,\n UnconfigureOptions,\n SpawnOptions\n> {\n name: string;\n aliases?: string[];\n label: string;\n id: string;\n summary: string;\n branding?: ProviderBranding;\n disabled?: boolean;\n supportsStdinPrompt?: boolean;\n supportsMcpSpawn?: boolean;\n requiresProvider?: boolean;\n configurePrompts?: ProviderConfigurePrompts;\n postConfigureMessages?: string[];\n extendConfigurePayload?: ProviderService<\n ConfigureOptions,\n UnconfigureOptions,\n SpawnOptions\n >[\"extendConfigurePayload\"];\n isolatedEnv?: ProviderIsolatedEnv;\n manifest: ManifestVersionDefinition;\n install?: ServiceInstallDefinition;\n test?: ProviderService<ConfigureOptions, UnconfigureOptions, SpawnOptions>[\"test\"];\n spawn?: ProviderService<\n ConfigureOptions,\n UnconfigureOptions,\n SpawnOptions\n >[\"spawn\"];\n}\n\nexport function createProvider<\n ConfigureOptions = any,\n UnconfigureOptions = ConfigureOptions,\n SpawnOptions = any\n>(\n opts: CreateProviderOptions<ConfigureOptions, UnconfigureOptions, SpawnOptions>\n): ProviderService<ConfigureOptions, UnconfigureOptions, SpawnOptions> {\n const provider: ProviderService<\n ConfigureOptions,\n UnconfigureOptions,\n SpawnOptions\n > = {\n id: opts.id,\n summary: opts.summary,\n name: opts.name,\n aliases: opts.aliases,\n label: opts.label,\n branding: opts.branding,\n disabled: opts.disabled,\n supportsStdinPrompt: opts.supportsStdinPrompt,\n supportsMcpSpawn: opts.supportsMcpSpawn,\n requiresProvider: opts.requiresProvider ?? true,\n configurePrompts: opts.configurePrompts,\n postConfigureMessages: opts.postConfigureMessages,\n extendConfigurePayload: opts.extendConfigurePayload,\n isolatedEnv: opts.isolatedEnv,\n async configure(context, runOptions) {\n await runMutations(opts.manifest.configure, {\n fs: context.fs,\n homeDir: context.env.homeDir,\n observers: runOptions?.observers,\n templates: loadTemplate,\n pathMapper: context.pathMapper\n }, context.options as Record<string, unknown>);\n context.command.flushDryRun({ emitIfEmpty: false });\n },\n async unconfigure(context, runOptions) {\n if (!opts.manifest.unconfigure) {\n return false;\n }\n const result = await runMutations(opts.manifest.unconfigure, {\n fs: context.fs,\n homeDir: context.env.homeDir,\n observers: runOptions?.observers,\n templates: loadTemplate,\n pathMapper: context.pathMapper\n }, context.options as Record<string, unknown>);\n context.command.flushDryRun({ emitIfEmpty: false });\n return result.changed;\n }\n };\n\n if (opts.install) {\n provider.install = createInstallRunner(opts.install);\n }\n\n if (opts.test) {\n provider.test = opts.test;\n }\n\n if (opts.spawn) {\n provider.spawn = opts.spawn;\n }\n\n return provider;\n}\n\nfunction createInstallRunner(definition: ServiceInstallDefinition) {\n return async (context: ProviderContext): Promise<void> => {\n await runServiceInstall(definition, {\n isDryRun: context.logger.context.dryRun,\n runCommand: context.command.runCommand,\n logger: (message) => context.logger.verbose(message),\n platform: context.env.platform\n });\n };\n}\n", "import {\n configMutation,\n fileMutation,\n templateMutation\n} from \"@poe-code/config-mutations\";\nimport { createProvider } from \"./create-provider.js\";\nimport type { ProviderConfigurePayloadContext } from \"../cli/service-registry.js\";\n\ninterface TinyHttpMcpServerOauthConfig {\n resource: string;\n authorizationServers: string[];\n scopesSupported: string[];\n requiredScopes: string[];\n bearerMethodsSupported: string[];\n verifierModule: string;\n verifierExport: string;\n}\n\ninterface TinyHttpMcpServerConfigureContext extends Record<string, unknown> {\n name: string;\n version: string;\n listen: {\n hostname: string;\n path: string;\n port: number;\n };\n oauth: TinyHttpMcpServerOauthConfig;\n}\n\nconst SCAFFOLD_DIRECTORY = \"~/.poe-code/tiny-http-mcp-server\";\nconst CONFIG_FILE = `${SCAFFOLD_DIRECTORY}/config.json`;\nconst SERVER_FILE = `${SCAFFOLD_DIRECTORY}/server.mjs`;\nconst VERIFIER_FILE = `${SCAFFOLD_DIRECTORY}/verify-token.mjs`;\n\nconst DEFAULT_CONFIG: TinyHttpMcpServerConfigureContext = {\n name: \"oauth-http-server\",\n version: \"1.0.0\",\n listen: {\n hostname: \"127.0.0.1\",\n path: \"/mcp\",\n port: 3000,\n },\n oauth: {\n resource: \"https://example.com/mcp\",\n authorizationServers: [\"https://auth.example.com\"],\n scopesSupported: [\"mcp.read\", \"mcp.write\"],\n requiredScopes: [\"mcp.read\"],\n bearerMethodsSupported: [\"header\"],\n verifierModule: \"./verify-token.mjs\",\n verifierExport: \"default\",\n },\n};\n\nfunction normalizeString(value: string): string {\n return value.trim();\n}\n\nfunction normalizeStringList(values: readonly string[]): string[] {\n const normalized: string[] = [];\n\n for (const value of values) {\n const trimmed = normalizeString(value);\n if (trimmed.length === 0 || normalized.includes(trimmed)) {\n continue;\n }\n normalized.push(trimmed);\n }\n\n return normalized;\n}\n\nfunction splitCommaSeparated(value: string): string[] {\n return normalizeStringList(value.split(\",\"));\n}\n\nfunction readStringOption(\n context: ProviderConfigurePayloadContext,\n key: string\n): string | undefined {\n const value = context.commandOptions[key];\n return typeof value === \"string\" && value.trim().length > 0\n ? normalizeString(value)\n : undefined;\n}\n\nfunction readStringArrayOption(\n context: ProviderConfigurePayloadContext,\n key: string\n): string[] | undefined {\n const value = context.commandOptions[key];\n if (!Array.isArray(value)) {\n return undefined;\n }\n const normalized = normalizeStringList(\n value.filter((entry): entry is string => typeof entry === \"string\")\n );\n return normalized.length > 0 ? normalized : undefined;\n}\n\nasync function promptForValue(\n context: ProviderConfigurePayloadContext,\n input: {\n key: string;\n message: string;\n defaultValue: string;\n }\n): Promise<string> {\n const response = await context.prompts({\n name: input.key,\n message: input.message,\n type: \"text\",\n initial: input.defaultValue,\n });\n const value = response[input.key];\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new Error(`Missing value for ${input.message}.`);\n }\n return normalizeString(value);\n}\n\nasync function resolveStringField(\n context: ProviderConfigurePayloadContext,\n input: {\n optionKey: string;\n promptKey: string;\n message: string;\n defaultValue: string;\n }\n): Promise<string> {\n const configured = readStringOption(context, input.optionKey);\n if (configured !== undefined) {\n return configured;\n }\n if (context.assumeYes) {\n return input.defaultValue;\n }\n return promptForValue(context, {\n key: input.promptKey,\n message: input.message,\n defaultValue: input.defaultValue,\n });\n}\n\nasync function resolveStringListField(\n context: ProviderConfigurePayloadContext,\n input: {\n optionKey: string;\n promptKey: string;\n message: string;\n defaultValue: string[];\n }\n): Promise<string[]> {\n const configured = readStringArrayOption(context, input.optionKey);\n if (configured !== undefined) {\n return configured;\n }\n if (context.assumeYes) {\n return [...input.defaultValue];\n }\n const response = await promptForValue(context, {\n key: input.promptKey,\n message: input.message,\n defaultValue: input.defaultValue.join(\", \"),\n });\n return splitCommaSeparated(response);\n}\n\nasync function resolveTinyHttpMcpServerConfig(\n context: ProviderConfigurePayloadContext\n): Promise<TinyHttpMcpServerConfigureContext> {\n return {\n name: DEFAULT_CONFIG.name,\n version: DEFAULT_CONFIG.version,\n listen: { ...DEFAULT_CONFIG.listen },\n oauth: {\n resource: await resolveStringField(context, {\n optionKey: \"oauthResource\",\n promptKey: \"oauthResource\",\n message: \"OAuth protected resource URI\",\n defaultValue: DEFAULT_CONFIG.oauth.resource,\n }),\n authorizationServers: await resolveStringListField(context, {\n optionKey: \"oauthAuthorizationServer\",\n promptKey: \"oauthAuthorizationServers\",\n message: \"OAuth authorization server issuers (comma-separated)\",\n defaultValue: DEFAULT_CONFIG.oauth.authorizationServers,\n }),\n scopesSupported: await resolveStringListField(context, {\n optionKey: \"oauthSupportedScope\",\n promptKey: \"oauthSupportedScopes\",\n message: \"OAuth supported scopes (comma-separated)\",\n defaultValue: DEFAULT_CONFIG.oauth.scopesSupported,\n }),\n requiredScopes: await resolveStringListField(context, {\n optionKey: \"oauthRequiredScope\",\n promptKey: \"oauthRequiredScopes\",\n message: \"OAuth required scopes (comma-separated)\",\n defaultValue: DEFAULT_CONFIG.oauth.requiredScopes,\n }),\n bearerMethodsSupported: await resolveStringListField(context, {\n optionKey: \"oauthBearerMethod\",\n promptKey: \"oauthBearerMethods\",\n message: \"OAuth bearer methods (comma-separated)\",\n defaultValue: DEFAULT_CONFIG.oauth.bearerMethodsSupported,\n }),\n verifierModule: await resolveStringField(context, {\n optionKey: \"oauthVerifierModule\",\n promptKey: \"oauthVerifierModule\",\n message: \"OAuth verifier module path or specifier\",\n defaultValue: DEFAULT_CONFIG.oauth.verifierModule,\n }),\n verifierExport: await resolveStringField(context, {\n optionKey: \"oauthVerifierExport\",\n promptKey: \"oauthVerifierExport\",\n message: \"OAuth verifier export name\",\n defaultValue: DEFAULT_CONFIG.oauth.verifierExport,\n }),\n },\n };\n}\n\nexport const tinyHttpMcpServerService = createProvider<TinyHttpMcpServerConfigureContext>({\n id: \"tiny-http-mcp-server\",\n name: \"tiny-http-mcp-server\",\n label: \"tiny-http-mcp-server\",\n summary: \"Scaffold an OAuth-protected tiny-http-mcp-server example.\",\n requiresProvider: false,\n async extendConfigurePayload(context) {\n return resolveTinyHttpMcpServerConfig(context);\n },\n manifest: {\n configure: [\n fileMutation.ensureDirectory({ path: SCAFFOLD_DIRECTORY }),\n configMutation.merge({\n target: CONFIG_FILE,\n value: (ctx) => {\n const options = ctx as unknown as TinyHttpMcpServerConfigureContext;\n return {\n name: options.name,\n version: options.version,\n listen: {\n hostname: options.listen.hostname,\n path: options.listen.path,\n port: options.listen.port,\n },\n oauth: {\n resource: options.oauth.resource,\n authorizationServers: options.oauth.authorizationServers,\n scopesSupported: options.oauth.scopesSupported,\n requiredScopes: options.oauth.requiredScopes,\n bearerMethodsSupported: options.oauth.bearerMethodsSupported,\n verifierModule: options.oauth.verifierModule,\n verifierExport: options.oauth.verifierExport,\n },\n };\n },\n }),\n fileMutation.backup({ target: SERVER_FILE }),\n templateMutation.write({\n target: SERVER_FILE,\n templateId: \"tiny-http-mcp-server/server.mjs.mustache\",\n }),\n fileMutation.backup({ target: VERIFIER_FILE }),\n templateMutation.write({\n target: VERIFIER_FILE,\n templateId: \"tiny-http-mcp-server/verify-token.mjs.mustache\",\n }),\n ],\n unconfigure: [\n fileMutation.remove({ target: CONFIG_FILE }),\n fileMutation.remove({ target: SERVER_FILE }),\n fileMutation.remove({ target: VERIFIER_FILE }),\n fileMutation.removeDirectory({ path: SCAFFOLD_DIRECTORY }),\n ],\n },\n});\n\nexport const provider = tinyHttpMcpServerService;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["parse", "merge", "prune", "parse", "merge", "prune", "isConfigObject", "parse", "serialize", "merge", "prune", "isConfigObject", "parse", "serialize", "merge", "prune", "path", "isConfigObject", "Mustache", "provider"]
|
|
7
|
+
}
|
|
@@ -3,38 +3,24 @@ name: poe-code-pipeline-plan
|
|
|
3
3
|
description: 'Generate a Pipeline plan markdown file with YAML frontmatter from a user request. Triggers on: create a pipeline plan, write plan for, plan this feature, pipeline plan.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
# Pipeline plan
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Write the plan as YAML frontmatter. Each task's `prompt` must be self-contained — no relying on the markdown body or earlier tasks at runtime.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Where to write (first match wins)
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
1. Request mentions an `.md` file → edit it in place.
|
|
13
|
+
2. A file in the plan directory matches the topic (filename stem or `# heading`) → overwrite it, regardless of its `kind:`. One file per topic.
|
|
14
|
+
3. Otherwise → create `<plan-directory>/<name>.md`.
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
2. Otherwise write a new file at `<plan-directory>/plan-<name>.md` (see Plan Directory section below).
|
|
16
|
-
3. Find the `steps.yaml` file. Check these locations in order and use the first one found:
|
|
17
|
-
a. `<project-root>/.poe-code/pipeline/steps.yaml` (project-level)
|
|
18
|
-
b. `~/.poe-code/pipeline/steps.yaml` (user-global)
|
|
19
|
-
If found, read it to determine available steps and note any `setup`/`teardown` hooks defined there. If not found in either location, use stepless tasks.
|
|
16
|
+
## Steps
|
|
20
17
|
|
|
21
|
-
|
|
18
|
+
Read the first `steps.yaml` found at `<project-root>/.poe-code/pipeline/steps.yaml` then `~/.poe-code/pipeline/steps.yaml`.
|
|
22
19
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
- Use short kebab-case ids.
|
|
26
|
-
- Keep titles concise and descriptive.
|
|
27
|
-
- The available steps come from the `steps.yaml` file you found (project or global). Use the current step names instead of inventing hardcoded ones.
|
|
28
|
-
- If no step configuration is present, use stepless tasks with scalar `status: open`.
|
|
29
|
-
- If step configuration is present, start every configured step status at `open`.
|
|
30
|
-
- `setup` and `teardown` defined in `steps.yaml` are inherited automatically.
|
|
31
|
-
- To disable an inherited hook for a specific plan, set `setup: false` or `teardown: false`.
|
|
32
|
-
- To override an inherited hook, define the full block with a `prompt` field.
|
|
33
|
-
- The markdown body is for context, notes, acceptance criteria, or the design doc. Keep executable pipeline config in the YAML frontmatter.
|
|
34
|
-
- Do not rely on the body alone for runtime context. Each task prompt must still include everything it needs directly.
|
|
35
|
-
- Start the frontmatter with canonical metadata: `$schema: https://poe-platform.github.io/poe-code/schemas/plans/pipeline.schema.json`, `kind: pipeline`, and `version: 1`.
|
|
20
|
+
- Without one: stepless tasks, scalar `status: open`.
|
|
21
|
+
- With one: per task, use judgement to pick only the configured steps that genuinely apply (e.g. a docs-only task probably doesn't need `test`; a config bump may not need its own `commit` step). Set every step you include to `open`. `setup`/`teardown` are inherited; set `setup: false` to disable or define a full block to override.
|
|
36
22
|
|
|
37
|
-
##
|
|
23
|
+
## Format
|
|
38
24
|
|
|
39
25
|
```markdown
|
|
40
26
|
---
|
|
@@ -42,41 +28,67 @@ $schema: https://poe-platform.github.io/poe-code/schemas/plans/pipeline.schema.j
|
|
|
42
28
|
kind: pipeline
|
|
43
29
|
version: 1
|
|
44
30
|
|
|
45
|
-
# setup/teardown are inherited from steps.yaml automatically.
|
|
46
|
-
# Include them only to disable or override:
|
|
47
|
-
#
|
|
48
|
-
# setup: false # disable the inherited setup hook
|
|
49
|
-
# teardown: false # disable the inherited teardown hook
|
|
50
|
-
# setup: # override with a different prompt
|
|
51
|
-
# prompt: Custom setup
|
|
52
|
-
# mode: yolo
|
|
53
|
-
|
|
54
31
|
tasks:
|
|
55
|
-
- id:
|
|
56
|
-
title:
|
|
32
|
+
- id: validate-signup-input
|
|
33
|
+
title: Validate signup request body
|
|
57
34
|
prompt: |
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
35
|
+
In src/api/signup.ts, validate the request body before the handler
|
|
36
|
+
runs. Reject when email is missing, malformed, or > 254 chars, or
|
|
37
|
+
password is < 8 chars. Return 400 with a JSON `{ code }` on reject.
|
|
38
|
+
status:
|
|
39
|
+
implement: open
|
|
40
|
+
test: open
|
|
41
|
+
|
|
42
|
+
- id: rate-limit-signup
|
|
43
|
+
title: Rate-limit signup to 5/hour per IP
|
|
44
|
+
prompt: |
|
|
45
|
+
Add a 5/hour-per-IP limit to src/api/signup.ts using the existing
|
|
46
|
+
limiter in src/middleware/rate-limit.ts. On exceed return 429 with
|
|
47
|
+
a Retry-After header.
|
|
48
|
+
status:
|
|
49
|
+
implement: open
|
|
50
|
+
test: open
|
|
51
|
+
|
|
52
|
+
- id: audit-failed-signups
|
|
53
|
+
title: Log failed signups to the audit log
|
|
54
|
+
prompt: |
|
|
55
|
+
When signup fails validation or rate limiting, write {ip, ts, reason}
|
|
56
|
+
via src/audit/logger.ts. Never log the password attempt.
|
|
57
|
+
status:
|
|
58
|
+
implement: open
|
|
59
|
+
test: open
|
|
60
|
+
|
|
61
|
+
- id: document-signup-limits
|
|
62
|
+
title: Document signup validation and rate limits
|
|
63
|
+
prompt: |
|
|
64
|
+
Add a "Signup limits" section to docs/api/signup.md covering email
|
|
65
|
+
length, password length, and the 5/hour-per-IP rate limit.
|
|
66
|
+
status:
|
|
67
|
+
implement: open
|
|
66
68
|
---
|
|
67
69
|
|
|
68
70
|
# Context
|
|
69
71
|
|
|
70
|
-
|
|
71
|
-
This body is for human-readable context and future tooling.
|
|
72
|
-
Any context needed at runtime must still appear in each task prompt.
|
|
72
|
+
Design notes or acceptance criteria.
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
Stepless variant — when no `steps.yaml` is present, `status` is a scalar instead of a per-step map:
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
```yaml
|
|
78
|
+
tasks:
|
|
79
|
+
- id: bump-node-version
|
|
80
|
+
title: Bump Node engine to 20
|
|
81
|
+
prompt: |
|
|
82
|
+
Update `engines.node` in package.json to `>=20`. Update the same
|
|
83
|
+
pin in .nvmrc and the Node version in .github/workflows/ci.yml.
|
|
84
|
+
status: open
|
|
78
85
|
|
|
79
|
-
|
|
86
|
+
- id: drop-deprecated-flag
|
|
87
|
+
title: Remove the deprecated --legacy-render flag
|
|
88
|
+
prompt: |
|
|
89
|
+
In src/cli/render.ts remove the `--legacy-render` flag and any
|
|
90
|
+
branches that read it. The flag has been a no-op since v3.2.
|
|
91
|
+
status: open
|
|
92
|
+
```
|
|
80
93
|
|
|
81
|
-
|
|
82
|
-
- If `poe-code` is not available as a global command, use `npx poe-code` instead.
|
|
94
|
+
Validate with `poe-code pipeline validate <path>` (or `npx poe-code …`).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poe-code",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.192",
|
|
4
4
|
"description": "CLI tool to configure Poe API for developer workflows.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"packages/*"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
|
-
"build": "turbo run build && npm run codegen:plan-schemas &&
|
|
22
|
+
"build": "turbo run build && npm run codegen:plan-schemas && tsc -p tsconfig.build.json && node scripts/generate-bin-wrappers.mjs && node scripts/bundle.mjs",
|
|
23
23
|
"build:deps": "node scripts/list-workspace-deps.mjs",
|
|
24
24
|
"codegen:python-types": "tsx scripts/generate-agent-spawn-py-types.ts",
|
|
25
25
|
"codegen:check:python-types": "tsx scripts/generate-agent-spawn-py-types.ts --check",
|
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
"poe-codex": "dist/bin/poe-codex.js",
|
|
84
84
|
"poe-opencode": "dist/bin/poe-opencode.js",
|
|
85
85
|
"poe-agent": "dist/bin/poe-agent.js",
|
|
86
|
+
"tiny-oauth-test-server": "packages/tiny-oauth-test-server/dist/cli.js",
|
|
86
87
|
"tiny-stdio-mcp-test-server": "packages/tiny-stdio-mcp-test-server/dist/cli.js"
|
|
87
88
|
},
|
|
88
89
|
"files": [
|
|
@@ -106,6 +107,7 @@
|
|
|
106
107
|
"diff": ">=8.0.3",
|
|
107
108
|
"fast-glob": "^3.3.3",
|
|
108
109
|
"gray-matter": "^4.0.3",
|
|
110
|
+
"jose": "^6.1.3",
|
|
109
111
|
"jsonc-parser": "^3.3.1",
|
|
110
112
|
"mustache": "^4.2.0",
|
|
111
113
|
"openai": "^6.34.0",
|
|
@@ -122,6 +124,7 @@
|
|
|
122
124
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
123
125
|
"@poe-code/agent-defs": "*",
|
|
124
126
|
"@poe-code/agent-harness-tools": "*",
|
|
127
|
+
"@poe-code/agent-human-in-loop": "*",
|
|
125
128
|
"@poe-code/agent-mcp-config": "*",
|
|
126
129
|
"@poe-code/agent-skill-config": "*",
|
|
127
130
|
"@poe-code/agent-spawn": "*",
|
|
@@ -131,6 +134,7 @@
|
|
|
131
134
|
"@poe-code/design-system": "*",
|
|
132
135
|
"@poe-code/e2e-test-runner": "*",
|
|
133
136
|
"@poe-code/experiment-loop": "*",
|
|
137
|
+
"@poe-code/file-lock": "*",
|
|
134
138
|
"@poe-code/github-workflows": "*",
|
|
135
139
|
"@poe-code/markdown-reader": "*",
|
|
136
140
|
"@poe-code/memory": "*",
|
|
@@ -145,6 +149,7 @@
|
|
|
145
149
|
"@poe-code/py-poe-spawn": "*",
|
|
146
150
|
"@poe-code/ralph": "*",
|
|
147
151
|
"@poe-code/superintendent": "*",
|
|
152
|
+
"@poe-code/task-list": "*",
|
|
148
153
|
"@poe-code/workspace-resolver": "*",
|
|
149
154
|
"@poe-code/worktree": "*",
|
|
150
155
|
"@types/mustache": "^4.2.6",
|
|
@@ -161,6 +166,7 @@
|
|
|
161
166
|
"globals": "^17.3.0",
|
|
162
167
|
"husky": "^9.1.7",
|
|
163
168
|
"memfs": "^4.56.10",
|
|
169
|
+
"mcp-oauth": "*",
|
|
164
170
|
"opencode-poe-auth": "*",
|
|
165
171
|
"poe-oauth": "*",
|
|
166
172
|
"prettier": "^3.8.1",
|
|
@@ -168,7 +174,9 @@
|
|
|
168
174
|
"terminal-pilot-mcp": "*",
|
|
169
175
|
"terminal-png": "*",
|
|
170
176
|
"tiny-http-mcp-server": "*",
|
|
177
|
+
"tiny-http-mcp-oauth-test-server": "*",
|
|
171
178
|
"tiny-mcp-client": "*",
|
|
179
|
+
"tiny-oauth-test-server": "*",
|
|
172
180
|
"tiny-stdio-mcp-server": "*",
|
|
173
181
|
"tiny-stdio-mcp-test-server": "*",
|
|
174
182
|
"tokenfill": "*",
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import type { ExplainResult
|
|
1
|
+
import type { ExplainResult } from "./types.js";
|
|
2
2
|
export declare function runMemoryExplain(input: {
|
|
3
3
|
root: string;
|
|
4
4
|
relPath: string;
|
|
5
5
|
budget: number;
|
|
6
6
|
agent?: string;
|
|
7
|
-
spawnFn?: SpawnFn;
|
|
8
7
|
}): Promise<ExplainResult>;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import type { ExplainResult, MemoryRoot
|
|
1
|
+
import type { ExplainResult, MemoryRoot } from "./types.js";
|
|
2
2
|
export type ExplainOptions = {
|
|
3
3
|
relPath: string;
|
|
4
4
|
budget: number;
|
|
5
5
|
agent?: string;
|
|
6
|
-
spawnFn?: SpawnFn;
|
|
7
6
|
};
|
|
8
7
|
export declare function explainPage(root: MemoryRoot, options: ExplainOptions): Promise<ExplainResult>;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
1
3
|
import { countTokens } from "tokenfill";
|
|
4
|
+
import { spawn } from "@poe-code/agent-spawn";
|
|
5
|
+
import { resolveAgent } from "@poe-code/poe-code-config";
|
|
2
6
|
import { readPage } from "./pages.js";
|
|
3
|
-
import {
|
|
7
|
+
import { selectQueryContext } from "./query.js";
|
|
4
8
|
export async function explainPage(root, options) {
|
|
5
9
|
const targetPage = await readPageIfPresent(root, options.relPath);
|
|
6
10
|
if (targetPage === undefined) {
|
|
@@ -21,18 +25,18 @@ export async function explainPage(root, options) {
|
|
|
21
25
|
if (tokensUsed > options.budget) {
|
|
22
26
|
throw new Error(`budget too small; needs at least ${tokensUsed} tokens`);
|
|
23
27
|
}
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const [agent] = args;
|
|
31
|
-
return spawnFn(agent, prompt);
|
|
32
|
-
}
|
|
33
|
-
});
|
|
28
|
+
const configOptions = {
|
|
29
|
+
fs: fs,
|
|
30
|
+
filePath: path.join(inferRepoRoot(root), "poe-code.json")
|
|
31
|
+
};
|
|
32
|
+
const agentId = (await resolveAgent(configOptions, options.agent ?? null)) ?? options.agent ?? "claude-code";
|
|
33
|
+
const response = (await spawn(agentId, { prompt }));
|
|
34
34
|
return {
|
|
35
|
-
|
|
35
|
+
answer: response.answer,
|
|
36
|
+
citations: response.citations,
|
|
37
|
+
tokensUsed: response.tokensUsed,
|
|
38
|
+
budget: options.budget,
|
|
39
|
+
exitCode: response.exitCode,
|
|
36
40
|
inboundPages: relatedPages
|
|
37
41
|
.filter((page) => page.relPath !== targetPage.relPath)
|
|
38
42
|
.filter((page) => (page.frontmatter.sources ?? []).some((source) => source.path === targetPage.relPath))
|
|
@@ -75,3 +79,6 @@ async function readPageIfPresent(root, relPath) {
|
|
|
75
79
|
throw error;
|
|
76
80
|
}
|
|
77
81
|
}
|
|
82
|
+
function inferRepoRoot(root) {
|
|
83
|
+
return path.resolve(root, "..", "..");
|
|
84
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AuditClaimsOptions, PageAudit } from "./audit.js";
|
|
2
|
+
import type { ExplainOptions } from "./explain.js";
|
|
3
|
+
import type { ExplainResult, IngestOptions, IngestResult, MemoryDiff, MemoryPage, MemoryRoot, PageFrontmatter, QueryOptions, QueryResult, SearchHit, TokenStats } from "./types.js";
|
|
4
|
+
export type OpenMemoryOptions = {
|
|
5
|
+
root: MemoryRoot;
|
|
6
|
+
agent?: string;
|
|
7
|
+
};
|
|
8
|
+
export type StatusInfo = {
|
|
9
|
+
pageCount: number;
|
|
10
|
+
totalBytes: number;
|
|
11
|
+
lastWriteAt: string | null;
|
|
12
|
+
initialized: boolean;
|
|
13
|
+
};
|
|
14
|
+
export type AuditCallOptions = AuditClaimsOptions & {
|
|
15
|
+
repoRoot: string;
|
|
16
|
+
};
|
|
17
|
+
export interface MemoryHandle {
|
|
18
|
+
readonly root: MemoryRoot;
|
|
19
|
+
listPages(): Promise<MemoryPage[]>;
|
|
20
|
+
readPage(relPath: string): Promise<MemoryPage>;
|
|
21
|
+
searchMemory(query: string): Promise<SearchHit[]>;
|
|
22
|
+
statusOf(): Promise<StatusInfo>;
|
|
23
|
+
computeTokenStats(): Promise<TokenStats>;
|
|
24
|
+
explainPage(opts: ExplainOptions): Promise<ExplainResult>;
|
|
25
|
+
writePage(relPath: string, body: string, opts: {
|
|
26
|
+
reason: string;
|
|
27
|
+
frontmatter?: PageFrontmatter;
|
|
28
|
+
}): Promise<MemoryDiff>;
|
|
29
|
+
appendToPage(relPath: string, content: string, opts: {
|
|
30
|
+
reason: string;
|
|
31
|
+
}): Promise<MemoryDiff>;
|
|
32
|
+
clearMemory(): Promise<void>;
|
|
33
|
+
query(opts: QueryOptions): Promise<QueryResult>;
|
|
34
|
+
ingest(opts: IngestOptions): Promise<IngestResult>;
|
|
35
|
+
auditClaims(opts: AuditCallOptions): Promise<PageAudit[]>;
|
|
36
|
+
}
|
|
37
|
+
export declare function openMemory(opts: OpenMemoryOptions): MemoryHandle;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { auditClaims as auditClaimsFree } from "./audit.js";
|
|
3
|
+
import { explainPage as explainPageFree } from "./explain.js";
|
|
4
|
+
import { ingest as ingestFree } from "./ingest.js";
|
|
5
|
+
import { listPages, readPage } from "./pages.js";
|
|
6
|
+
import { queryMemory } from "./query.js";
|
|
7
|
+
import { searchMemory } from "./search.js";
|
|
8
|
+
import { statusOf } from "./status.js";
|
|
9
|
+
import { computeTokenStats } from "./tokens.js";
|
|
10
|
+
import { appendToPage, clearMemory, writePage } from "./write.js";
|
|
11
|
+
export function openMemory(opts) {
|
|
12
|
+
if (!path.isAbsolute(opts.root)) {
|
|
13
|
+
throw new Error(`openMemory: root must be absolute, got ${opts.root}`);
|
|
14
|
+
}
|
|
15
|
+
const root = opts.root;
|
|
16
|
+
const defaultAgent = opts.agent;
|
|
17
|
+
return {
|
|
18
|
+
root,
|
|
19
|
+
listPages: async () => await listPages(root),
|
|
20
|
+
readPage: async (relPath) => await readPage(root, relPath),
|
|
21
|
+
searchMemory: async (query) => await searchMemory(root, query),
|
|
22
|
+
statusOf: async () => await statusOf(root),
|
|
23
|
+
computeTokenStats: async () => await computeTokenStats(root),
|
|
24
|
+
explainPage: async (options) => await explainPageFree(root, withDefaultAgent(options, defaultAgent)),
|
|
25
|
+
writePage: async (relPath, body, options) => await writePage(root, relPath, body, options),
|
|
26
|
+
appendToPage: async (relPath, content, options) => await appendToPage(root, relPath, content, options),
|
|
27
|
+
clearMemory: async () => await clearMemory(root),
|
|
28
|
+
query: async (options) => await queryMemory(root, withDefaultAgent(options, defaultAgent)),
|
|
29
|
+
ingest: async (options) => await ingestFree(root, withDefaultAgent(options, defaultAgent)),
|
|
30
|
+
auditClaims: async ({ repoRoot, ...options }) => await auditClaimsFree(root, repoRoot, options)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function withDefaultAgent(options, agent) {
|
|
34
|
+
if (options.agent !== undefined || agent === undefined) {
|
|
35
|
+
return options;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
...options,
|
|
39
|
+
agent
|
|
40
|
+
};
|
|
41
|
+
}
|