terminal-pilot 0.0.13 → 0.0.15

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.
Files changed (63) hide show
  1. package/dist/cli.js +7210 -470
  2. package/dist/cli.js.map +4 -4
  3. package/dist/commands/close-session.d.ts +5 -5
  4. package/dist/commands/close-session.js +107 -13
  5. package/dist/commands/close-session.js.map +4 -4
  6. package/dist/commands/create-session.d.ts +17 -17
  7. package/dist/commands/create-session.js +107 -13
  8. package/dist/commands/create-session.js.map +4 -4
  9. package/dist/commands/fill.d.ts +7 -7
  10. package/dist/commands/fill.js +107 -13
  11. package/dist/commands/fill.js.map +4 -4
  12. package/dist/commands/get-session.d.ts +5 -5
  13. package/dist/commands/get-session.js +107 -13
  14. package/dist/commands/get-session.js.map +4 -4
  15. package/dist/commands/index.d.ts +124 -124
  16. package/dist/commands/index.js +184 -27
  17. package/dist/commands/index.js.map +4 -4
  18. package/dist/commands/install.d.ts +9 -9
  19. package/dist/commands/install.js +107 -13
  20. package/dist/commands/install.js.map +4 -4
  21. package/dist/commands/installer.js +3 -1
  22. package/dist/commands/installer.js.map +3 -3
  23. package/dist/commands/list-sessions.d.ts +3 -3
  24. package/dist/commands/list-sessions.js +107 -13
  25. package/dist/commands/list-sessions.js.map +4 -4
  26. package/dist/commands/press-key.d.ts +7 -7
  27. package/dist/commands/press-key.js +107 -13
  28. package/dist/commands/press-key.js.map +4 -4
  29. package/dist/commands/read-history.d.ts +7 -7
  30. package/dist/commands/read-history.js +107 -13
  31. package/dist/commands/read-history.js.map +4 -4
  32. package/dist/commands/read-screen.d.ts +5 -5
  33. package/dist/commands/read-screen.js +107 -13
  34. package/dist/commands/read-screen.js.map +4 -4
  35. package/dist/commands/resize.d.ts +9 -9
  36. package/dist/commands/resize.js +107 -13
  37. package/dist/commands/resize.js.map +4 -4
  38. package/dist/commands/runtime.d.ts +1 -1
  39. package/dist/commands/runtime.js +3 -1
  40. package/dist/commands/runtime.js.map +3 -3
  41. package/dist/commands/screenshot.d.ts +11 -11
  42. package/dist/commands/screenshot.js +107 -13
  43. package/dist/commands/screenshot.js.map +4 -4
  44. package/dist/commands/send-signal.d.ts +7 -7
  45. package/dist/commands/send-signal.js +107 -13
  46. package/dist/commands/send-signal.js.map +4 -4
  47. package/dist/commands/type.d.ts +7 -7
  48. package/dist/commands/type.js +107 -13
  49. package/dist/commands/type.js.map +4 -4
  50. package/dist/commands/uninstall.d.ts +5 -5
  51. package/dist/commands/uninstall.js +107 -13
  52. package/dist/commands/uninstall.js.map +4 -4
  53. package/dist/commands/wait-for-exit.d.ts +7 -7
  54. package/dist/commands/wait-for-exit.js +107 -13
  55. package/dist/commands/wait-for-exit.js.map +4 -4
  56. package/dist/commands/wait-for.d.ts +11 -11
  57. package/dist/commands/wait-for.js +107 -13
  58. package/dist/commands/wait-for.js.map +4 -4
  59. package/dist/testing/cli-repl.js +7209 -470
  60. package/dist/testing/cli-repl.js.map +4 -4
  61. package/dist/testing/qa-cli.js +7218 -479
  62. package/dist/testing/qa-cli.js.map +4 -4
  63. package/package.json +3 -3
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../../cmdkit/src/index.ts", "../../../cmdkit-schema/src/index.ts", "../../src/commands/installer.ts", "../../../agent-skill-config/src/configs.ts", "../../../agent-defs/src/agents/claude-code.ts", "../../../agent-defs/src/agents/claude-desktop.ts", "../../../agent-defs/src/agents/codex.ts", "../../../agent-defs/src/agents/opencode.ts", "../../../agent-defs/src/agents/kimi.ts", "../../../agent-defs/src/agents/goose.ts", "../../../agent-defs/src/agents/poe-agent.ts", "../../../agent-defs/src/registry.ts", "../../../config-mutations/src/execution/apply-mutation.ts", "../../../config-mutations/src/formats/json.ts", "../../../config-mutations/src/formats/toml.ts", "../../../config-mutations/src/formats/yaml.ts", "../../../config-mutations/src/execution/path-utils.ts", "../../../config-mutations/src/template/render.ts", "../../../agent-skill-config/src/templates.ts", "../../src/commands/uninstall.ts"],
4
- "sourcesContent": ["import { fileURLToPath } from \"node:url\";\nimport type { ObjectSchema, Static } from \"@poe-code/cmdkit-schema\";\nimport type { LoggerOutput, RenderTableOptions, ThemePalette } from \"@poe-code/design-system\";\n\nconst commandConfigSymbol = Symbol(\"cmdkit.command.config\");\nconst groupConfigSymbol = Symbol(\"cmdkit.group.config\");\nconst commandSourcePathSymbol = Symbol(\"cmdkit.command.sourcePath\");\n\ntype ScopeValue = \"cli\" | \"mcp\" | \"sdk\";\ntype AnyObjectSchema = ObjectSchema<Record<string, never>>;\ntype EmptyServices = Record<string, never>;\ntype ScopeInput = readonly Scope[] | undefined;\n\nexport type Scope = ScopeValue;\n\nexport interface SecretDefinition {\n env: string;\n description?: string;\n optional?: boolean;\n}\n\nexport type SecretDeclarations = Record<string, SecretDefinition>;\n\ntype OptionalSecretKeys<TSecrets extends SecretDeclarations> = {\n [TKey in keyof TSecrets]: TSecrets[TKey] extends { optional: true } ? TKey : never;\n}[keyof TSecrets];\n\ntype RequiredSecretKeys<TSecrets extends SecretDeclarations> = Exclude<\n keyof TSecrets,\n OptionalSecretKeys<TSecrets>\n>;\n\nexport type InferSecrets<TSecrets extends SecretDeclarations | undefined> =\n TSecrets extends SecretDeclarations\n ? { [TKey in RequiredSecretKeys<TSecrets>]: string } & {\n [TKey in OptionalSecretKeys<TSecrets>]?: string;\n }\n : Record<string, never>;\n\nexport interface HandlerFs {\n readFile(path: string, encoding?: BufferEncoding): Promise<string>;\n writeFile(path: string, contents: string): Promise<void>;\n exists(path: string): Promise<boolean>;\n}\n\nexport interface HandlerEnv {\n get(key: string): string | undefined;\n}\n\nexport interface RenderPrimitives {\n logger: LoggerOutput;\n renderTable(options: RenderTableOptions): string;\n getTheme(): ThemePalette;\n note(message: string, title?: string): void;\n}\n\nexport interface CheckResult {\n ok: boolean;\n message?: string;\n}\n\nexport type GroupCheckContext<TServices extends object = EmptyServices> = TServices & {\n params?: unknown;\n secrets?: Record<string, string | undefined>;\n fetch: typeof globalThis.fetch;\n fs: HandlerFs;\n env: HandlerEnv;\n progress(message: string): void;\n};\n\nexport type CommandCheckContext<\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TSecrets extends SecretDeclarations | undefined = undefined,\n TServices extends object = EmptyServices,\n> = TServices & {\n params?: Static<TParamsSchema>;\n secrets?: InferSecrets<TSecrets>;\n fetch: typeof globalThis.fetch;\n fs: HandlerFs;\n env: HandlerEnv;\n progress(message: string): void;\n};\n\nexport interface Requires<TContext = unknown> {\n auth?: boolean;\n apiVersion?: string;\n check?: (ctx: TContext) => Promise<CheckResult>;\n}\n\nexport interface Renderers<TResult> {\n rich?: (result: TResult, primitives: RenderPrimitives) => void;\n markdown?: (result: TResult, primitives: RenderPrimitives) => string;\n json?: (result: TResult, primitives: RenderPrimitives) => unknown;\n}\n\nexport type HandlerContext<\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TSecrets extends SecretDeclarations | undefined = undefined,\n TServices extends object = EmptyServices,\n> = TServices & {\n params: Static<TParamsSchema>;\n secrets: InferSecrets<TSecrets>;\n fetch: typeof globalThis.fetch;\n fs: HandlerFs;\n env: HandlerEnv;\n progress(message: string): void;\n};\n\nexport interface CommandConfig<\n TServices extends object,\n TParamsSchema extends ObjectSchema<any>,\n TSecrets extends SecretDeclarations | undefined,\n TResult,\n> {\n name: string;\n description?: string;\n aliases?: string[];\n positional?: string[];\n params: TParamsSchema;\n secrets?: TSecrets;\n scope?: Scope[];\n confirm?: boolean;\n requires?: Requires<CommandCheckContext<TParamsSchema, TSecrets, TServices>>;\n handler: (ctx: HandlerContext<TParamsSchema, TSecrets, TServices>) => Promise<TResult>;\n render?: Renderers<TResult>;\n}\n\nexport interface Command<\n TServices extends object = EmptyServices,\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TSecrets extends SecretDeclarations | undefined = undefined,\n TResult = unknown,\n> {\n kind: \"command\";\n name: string;\n description?: string;\n aliases: string[];\n positional: string[];\n params: TParamsSchema;\n secrets: SecretDeclarations;\n scope: Scope[];\n confirm: boolean;\n requires?: Requires<any>;\n handler: (ctx: HandlerContext<TParamsSchema, TSecrets, TServices>) => Promise<TResult>;\n render?: Renderers<TResult>;\n}\n\nexport interface GroupConfig<TServices extends object> {\n name: string;\n description?: string;\n aliases?: string[];\n scope?: Scope[];\n secrets?: SecretDeclarations;\n requires?: Requires<GroupCheckContext<TServices>>;\n children: Array<CommandNode<TServices>>;\n default?: Command<TServices, any, any, any>;\n}\n\nexport interface Group<TServices extends object = EmptyServices> {\n kind: \"group\";\n name: string;\n description?: string;\n aliases: string[];\n scope?: Scope[];\n secrets: SecretDeclarations;\n requires?: Requires<any>;\n children: Array<CommandNode<TServices>>;\n default?: Command<TServices, any, any, any>;\n}\n\nexport type CommandNode<TServices extends object = EmptyServices> =\n | Command<TServices, any, any, any>\n | Group<TServices>;\n\nexport interface CommandTypeInfo<\n TName extends string = string,\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TResult = unknown,\n TOwnScope extends ScopeInput = ScopeInput,\n> {\n name: TName;\n params: TParamsSchema;\n result: TResult;\n ownScope: TOwnScope;\n}\n\nexport interface GroupTypeInfo<\n TServices extends object = EmptyServices,\n TName extends string = string,\n TChildren extends readonly unknown[] = readonly CommandNode<TServices>[],\n TOwnScope extends ScopeInput = ScopeInput,\n> {\n name: TName;\n children: TChildren;\n ownScope: TOwnScope;\n}\n\ntype TypedCommandMetadata<\n TName extends string,\n TParamsSchema extends ObjectSchema<any>,\n TResult,\n TOwnScope extends ScopeInput,\n> = {\n readonly __cmdkitCommandTypeInfo: CommandTypeInfo<TName, TParamsSchema, TResult, TOwnScope>;\n};\n\ntype TypedGroupMetadata<\n TServices extends object,\n TName extends string,\n TChildren extends readonly unknown[],\n TOwnScope extends ScopeInput,\n> = {\n readonly __cmdkitGroupTypeInfo: GroupTypeInfo<TServices, TName, TChildren, TOwnScope>;\n};\n\ninterface InternalCommandConfig {\n scope?: Scope[];\n secrets: SecretDeclarations;\n requires?: Requires<any>;\n sourcePath?: string;\n}\n\ninterface InternalGroupConfig<TServices extends object> {\n scope?: Scope[];\n secrets: SecretDeclarations;\n requires?: Requires<any>;\n children: Array<CommandNode<TServices>>;\n default?: Command<TServices, any, any, any>;\n}\n\ninterface InheritedMetadata {\n scope?: Scope[];\n secrets: SecretDeclarations;\n requires?: Requires<any>;\n}\n\nexport class UserError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UserError\";\n }\n}\n\nexport interface CommandRequirementOptions {\n apiVersion?: string;\n authEnvVar?: string;\n env?: Record<string, string | undefined>;\n}\n\nfunction cloneScope(scope: Scope[] | undefined): Scope[] | undefined {\n return scope === undefined ? undefined : [...scope];\n}\n\nfunction cloneSecretDefinition(secret: SecretDefinition): SecretDefinition {\n return {\n env: secret.env,\n description: secret.description,\n optional: secret.optional,\n };\n}\n\nfunction cloneSecrets(secrets: SecretDeclarations | undefined): SecretDeclarations {\n if (secrets === undefined) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(secrets).map(([key, secret]) => [key, cloneSecretDefinition(secret)])\n );\n}\n\nfunction cloneRequires<TContext>(requires: Requires<TContext> | undefined): Requires<TContext> | undefined {\n if (requires === undefined) {\n return undefined;\n }\n\n return {\n auth: requires.auth,\n apiVersion: requires.apiVersion,\n check: requires.check,\n };\n}\n\nfunction parseStackPath(candidate: string): string | undefined {\n if (candidate.startsWith(\"file://\")) {\n try {\n return fileURLToPath(candidate);\n } catch {\n return undefined;\n }\n }\n\n if (candidate.startsWith(\"/\")) {\n return candidate;\n }\n\n return undefined;\n}\n\nfunction extractStackPath(line: string): string | undefined {\n const trimmed = line.trim();\n const fileIndex = trimmed.indexOf(\"file://\");\n\n if (fileIndex >= 0) {\n const location = trimmed.slice(fileIndex);\n const separatorIndex = location.lastIndexOf(\":\");\n const previousSeparatorIndex = separatorIndex >= 0 ? location.lastIndexOf(\":\", separatorIndex - 1) : -1;\n const candidate =\n separatorIndex >= 0 && previousSeparatorIndex >= 0\n ? location.slice(0, previousSeparatorIndex)\n : location;\n\n return parseStackPath(candidate);\n }\n\n const slashIndex = trimmed.indexOf(\"/\");\n if (slashIndex < 0) {\n return undefined;\n }\n\n const location = trimmed.slice(slashIndex);\n const separatorIndex = location.lastIndexOf(\":\");\n const previousSeparatorIndex = separatorIndex >= 0 ? location.lastIndexOf(\":\", separatorIndex - 1) : -1;\n const candidate =\n separatorIndex >= 0 && previousSeparatorIndex >= 0\n ? location.slice(0, previousSeparatorIndex)\n : location;\n\n return parseStackPath(candidate);\n}\n\nfunction inferCommandSourcePath(): string | undefined {\n const stack = new Error().stack;\n\n if (typeof stack !== \"string\") {\n return undefined;\n }\n\n for (const line of stack.split(\"\\n\").slice(1)) {\n const candidate = extractStackPath(line);\n\n if (candidate === undefined) {\n continue;\n }\n\n if (\n candidate.includes(\"/packages/cmdkit/src/index.ts\") ||\n candidate.includes(\"/packages/cmdkit/dist/index.js\")\n ) {\n continue;\n }\n\n return candidate;\n }\n\n return undefined;\n}\n\nfunction composeChecks(\n parentCheck: Requires<any>[\"check\"] | undefined,\n childCheck: Requires<any>[\"check\"] | undefined\n): Requires<any>[\"check\"] | undefined {\n if (parentCheck === undefined) {\n return childCheck;\n }\n\n if (childCheck === undefined) {\n return parentCheck;\n }\n\n return async (ctx) => {\n const parentResult = await parentCheck(ctx);\n if (!parentResult.ok) {\n return parentResult;\n }\n\n return childCheck(ctx);\n };\n}\n\nfunction mergeRequires(parent: Requires<any> | undefined, child: Requires<any> | undefined): Requires<any> | undefined {\n if (parent === undefined && child === undefined) {\n return undefined;\n }\n\n const merged: Requires<any> = {\n auth: child?.auth ?? parent?.auth,\n apiVersion: child?.apiVersion ?? parent?.apiVersion,\n check: composeChecks(parent?.check, child?.check),\n };\n\n if (\n merged.auth === undefined &&\n merged.apiVersion === undefined &&\n merged.check === undefined\n ) {\n return undefined;\n }\n\n return merged;\n}\n\nfunction parseSimpleSemver(value: string): [number, number, number] | undefined {\n const parts = value.split(\".\");\n if (parts.length !== 3) {\n return undefined;\n }\n\n const parsed = parts.map((part) => {\n if (part.length === 0) {\n return Number.NaN;\n }\n\n for (const char of part) {\n if (char < \"0\" || char > \"9\") {\n return Number.NaN;\n }\n }\n\n return Number(part);\n });\n\n if (parsed.some((part) => !Number.isInteger(part) || part < 0)) {\n return undefined;\n }\n\n return parsed as [number, number, number];\n}\n\nfunction parseMinimumApiVersion(requirement: string): [number, number, number] | undefined {\n if (!requirement.startsWith(\">=\")) {\n return undefined;\n }\n\n return parseSimpleSemver(requirement.slice(2).trim());\n}\n\nfunction compareSemver(left: [number, number, number], right: [number, number, number]): number {\n for (let index = 0; index < left.length; index += 1) {\n if (left[index] === right[index]) {\n continue;\n }\n\n return left[index]! > right[index]! ? 1 : -1;\n }\n\n return 0;\n}\n\nexport function resolveCommandSecrets(\n command: Command<any, any, any, any>,\n env: Record<string, string | undefined> = process.env\n): Record<string, string | undefined> {\n const secrets: Record<string, string | undefined> = {};\n\n for (const [name, secret] of Object.entries(command.secrets)) {\n const value = env[secret.env];\n\n if (value === undefined && secret.optional !== true) {\n const details = secret.description ? `\\n ${secret.description}` : \"\";\n throw new UserError(`Error: Missing required secret ${secret.env}${details}`);\n }\n\n secrets[name] = value;\n }\n\n return secrets;\n}\n\nexport async function assertCommandRequirements(\n command: Command<any, any, any, any>,\n context: GroupCheckContext<any>,\n options: CommandRequirementOptions = {}\n): Promise<void> {\n const requires = command.requires;\n if (requires === undefined) {\n return;\n }\n\n const env = options.env ?? process.env;\n const authEnvVar = options.authEnvVar ?? \"POE_API_KEY\";\n\n if (requires.auth === true && env[authEnvVar] === undefined) {\n throw new UserError(\n `Error: Command \"${command.name}\" requires authentication.\\n Run 'poe-code login' first.`\n );\n }\n\n if (requires.apiVersion !== undefined) {\n const minimumVersion = parseMinimumApiVersion(requires.apiVersion);\n if (minimumVersion === undefined) {\n throw new UserError(\n `Error: Command \"${command.name}\" has invalid apiVersion requirement \"${requires.apiVersion}\". Expected format \">=X.Y.Z\".`\n );\n }\n\n if (options.apiVersion === undefined) {\n throw new UserError(\n `Error: Command \"${command.name}\" requires API version ${requires.apiVersion}, but no runner API version was provided.`\n );\n }\n\n const runnerVersion = parseSimpleSemver(options.apiVersion);\n if (runnerVersion === undefined) {\n throw new UserError(\n `Error: Command \"${command.name}\" requires API version ${requires.apiVersion}, but runner API version \"${options.apiVersion}\" is not valid semver.`\n );\n }\n\n if (compareSemver(runnerVersion, minimumVersion) < 0) {\n throw new UserError(\n `Error: Command \"${command.name}\" requires API version ${requires.apiVersion}, but runner API version is ${options.apiVersion}.`\n );\n }\n }\n\n const checkResult = await requires.check?.(context);\n if (checkResult && !checkResult.ok) {\n throw new UserError(checkResult.message ?? \"Command precondition failed.\");\n }\n}\n\nfunction mergeSecrets(parent: SecretDeclarations, child: SecretDeclarations): SecretDeclarations {\n return cloneSecrets({\n ...parent,\n ...child,\n });\n}\n\nfunction resolveCommandScope(ownScope: Scope[] | undefined, inheritedScope: Scope[] | undefined): Scope[] {\n return cloneScope(ownScope ?? inheritedScope) ?? [\"cli\", \"sdk\"];\n}\n\nfunction resolveGroupScope(ownScope: Scope[] | undefined, inheritedScope: Scope[] | undefined): Scope[] | undefined {\n return cloneScope(ownScope ?? inheritedScope);\n}\n\nfunction createBaseCommand<\n TServices extends object,\n TParamsSchema extends ObjectSchema<any>,\n TSecrets extends SecretDeclarations | undefined,\n TResult,\n>(\n config: CommandConfig<TServices, TParamsSchema, TSecrets, TResult>\n): Command<TServices, TParamsSchema, TSecrets, TResult> {\n const command: Command<TServices, TParamsSchema, TSecrets, TResult> = {\n kind: \"command\",\n name: config.name,\n description: config.description,\n aliases: [...(config.aliases ?? [])],\n positional: [...(config.positional ?? [])],\n params: config.params,\n secrets: cloneSecrets(config.secrets),\n scope: resolveCommandScope(config.scope, undefined),\n confirm: config.confirm ?? false,\n requires: cloneRequires(config.requires),\n handler: config.handler,\n render: config.render,\n };\n\n Object.defineProperty(command, commandConfigSymbol, {\n value: {\n scope: cloneScope(config.scope),\n secrets: cloneSecrets(config.secrets),\n requires: cloneRequires(config.requires),\n sourcePath: inferCommandSourcePath(),\n } satisfies InternalCommandConfig,\n });\n\n return command;\n}\n\nfunction createBaseGroup<TServices extends object>(config: GroupConfig<TServices>): Group<TServices> {\n const group: Group<TServices> = {\n kind: \"group\",\n name: config.name,\n description: config.description,\n aliases: [...(config.aliases ?? [])],\n scope: resolveGroupScope(config.scope, undefined),\n secrets: cloneSecrets(config.secrets),\n requires: cloneRequires(config.requires),\n children: [],\n default: undefined,\n };\n\n Object.defineProperty(group, groupConfigSymbol, {\n value: {\n scope: cloneScope(config.scope),\n secrets: cloneSecrets(config.secrets),\n requires: cloneRequires(config.requires),\n children: [...config.children],\n default: config.default,\n } satisfies InternalGroupConfig<TServices>,\n });\n\n return group;\n}\n\nfunction getInternalCommandConfig(command: Command<any, any, any, any>): InternalCommandConfig {\n return (command as Command<any, any, any, any> & { [commandConfigSymbol]: InternalCommandConfig })[\n commandConfigSymbol\n ];\n}\n\nfunction getInternalGroupConfig<TServices extends object>(group: Group<TServices>): InternalGroupConfig<TServices> {\n return (group as Group<TServices> & { [groupConfigSymbol]: InternalGroupConfig<TServices> })[\n groupConfigSymbol\n ];\n}\n\nfunction materializeCommand<\n TServices extends object,\n TParamsSchema extends ObjectSchema<any>,\n TSecrets extends SecretDeclarations | undefined,\n TResult,\n>(\n command: Command<TServices, TParamsSchema, TSecrets, TResult>,\n inherited: InheritedMetadata\n): Command<TServices, TParamsSchema, TSecrets, TResult> {\n const internal = getInternalCommandConfig(command);\n\n const materialized: Command<TServices, TParamsSchema, TSecrets, TResult> = {\n kind: \"command\",\n name: command.name,\n description: command.description,\n aliases: [...command.aliases],\n positional: [...command.positional],\n params: command.params,\n secrets: mergeSecrets(inherited.secrets, internal.secrets),\n scope: resolveCommandScope(internal.scope, inherited.scope),\n confirm: command.confirm,\n requires: mergeRequires(inherited.requires, internal.requires),\n handler: command.handler,\n render: command.render,\n };\n\n Object.defineProperty(materialized, commandConfigSymbol, {\n value: {\n scope: cloneScope(internal.scope),\n secrets: cloneSecrets(internal.secrets),\n requires: cloneRequires(internal.requires),\n sourcePath: internal.sourcePath,\n } satisfies InternalCommandConfig,\n });\n\n Object.defineProperty(materialized, commandSourcePathSymbol, {\n value: internal.sourcePath,\n });\n\n return materialized;\n}\n\nfunction materializeGroup<TServices extends object>(\n group: Group<TServices>,\n inherited: InheritedMetadata\n): Group<TServices> {\n const internal = getInternalGroupConfig(group);\n const scope = resolveGroupScope(internal.scope, inherited.scope);\n const secrets = mergeSecrets(inherited.secrets, internal.secrets);\n const requires = mergeRequires(inherited.requires, internal.requires);\n const materializedChildren = internal.children.map((child) =>\n materializeNode(child, {\n scope,\n secrets,\n requires,\n })\n );\n\n let defaultChild: Command<TServices, any, any, any> | undefined;\n\n if (internal.default !== undefined) {\n const defaultIndex = internal.children.indexOf(internal.default);\n\n if (defaultIndex === -1) {\n throw new UserError(`Default command \"${internal.default.name}\" must be listed in children.`);\n }\n\n const resolvedDefault = materializedChildren[defaultIndex];\n if (resolvedDefault?.kind !== \"command\") {\n throw new UserError(`Default child \"${internal.default.name}\" must be a command.`);\n }\n\n defaultChild = resolvedDefault;\n }\n\n const materialized: Group<TServices> = {\n kind: \"group\",\n name: group.name,\n description: group.description,\n aliases: [...group.aliases],\n scope,\n secrets,\n requires,\n children: materializedChildren,\n default: defaultChild,\n };\n\n Object.defineProperty(materialized, groupConfigSymbol, {\n value: {\n scope: cloneScope(internal.scope),\n secrets: cloneSecrets(internal.secrets),\n requires: cloneRequires(internal.requires),\n children: [...internal.children],\n default: internal.default,\n } satisfies InternalGroupConfig<TServices>,\n });\n\n return materialized;\n}\n\nfunction materializeNode<TServices extends object>(\n node: CommandNode<TServices>,\n inherited: InheritedMetadata\n): CommandNode<TServices> {\n if (node.kind === \"command\") {\n return materializeCommand(node, inherited);\n }\n\n return materializeGroup(node, inherited);\n}\n\nexport function defineCommand<\n TServices extends object = EmptyServices,\n TName extends string = string,\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TSecrets extends SecretDeclarations | undefined = undefined,\n TResult = unknown,\n TOwnScope extends ScopeInput = undefined,\n>(\n config: Omit<CommandConfig<TServices, TParamsSchema, TSecrets, TResult>, \"name\" | \"scope\"> & {\n name: TName;\n scope?: TOwnScope;\n }\n): Command<TServices, TParamsSchema, TSecrets, TResult> &\n TypedCommandMetadata<TName, TParamsSchema, TResult, TOwnScope> {\n return materializeCommand(createBaseCommand(config as CommandConfig<TServices, TParamsSchema, TSecrets, TResult>), {\n scope: undefined,\n secrets: {},\n requires: undefined,\n }) as Command<TServices, TParamsSchema, TSecrets, TResult> &\n TypedCommandMetadata<TName, TParamsSchema, TResult, TOwnScope>;\n}\n\nexport function defineGroup<\n TServices extends object = EmptyServices,\n TName extends string = string,\n TChildren extends readonly unknown[] = readonly CommandNode<TServices>[],\n TOwnScope extends ScopeInput = undefined,\n>(\n config: Omit<GroupConfig<TServices>, \"name\" | \"children\" | \"scope\"> & {\n name: TName;\n children: TChildren & readonly CommandNode<TServices>[];\n scope?: TOwnScope;\n }\n): Group<TServices> & TypedGroupMetadata<TServices, TName, TChildren, TOwnScope> {\n return materializeGroup(createBaseGroup(config as unknown as GroupConfig<TServices>), {\n scope: undefined,\n secrets: {},\n requires: undefined,\n }) as Group<TServices> & TypedGroupMetadata<TServices, TName, TChildren, TOwnScope>;\n}\n\nexport function getCommandSourcePath(command: Command<any, any, any, any>): string | undefined {\n return (command as Command<any, any, any, any> & { [commandSourcePathSymbol]?: string })[\n commandSourcePathSymbol\n ];\n}\n\nexport { S, toJsonSchema } from \"@poe-code/cmdkit-schema\";\nexport type { AnySchema, ArraySchema, BooleanSchema, EnumSchema, JsonSchema, NumberSchema, ObjectSchema, OptionalSchema, Static, StringSchema } from \"@poe-code/cmdkit-schema\";\n", "type JsonSchemaType = \"string\" | \"number\" | \"integer\" | \"boolean\" | \"array\" | \"object\";\ntype SchemaKind =\n | \"string\"\n | \"number\"\n | \"boolean\"\n | \"enum\"\n | \"array\"\n | \"object\"\n | \"optional\";\ntype EnumValue = string | number | boolean;\ntype JsonSchemaEnumValue = EnumValue | null;\ntype NumberJsonType = \"number\" | \"integer\";\ntype NonEmptyReadonlyArray<T> = readonly [T, ...T[]];\ntype ObjectShape = Record<string, AnySchema>;\ntype SchemaScope = \"cli\" | \"mcp\" | \"sdk\";\ntype StringMetadata = {\n format?: string;\n maxLength?: number;\n minLength?: number;\n pattern?: string;\n};\ntype NumberMetadata = {\n maximum?: number;\n minimum?: number;\n};\ntype ArrayMetadata = {\n maxItems?: number;\n minItems?: number;\n};\ntype ObjectMetadata = {\n additionalProperties?: boolean;\n};\ntype OptionalKeys<TShape extends ObjectShape> = {\n [TKey in keyof TShape]: TShape[TKey] extends OptionalSchema<any> ? TKey : never;\n}[keyof TShape];\ntype RequiredKeys<TShape extends ObjectShape> = Exclude<keyof TShape, OptionalKeys<TShape>>;\n\ntype PropertyStatic<TSchema extends AnySchema> = TSchema extends OptionalSchema<infer TInner>\n ? Static<TInner>\n : Static<TSchema>;\n\ntype InferObject<TShape extends ObjectShape> = {\n [TKey in RequiredKeys<TShape>]: PropertyStatic<TShape[TKey]>;\n} & {\n [TKey in OptionalKeys<TShape>]?: PropertyStatic<TShape[TKey]>;\n};\n\ntype SchemaOptions<TDefault> = {\n description?: string;\n default?: TDefault;\n nullable?: boolean;\n requiredScopes?: readonly SchemaScope[];\n short?: string;\n scope?: readonly SchemaScope[];\n};\n\ninterface SchemaBase<TKind extends SchemaKind, TStatic> {\n readonly kind: TKind;\n readonly description?: string;\n readonly default?: TStatic;\n readonly nullable?: boolean;\n readonly requiredScopes?: readonly SchemaScope[];\n readonly short?: string;\n readonly scope?: readonly SchemaScope[];\n readonly __static?: TStatic;\n}\n\nexport interface JsonSchema {\n additionalProperties?: boolean;\n type?: JsonSchemaType;\n description?: string;\n default?: unknown;\n enum?: ReadonlyArray<JsonSchemaEnumValue>;\n format?: string;\n items?: JsonSchema;\n maxItems?: number;\n maximum?: number;\n maxLength?: number;\n minItems?: number;\n minimum?: number;\n minLength?: number;\n nullable?: boolean;\n pattern?: string;\n properties?: Record<string, JsonSchema>;\n required?: string[];\n}\n\nexport interface StringSchema extends SchemaBase<\"string\", string>, StringMetadata {}\n\nexport interface NumberSchema extends SchemaBase<\"number\", number>, NumberMetadata {\n readonly jsonType?: NumberJsonType;\n}\n\nexport type BooleanSchema = SchemaBase<\"boolean\", boolean>;\n\nexport interface EnumSchema<TValues extends NonEmptyReadonlyArray<EnumValue>>\n extends SchemaBase<\"enum\", TValues[number]> {\n readonly values: TValues;\n readonly jsonType?: \"integer\";\n readonly labels?: Partial<Record<string, string>>;\n readonly loadOptions?:\n | (() => Array<{ label: string; value: string }>)\n | (() => Promise<Array<{ label: string; value: string }>>);\n}\n\nexport interface ArraySchema<TItem extends AnySchema>\n extends SchemaBase<\"array\", Array<Static<TItem>>>, ArrayMetadata {\n readonly item: TItem;\n}\n\nexport interface ObjectSchema<TShape extends ObjectShape>\n extends SchemaBase<\"object\", InferObject<TShape>>, ObjectMetadata {\n readonly shape: TShape;\n}\n\nexport interface OptionalSchema<TInner extends AnySchema>\n extends SchemaBase<\"optional\", Static<TInner> | undefined> {\n readonly inner: TInner;\n}\n\nexport type AnySchema =\n | StringSchema\n | NumberSchema\n | BooleanSchema\n | EnumSchema<NonEmptyReadonlyArray<EnumValue>>\n | ArraySchema<AnySchema>\n | ObjectSchema<ObjectShape>\n | OptionalSchema<AnySchema>;\n\nexport type Static<TSchema extends AnySchema> = TSchema extends SchemaBase<any, infer TStatic>\n ? TStatic\n : never;\n\nfunction withMetadata<TSchema extends AnySchema>(\n schema: TSchema,\n jsonSchema: JsonSchema\n): JsonSchema {\n if (schema.description !== undefined) {\n jsonSchema.description = schema.description;\n }\n\n if (schema.default !== undefined) {\n jsonSchema.default = schema.default;\n }\n\n if (schema.nullable === true) {\n jsonSchema.nullable = true;\n }\n\n return jsonSchema;\n}\n\nfunction withStringMetadata(schema: StringSchema, jsonSchema: JsonSchema): JsonSchema {\n if (schema.minLength !== undefined) {\n jsonSchema.minLength = schema.minLength;\n }\n\n if (schema.maxLength !== undefined) {\n jsonSchema.maxLength = schema.maxLength;\n }\n\n if (schema.pattern !== undefined) {\n jsonSchema.pattern = schema.pattern;\n }\n\n if (schema.format !== undefined) {\n jsonSchema.format = schema.format;\n }\n\n return withMetadata(schema, jsonSchema);\n}\n\nfunction withNumberMetadata(schema: NumberSchema, jsonSchema: JsonSchema): JsonSchema {\n if (schema.minimum !== undefined) {\n jsonSchema.minimum = schema.minimum;\n }\n\n if (schema.maximum !== undefined) {\n jsonSchema.maximum = schema.maximum;\n }\n\n return withMetadata(schema, jsonSchema);\n}\n\nfunction withArrayMetadata(schema: ArraySchema<any>, jsonSchema: JsonSchema): JsonSchema {\n if (schema.minItems !== undefined) {\n jsonSchema.minItems = schema.minItems;\n }\n\n if (schema.maxItems !== undefined) {\n jsonSchema.maxItems = schema.maxItems;\n }\n\n return withMetadata(schema, jsonSchema);\n}\n\nfunction withObjectMetadata(schema: ObjectSchema<any>, jsonSchema: JsonSchema): JsonSchema {\n if (schema.additionalProperties !== undefined) {\n jsonSchema.additionalProperties = schema.additionalProperties;\n }\n\n return withMetadata(schema, jsonSchema);\n}\n\nfunction getEnumJsonType(values: ReadonlyArray<EnumValue>): JsonSchemaType | undefined {\n const [firstValue] = values;\n\n if (firstValue === undefined) {\n return undefined;\n }\n\n const firstType = typeof firstValue;\n const isSinglePrimitiveType = values.every((value) => typeof value === firstType);\n\n if (!isSinglePrimitiveType) {\n return undefined;\n }\n\n if (firstType === \"string\" || firstType === \"number\" || firstType === \"boolean\") {\n return firstType;\n }\n\n return undefined;\n}\n\nfunction isOptionalSchema(schema: AnySchema): schema is OptionalSchema<AnySchema> {\n return schema.kind === \"optional\";\n}\n\nfunction assertValidEnumValues(values: ReadonlyArray<EnumValue>): void {\n if (values.length === 0) {\n throw new Error(\"Enum schema requires at least one value\");\n }\n\n const uniqueValues = new Set(values);\n\n if (uniqueValues.size !== values.length) {\n throw new Error(\"Enum schema values must be unique\");\n }\n}\n\nfunction unwrapOptional(schema: AnySchema): Exclude<AnySchema, OptionalSchema<AnySchema>> {\n if (isOptionalSchema(schema)) {\n return unwrapOptional(schema.inner);\n }\n\n return schema;\n}\n\nexport const S = {\n String(options: SchemaOptions<string> & StringMetadata = {}): StringSchema {\n return {\n kind: \"string\",\n ...options,\n };\n },\n\n Number(\n options: SchemaOptions<number> & NumberMetadata & { jsonType?: NumberJsonType } = {}\n ): NumberSchema {\n return {\n kind: \"number\",\n ...options,\n };\n },\n\n Boolean(options: SchemaOptions<boolean> = {}): BooleanSchema {\n return {\n kind: \"boolean\",\n ...options,\n };\n },\n\n Enum<const TValues extends NonEmptyReadonlyArray<EnumValue>>(\n values: TValues,\n options: SchemaOptions<TValues[number]> & {\n jsonType?: \"integer\";\n labels?: Partial<Record<string, string>>;\n loadOptions?:\n | (() => Array<{ label: string; value: string }>)\n | (() => Promise<Array<{ label: string; value: string }>>);\n } = {}\n ): EnumSchema<TValues> {\n assertValidEnumValues(values);\n\n return {\n kind: \"enum\",\n values,\n ...options,\n };\n },\n\n Array<TItem extends AnySchema>(\n item: TItem,\n options: SchemaOptions<Array<Static<TItem>>> & ArrayMetadata = {}\n ): ArraySchema<TItem> {\n return {\n kind: \"array\",\n item,\n ...options,\n };\n },\n\n Object<const TShape extends ObjectShape>(\n shape: TShape,\n options: SchemaOptions<InferObject<TShape>> & ObjectMetadata = {}\n ): ObjectSchema<TShape> {\n return {\n kind: \"object\",\n shape,\n ...options,\n };\n },\n\n Optional<TInner extends AnySchema>(inner: TInner): OptionalSchema<TInner> {\n return {\n kind: \"optional\",\n inner,\n };\n },\n} as const;\n\nexport function toJsonSchema(schema: AnySchema): JsonSchema {\n const unwrappedSchema = unwrapOptional(schema);\n\n switch (unwrappedSchema.kind) {\n case \"string\":\n return withStringMetadata(unwrappedSchema, { type: \"string\" });\n\n case \"number\":\n return withNumberMetadata(unwrappedSchema, { type: unwrappedSchema.jsonType ?? \"number\" });\n\n case \"boolean\":\n return withMetadata(unwrappedSchema, { type: \"boolean\" });\n\n case \"enum\": {\n const jsonSchema: JsonSchema = {\n enum:\n unwrappedSchema.nullable === true\n ? [...unwrappedSchema.values, null]\n : [...unwrappedSchema.values],\n };\n const enumType = unwrappedSchema.jsonType ?? getEnumJsonType(unwrappedSchema.values);\n\n if (enumType !== undefined) {\n jsonSchema.type = enumType;\n }\n\n return withMetadata(unwrappedSchema, jsonSchema);\n }\n\n case \"array\":\n return withArrayMetadata(unwrappedSchema, {\n type: \"array\",\n items: toJsonSchema(unwrappedSchema.item),\n });\n\n case \"object\": {\n const properties: Record<string, JsonSchema> = {};\n const required: string[] = [];\n\n for (const [key, propertySchema] of Object.entries(unwrappedSchema.shape)) {\n properties[key] = toJsonSchema(propertySchema);\n\n if (!isOptionalSchema(propertySchema)) {\n required.push(key);\n }\n }\n\n return withObjectMetadata(unwrappedSchema, {\n type: \"object\",\n properties,\n required,\n });\n }\n }\n}\n", "import os from \"node:os\";\nimport path from \"node:path\";\nimport * as nodeFs from \"node:fs/promises\";\nimport { readFile } from \"node:fs/promises\";\nimport { UserError } from \"@poe-code/cmdkit\";\nimport {\n getAgentConfig,\n resolveAgentSupport as resolveSkillAgentSupport,\n supportedAgents as skillSupportedAgents\n} from \"@poe-code/agent-skill-config\";\n\nexport type TerminalPilotInstallerFileSystem = {\n readFile(path: string, encoding: \"utf8\"): Promise<string>;\n writeFile(\n path: string,\n content: string,\n options?: { encoding: \"utf8\" }\n ): Promise<void>;\n mkdir(path: string, options?: { recursive: boolean }): Promise<void>;\n unlink(path: string): Promise<void>;\n rm?(\n path: string,\n options?: { recursive?: boolean; force?: boolean }\n ): Promise<void>;\n stat(path: string): Promise<{ mode?: number }>;\n readdir(path: string): Promise<string[]>;\n chmod?(path: string, mode: number): Promise<void>;\n};\n\nexport type TerminalPilotInstallScope = \"global\" | \"local\";\nexport type TerminalPilotInstallerPlatform = \"darwin\" | \"linux\" | \"win32\";\n\nexport const DEFAULT_INSTALL_AGENT = \"claude-code\";\nexport const DEFAULT_INSTALL_SCOPE: TerminalPilotInstallScope = \"local\";\nexport const TERMINAL_PILOT_SKILL_NAME = \"terminal-pilot\";\nexport const installableAgents = skillSupportedAgents;\n\nexport type TerminalPilotInstallerServices = {\n fs?: TerminalPilotInstallerFileSystem;\n cwd?: string;\n homeDir?: string;\n platform?: TerminalPilotInstallerPlatform;\n};\n\nfunction isNotFoundError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n );\n}\n\nexport function resolveInstallerServices(\n installer: TerminalPilotInstallerServices | undefined\n): Required<TerminalPilotInstallerServices> {\n return {\n fs: installer?.fs ?? (nodeFs as TerminalPilotInstallerFileSystem),\n cwd: installer?.cwd ?? process.cwd(),\n homeDir: installer?.homeDir ?? os.homedir(),\n platform: installer?.platform ?? (process.platform as TerminalPilotInstallerPlatform)\n };\n}\n\nfunction throwUnsupportedAgent(agent: string): never {\n throw new UserError(`Unsupported agent: ${agent}`);\n}\n\nexport function resolveInstallableAgent(agent: string): string {\n const skillSupport = resolveSkillAgentSupport(agent);\n\n if (\n skillSupport.status !== \"supported\" ||\n !skillSupport.id\n ) {\n throwUnsupportedAgent(agent);\n }\n\n return skillSupport.id;\n}\n\nexport function resolveInstallScope(input: {\n local?: boolean;\n global?: boolean;\n}): TerminalPilotInstallScope {\n if (input.local && input.global) {\n throw new UserError(\"Use either --local or --global, not both.\");\n }\n\n if (input.local) {\n return \"local\";\n }\n\n if (input.global) {\n return \"global\";\n }\n\n return DEFAULT_INSTALL_SCOPE;\n}\n\nlet terminalPilotTemplateCache: string | undefined;\n\nexport async function loadTerminalPilotTemplate(): Promise<string> {\n if (terminalPilotTemplateCache !== undefined) {\n return terminalPilotTemplateCache;\n }\n\n const candidates = [\n new URL(\"./templates/terminal-pilot.md\", import.meta.url),\n new URL(\"../templates/terminal-pilot.md\", import.meta.url),\n new URL(\"../../../agent-skill-config/src/templates/terminal-pilot.md\", import.meta.url)\n ];\n\n for (const candidate of candidates) {\n try {\n terminalPilotTemplateCache = await readFile(candidate, \"utf8\");\n return terminalPilotTemplateCache;\n } catch (error) {\n if (!isNotFoundError(error)) {\n throw error;\n }\n }\n }\n\n throw new UserError(\"terminal-pilot skill template is missing.\");\n}\n\nfunction resolveHomeRelativePath(targetPath: string, homeDir: string): string {\n if (targetPath === \"~\") {\n return homeDir;\n }\n\n if (targetPath.startsWith(\"~/\")) {\n return path.join(homeDir, targetPath.slice(2));\n }\n\n return targetPath;\n}\n\nexport function getSkillFolderWithHome(\n agent: string,\n scope: TerminalPilotInstallScope,\n cwd: string,\n homeDir: string\n): {\n displayPath: string;\n fullPath: string;\n} {\n const config = getAgentConfig(agent);\n\n if (!config) {\n throwUnsupportedAgent(agent);\n }\n\n return {\n displayPath: path.join(\n scope === \"global\" ? config.globalSkillDir : config.localSkillDir,\n TERMINAL_PILOT_SKILL_NAME\n ),\n fullPath: path.join(\n scope === \"global\"\n ? resolveHomeRelativePath(config.globalSkillDir, homeDir)\n : path.resolve(cwd, config.localSkillDir),\n TERMINAL_PILOT_SKILL_NAME\n )\n };\n}\n\nexport async function removeSkillFolder(\n fs: TerminalPilotInstallerFileSystem,\n folderPath: string\n): Promise<boolean> {\n try {\n await fs.stat(folderPath);\n } catch (error) {\n if (isNotFoundError(error)) {\n return false;\n }\n throw error;\n }\n\n if (typeof fs.rm !== \"function\") {\n throw new UserError(\"The configured filesystem does not support removing directories.\");\n }\n\n await fs.rm(folderPath, { recursive: true, force: true });\n return true;\n}\n", "import os from \"node:os\";\nimport path from \"node:path\";\nimport { resolveAgentId } from \"@poe-code/agent-defs\";\n\nexport interface AgentSkillConfig {\n globalSkillDir: string;\n localSkillDir: string;\n}\n\nexport type SkillScope = \"global\" | \"local\";\n\nconst agentSkillConfigs: Record<string, AgentSkillConfig> = {\n \"claude-code\": {\n globalSkillDir: \"~/.claude/skills\",\n localSkillDir: \".claude/skills\"\n },\n codex: {\n globalSkillDir: \"~/.codex/skills\",\n localSkillDir: \".codex/skills\"\n },\n opencode: {\n globalSkillDir: \"~/.config/opencode/skills\",\n localSkillDir: \".opencode/skills\"\n },\n goose: {\n globalSkillDir: \"~/.agents/skills\",\n localSkillDir: \".agents/skills\"\n }\n};\n\nexport const supportedAgents = Object.keys(agentSkillConfigs) as readonly string[];\n\nexport type AgentSupportStatus = \"supported\" | \"unsupported\" | \"unknown\";\n\nexport interface AgentSupportResult {\n status: AgentSupportStatus;\n input: string;\n id?: string;\n config?: AgentSkillConfig;\n}\n\nexport function resolveAgentSupport(\n input: string,\n registry: Record<string, AgentSkillConfig> = agentSkillConfigs\n): AgentSupportResult {\n const resolvedId = resolveAgentId(input);\n if (!resolvedId) {\n return { status: \"unknown\", input };\n }\n\n const config = registry[resolvedId];\n if (!config) {\n return { status: \"unsupported\", input, id: resolvedId };\n }\n\n return { status: \"supported\", input, id: resolvedId, config };\n}\n\nexport function getAgentConfig(agentId: string): AgentSkillConfig | undefined {\n const support = resolveAgentSupport(agentId);\n return support.status === \"supported\" ? support.config : undefined;\n}\n\nfunction expandHome(targetPath: string): string {\n if (!targetPath?.startsWith(\"~\")) {\n return targetPath;\n }\n\n if (targetPath === \"~\") {\n return os.homedir();\n }\n\n // Handle ~./ -> ~/.\n if (targetPath.startsWith(\"~./\")) {\n targetPath = `~/.${targetPath.slice(3)}`;\n }\n\n let remainder = targetPath.slice(1);\n if (remainder.startsWith(\"/\") || remainder.startsWith(\"\\\\\")) {\n remainder = remainder.slice(1);\n } else if (remainder.startsWith(\".\")) {\n remainder = remainder.slice(1);\n if (remainder.startsWith(\"/\") || remainder.startsWith(\"\\\\\")) {\n remainder = remainder.slice(1);\n }\n }\n\n return remainder.length === 0 ? os.homedir() : path.join(os.homedir(), remainder);\n}\n\nexport function resolveSkillDir(config: AgentSkillConfig, scope: SkillScope, cwd: string): string {\n if (scope === \"global\") {\n return path.resolve(expandHome(config.globalSkillDir));\n }\n\n return path.resolve(cwd, config.localSkillDir);\n}\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const claudeCodeAgent: AgentDefinition = {\n id: \"claude-code\",\n name: \"claude-code\",\n label: \"Claude Code\",\n summary: \"Configure Claude Code to route through Poe.\",\n aliases: [\"claude\"],\n binaryName: \"claude\",\n configPath: \"~/.claude/settings.json\",\n branding: {\n colors: {\n dark: \"#C15F3C\",\n light: \"#C15F3C\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const claudeDesktopAgent: AgentDefinition = {\n id: \"claude-desktop\",\n name: \"claude-desktop\",\n label: \"Claude Desktop\",\n summary: \"Anthropic's official desktop application for Claude\",\n configPath: \"~/.claude/settings.json\",\n branding: {\n colors: {\n dark: \"#D97757\",\n light: \"#D97757\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const codexAgent: AgentDefinition = {\n id: \"codex\",\n name: \"codex\",\n label: \"Codex\",\n summary: \"Configure Codex to use Poe as the model provider.\",\n binaryName: \"codex\",\n configPath: \"~/.codex/config.toml\",\n branding: {\n colors: {\n dark: \"#D5D9DF\",\n light: \"#7A7F86\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const openCodeAgent: AgentDefinition = {\n id: \"opencode\",\n name: \"opencode\",\n label: \"OpenCode CLI\",\n summary: \"Configure OpenCode CLI to use the Poe API.\",\n binaryName: \"opencode\",\n configPath: \"~/.config/opencode/config.json\",\n branding: {\n colors: {\n dark: \"#4A4F55\",\n light: \"#2F3338\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const kimiAgent: AgentDefinition = {\n id: \"kimi\",\n name: \"kimi\",\n label: \"Kimi\",\n summary: \"Configure Kimi CLI to use Poe API\",\n aliases: [\"kimi-cli\"],\n binaryName: \"kimi\",\n configPath: \"~/.kimi/config.toml\",\n branding: {\n colors: {\n dark: \"#7B68EE\",\n light: \"#6A5ACD\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const gooseAgent: AgentDefinition = {\n id: \"goose\",\n name: \"goose\",\n label: \"Goose\",\n summary: \"Block's open-source AI agent with ACP support.\",\n binaryName: \"goose\",\n configPath: \"~/.config/goose/config.yaml\",\n branding: {\n colors: {\n dark: \"#FF6B35\",\n light: \"#E85D26\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const poeAgentAgent: AgentDefinition = {\n id: \"poe-agent\",\n name: \"poe-agent\",\n label: \"Poe Agent\",\n summary: \"Run one-shot prompts with the built-in Poe agent runtime.\",\n configPath: \"~/.poe-code/config.json\",\n branding: {\n colors: {\n dark: \"#A465F7\",\n light: \"#7A3FD3\"\n }\n }\n};\n", "import type { AgentDefinition } from \"./types.js\";\nimport {\n claudeCodeAgent,\n claudeDesktopAgent,\n codexAgent,\n openCodeAgent,\n kimiAgent,\n gooseAgent,\n poeAgentAgent\n} from \"./agents/index.js\";\n\nexport const allAgents: AgentDefinition[] = [\n claudeCodeAgent,\n claudeDesktopAgent,\n codexAgent,\n openCodeAgent,\n kimiAgent,\n gooseAgent,\n poeAgentAgent\n];\n\nconst lookup = new Map<string, string>();\n\nfor (const agent of allAgents) {\n const values = [agent.id, agent.name, ...(agent.aliases ?? [])];\n for (const value of values) {\n const normalized = value.toLowerCase();\n if (!lookup.has(normalized)) {\n lookup.set(normalized, agent.id);\n }\n }\n}\n\nexport function resolveAgentId(input: string): string | undefined {\n if (!input) {\n return undefined;\n }\n return lookup.get(input.toLowerCase());\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 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 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 { readFile, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { TemplateLoader } from \"@poe-code/config-mutations\";\n\nconst TEMPLATE_IDS = [\"poe-generate.md\", \"terminal-pilot.md\"] as const;\ntype TemplateId = (typeof TEMPLATE_IDS)[number];\n\nconst cache = new Map<TemplateId, string>();\n\nasync function pathExists(target: string): Promise<boolean> {\n try {\n await stat(target);\n return true;\n } catch (error) {\n if (error && typeof error === \"object\" && \"code\" in error && error.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nasync function findPackageRoot(entryFilePath: string): Promise<string> {\n let current = path.dirname(entryFilePath);\n while (true) {\n if (await pathExists(path.join(current, \"package.json\"))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n throw new Error(\"Unable to locate package root for agent-skill-config templates.\");\n }\n current = parent;\n }\n}\n\nasync function resolveTemplatePath(templateId: TemplateId): Promise<string> {\n const packageRoot = await findPackageRoot(fileURLToPath(import.meta.url));\n const candidates = [\n path.join(packageRoot, \"src\", \"templates\", templateId),\n path.join(packageRoot, \"dist\", \"templates\", templateId),\n path.join(packageRoot, \"dist\", \"templates\", \"skill\", templateId)\n ];\n\n for (const candidate of candidates) {\n if (await pathExists(candidate)) {\n return candidate;\n }\n }\n\n throw new Error(`Template not found: ${templateId}`);\n}\n\nfunction isKnownTemplate(templateId: string): templateId is TemplateId {\n return (TEMPLATE_IDS as readonly string[]).includes(templateId);\n}\n\nexport async function loadTemplate(templateId: string): Promise<string> {\n if (!isKnownTemplate(templateId)) {\n throw new Error(`Template not found: ${templateId}`);\n }\n\n const cached = cache.get(templateId);\n if (cached !== undefined) {\n return cached;\n }\n\n const resolved = await resolveTemplatePath(templateId);\n const content = await readFile(resolved, \"utf8\");\n cache.set(templateId, content);\n return content;\n}\n\nexport function createTemplateLoader(): TemplateLoader {\n return loadTemplate;\n}\n", "import { defineCommand, S } from \"@poe-code/cmdkit\";\nimport type { TerminalPilotCommandServices } from \"./runtime.js\";\nimport {\n DEFAULT_INSTALL_AGENT,\n getSkillFolderWithHome,\n installableAgents,\n removeSkillFolder,\n resolveInstallableAgent,\n resolveInstallerServices\n} from \"./installer.js\";\n\nconst params = S.Object({\n agent: S.Enum(installableAgents as [string, ...string[]], {\n description: \"Agent to uninstall terminal-pilot from\",\n default: DEFAULT_INSTALL_AGENT\n })\n});\n\nexport const uninstall = defineCommand<\n TerminalPilotCommandServices,\n \"uninstall\",\n typeof params,\n undefined,\n {\n agent: string;\n removedSkillPaths: string[];\n },\n readonly [\"cli\"]\n>({\n name: \"uninstall\",\n description: \"Remove the terminal-pilot CLI skill.\",\n scope: [\"cli\"],\n positional: [\"agent\"],\n params,\n handler: async ({ params, terminalPilotInstaller }) => {\n const services = resolveInstallerServices(terminalPilotInstaller);\n const agent = resolveInstallableAgent(params.agent);\n const localSkill = getSkillFolderWithHome(\n agent,\n \"local\",\n services.cwd,\n services.homeDir\n );\n const globalSkill = getSkillFolderWithHome(\n agent,\n \"global\",\n services.cwd,\n services.homeDir\n );\n const removedSkillPaths: string[] = [];\n\n if (await removeSkillFolder(services.fs, localSkill.fullPath)) {\n removedSkillPaths.push(localSkill.displayPath);\n }\n\n if (await removeSkillFolder(services.fs, globalSkill.fullPath)) {\n removedSkillPaths.push(globalSkill.displayPath);\n }\n\n return {\n agent,\n removedSkillPaths\n };\n }\n});\n"],
5
- "mappings": "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",
6
- "names": ["location", "separatorIndex", "previousSeparatorIndex", "candidate", "os", "path", "readFile", "path", "Mustache", "path", "fileURLToPath", "os", "path", "params"]
3
+ "sources": ["../../../toolcraft/src/index.ts", "../../../toolcraft/src/user-error.ts", "../../../toolcraft/src/human-in-loop/config.ts", "../../../toolcraft-schema/src/json.ts", "../../../toolcraft-schema/src/oneof.ts", "../../../toolcraft-schema/src/record.ts", "../../../toolcraft-schema/src/union.ts", "../../../toolcraft-schema/src/index.ts", "../../src/commands/installer.ts", "../../../agent-skill-config/src/configs.ts", "../../../agent-defs/src/agents/claude-code.ts", "../../../agent-defs/src/agents/claude-desktop.ts", "../../../agent-defs/src/agents/codex.ts", "../../../agent-defs/src/agents/opencode.ts", "../../../agent-defs/src/agents/kimi.ts", "../../../agent-defs/src/agents/goose.ts", "../../../agent-defs/src/agents/poe-agent.ts", "../../../agent-defs/src/registry.ts", "../../../config-mutations/src/execution/apply-mutation.ts", "../../../config-mutations/src/formats/json.ts", "../../../config-mutations/src/formats/toml.ts", "../../../config-mutations/src/formats/yaml.ts", "../../../config-mutations/src/execution/path-utils.ts", "../../../config-mutations/src/template/render.ts", "../../../agent-skill-config/src/templates.ts", "../../src/commands/uninstall.ts"],
4
+ "sourcesContent": ["import { fileURLToPath } from \"node:url\";\nimport type { McpServerConfig } from \"@poe-code/agent-mcp-config\";\nimport type { ObjectSchema, Static } from \"toolcraft-schema\";\nimport type { LoggerOutput, RenderTableOptions, ThemePalette } from \"@poe-code/design-system\";\nimport { ApprovalDeclinedError } from \"./human-in-loop/types.js\";\nimport type { HumanInLoopConfig, HumanInLoopPending, HumanInLoopRuntimeOptions } from \"./human-in-loop/types.js\";\nimport { mergeHumanInLoopFromGroup, validateHumanInLoopOnDefine } from \"./human-in-loop/config.js\";\nimport { UserError } from \"./user-error.js\";\n\nconst commandConfigSymbol = Symbol(\"toolcraft.command.config\");\nconst groupConfigSymbol = Symbol(\"toolcraft.group.config\");\nconst commandSourcePathSymbol = Symbol(\"toolcraft.command.sourcePath\");\n\ntype ScopeValue = \"cli\" | \"mcp\" | \"sdk\";\ntype AnyObjectSchema = ObjectSchema<Record<string, never>>;\ntype EmptyServices = Record<string, never>;\ntype ScopeInput = readonly Scope[] | undefined;\ntype HumanInLoopMode = \"sync\" | \"async\";\ntype HumanInLoopModeInput = HumanInLoopMode | null | undefined;\n\nexport type Scope = ScopeValue;\n\ntype ResolveOwnHumanInLoopMode<TValue> = TValue extends { mode: infer TMode extends HumanInLoopMode }\n ? TMode\n : TValue extends null\n ? null\n : undefined;\n\nexport interface SecretDefinition {\n env: string;\n description?: string;\n optional?: boolean;\n}\n\nexport type SecretDeclarations = Record<string, SecretDefinition>;\n\ntype OptionalSecretKeys<TSecrets extends SecretDeclarations> = {\n [TKey in keyof TSecrets]: TSecrets[TKey] extends { optional: true } ? TKey : never;\n}[keyof TSecrets];\n\ntype RequiredSecretKeys<TSecrets extends SecretDeclarations> = Exclude<\n keyof TSecrets,\n OptionalSecretKeys<TSecrets>\n>;\n\nexport type InferSecrets<TSecrets extends SecretDeclarations | undefined> =\n TSecrets extends SecretDeclarations\n ? { [TKey in RequiredSecretKeys<TSecrets>]: string } & {\n [TKey in OptionalSecretKeys<TSecrets>]?: string;\n }\n : Record<string, never>;\n\nexport interface HandlerFs {\n readFile(path: string, encoding?: BufferEncoding): Promise<string>;\n writeFile(path: string, contents: string): Promise<void>;\n exists(path: string): Promise<boolean>;\n}\n\nexport interface HandlerEnv {\n get(key: string): string | undefined;\n}\n\nexport interface RenderPrimitives {\n logger: LoggerOutput;\n renderTable(options: RenderTableOptions): string;\n getTheme(): ThemePalette;\n note(message: string, title?: string): void;\n}\n\nexport interface CheckResult {\n ok: boolean;\n message?: string;\n}\n\nexport type GroupCheckContext<TServices extends object = EmptyServices> = TServices & {\n params?: unknown;\n secrets?: Record<string, string | undefined>;\n fetch: typeof globalThis.fetch;\n fs: HandlerFs;\n env: HandlerEnv;\n progress(message: string): void;\n};\n\nexport type CommandCheckContext<\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TSecrets extends SecretDeclarations | undefined = undefined,\n TServices extends object = EmptyServices,\n> = TServices & {\n params?: Static<TParamsSchema>;\n secrets?: InferSecrets<TSecrets>;\n fetch: typeof globalThis.fetch;\n fs: HandlerFs;\n env: HandlerEnv;\n progress(message: string): void;\n};\n\nexport interface Requires<TContext = unknown> {\n auth?: boolean;\n apiVersion?: string;\n check?: (ctx: TContext) => Promise<CheckResult>;\n}\n\nexport interface Renderers<TResult> {\n rich?: (result: TResult, primitives: RenderPrimitives) => void;\n markdown?: (result: TResult, primitives: RenderPrimitives) => string;\n json?: (result: TResult, primitives: RenderPrimitives) => unknown;\n}\n\nexport type HandlerContext<\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TSecrets extends SecretDeclarations | undefined = undefined,\n TServices extends object = EmptyServices,\n> = TServices & {\n params: Static<TParamsSchema>;\n secrets: InferSecrets<TSecrets>;\n fetch: typeof globalThis.fetch;\n fs: HandlerFs;\n env: HandlerEnv;\n progress(message: string): void;\n};\n\nexport interface CommandConfig<\n TServices extends object,\n TParamsSchema extends ObjectSchema<any>,\n TSecrets extends SecretDeclarations | undefined,\n TResult,\n> {\n name: string;\n description?: string;\n aliases?: string[];\n positional?: string[];\n params: TParamsSchema;\n secrets?: TSecrets;\n scope?: Scope[];\n confirm?: boolean;\n humanInLoop?: HumanInLoopConfig<TParamsSchema> | null;\n requires?: Requires<CommandCheckContext<TParamsSchema, TSecrets, TServices>>;\n handler: (ctx: HandlerContext<TParamsSchema, TSecrets, TServices>) => Promise<TResult>;\n render?: Renderers<TResult>;\n}\n\nexport interface Command<\n TServices extends object = EmptyServices,\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TSecrets extends SecretDeclarations | undefined = undefined,\n TResult = unknown,\n> {\n kind: \"command\";\n name: string;\n description?: string;\n aliases: string[];\n positional: string[];\n params: TParamsSchema;\n secrets: SecretDeclarations;\n scope: Scope[];\n confirm: boolean;\n humanInLoop?: HumanInLoopConfig<TParamsSchema> | null;\n requires?: Requires<any>;\n handler: (ctx: HandlerContext<TParamsSchema, TSecrets, TServices>) => Promise<TResult>;\n render?: Renderers<TResult>;\n}\n\nexport interface GroupConfig<TServices extends object> {\n name: string;\n description?: string;\n aliases?: string[];\n mcp?: McpServerConfig;\n scope?: Scope[];\n humanInLoop?: HumanInLoopConfig<AnyObjectSchema> | null;\n secrets?: SecretDeclarations;\n tools?: string[];\n rename?: Record<string, string>;\n requires?: Requires<GroupCheckContext<TServices>>;\n children: Array<CommandNode<TServices>>;\n default?: Command<TServices, any, any, any>;\n}\n\nexport interface Group<TServices extends object = EmptyServices> {\n kind: \"group\";\n name: string;\n description?: string;\n aliases: string[];\n scope?: Scope[];\n humanInLoop?: HumanInLoopConfig<AnyObjectSchema> | null;\n secrets: SecretDeclarations;\n requires?: Requires<any>;\n children: Array<CommandNode<TServices>>;\n default?: Command<TServices, any, any, any>;\n}\n\nexport type CommandNode<TServices extends object = EmptyServices> =\n | Command<TServices, any, any, any>\n | Group<TServices>;\n\nexport interface CommandTypeInfo<\n TName extends string = string,\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TResult = unknown,\n TOwnScope extends ScopeInput = ScopeInput,\n TOwnHumanInLoopMode extends HumanInLoopModeInput = undefined,\n> {\n name: TName;\n params: TParamsSchema;\n result: TResult;\n ownScope: TOwnScope;\n ownHumanInLoopMode: TOwnHumanInLoopMode;\n}\n\nexport interface GroupTypeInfo<\n TServices extends object = EmptyServices,\n TName extends string = string,\n TChildren extends readonly unknown[] = readonly CommandNode<TServices>[],\n TOwnScope extends ScopeInput = ScopeInput,\n TOwnHumanInLoopMode extends HumanInLoopModeInput = undefined,\n> {\n name: TName;\n children: TChildren;\n ownScope: TOwnScope;\n ownHumanInLoopMode: TOwnHumanInLoopMode;\n}\n\ntype TypedCommandMetadata<\n TName extends string,\n TParamsSchema extends ObjectSchema<any>,\n TResult,\n TOwnScope extends ScopeInput,\n TOwnHumanInLoopMode extends HumanInLoopModeInput,\n> = {\n readonly __agentKitCommandTypeInfo: CommandTypeInfo<\n TName,\n TParamsSchema,\n TResult,\n TOwnScope,\n TOwnHumanInLoopMode\n >;\n};\n\ntype TypedGroupMetadata<\n TServices extends object,\n TName extends string,\n TChildren extends readonly unknown[],\n TOwnScope extends ScopeInput,\n TOwnHumanInLoopMode extends HumanInLoopModeInput,\n> = {\n readonly __agentKitGroupTypeInfo: GroupTypeInfo<\n TServices,\n TName,\n TChildren,\n TOwnScope,\n TOwnHumanInLoopMode\n >;\n};\n\ninterface InternalCommandConfig {\n scope?: Scope[];\n humanInLoop?: HumanInLoopConfig<ObjectSchema<any>> | null;\n secrets: SecretDeclarations;\n requires?: Requires<any>;\n sourcePath?: string;\n}\n\ninterface InternalGroupConfig<TServices extends object> {\n mcp?: McpServerConfig;\n scope?: Scope[];\n humanInLoop?: HumanInLoopConfig<AnyObjectSchema> | null;\n secrets: SecretDeclarations;\n tools?: string[];\n rename?: Record<string, string>;\n requires?: Requires<any>;\n children: Array<CommandNode<TServices>>;\n default?: Command<TServices, any, any, any>;\n}\n\ninterface InheritedMetadata {\n scope?: Scope[];\n humanInLoop?: HumanInLoopConfig<AnyObjectSchema> | null;\n secrets: SecretDeclarations;\n requires?: Requires<any>;\n}\n\nexport interface CommandRequirementOptions {\n apiVersion?: string;\n authEnvVar?: string;\n env?: Record<string, string | undefined>;\n}\n\nfunction cloneScope(scope: Scope[] | undefined): Scope[] | undefined {\n return scope === undefined ? undefined : [...scope];\n}\n\nfunction cloneSecretDefinition(secret: SecretDefinition): SecretDefinition {\n return {\n env: secret.env,\n description: secret.description,\n optional: secret.optional,\n };\n}\n\nfunction cloneSecrets(secrets: SecretDeclarations | undefined): SecretDeclarations {\n if (secrets === undefined) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(secrets).map(([key, secret]) => [key, cloneSecretDefinition(secret)])\n );\n}\n\nfunction cloneRequires<TContext>(requires: Requires<TContext> | undefined): Requires<TContext> | undefined {\n if (requires === undefined) {\n return undefined;\n }\n\n return {\n auth: requires.auth,\n apiVersion: requires.apiVersion,\n check: requires.check,\n };\n}\n\nfunction cloneStringArray(values: string[] | undefined): string[] | undefined {\n return values === undefined ? undefined : [...values];\n}\n\nfunction cloneStringRecord(values: Record<string, string> | undefined): Record<string, string> | undefined {\n return values === undefined ? undefined : { ...values };\n}\n\nfunction cloneMcpServerConfig(config: McpServerConfig | undefined): McpServerConfig | undefined {\n if (config === undefined) {\n return undefined;\n }\n\n if (config.transport === \"stdio\") {\n return {\n transport: \"stdio\",\n command: config.command,\n args: cloneStringArray(config.args),\n env: cloneStringRecord(config.env),\n };\n }\n\n return {\n transport: \"http\",\n url: config.url,\n headers: cloneStringRecord(config.headers),\n };\n}\n\nfunction cloneRenameMap(rename: Record<string, string> | undefined): Record<string, string> | undefined {\n return rename === undefined ? undefined : { ...rename };\n}\n\nfunction validateRenameMap(rename: Record<string, string> | undefined): void {\n if (rename === undefined) {\n return;\n }\n\n const seenTargets = new Map<string, string>();\n\n for (const [upstreamName, targetPath] of Object.entries(rename)) {\n if (targetPath.length === 0) {\n throw new UserError(`Invalid rename target for upstream tool \"${upstreamName}\": path cannot be empty.`);\n }\n\n if (targetPath.split(\".\").some((segment) => segment.length === 0)) {\n throw new UserError(\n `Invalid rename target for upstream tool \"${upstreamName}\": \"${targetPath}\" contains an empty segment.`\n );\n }\n\n const existingUpstreamName = seenTargets.get(targetPath);\n if (existingUpstreamName !== undefined) {\n throw new UserError(\n `Duplicate rename target \"${targetPath}\" for upstream tools \"${existingUpstreamName}\" and \"${upstreamName}\".`\n );\n }\n\n seenTargets.set(targetPath, upstreamName);\n }\n}\n\nfunction parseStackPath(candidate: string): string | undefined {\n if (candidate.startsWith(\"file://\")) {\n try {\n return fileURLToPath(candidate);\n } catch {\n return undefined;\n }\n }\n\n if (candidate.startsWith(\"/\")) {\n return candidate;\n }\n\n return undefined;\n}\n\nfunction extractStackPath(line: string): string | undefined {\n const trimmed = line.trim();\n const fileIndex = trimmed.indexOf(\"file://\");\n\n if (fileIndex >= 0) {\n const location = trimmed.slice(fileIndex);\n const separatorIndex = location.lastIndexOf(\":\");\n const previousSeparatorIndex = separatorIndex >= 0 ? location.lastIndexOf(\":\", separatorIndex - 1) : -1;\n const candidate =\n separatorIndex >= 0 && previousSeparatorIndex >= 0\n ? location.slice(0, previousSeparatorIndex)\n : location;\n\n return parseStackPath(candidate);\n }\n\n const slashIndex = trimmed.indexOf(\"/\");\n if (slashIndex < 0) {\n return undefined;\n }\n\n const location = trimmed.slice(slashIndex);\n const separatorIndex = location.lastIndexOf(\":\");\n const previousSeparatorIndex = separatorIndex >= 0 ? location.lastIndexOf(\":\", separatorIndex - 1) : -1;\n const candidate =\n separatorIndex >= 0 && previousSeparatorIndex >= 0\n ? location.slice(0, previousSeparatorIndex)\n : location;\n\n return parseStackPath(candidate);\n}\n\nfunction inferCommandSourcePath(): string | undefined {\n const stack = new Error().stack;\n\n if (typeof stack !== \"string\") {\n return undefined;\n }\n\n for (const line of stack.split(\"\\n\").slice(1)) {\n const candidate = extractStackPath(line);\n\n if (candidate === undefined) {\n continue;\n }\n\n if (\n candidate.includes(\"/packages/toolcraft/src/index.ts\") ||\n candidate.includes(\"/packages/toolcraft/dist/index.js\") ||\n candidate.includes(\"/node_modules/toolcraft/dist/index.js\")\n ) {\n continue;\n }\n\n return candidate;\n }\n\n return undefined;\n}\n\nfunction composeChecks(\n parentCheck: Requires<any>[\"check\"] | undefined,\n childCheck: Requires<any>[\"check\"] | undefined\n): Requires<any>[\"check\"] | undefined {\n if (parentCheck === undefined) {\n return childCheck;\n }\n\n if (childCheck === undefined) {\n return parentCheck;\n }\n\n return async (ctx) => {\n const parentResult = await parentCheck(ctx);\n if (!parentResult.ok) {\n return parentResult;\n }\n\n return childCheck(ctx);\n };\n}\n\nfunction mergeRequires(parent: Requires<any> | undefined, child: Requires<any> | undefined): Requires<any> | undefined {\n if (parent === undefined && child === undefined) {\n return undefined;\n }\n\n const merged: Requires<any> = {\n auth: child?.auth ?? parent?.auth,\n apiVersion: child?.apiVersion ?? parent?.apiVersion,\n check: composeChecks(parent?.check, child?.check),\n };\n\n if (\n merged.auth === undefined &&\n merged.apiVersion === undefined &&\n merged.check === undefined\n ) {\n return undefined;\n }\n\n return merged;\n}\n\nfunction parseSimpleSemver(value: string): [number, number, number] | undefined {\n const parts = value.split(\".\");\n if (parts.length !== 3) {\n return undefined;\n }\n\n const parsed = parts.map((part) => {\n if (part.length === 0) {\n return Number.NaN;\n }\n\n for (const char of part) {\n if (char < \"0\" || char > \"9\") {\n return Number.NaN;\n }\n }\n\n return Number(part);\n });\n\n if (parsed.some((part) => !Number.isInteger(part) || part < 0)) {\n return undefined;\n }\n\n return parsed as [number, number, number];\n}\n\nfunction parseMinimumApiVersion(requirement: string): [number, number, number] | undefined {\n if (!requirement.startsWith(\">=\")) {\n return undefined;\n }\n\n return parseSimpleSemver(requirement.slice(2).trim());\n}\n\nfunction compareSemver(left: [number, number, number], right: [number, number, number]): number {\n for (let index = 0; index < left.length; index += 1) {\n if (left[index] === right[index]) {\n continue;\n }\n\n return left[index]! > right[index]! ? 1 : -1;\n }\n\n return 0;\n}\n\nexport function resolveCommandSecrets(\n command: Command<any, any, any, any>,\n env: Record<string, string | undefined> = process.env\n): Record<string, string | undefined> {\n const secrets: Record<string, string | undefined> = {};\n\n for (const [name, secret] of Object.entries(command.secrets)) {\n const value = env[secret.env];\n\n if (value === undefined && secret.optional !== true) {\n const details = secret.description ? `\\n ${secret.description}` : \"\";\n throw new UserError(`Error: Missing required secret ${secret.env}${details}`);\n }\n\n secrets[name] = value;\n }\n\n return secrets;\n}\n\nexport async function assertCommandRequirements(\n command: Command<any, any, any, any>,\n context: GroupCheckContext<any>,\n options: CommandRequirementOptions = {}\n): Promise<void> {\n const requires = command.requires;\n if (requires === undefined) {\n return;\n }\n\n const env = options.env ?? process.env;\n const authEnvVar = options.authEnvVar ?? \"POE_API_KEY\";\n\n if (requires.auth === true && env[authEnvVar] === undefined) {\n throw new UserError(\n `Error: Command \"${command.name}\" requires authentication.\\n Run 'poe-code login' first.`\n );\n }\n\n if (requires.apiVersion !== undefined) {\n const minimumVersion = parseMinimumApiVersion(requires.apiVersion);\n if (minimumVersion === undefined) {\n throw new UserError(\n `Error: Command \"${command.name}\" has invalid apiVersion requirement \"${requires.apiVersion}\". Expected format \">=X.Y.Z\".`\n );\n }\n\n if (options.apiVersion === undefined) {\n throw new UserError(\n `Error: Command \"${command.name}\" requires API version ${requires.apiVersion}, but no runner API version was provided.`\n );\n }\n\n const runnerVersion = parseSimpleSemver(options.apiVersion);\n if (runnerVersion === undefined) {\n throw new UserError(\n `Error: Command \"${command.name}\" requires API version ${requires.apiVersion}, but runner API version \"${options.apiVersion}\" is not valid semver.`\n );\n }\n\n if (compareSemver(runnerVersion, minimumVersion) < 0) {\n throw new UserError(\n `Error: Command \"${command.name}\" requires API version ${requires.apiVersion}, but runner API version is ${options.apiVersion}.`\n );\n }\n }\n\n const checkResult = await requires.check?.(context);\n if (checkResult && !checkResult.ok) {\n throw new UserError(checkResult.message ?? \"Command precondition failed.\");\n }\n}\n\nfunction mergeSecrets(parent: SecretDeclarations, child: SecretDeclarations): SecretDeclarations {\n return cloneSecrets({\n ...parent,\n ...child,\n });\n}\n\nfunction resolveCommandScope(ownScope: Scope[] | undefined, inheritedScope: Scope[] | undefined): Scope[] {\n return cloneScope(ownScope ?? inheritedScope) ?? [\"cli\", \"sdk\"];\n}\n\nfunction resolveGroupScope(ownScope: Scope[] | undefined, inheritedScope: Scope[] | undefined): Scope[] | undefined {\n return cloneScope(ownScope ?? inheritedScope);\n}\n\nfunction createBaseCommand<\n TServices extends object,\n TParamsSchema extends ObjectSchema<any>,\n TSecrets extends SecretDeclarations | undefined,\n TResult,\n>(\n config: CommandConfig<TServices, TParamsSchema, TSecrets, TResult>\n): Command<TServices, TParamsSchema, TSecrets, TResult> {\n const command: Command<TServices, TParamsSchema, TSecrets, TResult> = {\n kind: \"command\",\n name: config.name,\n description: config.description,\n aliases: [...(config.aliases ?? [])],\n positional: [...(config.positional ?? [])],\n params: config.params,\n secrets: cloneSecrets(config.secrets),\n scope: resolveCommandScope(config.scope, undefined),\n confirm: config.confirm ?? false,\n humanInLoop: config.humanInLoop,\n requires: cloneRequires(config.requires),\n handler: config.handler,\n render: config.render,\n };\n\n Object.defineProperty(command, commandConfigSymbol, {\n value: {\n scope: cloneScope(config.scope),\n humanInLoop: config.humanInLoop,\n secrets: cloneSecrets(config.secrets),\n requires: cloneRequires(config.requires),\n sourcePath: inferCommandSourcePath(),\n } satisfies InternalCommandConfig,\n });\n\n return command;\n}\n\nfunction createBaseGroup<TServices extends object>(config: GroupConfig<TServices>): Group<TServices> {\n const group: Group<TServices> = {\n kind: \"group\",\n name: config.name,\n description: config.description,\n aliases: [...(config.aliases ?? [])],\n scope: resolveGroupScope(config.scope, undefined),\n humanInLoop: config.humanInLoop,\n secrets: cloneSecrets(config.secrets),\n requires: cloneRequires(config.requires),\n children: [],\n default: undefined,\n };\n\n Object.defineProperty(group, groupConfigSymbol, {\n value: {\n mcp: cloneMcpServerConfig(config.mcp),\n scope: cloneScope(config.scope),\n humanInLoop: config.humanInLoop,\n secrets: cloneSecrets(config.secrets),\n tools: cloneStringArray(config.tools),\n rename: cloneRenameMap(config.rename),\n requires: cloneRequires(config.requires),\n children: [...config.children],\n default: config.default,\n } satisfies InternalGroupConfig<TServices>,\n });\n\n return group;\n}\n\nfunction getInternalCommandConfig(command: Command<any, any, any, any>): InternalCommandConfig {\n return (command as Command<any, any, any, any> & { [commandConfigSymbol]: InternalCommandConfig })[\n commandConfigSymbol\n ];\n}\n\nfunction getInternalGroupConfig<TServices extends object>(group: Group<TServices>): InternalGroupConfig<TServices> {\n return (group as Group<TServices> & { [groupConfigSymbol]: InternalGroupConfig<TServices> })[\n groupConfigSymbol\n ];\n}\n\nfunction materializeCommand<\n TServices extends object,\n TParamsSchema extends ObjectSchema<any>,\n TSecrets extends SecretDeclarations | undefined,\n TResult,\n>(\n command: Command<TServices, TParamsSchema, TSecrets, TResult>,\n inherited: InheritedMetadata\n): Command<TServices, TParamsSchema, TSecrets, TResult> {\n const internal = getInternalCommandConfig(command);\n\n const materialized: Command<TServices, TParamsSchema, TSecrets, TResult> = {\n kind: \"command\",\n name: command.name,\n description: command.description,\n aliases: [...command.aliases],\n positional: [...command.positional],\n params: command.params,\n secrets: mergeSecrets(inherited.secrets, internal.secrets),\n scope: resolveCommandScope(internal.scope, inherited.scope),\n confirm: command.confirm,\n humanInLoop: mergeHumanInLoopFromGroup(inherited.humanInLoop, internal.humanInLoop),\n requires: mergeRequires(inherited.requires, internal.requires),\n handler: command.handler,\n render: command.render,\n };\n\n Object.defineProperty(materialized, commandConfigSymbol, {\n value: {\n scope: cloneScope(internal.scope),\n humanInLoop: internal.humanInLoop,\n secrets: cloneSecrets(internal.secrets),\n requires: cloneRequires(internal.requires),\n sourcePath: internal.sourcePath,\n } satisfies InternalCommandConfig,\n });\n\n Object.defineProperty(materialized, commandSourcePathSymbol, {\n value: internal.sourcePath,\n });\n\n return materialized;\n}\n\nfunction mergeInheritedMetadata<TServices extends object>(\n group: InternalGroupConfig<TServices>,\n inherited: InheritedMetadata\n): InheritedMetadata {\n return {\n scope: resolveGroupScope(group.scope, inherited.scope),\n humanInLoop: mergeHumanInLoopFromGroup(inherited.humanInLoop, group.humanInLoop),\n secrets: mergeSecrets(inherited.secrets, group.secrets),\n requires: mergeRequires(inherited.requires, group.requires),\n };\n}\n\nfunction materializeGroup<TServices extends object>(\n group: Group<TServices>,\n inherited: InheritedMetadata\n): Group<TServices> {\n const internal = getInternalGroupConfig(group);\n const mergedInherited = mergeInheritedMetadata(internal, inherited);\n const materializedChildren = internal.children.map((child) => materializeNode(child, mergedInherited));\n\n let defaultChild: Command<TServices, any, any, any> | undefined;\n\n if (internal.default !== undefined) {\n const defaultIndex = internal.children.indexOf(internal.default);\n\n if (defaultIndex === -1) {\n throw new UserError(`Default command \"${internal.default.name}\" must be listed in children.`);\n }\n\n const resolvedDefault = materializedChildren[defaultIndex];\n if (resolvedDefault?.kind !== \"command\") {\n throw new UserError(`Default child \"${internal.default.name}\" must be a command.`);\n }\n\n defaultChild = resolvedDefault;\n }\n\n const materialized: Group<TServices> = {\n kind: \"group\",\n name: group.name,\n description: group.description,\n aliases: [...group.aliases],\n scope: mergedInherited.scope,\n humanInLoop: mergedInherited.humanInLoop,\n secrets: mergedInherited.secrets,\n requires: mergedInherited.requires,\n children: materializedChildren,\n default: defaultChild,\n };\n\n Object.defineProperty(materialized, groupConfigSymbol, {\n value: {\n mcp: cloneMcpServerConfig(internal.mcp),\n scope: cloneScope(internal.scope),\n humanInLoop: internal.humanInLoop,\n secrets: cloneSecrets(internal.secrets),\n tools: cloneStringArray(internal.tools),\n rename: cloneRenameMap(internal.rename),\n requires: cloneRequires(internal.requires),\n children: [...internal.children],\n default: internal.default,\n } satisfies InternalGroupConfig<TServices>,\n });\n\n return materialized;\n}\n\nfunction materializeNode<TServices extends object>(\n node: CommandNode<TServices>,\n inherited: InheritedMetadata\n): CommandNode<TServices> {\n if (node.kind === \"command\") {\n return materializeCommand(node, inherited);\n }\n\n return materializeGroup(node, inherited);\n}\n\nexport function defineCommand<\n TServices extends object = EmptyServices,\n TName extends string = string,\n TParamsSchema extends ObjectSchema<any> = AnyObjectSchema,\n TSecrets extends SecretDeclarations | undefined = undefined,\n TResult = unknown,\n TOwnScope extends ScopeInput = undefined,\n TOwnHumanInLoop extends HumanInLoopConfig<TParamsSchema> | null | undefined = undefined,\n>(\n config: Omit<CommandConfig<TServices, TParamsSchema, TSecrets, TResult>, \"name\" | \"scope\" | \"humanInLoop\"> & {\n name: TName;\n scope?: TOwnScope;\n humanInLoop?: TOwnHumanInLoop;\n }\n): Command<TServices, TParamsSchema, TSecrets, TResult> &\n TypedCommandMetadata<TName, TParamsSchema, TResult, TOwnScope, ResolveOwnHumanInLoopMode<TOwnHumanInLoop>> {\n validateHumanInLoopOnDefine(config);\n\n return materializeCommand(createBaseCommand(config as CommandConfig<TServices, TParamsSchema, TSecrets, TResult>), {\n scope: undefined,\n humanInLoop: undefined,\n secrets: {},\n requires: undefined,\n }) as Command<TServices, TParamsSchema, TSecrets, TResult> &\n TypedCommandMetadata<TName, TParamsSchema, TResult, TOwnScope, ResolveOwnHumanInLoopMode<TOwnHumanInLoop>>;\n}\n\nexport function defineGroup<\n TServices extends object = EmptyServices,\n TName extends string = string,\n TChildren extends readonly unknown[] = readonly CommandNode<TServices>[],\n TOwnScope extends ScopeInput = undefined,\n TOwnHumanInLoop extends HumanInLoopConfig<AnyObjectSchema> | null | undefined = undefined,\n>(\n config: Omit<GroupConfig<TServices>, \"name\" | \"children\" | \"scope\" | \"humanInLoop\"> & {\n name: TName;\n children: TChildren & readonly CommandNode<TServices>[];\n scope?: TOwnScope;\n humanInLoop?: TOwnHumanInLoop;\n }\n): Group<TServices> &\n TypedGroupMetadata<TServices, TName, TChildren, TOwnScope, ResolveOwnHumanInLoopMode<TOwnHumanInLoop>> {\n validateRenameMap(config.rename);\n validateHumanInLoopOnDefine(config);\n\n return materializeGroup(createBaseGroup(config as unknown as GroupConfig<TServices>), {\n scope: undefined,\n humanInLoop: undefined,\n secrets: {},\n requires: undefined,\n }) as Group<TServices> &\n TypedGroupMetadata<TServices, TName, TChildren, TOwnScope, ResolveOwnHumanInLoopMode<TOwnHumanInLoop>>;\n}\n\nexport function getCommandSourcePath(command: Command<any, any, any, any>): string | undefined {\n return (command as Command<any, any, any, any> & { [commandSourcePathSymbol]?: string })[\n commandSourcePathSymbol\n ];\n}\n\nexport { S, toJsonSchema } from \"toolcraft-schema\";\nexport { ApprovalDeclinedError, UserError };\nexport type { AnySchema, ArraySchema, BooleanSchema, EnumSchema, JsonSchema, NumberSchema, ObjectSchema, OptionalSchema, Static, StringSchema } from \"toolcraft-schema\";\nexport type { HumanInLoopConfig, HumanInLoopPending, HumanInLoopRuntimeOptions };\n", "export class UserError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"UserError\";\n }\n}\n", "import type { ObjectSchema } from \"toolcraft-schema\";\nimport type { HumanInLoopConfig } from \"./types.js\";\n\ntype HumanInLoopValue<TParamsSchema extends ObjectSchema<any>> =\n | HumanInLoopConfig<TParamsSchema>\n | null\n | undefined;\n\nexport function validateHumanInLoopOnDefine<TParamsSchema extends ObjectSchema<any>>(config: {\n name: string;\n confirm?: boolean;\n children?: readonly unknown[];\n humanInLoop?: HumanInLoopValue<TParamsSchema>;\n}): void {\n const label = Array.isArray(config.children) ? \"group\" : \"command\";\n\n if (config.confirm === true && config.humanInLoop !== undefined && config.humanInLoop !== null) {\n throw new Error(`${label} '${config.name}': use either confirm or humanInLoop, not both`);\n }\n\n if (config.humanInLoop === undefined || config.humanInLoop === null) {\n return;\n }\n\n if (config.humanInLoop.mode !== \"sync\" && config.humanInLoop.mode !== \"async\") {\n throw new Error(`${label} '${config.name}': humanInLoop.mode must be \"sync\" or \"async\"`);\n }\n\n if (typeof config.humanInLoop.message !== \"function\") {\n throw new Error(`${label} '${config.name}': humanInLoop.message must be a function`);\n }\n}\n\nexport function mergeHumanInLoopFromGroup<\n TGroupParamsSchema extends ObjectSchema<any>,\n TChildParamsSchema extends ObjectSchema<any>,\n>(\n groupHumanInLoop: HumanInLoopValue<TGroupParamsSchema>,\n childHumanInLoop: HumanInLoopValue<TChildParamsSchema>\n): HumanInLoopValue<TChildParamsSchema> {\n if (childHumanInLoop !== undefined) {\n return childHumanInLoop;\n }\n\n return groupHumanInLoop as HumanInLoopValue<TChildParamsSchema>;\n}\n", "import type { SchemaBase } from \"./index.js\";\n\ntype JsonPrimitive = string | number | boolean | null;\n\nexport type JsonValue = JsonPrimitive | { [key: string]: JsonValue } | JsonValue[];\n\nexport interface JsonValueSchema extends SchemaBase<\"json\", JsonValue> {\n readonly kind: \"json\";\n}\n\nexport function Json(): JsonValueSchema {\n return {\n kind: \"json\",\n };\n}\n", "import type { ObjectSchema, SchemaBase, Static } from \"./index.js\";\n\ntype OneOfStatic<\n TBranches extends Record<string, ObjectSchema<any>>,\n TDiscriminator extends string,\n> = {\n [TBranchName in keyof TBranches & string]: Omit<Static<TBranches[TBranchName]>, TDiscriminator> & {\n [TFieldName in TDiscriminator]: TBranchName;\n };\n}[keyof TBranches & string];\n\nexport interface OneOfSchema<\n TBranches extends Record<string, ObjectSchema<any>>,\n TDiscriminator extends string = string,\n> extends SchemaBase<\"oneOf\", OneOfStatic<TBranches, TDiscriminator>> {\n readonly discriminator: TDiscriminator;\n readonly branches: TBranches;\n}\n\nfunction assertValidBranches(branches: Record<string, ObjectSchema<any>>): void {\n if (Object.keys(branches).length === 0) {\n throw new Error(\"OneOf schema requires at least one branch\");\n }\n}\n\nexport function OneOf<\n TDiscriminator extends string,\n TBranches extends Record<string, ObjectSchema<any>>,\n>(config: {\n discriminator: TDiscriminator;\n branches: TBranches;\n}): OneOfSchema<TBranches, TDiscriminator> {\n assertValidBranches(config.branches);\n\n return {\n kind: \"oneOf\",\n discriminator: config.discriminator,\n branches: config.branches,\n };\n}\n", "import type { AnySchema, SchemaBase, Static } from \"./index.js\";\n\nexport interface RecordSchema<TValue extends AnySchema>\n extends SchemaBase<\"record\", Record<string, Static<TValue>>> {\n readonly value: TValue;\n}\n\nexport function Record<TValue extends AnySchema>(value: TValue): RecordSchema<TValue> {\n return {\n kind: \"record\",\n value,\n };\n}\n", "import type { AnySchema, ObjectSchema, OptionalSchema, SchemaBase, Static } from \"./index.js\";\n\ntype UnionStatic<TBranches extends readonly ObjectSchema<any>[]> = Static<TBranches[number]>;\n\nexport interface UnionSchema<TBranches extends readonly ObjectSchema<any>[]>\n extends SchemaBase<\"union\", UnionStatic<TBranches>> {\n readonly branches: TBranches;\n}\n\nfunction isOptionalSchema(schema: AnySchema): schema is OptionalSchema<AnySchema> {\n return schema.kind === \"optional\";\n}\n\nfunction getRequiredKeyFingerprint(schema: ObjectSchema<any>): string {\n const requiredKeys = Object.keys(schema.shape)\n .filter((key) => !isOptionalSchema(schema.shape[key] as AnySchema))\n .sort();\n\n return JSON.stringify(requiredKeys);\n}\n\nfunction assertValidBranches(branches: readonly ObjectSchema<any>[]): void {\n if (branches.length === 0) {\n throw new Error(\"Union schema requires at least one branch\");\n }\n\n const fingerprints = new Set<string>();\n\n for (const branch of branches) {\n const fingerprint = getRequiredKeyFingerprint(branch);\n\n if (fingerprints.has(fingerprint)) {\n throw new Error(\"Union schema branches must have unique required-key fingerprints\");\n }\n\n fingerprints.add(fingerprint);\n }\n}\n\nexport function Union<const TBranches extends readonly ObjectSchema<any>[]>(\n branches: TBranches\n): UnionSchema<TBranches> {\n assertValidBranches(branches);\n\n return {\n kind: \"union\",\n branches,\n };\n}\n", "import { Json } from \"./json.js\";\nimport { OneOf } from \"./oneof.js\";\nimport { Record as RecordBuilder } from \"./record.js\";\nimport { Union } from \"./union.js\";\nimport type { JsonValue, JsonValueSchema } from \"./json.js\";\nimport type { OneOfSchema } from \"./oneof.js\";\nimport type { RecordSchema } from \"./record.js\";\nimport type { UnionSchema } from \"./union.js\";\n\ntype JsonSchemaType = \"string\" | \"number\" | \"integer\" | \"boolean\" | \"array\" | \"object\";\ntype SchemaKind =\n | \"string\"\n | \"number\"\n | \"boolean\"\n | \"enum\"\n | \"array\"\n | \"object\"\n | \"optional\"\n | \"oneOf\"\n | \"union\"\n | \"record\"\n | \"json\";\ntype EnumValue = string | number | boolean;\ntype JsonSchemaEnumValue = EnumValue | null;\ntype NumberJsonType = \"number\" | \"integer\";\ntype NonEmptyReadonlyArray<T> = readonly [T, ...T[]];\ntype ObjectShape = Record<string, AnySchema>;\ntype SchemaScope = \"cli\" | \"mcp\" | \"sdk\";\ntype StringMetadata = {\n format?: string;\n maxLength?: number;\n minLength?: number;\n pattern?: string;\n};\ntype NumberMetadata = {\n maximum?: number;\n minimum?: number;\n};\ntype ArrayMetadata = {\n maxItems?: number;\n minItems?: number;\n};\ntype ObjectMetadata = {\n additionalProperties?: boolean;\n};\ntype OptionalKeys<TShape extends ObjectShape> = {\n [TKey in keyof TShape]: TShape[TKey] extends OptionalSchema<any> ? TKey : never;\n}[keyof TShape];\ntype RequiredKeys<TShape extends ObjectShape> = Exclude<keyof TShape, OptionalKeys<TShape>>;\n\ntype PropertyStatic<TSchema extends AnySchema> = TSchema extends OptionalSchema<infer TInner>\n ? Static<TInner>\n : Static<TSchema>;\n\ntype InferObject<TShape extends ObjectShape> = {\n [TKey in RequiredKeys<TShape>]: PropertyStatic<TShape[TKey]>;\n} & {\n [TKey in OptionalKeys<TShape>]?: PropertyStatic<TShape[TKey]>;\n};\n\ntype SchemaOptions<TDefault> = {\n description?: string;\n default?: TDefault;\n nullable?: boolean;\n requiredScopes?: readonly SchemaScope[];\n short?: string;\n scope?: readonly SchemaScope[];\n};\n\nexport interface SchemaBase<TKind extends SchemaKind, TStatic> {\n readonly kind: TKind;\n readonly description?: string;\n readonly default?: TStatic;\n readonly nullable?: boolean;\n readonly requiredScopes?: readonly SchemaScope[];\n readonly short?: string;\n readonly scope?: readonly SchemaScope[];\n readonly __static?: TStatic;\n}\n\nexport interface JsonSchema {\n additionalProperties?: boolean | JsonSchema;\n type?: JsonSchemaType;\n description?: string;\n default?: unknown;\n enum?: ReadonlyArray<JsonSchemaEnumValue>;\n format?: string;\n items?: JsonSchema;\n maxItems?: number;\n maximum?: number;\n maxLength?: number;\n minItems?: number;\n minimum?: number;\n minLength?: number;\n nullable?: boolean;\n oneOf?: JsonSchema[];\n pattern?: string;\n properties?: Record<string, JsonSchema>;\n required?: string[];\n}\n\nexport interface StringSchema extends SchemaBase<\"string\", string>, StringMetadata {}\n\nexport interface NumberSchema extends SchemaBase<\"number\", number>, NumberMetadata {\n readonly jsonType?: NumberJsonType;\n}\n\nexport type BooleanSchema = SchemaBase<\"boolean\", boolean>;\n\nexport interface EnumSchema<TValues extends NonEmptyReadonlyArray<EnumValue>>\n extends SchemaBase<\"enum\", TValues[number]> {\n readonly values: TValues;\n readonly jsonType?: \"integer\";\n readonly labels?: Partial<Record<string, string>>;\n readonly loadOptions?:\n | (() => Array<{ label: string; value: string }>)\n | (() => Promise<Array<{ label: string; value: string }>>);\n}\n\nexport interface ArraySchema<TItem extends AnySchema>\n extends SchemaBase<\"array\", Array<Static<TItem>>>, ArrayMetadata {\n readonly item: TItem;\n}\n\nexport interface ObjectSchema<TShape extends ObjectShape>\n extends SchemaBase<\"object\", InferObject<TShape>>, ObjectMetadata {\n readonly shape: TShape;\n}\n\nexport interface OptionalSchema<TInner extends AnySchema>\n extends SchemaBase<\"optional\", Static<TInner> | undefined> {\n readonly inner: TInner;\n}\n\nexport type AnySchema =\n | StringSchema\n | NumberSchema\n | BooleanSchema\n | EnumSchema<NonEmptyReadonlyArray<EnumValue>>\n | ArraySchema<AnySchema>\n | ObjectSchema<ObjectShape>\n | OptionalSchema<AnySchema>\n | OneOfSchema<Record<string, ObjectSchema<any>>, string>\n | UnionSchema<readonly ObjectSchema<any>[]>\n | RecordSchema<AnySchema>\n | JsonValueSchema;\n\nexport type Static<TSchema extends AnySchema> = TSchema extends SchemaBase<any, infer TStatic>\n ? TStatic\n : never;\n\nfunction withMetadata<TSchema extends AnySchema>(\n schema: TSchema,\n jsonSchema: JsonSchema\n): JsonSchema {\n if (schema.description !== undefined) {\n jsonSchema.description = schema.description;\n }\n\n if (schema.default !== undefined) {\n jsonSchema.default = schema.default;\n }\n\n if (schema.nullable === true) {\n jsonSchema.nullable = true;\n }\n\n return jsonSchema;\n}\n\nfunction withStringMetadata(schema: StringSchema, jsonSchema: JsonSchema): JsonSchema {\n if (schema.minLength !== undefined) {\n jsonSchema.minLength = schema.minLength;\n }\n\n if (schema.maxLength !== undefined) {\n jsonSchema.maxLength = schema.maxLength;\n }\n\n if (schema.pattern !== undefined) {\n jsonSchema.pattern = schema.pattern;\n }\n\n if (schema.format !== undefined) {\n jsonSchema.format = schema.format;\n }\n\n return withMetadata(schema, jsonSchema);\n}\n\nfunction withNumberMetadata(schema: NumberSchema, jsonSchema: JsonSchema): JsonSchema {\n if (schema.minimum !== undefined) {\n jsonSchema.minimum = schema.minimum;\n }\n\n if (schema.maximum !== undefined) {\n jsonSchema.maximum = schema.maximum;\n }\n\n return withMetadata(schema, jsonSchema);\n}\n\nfunction withArrayMetadata(schema: ArraySchema<any>, jsonSchema: JsonSchema): JsonSchema {\n if (schema.minItems !== undefined) {\n jsonSchema.minItems = schema.minItems;\n }\n\n if (schema.maxItems !== undefined) {\n jsonSchema.maxItems = schema.maxItems;\n }\n\n return withMetadata(schema, jsonSchema);\n}\n\nfunction withObjectMetadata(schema: ObjectSchema<any>, jsonSchema: JsonSchema): JsonSchema {\n if (schema.additionalProperties !== undefined) {\n jsonSchema.additionalProperties = schema.additionalProperties;\n }\n\n return withMetadata(schema, jsonSchema);\n}\n\nfunction getEnumJsonType(values: ReadonlyArray<EnumValue>): JsonSchemaType | undefined {\n const [firstValue] = values;\n\n if (firstValue === undefined) {\n return undefined;\n }\n\n const firstType = typeof firstValue;\n const isSinglePrimitiveType = values.every((value) => typeof value === firstType);\n\n if (!isSinglePrimitiveType) {\n return undefined;\n }\n\n if (firstType === \"string\" || firstType === \"number\" || firstType === \"boolean\") {\n return firstType;\n }\n\n return undefined;\n}\n\nfunction isOptionalSchema(schema: AnySchema): schema is OptionalSchema<AnySchema> {\n return schema.kind === \"optional\";\n}\n\nfunction assertValidEnumValues(values: ReadonlyArray<EnumValue>): void {\n if (values.length === 0) {\n throw new Error(\"Enum schema requires at least one value\");\n }\n\n const uniqueValues = new Set(values);\n\n if (uniqueValues.size !== values.length) {\n throw new Error(\"Enum schema values must be unique\");\n }\n}\n\nfunction unwrapOptional(schema: AnySchema): Exclude<AnySchema, OptionalSchema<AnySchema>> {\n if (isOptionalSchema(schema)) {\n return unwrapOptional(schema.inner);\n }\n\n return schema;\n}\n\nfunction withInjectedDiscriminator(\n schema: ObjectSchema<any>,\n discriminator: string,\n branchName: string\n): JsonSchema {\n const branchJsonSchema = toJsonSchema(schema);\n const properties = {\n ...(branchJsonSchema.properties ?? {}),\n [discriminator]: {\n type: \"string\",\n enum: [branchName],\n } satisfies JsonSchema,\n };\n const required = [...new Set([...(branchJsonSchema.required ?? []), discriminator])];\n\n return {\n ...branchJsonSchema,\n type: \"object\",\n properties,\n required,\n };\n}\n\nexport const S = {\n String(options: SchemaOptions<string> & StringMetadata = {}): StringSchema {\n return {\n kind: \"string\",\n ...options,\n };\n },\n\n Number(\n options: SchemaOptions<number> & NumberMetadata & { jsonType?: NumberJsonType } = {}\n ): NumberSchema {\n return {\n kind: \"number\",\n ...options,\n };\n },\n\n Boolean(options: SchemaOptions<boolean> = {}): BooleanSchema {\n return {\n kind: \"boolean\",\n ...options,\n };\n },\n\n Enum<const TValues extends NonEmptyReadonlyArray<EnumValue>>(\n values: TValues,\n options: SchemaOptions<TValues[number]> & {\n jsonType?: \"integer\";\n labels?: Partial<Record<string, string>>;\n loadOptions?:\n | (() => Array<{ label: string; value: string }>)\n | (() => Promise<Array<{ label: string; value: string }>>);\n } = {}\n ): EnumSchema<TValues> {\n assertValidEnumValues(values);\n\n return {\n kind: \"enum\",\n values,\n ...options,\n };\n },\n\n Array<TItem extends AnySchema>(\n item: TItem,\n options: SchemaOptions<Array<Static<TItem>>> & ArrayMetadata = {}\n ): ArraySchema<TItem> {\n return {\n kind: \"array\",\n item,\n ...options,\n };\n },\n\n Object<const TShape extends ObjectShape>(\n shape: TShape,\n options: SchemaOptions<InferObject<TShape>> & ObjectMetadata = {}\n ): ObjectSchema<TShape> {\n return {\n kind: \"object\",\n shape,\n ...options,\n };\n },\n\n Optional<TInner extends AnySchema>(inner: TInner): OptionalSchema<TInner> {\n return {\n kind: \"optional\",\n inner,\n };\n },\n\n OneOf,\n\n Union,\n\n Record: RecordBuilder,\n\n Json,\n} as const;\n\nexport function toJsonSchema(schema: AnySchema): JsonSchema {\n const unwrappedSchema = unwrapOptional(schema);\n\n switch (unwrappedSchema.kind) {\n case \"string\":\n return withStringMetadata(unwrappedSchema, { type: \"string\" });\n\n case \"number\":\n return withNumberMetadata(unwrappedSchema, { type: unwrappedSchema.jsonType ?? \"number\" });\n\n case \"boolean\":\n return withMetadata(unwrappedSchema, { type: \"boolean\" });\n\n case \"enum\": {\n const jsonSchema: JsonSchema = {\n enum:\n unwrappedSchema.nullable === true\n ? [...unwrappedSchema.values, null]\n : [...unwrappedSchema.values],\n };\n const enumType = unwrappedSchema.jsonType ?? getEnumJsonType(unwrappedSchema.values);\n\n if (enumType !== undefined) {\n jsonSchema.type = enumType;\n }\n\n return withMetadata(unwrappedSchema, jsonSchema);\n }\n\n case \"array\":\n return withArrayMetadata(unwrappedSchema, {\n type: \"array\",\n items: toJsonSchema(unwrappedSchema.item),\n });\n\n case \"object\": {\n const properties: Record<string, JsonSchema> = {};\n const required: string[] = [];\n\n for (const [key, propertySchema] of Object.entries(unwrappedSchema.shape)) {\n properties[key] = toJsonSchema(propertySchema);\n\n if (!isOptionalSchema(propertySchema)) {\n required.push(key);\n }\n }\n\n return withObjectMetadata(unwrappedSchema, {\n type: \"object\",\n properties,\n required,\n });\n }\n\n case \"oneOf\":\n return withMetadata(unwrappedSchema, {\n oneOf: Object.entries(unwrappedSchema.branches).map(([branchName, branchSchema]) =>\n withInjectedDiscriminator(branchSchema, unwrappedSchema.discriminator, branchName)\n ),\n });\n\n case \"union\":\n return withMetadata(unwrappedSchema, {\n oneOf: unwrappedSchema.branches.map((branchSchema) => toJsonSchema(branchSchema)),\n });\n\n case \"record\":\n return withMetadata(unwrappedSchema, {\n type: \"object\",\n additionalProperties: toJsonSchema(unwrappedSchema.value),\n });\n\n case \"json\":\n return withMetadata(unwrappedSchema, {});\n }\n}\n\nexport { Json, OneOf, RecordBuilder as Record, Union };\nexport type { JsonValue, JsonValueSchema, OneOfSchema, RecordSchema, UnionSchema };\n", "import os from \"node:os\";\nimport path from \"node:path\";\nimport * as nodeFs from \"node:fs/promises\";\nimport { readFile } from \"node:fs/promises\";\nimport { UserError } from \"toolcraft\";\nimport {\n getAgentConfig,\n resolveAgentSupport as resolveSkillAgentSupport,\n supportedAgents as skillSupportedAgents\n} from \"@poe-code/agent-skill-config\";\n\nexport type TerminalPilotInstallerFileSystem = {\n readFile(path: string, encoding: \"utf8\"): Promise<string>;\n writeFile(\n path: string,\n content: string,\n options?: { encoding: \"utf8\" }\n ): Promise<void>;\n mkdir(path: string, options?: { recursive: boolean }): Promise<void>;\n unlink(path: string): Promise<void>;\n rm?(\n path: string,\n options?: { recursive?: boolean; force?: boolean }\n ): Promise<void>;\n stat(path: string): Promise<{ mode?: number }>;\n readdir(path: string): Promise<string[]>;\n chmod?(path: string, mode: number): Promise<void>;\n};\n\nexport type TerminalPilotInstallScope = \"global\" | \"local\";\nexport type TerminalPilotInstallerPlatform = \"darwin\" | \"linux\" | \"win32\";\n\nexport const DEFAULT_INSTALL_AGENT = \"claude-code\";\nexport const DEFAULT_INSTALL_SCOPE: TerminalPilotInstallScope = \"local\";\nexport const TERMINAL_PILOT_SKILL_NAME = \"terminal-pilot\";\nexport const installableAgents = skillSupportedAgents;\n\nexport type TerminalPilotInstallerServices = {\n fs?: TerminalPilotInstallerFileSystem;\n cwd?: string;\n homeDir?: string;\n platform?: TerminalPilotInstallerPlatform;\n};\n\nfunction isNotFoundError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n );\n}\n\nexport function resolveInstallerServices(\n installer: TerminalPilotInstallerServices | undefined\n): Required<TerminalPilotInstallerServices> {\n return {\n fs: installer?.fs ?? (nodeFs as TerminalPilotInstallerFileSystem),\n cwd: installer?.cwd ?? process.cwd(),\n homeDir: installer?.homeDir ?? os.homedir(),\n platform: installer?.platform ?? (process.platform as TerminalPilotInstallerPlatform)\n };\n}\n\nfunction throwUnsupportedAgent(agent: string): never {\n throw new UserError(`Unsupported agent: ${agent}`);\n}\n\nexport function resolveInstallableAgent(agent: string): string {\n const skillSupport = resolveSkillAgentSupport(agent);\n\n if (\n skillSupport.status !== \"supported\" ||\n !skillSupport.id\n ) {\n throwUnsupportedAgent(agent);\n }\n\n return skillSupport.id;\n}\n\nexport function resolveInstallScope(input: {\n local?: boolean;\n global?: boolean;\n}): TerminalPilotInstallScope {\n if (input.local && input.global) {\n throw new UserError(\"Use either --local or --global, not both.\");\n }\n\n if (input.local) {\n return \"local\";\n }\n\n if (input.global) {\n return \"global\";\n }\n\n return DEFAULT_INSTALL_SCOPE;\n}\n\nlet terminalPilotTemplateCache: string | undefined;\n\nexport async function loadTerminalPilotTemplate(): Promise<string> {\n if (terminalPilotTemplateCache !== undefined) {\n return terminalPilotTemplateCache;\n }\n\n const candidates = [\n new URL(\"./templates/terminal-pilot.md\", import.meta.url),\n new URL(\"../templates/terminal-pilot.md\", import.meta.url),\n new URL(\"../../../agent-skill-config/src/templates/terminal-pilot.md\", import.meta.url)\n ];\n\n for (const candidate of candidates) {\n try {\n terminalPilotTemplateCache = await readFile(candidate, \"utf8\");\n return terminalPilotTemplateCache;\n } catch (error) {\n if (!isNotFoundError(error)) {\n throw error;\n }\n }\n }\n\n throw new UserError(\"terminal-pilot skill template is missing.\");\n}\n\nfunction resolveHomeRelativePath(targetPath: string, homeDir: string): string {\n if (targetPath === \"~\") {\n return homeDir;\n }\n\n if (targetPath.startsWith(\"~/\")) {\n return path.join(homeDir, targetPath.slice(2));\n }\n\n return targetPath;\n}\n\nexport function getSkillFolderWithHome(\n agent: string,\n scope: TerminalPilotInstallScope,\n cwd: string,\n homeDir: string\n): {\n displayPath: string;\n fullPath: string;\n} {\n const config = getAgentConfig(agent);\n\n if (!config) {\n throwUnsupportedAgent(agent);\n }\n\n return {\n displayPath: path.join(\n scope === \"global\" ? config.globalSkillDir : config.localSkillDir,\n TERMINAL_PILOT_SKILL_NAME\n ),\n fullPath: path.join(\n scope === \"global\"\n ? resolveHomeRelativePath(config.globalSkillDir, homeDir)\n : path.resolve(cwd, config.localSkillDir),\n TERMINAL_PILOT_SKILL_NAME\n )\n };\n}\n\nexport async function removeSkillFolder(\n fs: TerminalPilotInstallerFileSystem,\n folderPath: string\n): Promise<boolean> {\n try {\n await fs.stat(folderPath);\n } catch (error) {\n if (isNotFoundError(error)) {\n return false;\n }\n throw error;\n }\n\n if (typeof fs.rm !== \"function\") {\n throw new UserError(\"The configured filesystem does not support removing directories.\");\n }\n\n await fs.rm(folderPath, { recursive: true, force: true });\n return true;\n}\n", "import os from \"node:os\";\nimport path from \"node:path\";\nimport { resolveAgentId } from \"@poe-code/agent-defs\";\n\nexport interface AgentSkillConfig {\n globalSkillDir: string;\n localSkillDir: string;\n}\n\nexport type SkillScope = \"global\" | \"local\";\n\nconst agentSkillConfigs: Record<string, AgentSkillConfig> = {\n \"claude-code\": {\n globalSkillDir: \"~/.claude/skills\",\n localSkillDir: \".claude/skills\"\n },\n codex: {\n globalSkillDir: \"~/.codex/skills\",\n localSkillDir: \".codex/skills\"\n },\n opencode: {\n globalSkillDir: \"~/.config/opencode/skills\",\n localSkillDir: \".opencode/skills\"\n },\n goose: {\n globalSkillDir: \"~/.agents/skills\",\n localSkillDir: \".agents/skills\"\n }\n};\n\nexport const supportedAgents = Object.keys(agentSkillConfigs) as readonly string[];\n\nexport type AgentSupportStatus = \"supported\" | \"unsupported\" | \"unknown\";\n\nexport interface AgentSupportResult {\n status: AgentSupportStatus;\n input: string;\n id?: string;\n config?: AgentSkillConfig;\n}\n\nexport function resolveAgentSupport(\n input: string,\n registry: Record<string, AgentSkillConfig> = agentSkillConfigs\n): AgentSupportResult {\n const resolvedId = resolveAgentId(input);\n if (!resolvedId) {\n return { status: \"unknown\", input };\n }\n\n const config = registry[resolvedId];\n if (!config) {\n return { status: \"unsupported\", input, id: resolvedId };\n }\n\n return { status: \"supported\", input, id: resolvedId, config };\n}\n\nexport function getAgentConfig(agentId: string): AgentSkillConfig | undefined {\n const support = resolveAgentSupport(agentId);\n return support.status === \"supported\" ? support.config : undefined;\n}\n\nfunction expandHome(targetPath: string): string {\n if (!targetPath?.startsWith(\"~\")) {\n return targetPath;\n }\n\n if (targetPath === \"~\") {\n return os.homedir();\n }\n\n // Handle ~./ -> ~/.\n if (targetPath.startsWith(\"~./\")) {\n targetPath = `~/.${targetPath.slice(3)}`;\n }\n\n let remainder = targetPath.slice(1);\n if (remainder.startsWith(\"/\") || remainder.startsWith(\"\\\\\")) {\n remainder = remainder.slice(1);\n } else if (remainder.startsWith(\".\")) {\n remainder = remainder.slice(1);\n if (remainder.startsWith(\"/\") || remainder.startsWith(\"\\\\\")) {\n remainder = remainder.slice(1);\n }\n }\n\n return remainder.length === 0 ? os.homedir() : path.join(os.homedir(), remainder);\n}\n\nexport function resolveSkillDir(config: AgentSkillConfig, scope: SkillScope, cwd: string): string {\n if (scope === \"global\") {\n return path.resolve(expandHome(config.globalSkillDir));\n }\n\n return path.resolve(cwd, config.localSkillDir);\n}\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const claudeCodeAgent: AgentDefinition = {\n id: \"claude-code\",\n name: \"claude-code\",\n label: \"Claude Code\",\n summary: \"Configure Claude Code to route through Poe.\",\n aliases: [\"claude\"],\n binaryName: \"claude\",\n configPath: \"~/.claude/settings.json\",\n branding: {\n colors: {\n dark: \"#C15F3C\",\n light: \"#C15F3C\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const claudeDesktopAgent: AgentDefinition = {\n id: \"claude-desktop\",\n name: \"claude-desktop\",\n label: \"Claude Desktop\",\n summary: \"Anthropic's official desktop application for Claude\",\n configPath: \"~/.claude/settings.json\",\n branding: {\n colors: {\n dark: \"#D97757\",\n light: \"#D97757\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const codexAgent: AgentDefinition = {\n id: \"codex\",\n name: \"codex\",\n label: \"Codex\",\n summary: \"Configure Codex to use Poe as the model provider.\",\n binaryName: \"codex\",\n configPath: \"~/.codex/config.toml\",\n branding: {\n colors: {\n dark: \"#D5D9DF\",\n light: \"#7A7F86\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const openCodeAgent: AgentDefinition = {\n id: \"opencode\",\n name: \"opencode\",\n label: \"OpenCode CLI\",\n summary: \"Configure OpenCode CLI to use the Poe API.\",\n binaryName: \"opencode\",\n configPath: \"~/.config/opencode/config.json\",\n branding: {\n colors: {\n dark: \"#4A4F55\",\n light: \"#2F3338\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const kimiAgent: AgentDefinition = {\n id: \"kimi\",\n name: \"kimi\",\n label: \"Kimi\",\n summary: \"Configure Kimi CLI to use Poe API\",\n aliases: [\"kimi-cli\"],\n binaryName: \"kimi\",\n configPath: \"~/.kimi/config.toml\",\n branding: {\n colors: {\n dark: \"#7B68EE\",\n light: \"#6A5ACD\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const gooseAgent: AgentDefinition = {\n id: \"goose\",\n name: \"goose\",\n label: \"Goose\",\n summary: \"Block's open-source AI agent with ACP support.\",\n binaryName: \"goose\",\n configPath: \"~/.config/goose/config.yaml\",\n branding: {\n colors: {\n dark: \"#FF6B35\",\n light: \"#E85D26\"\n }\n }\n};\n", "import type { AgentDefinition } from \"../types.js\";\n\nexport const poeAgentAgent: AgentDefinition = {\n id: \"poe-agent\",\n name: \"poe-agent\",\n label: \"Poe Agent\",\n summary: \"Run one-shot prompts with the built-in Poe agent runtime.\",\n configPath: \"~/.poe-code/config.json\",\n branding: {\n colors: {\n dark: \"#A465F7\",\n light: \"#7A3FD3\"\n }\n }\n};\n", "import type { AgentDefinition } from \"./types.js\";\nimport {\n claudeCodeAgent,\n claudeDesktopAgent,\n codexAgent,\n openCodeAgent,\n kimiAgent,\n gooseAgent,\n poeAgentAgent\n} from \"./agents/index.js\";\n\nexport const allAgents: AgentDefinition[] = [\n claudeCodeAgent,\n claudeDesktopAgent,\n codexAgent,\n openCodeAgent,\n kimiAgent,\n gooseAgent,\n poeAgentAgent\n];\n\nconst lookup = new Map<string, string>();\n\nfor (const agent of allAgents) {\n const values = [agent.id, agent.name, ...(agent.aliases ?? [])];\n for (const value of values) {\n const normalized = value.toLowerCase();\n if (!lookup.has(normalized)) {\n lookup.set(normalized, agent.id);\n }\n }\n}\n\nexport function resolveAgentId(input: string): string | undefined {\n if (!input) {\n return undefined;\n }\n return lookup.get(input.toLowerCase());\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 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 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 { readFile, stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { TemplateLoader } from \"@poe-code/config-mutations\";\n\nconst TEMPLATE_IDS = [\"poe-generate.md\", \"terminal-pilot.md\"] as const;\ntype TemplateId = (typeof TEMPLATE_IDS)[number];\n\nconst cache = new Map<TemplateId, string>();\n\nasync function pathExists(target: string): Promise<boolean> {\n try {\n await stat(target);\n return true;\n } catch (error) {\n if (error && typeof error === \"object\" && \"code\" in error && error.code === \"ENOENT\") {\n return false;\n }\n throw error;\n }\n}\n\nasync function findPackageRoot(entryFilePath: string): Promise<string> {\n let current = path.dirname(entryFilePath);\n while (true) {\n if (await pathExists(path.join(current, \"package.json\"))) {\n return current;\n }\n const parent = path.dirname(current);\n if (parent === current) {\n throw new Error(\"Unable to locate package root for agent-skill-config templates.\");\n }\n current = parent;\n }\n}\n\nasync function resolveTemplatePath(templateId: TemplateId): Promise<string> {\n const packageRoot = await findPackageRoot(fileURLToPath(import.meta.url));\n const candidates = [\n path.join(packageRoot, \"src\", \"templates\", templateId),\n path.join(packageRoot, \"dist\", \"templates\", templateId),\n path.join(packageRoot, \"dist\", \"templates\", \"skill\", templateId)\n ];\n\n for (const candidate of candidates) {\n if (await pathExists(candidate)) {\n return candidate;\n }\n }\n\n throw new Error(`Template not found: ${templateId}`);\n}\n\nfunction isKnownTemplate(templateId: string): templateId is TemplateId {\n return (TEMPLATE_IDS as readonly string[]).includes(templateId);\n}\n\nexport async function loadTemplate(templateId: string): Promise<string> {\n if (!isKnownTemplate(templateId)) {\n throw new Error(`Template not found: ${templateId}`);\n }\n\n const cached = cache.get(templateId);\n if (cached !== undefined) {\n return cached;\n }\n\n const resolved = await resolveTemplatePath(templateId);\n const content = await readFile(resolved, \"utf8\");\n cache.set(templateId, content);\n return content;\n}\n\nexport function createTemplateLoader(): TemplateLoader {\n return loadTemplate;\n}\n", "import { defineCommand, S } from \"toolcraft\";\nimport type { TerminalPilotCommandServices } from \"./runtime.js\";\nimport {\n DEFAULT_INSTALL_AGENT,\n getSkillFolderWithHome,\n installableAgents,\n removeSkillFolder,\n resolveInstallableAgent,\n resolveInstallerServices\n} from \"./installer.js\";\n\nconst params = S.Object({\n agent: S.Enum(installableAgents as [string, ...string[]], {\n description: \"Agent to uninstall terminal-pilot from\",\n default: DEFAULT_INSTALL_AGENT\n })\n});\n\nexport const uninstall = defineCommand<\n TerminalPilotCommandServices,\n \"uninstall\",\n typeof params,\n undefined,\n {\n agent: string;\n removedSkillPaths: string[];\n },\n readonly [\"cli\"]\n>({\n name: \"uninstall\",\n description: \"Remove the terminal-pilot CLI skill.\",\n scope: [\"cli\"],\n positional: [\"agent\"],\n params,\n handler: async ({ params, terminalPilotInstaller }) => {\n const services = resolveInstallerServices(terminalPilotInstaller);\n const agent = resolveInstallableAgent(params.agent);\n const localSkill = getSkillFolderWithHome(\n agent,\n \"local\",\n services.cwd,\n services.homeDir\n );\n const globalSkill = getSkillFolderWithHome(\n agent,\n \"global\",\n services.cwd,\n services.homeDir\n );\n const removedSkillPaths: string[] = [];\n\n if (await removeSkillFolder(services.fs, localSkill.fullPath)) {\n removedSkillPaths.push(localSkill.displayPath);\n }\n\n if (await removeSkillFolder(services.fs, globalSkill.fullPath)) {\n removedSkillPaths.push(globalSkill.displayPath);\n }\n\n return {\n agent,\n removedSkillPaths\n };\n }\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["assertValidBranches", "location", "separatorIndex", "previousSeparatorIndex", "candidate", "os", "path", "readFile", "path", "Mustache", "path", "fileURLToPath", "os", "path", "params"]
7
7
  }
@@ -1,14 +1,14 @@
1
1
  import { type TerminalPilotCommandServices } from "./runtime.js";
2
- export declare const waitForExit: import("@poe-code/cmdkit").Command<TerminalPilotCommandServices, import("@poe-code/cmdkit-schema").ObjectSchema<{
3
- readonly session: import("@poe-code/cmdkit-schema").OptionalSchema<import("@poe-code/cmdkit-schema").StringSchema>;
4
- readonly timeout: import("@poe-code/cmdkit-schema").OptionalSchema<import("@poe-code/cmdkit-schema").NumberSchema>;
2
+ export declare const waitForExit: import("toolcraft").Command<TerminalPilotCommandServices, import("toolcraft-schema").ObjectSchema<{
3
+ readonly session: import("toolcraft-schema").OptionalSchema<import("toolcraft-schema").StringSchema>;
4
+ readonly timeout: import("toolcraft-schema").OptionalSchema<import("toolcraft-schema").NumberSchema>;
5
5
  }>, undefined, {
6
6
  exitCode: number;
7
7
  }> & {
8
- readonly __cmdkitCommandTypeInfo: import("@poe-code/cmdkit").CommandTypeInfo<"wait-for-exit", import("@poe-code/cmdkit-schema").ObjectSchema<{
9
- readonly session: import("@poe-code/cmdkit-schema").OptionalSchema<import("@poe-code/cmdkit-schema").StringSchema>;
10
- readonly timeout: import("@poe-code/cmdkit-schema").OptionalSchema<import("@poe-code/cmdkit-schema").NumberSchema>;
8
+ readonly __agentKitCommandTypeInfo: import("toolcraft").CommandTypeInfo<"wait-for-exit", import("toolcraft-schema").ObjectSchema<{
9
+ readonly session: import("toolcraft-schema").OptionalSchema<import("toolcraft-schema").StringSchema>;
10
+ readonly timeout: import("toolcraft-schema").OptionalSchema<import("toolcraft-schema").NumberSchema>;
11
11
  }>, {
12
12
  exitCode: number;
13
- }, readonly ["cli", "mcp", "sdk"]>;
13
+ }, readonly ["cli", "mcp", "sdk"], undefined>;
14
14
  };